Fixed vehicle dismount-store causing crash

This commit is contained in:
Obique
2018-12-30 19:48:48 -06:00
parent 38d6ae5d2c
commit ee0dc774ff
7 changed files with 56 additions and 56 deletions
@@ -27,7 +27,6 @@
package com.projectswg.holocore.resources.support.objects.awareness;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,12 +39,10 @@ public class ObjectAware {
private static final Collection<SWGObject> EMPTY_SET = Collections.emptyList();
private final SWGObject object;
private final EnumMap<AwarenessType, Collection<SWGObject>> awareness;
private final AtomicReference<TerrainMapChunk> chunk;
public ObjectAware(@NotNull SWGObject obj) {
this.object = obj;
public ObjectAware() {
this.awareness = new EnumMap<>(AwarenessType.class);
this.chunk = new AtomicReference<>(null);
for (AwarenessType type : AwarenessType.getValues()) {
@@ -55,9 +52,6 @@ public class ObjectAware {
public synchronized void setAware(@NotNull AwarenessType type, @NotNull Collection<SWGObject> objects) {
awareness.put(type, objects);
if (object instanceof CreatureObject)
((CreatureObject) object).flushObjectsAware();
}
@NotNull
@@ -82,7 +82,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
private final Map <String, SWGObject> slots = new ConcurrentHashMap<>();
private final Map <String, String> attributes = Collections.synchronizedMap(new LinkedHashMap<>());
private final Map<String, SlotDefinition> slotsAvailable = new ConcurrentHashMap<>();
private final ObjectAware awareness = new ObjectAware(this);
private final ObjectAware awareness = new ObjectAware();
private final Set<CreatureObject> observers = ConcurrentHashMap.newKeySet();
private final Map<ObjectDataAttribute, Object> dataAttributes = new EnumMap<>(ObjectDataAttribute.class);
private final Map<ServerAttribute, Object> serverAttributes= new EnumMap<>(ServerAttribute.class);
@@ -99,11 +99,18 @@ public class CreatureObject extends TangibleObject {
getAwareness().setAware(AwarenessType.SELF, List.of(this));
}
public void flushObjectsAware() {
public void flushObjectCreates() {
Player owner = getOwnerShallow();
if (getTerrain() == Terrain.GONE || owner == null || owner.getPlayerState() == PlayerState.DISCONNECTED)
return;
awareness.flushAware();
awareness.flushCreates(owner);
}
public void flushObjectDestroys() {
Player owner = getOwnerShallow();
if (getTerrain() == Terrain.GONE || owner == null || owner.getPlayerState() == PlayerState.DISCONNECTED)
return;
awareness.flushDestroys(owner);
}
public void resetObjectsAware() {
@@ -31,7 +31,6 @@ import com.projectswg.common.network.packets.swg.zone.*;
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline.BaselineType;
import com.projectswg.common.network.packets.swg.zone.building.UpdateCellPermissionMessage;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.global.player.PlayerState;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
@@ -53,23 +52,10 @@ public class CreatureObjectAwareness {
this.objectComparator = Comparator.comparingInt(CreatureObjectAwareness::getObjectDepth).thenComparingDouble(this::getDistance);
}
public synchronized void flushAware() {
Player target = creature.getOwner();
// If we're disconnected, no need to worry about awareness
if (target == null || target.getPlayerState() == PlayerState.DISCONNECTED) {
for (SWGObject obj : aware) {
obj.removeObserver(creature);
}
aware.clear();
awareIds.clear();
return;
}
public synchronized void flushCreates(@NotNull Player target) {
Set<SWGObject> newAware = creature.getAware();
List<SWGObject> create = new ArrayList<>();
List<SWGObject> destroy = new ArrayList<>();
List<SWGObject> added = new ArrayList<>();
List<SWGObject> removed = new ArrayList<>();
// Create Deltas
for (SWGObject createCandidate : newAware) {
@@ -79,31 +65,6 @@ public class CreatureObjectAwareness {
}
getCreateList(create, added);
for (SWGObject destroyCandidate : aware) {
if (newAware.contains(destroyCandidate))
continue;
removed.add(destroyCandidate);
}
getDestroyList(destroy, removed);
// Remove destroyed objects so that nobody tries to send a packet to us after we send the destroy
for (Iterator<SWGObject> it = aware.iterator(); it.hasNext(); ) {
SWGObject currentAware = it.next();
for (SWGObject remove : destroy) { // Since the "create" is filtered, aware could also have been filtered
if (isParent(currentAware, remove)) {
it.remove();
awareIds.remove(currentAware.getObjectId());
remove.removeObserver(creature);
break;
}
}
}
// Destroy the objects on the client
for (SWGObject obj : destroy) {
destroyObject(obj, target);
}
// Create the objects on the client
LinkedList<SWGObject> createStack = new LinkedList<>();
for (SWGObject obj : create) {
@@ -128,6 +89,42 @@ public class CreatureObjectAwareness {
assert aware.contains(creature) : "not aware of creature";
}
public synchronized void flushDestroys(@NotNull Player target) {
Set<SWGObject> newAware = creature.getAware();
List<SWGObject> destroy = new ArrayList<>();
List<SWGObject> removed = new ArrayList<>();
// Create Deltas
for (SWGObject destroyCandidate : aware) {
if (newAware.contains(destroyCandidate))
continue;
removed.add(destroyCandidate);
}
getDestroyList(destroy, removed);
// Remove destroyed objects so that nobody tries to send a packet to us after we send the destroy
for (Iterator<SWGObject> it = aware.iterator(); it.hasNext(); ) {
SWGObject currentAware = it.next();
for (SWGObject remove : destroy) { // Since the "create" is filtered, aware could also have been filtered
if (isParent(currentAware, remove)) {
it.remove();
awareIds.remove(currentAware.getObjectId());
remove.removeObserver(creature);
break;
}
}
}
// Destroy the objects on the client
for (SWGObject obj : destroy) {
destroyObject(obj, target);
}
// Hope we didn't screw anything up
assert aware.contains(creature.getSlottedObject("ghost")) : "not aware of ghost " + creature;
assert aware.contains(creature) : "not aware of creature";
}
public synchronized void resetObjectsAware() {
for (SWGObject obj : aware) {
obj.removeObserver(creature);
@@ -144,7 +141,7 @@ public class CreatureObjectAwareness {
return aware.contains(obj);
}
void getCreateList(List<SWGObject> list, List<SWGObject> added) {
private void getCreateList(List<SWGObject> list, List<SWGObject> added) {
added.sort(objectComparator);
for (SWGObject obj : added) {
SWGObject parent = obj.getParent();
@@ -163,7 +160,7 @@ public class CreatureObjectAwareness {
}
}
void getDestroyList(List<SWGObject> list, List<SWGObject> removed) {
private void getDestroyList(List<SWGObject> list, List<SWGObject> removed) {
removed.sort(objectComparator);
for (SWGObject obj : removed) {
// Don't delete our own parent nor child objects if we're deleting their parent (optimization)
@@ -185,7 +182,7 @@ public class CreatureObjectAwareness {
}
private boolean isBundledObject(SWGObject obj, SWGObject parent) {
return parent != null && (obj.getSlotArrangement() == -1 || obj.getBaselineType() == BaselineType.PLAY);
return parent != null && (obj.getSlotArrangement() == -1 || obj.getBaselineType() == BaselineType.PLAY || parent == creature);
}
private void createObject(@NotNull SWGObject obj, @NotNull Player target) {
@@ -49,7 +49,6 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class GroupObject extends SWGObject {
@@ -249,7 +248,6 @@ public class GroupObject extends SWGObject {
creature.setGroupId(0);
groupMembers.remove(member);
creature.setAware(AwarenessType.GROUP, List.of());
setAware(AwarenessType.GROUP, groupMembers.stream().map(GroupMember::getCreature).collect(Collectors.toList()));
}
groupMembers.sendDeltaMessage(this);
}
@@ -95,10 +95,12 @@ public class AwarenessService extends Service {
public void update() {
awareness.updateChunks();
onlinePlayers.forEach(CreatureObject::flushObjectCreates);
while (!positionUpdates.isEmpty()) {
Runnable r = positionUpdates.poll();
r.run();
}
onlinePlayers.forEach(CreatureObject::flushObjectDestroys);
onlinePlayers.forEach(CreatureObject::sendAndFlushAllDeltas);
}
@@ -115,8 +117,8 @@ public class AwarenessService extends Service {
break;
case PE_LOGGED_OUT:
if (creature != null) {
awareness.updateObject(creature);
onlinePlayers.remove(creature);
creature.resetObjectsAware();
}
break;
case PE_FIRST_ZONE:
@@ -213,6 +213,8 @@ public class TestObjectAwareness extends TestRunnerNoIntents {
private void update(CreatureObject obj) {
awareness.updateObject(obj);
awareness.updateChunks();
obj.flushObjectCreates();
obj.flushObjectDestroys();
}
private void moveNoAssert(TestLocation location) {