From 6c3e0c612c5f95dd0fdb0c7f1c5e606464303218 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Sun, 29 May 2016 17:55:44 -0500 Subject: [PATCH 01/24] Fixed NGE-397 'Deleted characters get removed properly' --- src/resources/objects/quadtree/QuadTree.java | 40 ++++++++++++++++++++ src/services/objects/ObjectAwareness.java | 3 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/resources/objects/quadtree/QuadTree.java b/src/resources/objects/quadtree/QuadTree.java index 7fba1c265..795e2ef55 100644 --- a/src/resources/objects/quadtree/QuadTree.java +++ b/src/resources/objects/quadtree/QuadTree.java @@ -56,6 +56,18 @@ public class QuadTree { headNode.insert(x, y, value); } + public boolean contains(double x, double y, V obj) { + return containsWithinRange(x, y, obj, DEFAULT_RANGE); + } + + public boolean containsWithinRange(double x, double y, V obj, double range) { + if (Double.isNaN(x) || Double.isNaN(y)) + return false; + if (x < minX || y < minY || x > maxX || y > maxY) + return false; + return headNode.containsWithinRange(x, y, obj, range); + } + public List get(double x, double y) { return getWithinRange(x, y, DEFAULT_RANGE); } @@ -198,6 +210,26 @@ public class QuadTree { obj.insert(v); } + public boolean containsWithinRange(double x, double y, V v, double range) { + if (obj != null && square(obj.x - x) + square(obj.y - y) <= square(range)) { + return obj.contains(v); + } + int mnX = (x - range <= minX) ? 0 : getIndex(x - range, minX, cellWidth); + int mnY = (y - range <= minY) ? 0 : getIndex(y - range, minY, cellHeight); + int mxX = (x + range >= maxX) ? subnodes.length() - 1 : getIndex(x + range, minX, cellWidth); + int mxY = (y + range >= maxY) ? subnodes.length() - 1 : getIndex(y + range, minY, cellHeight); + for (int xInd = mnX; xInd <= mxX; xInd++) { + for (int yInd = mnY-1; yInd <= mxY; yInd++) { + if (yInd < 0) + continue; + QuadNode node = subnodes.getSubnode(xInd, yInd); + if (node != null && node.containsWithinRange(x, y, v, range)) + return true; + } + } + return false; + } + public void getWithinRange(List list, double x, double y, double range) { if (obj != null && square(obj.x - x) + square(obj.y - y) <= square(range)) { obj.addAll(list); @@ -250,6 +282,14 @@ public class QuadTree { next.insert(value); } + public boolean contains(V v) { + if (value.equals(v)) + return true; + if (next != null) + return next.contains(v); + return false; + } + public int addAll(List list) { list.add(value); if (next != null) diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index ba2f8b20c..57ad6c1c7 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -286,7 +286,8 @@ public class ObjectAwareness extends Service { return; QuadTree tree = getTree(l); synchronized (tree) { - tree.put(l.getX(), l.getZ(), object); + if (!tree.get(l.getX(), l.getZ()).contains(object)) + tree.put(l.getX(), l.getZ(), object); } } From 576b2bd8be6f533a3272e055c32fb8e0de4497b6 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 00:16:48 -0500 Subject: [PATCH 02/24] Added parent to serialized output --- src/resources/objects/SWGObject.java | 31 +++++++++------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 91e73de5d..3d702edb6 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -58,6 +58,7 @@ import resources.player.Player; import resources.player.PlayerState; import resources.server_info.Log; import services.CoreManager; +import services.objects.ObjectCreator; import java.util.ArrayList; import java.util.Collection; @@ -1077,28 +1078,14 @@ public abstract class SWGObject extends BaselineObject implements Comparable attributes; - private ContainerPermissions containerPermissions; - private ObjectClassification classification = ObjectClassification.GENERATED; - private String objectName = ""; - private int volume = 0; - private float complexity = 1; - private int containerType = 0; - private double loadRange = 0; - private int areaId = -1; - - private final HashMap slots; - private final Map containedObjects; - */ @Override public void save(NetBufferStream stream) { - stream.addByte(0); + stream.addByte(1); location.save(stream); - containerPermissions.save(stream); + ContainerPermissionsFactory.save(containerPermissions, stream); + stream.addBoolean(parent != null && parent.getClassification() != ObjectClassification.GENERATED); + if (parent != null && parent.getClassification() != ObjectClassification.GENERATED) + SWGObjectFactory.save(ObjectCreator.createObjectFromTemplate(parent.getObjectId(), parent.getTemplate()), stream); synchronized (attributes) { stream.addMap(attributes, (e) -> { stream.addAscii(e.getKey()); @@ -1122,9 +1109,11 @@ public abstract class SWGObject extends BaselineObject implements Comparable= 1 && stream.getBoolean()) + parent = SWGObjectFactory.create(stream); stream.getList((i) -> attributes.put(stream.getAscii(), stream.getAscii())); classification = ObjectClassification.valueOf(stream.getAscii()); objectName = stream.getUnicode(); From 83d4ae2098c96966922ad081a039a3163b196e41 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 09:21:23 -0500 Subject: [PATCH 03/24] Fixed a weird issue with object IDs generated overlapping others --- src/resources/objects/SWGObject.java | 11 +++++---- src/services/objects/ObjectCreator.java | 26 ++++++++++----------- src/services/objects/ObjectManager.java | 30 +++++++++---------------- 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 3d702edb6..d63c90615 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -43,6 +43,7 @@ import resources.buildout.BuildoutArea; import resources.client_info.visitors.ObjectData.ObjectDataAttribute; import resources.common.CRC; import resources.containers.ContainerPermissions; +import resources.containers.ContainerPermissionsFactory; import resources.containers.ContainerResult; import resources.containers.DefaultPermissions; import resources.encodables.StringId; @@ -224,6 +225,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable maxObjectId) - maxObjectId = objectId; + if (objectId >= nextObjectId) + nextObjectId = objectId+1; + } + } + + private static long getNextObjectId() { + synchronized (OBJECT_ID_MUTEX) { + return nextObjectId++; } } @@ -108,19 +114,11 @@ public final class ObjectCreator { } public static SWGObject createObjectFromTemplate(String template) { - long id = 0; - synchronized (OBJECT_ID_MUTEX) { - id = maxObjectId++; - } - return createObjectFromTemplate(id, template); + return createObjectFromTemplate(getNextObjectId(), template); } public static T createObjectFromTemplate(String template, Class c) { - long id = 0; - synchronized (OBJECT_ID_MUTEX) { - id = maxObjectId++; - } - return createObjectFromTemplate(id, template, c); + return createObjectFromTemplate(getNextObjectId(), template, c); } private static SWGObject createObjectFromType(long objectId, String template, GameObjectType got) { diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index a0514ce81..b7512bd28 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -121,42 +121,31 @@ public class ObjectManager extends Manager { private void loadClientObjects() { Collection objects = clientBuildoutService.loadClientObjects(); for (SWGObject object : objects) { - putObject(object); new ObjectCreatedIntent(object).broadcast(); } } private void loadObject(SWGObject obj) { - obj.setOwner(null); - // if creature is not a player - if (!(obj instanceof CreatureObject && ((CreatureObject) obj).isLoggedOutPlayer())) - objectAwareness.add(obj); - else // If creature is a player + if (obj instanceof CreatureObject && ((CreatureObject) obj).isPlayer()) Scripts.invoke("objects/load_creature", "onLoad", obj); - putObject(obj); updateBuildoutParent(obj); addChildrenObjects(obj); - new ObjectCreatedIntent(obj).broadcast(); } private void updateBuildoutParent(SWGObject obj) { if (obj.getParent() != null) { - if (!obj.getParent().isGenerated()) { - long id = obj.getParent().getObjectId(); - SWGObject parent = getObjectById(id); - obj.moveToContainer(parent); - if (parent == null) - Log.e("ObjectManager", "Parent for %s is null! ParentID: %d", obj, id); - } else { - updateBuildoutParent(obj.getParent()); - } + long id = obj.getParent().getObjectId(); + SWGObject parent = getObjectById(id); + obj.moveToContainer(parent); + if (parent == null) + Log.e("ObjectManager", "Parent for %s is null! ParentID: %d", obj, id); } } private void addChildrenObjects(SWGObject obj) { + new ObjectCreatedIntent(obj).broadcast(); for (SWGObject child : obj.getContainedObjects()) { - putObject(child); addChildrenObjects(child); } } @@ -255,9 +244,10 @@ public class ObjectManager extends Manager { } private void putObject(SWGObject object) { - ObjectCreator.updateMaxObjectId(object.getObjectId()); synchronized (objectMap) { - objectMap.put(object.getObjectId(), object); + SWGObject replaced = objectMap.put(object.getObjectId(), object); + if (replaced != null) + Log.e(this, "Replaced object in object map! Old: %s New: %s", replaced, object); } } From ffb158db7da2c73f7d382bf5fbc651c3faf735fa Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 14:20:47 -0500 Subject: [PATCH 04/24] Decreased QuadTree sensitivity --- src/resources/objects/quadtree/QuadTree.java | 2 +- src/services/objects/ObjectAwareness.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resources/objects/quadtree/QuadTree.java b/src/resources/objects/quadtree/QuadTree.java index 795e2ef55..0f7d7b935 100644 --- a/src/resources/objects/quadtree/QuadTree.java +++ b/src/resources/objects/quadtree/QuadTree.java @@ -33,7 +33,7 @@ import java.util.NoSuchElementException; public class QuadTree { - private static final double DEFAULT_RANGE = 1E-5; + private static final double DEFAULT_RANGE = 1E-3; private final QuadNode headNode; private final double minX, minY, maxX, maxY; diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 57ad6c1c7..810fea83c 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -286,7 +286,7 @@ public class ObjectAwareness extends Service { return; QuadTree tree = getTree(l); synchronized (tree) { - if (!tree.get(l.getX(), l.getZ()).contains(object)) + if (!tree.contains(l.getX(), l.getZ(), object)) tree.put(l.getX(), l.getZ(), object); } } From 648844e287762cd811d91c3340f65d71fab1b016 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 14:45:11 -0500 Subject: [PATCH 05/24] Fixed equals in ContainerPermissions --- .../ContainerPermissionsFactory.java | 66 +++++++++++++++++++ .../containers/DefaultPermissions.java | 18 ++++- .../containers/InventoryPermissions.java | 12 +++- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 src/resources/containers/ContainerPermissionsFactory.java diff --git a/src/resources/containers/ContainerPermissionsFactory.java b/src/resources/containers/ContainerPermissionsFactory.java new file mode 100644 index 000000000..b801f8d46 --- /dev/null +++ b/src/resources/containers/ContainerPermissionsFactory.java @@ -0,0 +1,66 @@ +/************************************************************************************ + * Copyright (c) 2015 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * -------------------------------------------------------------------------------- * + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + * * + ***********************************************************************************/ +package resources.containers; + +import resources.network.NetBufferStream; + +public class ContainerPermissionsFactory { + + public static ContainerPermissions create(NetBufferStream stream) { + ContainerPermissions permissions; + byte type = stream.getByte(); + switch (type) { + case 1: + permissions = new DefaultPermissions(); + break; + case 2: + permissions = new InventoryPermissions(); + break; + case 3: + permissions = new WorldPermissions(); + break; + default: + throw new IllegalStateException("Unknown type byte! Type: " + type); + } + permissions.read(stream); + return permissions; + } + + public static void save(ContainerPermissions permissions, NetBufferStream stream) { + if (permissions instanceof DefaultPermissions) + stream.addByte(1); + else if (permissions instanceof InventoryPermissions) + stream.addByte(2); + else if (permissions instanceof WorldPermissions) + stream.addByte(3); + else + throw new IllegalArgumentException("Unknown permissions type! Permissions: " + permissions); + permissions.save(stream); + } + +} diff --git a/src/resources/containers/DefaultPermissions.java b/src/resources/containers/DefaultPermissions.java index 94e0a85dc..0a1718422 100644 --- a/src/resources/containers/DefaultPermissions.java +++ b/src/resources/containers/DefaultPermissions.java @@ -48,16 +48,28 @@ public class DefaultPermissions extends ContainerPermissions { @Override public boolean canRemove(SWGObject requester, SWGObject container) { - return requester.getOwner() == container.getOwner(); + if (requester.getOwner() == null) + return true; + if (container.getOwner() == null) + return false; + return requester.getOwner().equals(container.getOwner()); } @Override public boolean canMove(SWGObject requester, SWGObject container) { - return requester.getOwner() == container.getOwner(); + if (requester.getOwner() == null) + return true; + if (container.getOwner() == null) + return false; + return requester.getOwner().equals(container.getOwner()); } @Override public boolean canAdd(SWGObject requester, SWGObject container) { - return requester.getOwner() == container.getOwner(); + if (requester.getOwner() == null) + return true; + if (container.getOwner() == null) + return false; + return requester.getOwner().equals(container.getOwner()); } } diff --git a/src/resources/containers/InventoryPermissions.java b/src/resources/containers/InventoryPermissions.java index 5b039f600..ceb55e4b3 100644 --- a/src/resources/containers/InventoryPermissions.java +++ b/src/resources/containers/InventoryPermissions.java @@ -38,11 +38,19 @@ public class InventoryPermissions extends DefaultPermissions { @Override public boolean canView(SWGObject requester, SWGObject container) { - return requester.getOwner() == container.getOwner(); + if (requester.getOwner() == null) + return true; + if (container.getOwner() == null) + return false; + return requester.getOwner().equals(container.getOwner()); } @Override public boolean canEnter(SWGObject requester, SWGObject container) { - return requester.getOwner() == container.getOwner(); + if (requester.getOwner() == null) + return true; + if (container.getOwner() == null) + return false; + return requester.getOwner().equals(container.getOwner()); } } From c788f585251081902d097a34e937f30373f6ab7d Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 15:03:37 -0500 Subject: [PATCH 06/24] Fixed equipment transfer code --- scripts/commands/generic/transferItemArmor.js | 5 ----- scripts/commands/generic/transferItemMisc.js | 5 ----- scripts/commands/generic/transferItemWeapon.js | 10 ---------- src/resources/objects/creature/CreatureObject.java | 10 ++++++++-- src/services/player/CharacterCreationService.java | 7 +++---- 5 files changed, 11 insertions(+), 26 deletions(-) diff --git a/scripts/commands/generic/transferItemArmor.js b/scripts/commands/generic/transferItemArmor.js index 3edeb56cf..eaf377a70 100644 --- a/scripts/commands/generic/transferItemArmor.js +++ b/scripts/commands/generic/transferItemArmor.js @@ -12,11 +12,6 @@ function executeCommand(galacticManager, player, target, args) { switch (containerResult) { case ContainerResult.SUCCESS: - if (actor.getEquipmentList().contains(target)) { - actor.removeEquipment(target); - } else if (newContainer === actor) { - actor.addEquipment(target); - } break; case ContainerResult.CONTAINER_FULL: // TODO container03_prose if container is named diff --git a/scripts/commands/generic/transferItemMisc.js b/scripts/commands/generic/transferItemMisc.js index 3edeb56cf..eaf377a70 100644 --- a/scripts/commands/generic/transferItemMisc.js +++ b/scripts/commands/generic/transferItemMisc.js @@ -12,11 +12,6 @@ function executeCommand(galacticManager, player, target, args) { switch (containerResult) { case ContainerResult.SUCCESS: - if (actor.getEquipmentList().contains(target)) { - actor.removeEquipment(target); - } else if (newContainer === actor) { - actor.addEquipment(target); - } break; case ContainerResult.CONTAINER_FULL: // TODO container03_prose if container is named diff --git a/scripts/commands/generic/transferItemWeapon.js b/scripts/commands/generic/transferItemWeapon.js index 5a7dfb6e0..6769e34db 100644 --- a/scripts/commands/generic/transferItemWeapon.js +++ b/scripts/commands/generic/transferItemWeapon.js @@ -12,16 +12,6 @@ function executeCommand(galacticManager, player, target, args) { switch (containerResult) { case ContainerResult.SUCCESS: - var defaultWeapon = actor.getDefaultWeapon(); - if (actor.getEquipmentList().contains(target)) { - actor.removeEquipment(target); - actor.addEquipment(defaultWeapon); - actor.setEquippedWeapon(defaultWeapon); - } else if (newContainer === actor) { - actor.removeEquipment(defaultWeapon); - actor.addEquipment(target); - actor.setEquippedWeapon(target); - } break; case ContainerResult.CONTAINER_FULL: // TODO container03_prose if container is named diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 45fcdec6c..0faa5731f 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -87,15 +87,21 @@ public class CreatureObject extends TangibleObject { @Override public void addObject(SWGObject obj) { super.addObject(obj); - if (isEquipment(obj.getGameObjectType())) + if (isEquipment(obj.getGameObjectType())) { addEquipment(obj); + if (obj instanceof WeaponObject && defaultWeapon != null && !obj.equals(defaultWeapon)) + removeEquipment(defaultWeapon); + } } @Override public void removeObject(SWGObject obj) { super.removeObject(obj); - if (isEquipment(obj.getGameObjectType())) + if (isEquipment(obj.getGameObjectType())) { removeEquipment(obj); + if (obj instanceof WeaponObject && defaultWeapon != null && !obj.equals(defaultWeapon)) + addEquipment(defaultWeapon); + } } private boolean isEquipment(GameObjectType type) { diff --git a/src/services/player/CharacterCreationService.java b/src/services/player/CharacterCreationService.java index 42619a0b1..c1d37c714 100644 --- a/src/services/player/CharacterCreationService.java +++ b/src/services/player/CharacterCreationService.java @@ -406,10 +406,9 @@ public class CharacterCreationService extends Service { creatureObj.setDefaultWeapon(defWeapon); defWeapon.setMaxRange(5); creatureObj.setEquippedWeapon(defWeapon); - creatureObj.addEquipment(createInventoryObject(objManager, creatureObj, "object/tangible/inventory/shared_character_inventory.iff")); - creatureObj.addEquipment(createInventoryObject(objManager, creatureObj, "object/tangible/datapad/shared_character_datapad.iff")); - creatureObj.addEquipment(createInventoryObject(objManager, creatureObj, "object/tangible/inventory/shared_appearance_inventory.iff")); - creatureObj.addEquipment(defWeapon); + createInventoryObject(objManager, creatureObj, "object/tangible/inventory/shared_character_inventory.iff"); + createInventoryObject(objManager, creatureObj, "object/tangible/datapad/shared_character_datapad.iff"); + createInventoryObject(objManager, creatureObj, "object/tangible/inventory/shared_appearance_inventory.iff"); createInventoryObject(objManager, creatureObj, "object/tangible/bank/shared_character_bank.iff"); createInventoryObject(objManager, creatureObj, "object/tangible/mission_bag/shared_mission_bag.iff"); From c5bd7d1722e5411a95b7654d628771c316b20467 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 15:04:39 -0500 Subject: [PATCH 07/24] Fixed ID overwrite when reloading server --- src/services/objects/ObjectManager.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index b7512bd28..986a110f9 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -99,9 +99,13 @@ public class ObjectManager extends Manager { @Override public boolean initialize() { - loadClientObjects(); + Collection buildouts = clientBuildoutService.loadClientObjects(); if (!loadObjects()) return false; + for (SWGObject obj : buildouts) { + putObject(obj); + new ObjectCreatedIntent(obj).broadcast(); + } return super.initialize(); } @@ -118,13 +122,6 @@ public class ObjectManager extends Manager { return true; } - private void loadClientObjects() { - Collection objects = clientBuildoutService.loadClientObjects(); - for (SWGObject object : objects) { - new ObjectCreatedIntent(object).broadcast(); - } - } - private void loadObject(SWGObject obj) { if (obj instanceof CreatureObject && ((CreatureObject) obj).isPlayer()) Scripts.invoke("objects/load_creature", "onLoad", obj); @@ -145,6 +142,10 @@ public class ObjectManager extends Manager { private void addChildrenObjects(SWGObject obj) { new ObjectCreatedIntent(obj).broadcast(); + for (SWGObject child : obj.getSlots().values()) { + if (child != null) + addChildrenObjects(child); + } for (SWGObject child : obj.getContainedObjects()) { addChildrenObjects(child); } @@ -246,7 +247,7 @@ public class ObjectManager extends Manager { private void putObject(SWGObject object) { synchronized (objectMap) { SWGObject replaced = objectMap.put(object.getObjectId(), object); - if (replaced != null) + if (replaced != null && replaced != object) Log.e(this, "Replaced object in object map! Old: %s New: %s", replaced, object); } } From 27a50d6b4e7d7bf6880c44d1042ceeb9bb2e4173 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 15:53:16 -0500 Subject: [PATCH 08/24] Increased QuadTree sensitivity slightly --- src/resources/objects/quadtree/QuadTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/objects/quadtree/QuadTree.java b/src/resources/objects/quadtree/QuadTree.java index 0f7d7b935..795e2ef55 100644 --- a/src/resources/objects/quadtree/QuadTree.java +++ b/src/resources/objects/quadtree/QuadTree.java @@ -33,7 +33,7 @@ import java.util.NoSuchElementException; public class QuadTree { - private static final double DEFAULT_RANGE = 1E-3; + private static final double DEFAULT_RANGE = 1E-5; private final QuadNode headNode; private final double minX, minY, maxX, maxY; From 681386f326257412e09141fad6c1b42a9bd0bfdf Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 30 May 2016 16:29:50 -0500 Subject: [PATCH 09/24] Added backwards compatability with version 1 --- src/resources/objects/SWGObject.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index d63c90615..500920aa1 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -1079,7 +1079,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable= 1 && stream.getBoolean()) parent = SWGObjectFactory.create(stream); stream.getList((i) -> attributes.put(stream.getAscii(), stream.getAscii())); From f2f7e35177166eeeaeef62b9f576c2ae7129295a Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Tue, 31 May 2016 11:38:20 -0500 Subject: [PATCH 10/24] Fixed CREO equipment and SWGObject.removeObject --- src/resources/objects/SWGObject.java | 3 +- .../objects/creature/CreatureObject.java | 43 +++++-------------- .../player/CharacterCreationService.java | 2 - 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 500920aa1..6cf7addbc 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -163,7 +163,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable Date: Tue, 31 May 2016 12:03:33 -0500 Subject: [PATCH 11/24] Fixed equip/unequip into inventory --- src/resources/objects/SWGObject.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 6cf7addbc..406fffd21 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -46,6 +46,7 @@ import resources.containers.ContainerPermissions; import resources.containers.ContainerPermissionsFactory; import resources.containers.ContainerResult; import resources.containers.DefaultPermissions; +import resources.containers.ContainerPermissions.Permission; import resources.encodables.StringId; import resources.network.BaselineBuilder; import resources.network.BaselineObject; @@ -292,6 +293,16 @@ public abstract class SWGObject extends BaselineObject implements Comparable observers = new HashSet<>(); for (SWGObject aware : nearby) { - if (!aware.hasPermission(original, ContainerPermissions.Permission.VIEW)) + if (!aware.isVisible(original)) continue; if (aware instanceof CreatureObject) { Player awareOwner = aware.getOwner(); From 1652656bcbbd77d90ec32e38575dbb57c2956dd4 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Wed, 1 Jun 2016 08:53:48 -0500 Subject: [PATCH 12/24] Fixed equipment list bug --- .../encodables/player/Equipment.java | 22 +++++------ src/resources/objects/SWGObject.java | 21 +++++----- .../objects/creature/CreatureObject.java | 18 ++++++--- .../creature/CreatureObjectSharedNP.java | 39 +++++++++++++------ 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/src/resources/encodables/player/Equipment.java b/src/resources/encodables/player/Equipment.java index 3879747c8..35b79f0ba 100644 --- a/src/resources/encodables/player/Equipment.java +++ b/src/resources/encodables/player/Equipment.java @@ -52,23 +52,23 @@ public class Equipment implements Encodable, Persistable { private CRC template; public Equipment() { - this(0, null); + this(0, "", 4); } - public Equipment(long objectId, String template) { + public Equipment(SWGObject obj) { + this(obj.getObjectId(), obj.getTemplate(), obj.getSlotArrangement()); + if (obj instanceof WeaponObject) + this.weapon = (WeaponObject) obj; + } + + private Equipment(long objectId, String template, int arrangementId) { this.objectId = objectId; this.template = new CRC(template); this.customizationString = new byte[0]; this.arrangementId = 4; - this.objectId = 0; this.weapon = null; } - public Equipment(WeaponObject weapon) { - this(weapon.getObjectId(), weapon.getTemplate()); - this.weapon = weapon; - } - @Override public byte [] encode() { byte [] weaponData = new byte[0]; @@ -175,10 +175,10 @@ public class Equipment implements Encodable, Persistable { @Override public boolean equals(Object o) { - if (!(o instanceof SWGObject)) - return super.equals(o); + if (!(o instanceof Equipment)) + return false; - return ((SWGObject) o).getObjectId() == objectId; + return ((Equipment) o).getObjectId() == objectId; } @Override diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 406fffd21..8572eedb9 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -195,6 +195,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable 0) { Log.w("SWGObject", "Unable to add object to container! Container Full. Max Size: %d", container.getMaxContainerSize()); return ContainerResult.CONTAINER_FULL; } - } else { - // Item is going into slot(s) - for (String slotName : getArrangement().get(arrangementId - 4)) { - SWGObject equippedItem = container.getSlottedObject(slotName); - if (equippedItem != null) { - equippedItem.moveToContainer(requester, container.getSlottedObject("inventory")); - } - } } return ContainerResult.SUCCESS; } + + protected void handleSlotReplacement(SWGObject oldParent, SWGObject obj, int arrangement) { + for (String slot : obj.getArrangement().get(arrangement-4)) { + SWGObject slotObj = getSlottedObject(slot); + if (slotObj != null) + slotObj.moveToContainer(oldParent); + } + } /** * Checks if the passed object has all of the passed permissions diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index d22f72690..931b56dcf 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -86,7 +86,7 @@ public class CreatureObject extends TangibleObject { @Override public void addObject(SWGObject obj) { super.addObject(obj); - if (getArrangementId(obj) != -1 && !(obj instanceof PlayerObject)) { + if (obj.getSlotArrangement() != -1 && !(obj instanceof PlayerObject)) { addEquipment(obj); if (obj instanceof WeaponObject && defaultWeapon != null && !obj.equals(defaultWeapon)) { removeObject(defaultWeapon); @@ -97,10 +97,18 @@ public class CreatureObject extends TangibleObject { @Override public void removeObject(SWGObject obj) { super.removeObject(obj); - if (getArrangementId(obj) != -1 && !(obj instanceof PlayerObject)) { - removeEquipment(obj); - if (obj instanceof WeaponObject && defaultWeapon != null && !obj.equals(defaultWeapon)) { - addObject(defaultWeapon); + removeEquipment(obj); + if (obj instanceof WeaponObject && defaultWeapon != null && !obj.equals(defaultWeapon)) { + addObject(defaultWeapon); + } + } + + protected void handleSlotReplacement(SWGObject oldParent, SWGObject obj, int arrangement) { + SWGObject inventory = getSlottedObject("inventory"); + for (String slot : obj.getArrangement().get(arrangement-4)) { + SWGObject slotObj = getSlottedObject(slot); + if (slotObj != null) { + slotObj.moveToContainer(inventory); } } } diff --git a/src/resources/objects/creature/CreatureObjectSharedNP.java b/src/resources/objects/creature/CreatureObjectSharedNP.java index 8b7a59170..57a3c5eaa 100644 --- a/src/resources/objects/creature/CreatureObjectSharedNP.java +++ b/src/resources/objects/creature/CreatureObjectSharedNP.java @@ -79,44 +79,61 @@ class CreatureObjectSharedNP implements Persistable { } public void addEquipment(SWGObject obj, SWGObject target) { + if (getEquipment(obj) != null) + return; synchronized (equipmentList) { - if (obj instanceof WeaponObject) - equipmentList.add(new Equipment((WeaponObject) obj)); - else - equipmentList.add(new Equipment(obj.getObjectId(), obj.getTemplate())); + equipmentList.add(new Equipment(obj)); equipmentList.sendDeltaMessage(target); } } public void removeEquipment(SWGObject obj, SWGObject target) { + Equipment e = getEquipment(obj); + if (e == null) + return; + synchronized (equipmentList) { + equipmentList.remove(e); + equipmentList.sendDeltaMessage(target); + } + } + + public Equipment getEquipment(SWGObject obj) { synchronized (equipmentList) { for (Equipment equipment : equipmentList) { if (equipment.getObjectId() == obj.getObjectId()) { - equipmentList.remove(equipment); - equipmentList.sendDeltaMessage(target); - return; + return equipment; } } } + return null; } public void addAppearanceItem(SWGObject obj, SWGObject target) { synchronized (appearanceList) { - appearanceList.add(new Equipment(obj.getObjectId(), obj.getTemplate())); + appearanceList.add(new Equipment(obj)); appearanceList.sendDeltaMessage(target); } } public void removeAppearanceItem(SWGObject obj, SWGObject target) { + Equipment e = getEquipment(obj); + if (e == null) + return; + synchronized (appearanceList) { + appearanceList.remove(e); + appearanceList.sendDeltaMessage(target); + } + } + + public Equipment getAppearance(SWGObject obj) { synchronized (appearanceList) { for (Equipment equipment : appearanceList) { if (equipment.getObjectId() == obj.getObjectId()) { - appearanceList.remove(equipment); - appearanceList.sendDeltaMessage(target); - return; + return equipment; } } } + return null; } public SWGList getEquipmentList() { From 43af96e047e334f1c87d3ca54c9f9785b5b05ab0 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 2 Jun 2016 06:01:55 -0500 Subject: [PATCH 13/24] Re-did container permissions --- .../containers/ContainerPermissions.java | 190 ++------------- ...ory.java => ContainerPermissionsType.java} | 58 ++--- .../containers/DefaultPermissions.java | 16 +- .../containers/InventoryPermissions.java | 11 +- .../containers/WorldPermissions.java | 81 ------- src/resources/objects/SWGObject.java | 216 +++++------------- .../buildouts/TerrainBuildoutLoader.java | 6 - .../buildouts/TerrainSnapshotLoader.java | 8 +- .../creature/CreatureObjectSharedNP.java | 8 +- .../player/CharacterCreationService.java | 6 +- 10 files changed, 127 insertions(+), 473 deletions(-) rename src/resources/containers/{ContainerPermissionsFactory.java => ContainerPermissionsType.java} (70%) delete mode 100644 src/resources/containers/WorldPermissions.java diff --git a/src/resources/containers/ContainerPermissions.java b/src/resources/containers/ContainerPermissions.java index c0cee9bc4..7cf969c1f 100644 --- a/src/resources/containers/ContainerPermissions.java +++ b/src/resources/containers/ContainerPermissions.java @@ -26,182 +26,38 @@ ******************************************************************************/ package resources.containers; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import resources.network.NetBufferStream; import resources.objects.SWGObject; -import resources.persistable.Persistable; - -/** - * Structure for creating permission sets that will allow the object to be viewed/modified/added/removed by a requested - * object depending on the implemented abstract methods. - * @author Waverunner - */ -public abstract class ContainerPermissions implements Persistable { - - public static final WorldPermissions WORLD = new WorldPermissions(); - public static final InventoryPermissions INVENTORY = new InventoryPermissions(); - - private Map permissionGroups; - private List joinedGroups; +public abstract class ContainerPermissions { + public ContainerPermissions() { - this.permissionGroups = new HashMap<>(); - this.joinedGroups = new ArrayList<>(); - } - - protected boolean hasPermissions(String group, Permission... permissions) { - if (!hasPermissionGroup(group)) - return false; - - EnumSet groupPermissions = Permission.getFlags(permissionGroups.get(group)); - - for (Permission permission : permissions) { - if (!groupPermissions.contains(permission)) - return false; - } - - return true; - } - - public boolean hasPermissions(List requesterGroups, Permission ... permission) { - for (String group : requesterGroups) { - if (hasPermissions(group, permission)) - return true; - } - return false; - } - - public void addPermissions(String group, Permission... permissions) { - if (!hasPermissionGroup(group)) { - permissionGroups.put(group, Permission.valueOf(permissions)); - return; - } - - EnumSet groupPermissions = Permission.getFlags(permissionGroups.get(group)); - - for (Permission permission : permissions) { - groupPermissions.add(permission); - } - - synchronized (permissionGroups) { - permissionGroups.put(group, Permission.valueOf(groupPermissions)); - } - } - - public void removePermissions(String group, Permission... permissions) { - - if (!hasPermissionGroup(group)) - return; - - EnumSet groupPermissions = Permission.getFlags(permissionGroups.get(group)); - - for (Permission permission : permissions) { - groupPermissions.add(permission); - } - - synchronized (permissionGroups) { - permissionGroups.put(group, Permission.valueOf(groupPermissions)); - } - } - - public void clearPermissions(String group) { - synchronized (permissionGroups) { - if (permissionGroups.containsKey(group)) - permissionGroups.put(group, 0); - } - } - - public boolean hasPermissionGroup(String group) { - return permissionGroups.containsKey(group); - } - - public Set getPermissionGroups() { - synchronized(permissionGroups) { - return permissionGroups.keySet(); - } - } - - public List getJoinedGroups() { - return joinedGroups; - } - - public void addDefaultWorldPermissions() { - addPermissions("world", Permission.VIEW, Permission.ENTER); + } - @Override - public void save(NetBufferStream stream) { - stream.addByte(0); - synchronized (permissionGroups) { - stream.addMap(permissionGroups, (e) -> { - stream.addAscii(e.getKey()); - stream.addInt(e.getValue()); - }); - } - synchronized (joinedGroups) { - stream.addList(joinedGroups, (g) -> stream.addAscii(g)); - } - } - - @Override - public void read(NetBufferStream stream) { - stream.getByte(); - stream.getList((i) -> permissionGroups.put(stream.getAscii(), stream.getInt())); - stream.getList((i) -> joinedGroups.add(stream.getAscii())); - } - public abstract boolean canView(SWGObject viewer, SWGObject container); public abstract boolean canEnter(SWGObject requester, SWGObject container); public abstract boolean canRemove(SWGObject requester, SWGObject container); public abstract boolean canMove(SWGObject requester, SWGObject container); public abstract boolean canAdd(SWGObject requester, SWGObject container); - - public enum Permission { - VIEW(1), - REMOVE(1<<1), - ADD(1<<2), - MOVE(1<<3), - ENTER(1<<4); - - int bitmask; - - Permission(int bitmask) { - this.bitmask = bitmask; - } - - public static EnumSet getFlags(int bits) { - EnumSet states = EnumSet.noneOf(Permission.class); - for (Permission state : values()) { - if ((state.bitmask & bits) != 0) - states.add(state); - } - return states; - } - - public static int valueOf(EnumSet bitmaskSet) { - int value = 0; - - for (Permission permission : bitmaskSet) { - value += permission.bitmask; - } - - return value; - } - - public static int valueOf(Permission... permissions) { - int value = 0; - - for (Permission permission : permissions) { - value += permission.bitmask; - } - - return value; - } + + public boolean canView(SWGObject container) { + return canView(null, container); } + + public boolean canEnter(SWGObject container) { + return canEnter(null, container); + } + + public boolean canRemove(SWGObject container) { + return canRemove(null, container); + } + + public boolean canMove(SWGObject container) { + return canMove(null, container); + } + + public boolean canAdd(SWGObject container) { + return canAdd(null, container); + } + } diff --git a/src/resources/containers/ContainerPermissionsFactory.java b/src/resources/containers/ContainerPermissionsType.java similarity index 70% rename from src/resources/containers/ContainerPermissionsFactory.java rename to src/resources/containers/ContainerPermissionsType.java index b801f8d46..1feb242f1 100644 --- a/src/resources/containers/ContainerPermissionsFactory.java +++ b/src/resources/containers/ContainerPermissionsType.java @@ -27,40 +27,40 @@ ***********************************************************************************/ package resources.containers; -import resources.network.NetBufferStream; +import resources.objects.SWGObject; -public class ContainerPermissionsFactory { +public enum ContainerPermissionsType { + DEFAULT (new DefaultPermissions()), + INVENTORY (new InventoryPermissions()); - public static ContainerPermissions create(NetBufferStream stream) { - ContainerPermissions permissions; - byte type = stream.getByte(); - switch (type) { - case 1: - permissions = new DefaultPermissions(); - break; - case 2: - permissions = new InventoryPermissions(); - break; - case 3: - permissions = new WorldPermissions(); - break; - default: - throw new IllegalStateException("Unknown type byte! Type: " + type); - } - permissions.read(stream); + private final ContainerPermissions permissions; + + ContainerPermissionsType(ContainerPermissions permissions) { + this.permissions = permissions; + } + + public ContainerPermissions getContainerPermissions() { return permissions; } - public static void save(ContainerPermissions permissions, NetBufferStream stream) { - if (permissions instanceof DefaultPermissions) - stream.addByte(1); - else if (permissions instanceof InventoryPermissions) - stream.addByte(2); - else if (permissions instanceof WorldPermissions) - stream.addByte(3); - else - throw new IllegalArgumentException("Unknown permissions type! Permissions: " + permissions); - permissions.save(stream); + public boolean canView(SWGObject viewer, SWGObject container) { + return permissions.canView(viewer, container); + } + + public boolean canEnter(SWGObject viewer, SWGObject container) { + return permissions.canEnter(viewer, container); + } + + public boolean canRemove(SWGObject viewer, SWGObject container) { + return permissions.canRemove(viewer, container); + } + + public boolean canMove(SWGObject viewer, SWGObject container) { + return permissions.canMove(viewer, container); + } + + public boolean canAdd(SWGObject viewer, SWGObject container) { + return permissions.canAdd(viewer, container); } } diff --git a/src/resources/containers/DefaultPermissions.java b/src/resources/containers/DefaultPermissions.java index 0a1718422..95fe30a00 100644 --- a/src/resources/containers/DefaultPermissions.java +++ b/src/resources/containers/DefaultPermissions.java @@ -34,39 +34,39 @@ import resources.objects.SWGObject; * for every new object. * @author Waverunner */ -public class DefaultPermissions extends ContainerPermissions { +class DefaultPermissions extends ContainerPermissions { @Override public boolean canView(SWGObject requester, SWGObject container) { return true; } - + @Override public boolean canEnter(SWGObject requester, SWGObject container) { return true; } - + @Override public boolean canRemove(SWGObject requester, SWGObject container) { - if (requester.getOwner() == null) + if (requester == null || requester.getOwner() == null) return true; if (container.getOwner() == null) return false; return requester.getOwner().equals(container.getOwner()); } - + @Override public boolean canMove(SWGObject requester, SWGObject container) { - if (requester.getOwner() == null) + if (requester == null || requester.getOwner() == null) return true; if (container.getOwner() == null) return false; return requester.getOwner().equals(container.getOwner()); } - + @Override public boolean canAdd(SWGObject requester, SWGObject container) { - if (requester.getOwner() == null) + if (requester == null || requester.getOwner() == null) return true; if (container.getOwner() == null) return false; diff --git a/src/resources/containers/InventoryPermissions.java b/src/resources/containers/InventoryPermissions.java index ceb55e4b3..743a6cf13 100644 --- a/src/resources/containers/InventoryPermissions.java +++ b/src/resources/containers/InventoryPermissions.java @@ -29,16 +29,11 @@ package resources.containers; import resources.objects.SWGObject; -/** - * This set of permissions will allow only the owner to view the container. - * - * @author Waverunner - */ -public class InventoryPermissions extends DefaultPermissions { +class InventoryPermissions extends DefaultPermissions { @Override public boolean canView(SWGObject requester, SWGObject container) { - if (requester.getOwner() == null) + if (requester == null || requester.getOwner() == null) return true; if (container.getOwner() == null) return false; @@ -47,7 +42,7 @@ public class InventoryPermissions extends DefaultPermissions { @Override public boolean canEnter(SWGObject requester, SWGObject container) { - if (requester.getOwner() == null) + if (requester == null || requester.getOwner() == null) return true; if (container.getOwner() == null) return false; diff --git a/src/resources/containers/WorldPermissions.java b/src/resources/containers/WorldPermissions.java deleted file mode 100644 index 301f9cb68..000000000 --- a/src/resources/containers/WorldPermissions.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 /// Project SWG /// www.projectswg.com - * - * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on - * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. - * Our goal is to create an emulator which will provide a server for players to - * continue playing a game similar to the one they used to play. We are basing - * it on the final publish of the game prior to end-game events. - * - * This file is part of Holocore. - * - * -------------------------------------------------------------------------------- - * - * Holocore is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * Holocore is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Holocore. If not, see - ******************************************************************************/ - -package resources.containers; - -import resources.objects.SWGObject; - -/** - * This is essentially a universal "all-in-one" permission set for managing permission groups for world objects. This - * class makes use of permission groups. Every player joins the world permission group upon creation. When a specific - * group is needed, the object will have to remove the world permission set and replace it with their own group of - * permissions. - *

Example: In order to allow only certain players into an area of Jabba's palace, you would first - * create a permission group for the CellObject with a unique name. Then you need to add the named group to the - * players ContainerPermissions joinedGroups list in order for them to properly pass the checks. - *

- * This set of permissions will allow: - *
    - *
  1. View - If the viewer has joined a group that is recognized by the container with viewing permissions
  2. - *
  3. Enter - If the viewer has joined a group that is recognized by the container with enter permissions
  4. - *
  5. Remove, Move, Add - If the container has the same owner as the requester
  6. - *
- * @author Waverunner - */ -public class WorldPermissions extends DefaultPermissions { - - @Override - public boolean canView(SWGObject viewer, SWGObject container) { - if (super.canView(viewer, container)) - return true; - - return hasPermissions(viewer.getContainerPermissions().getJoinedGroups(), Permission.VIEW); - } - - @Override - public boolean canEnter(SWGObject requester, SWGObject container) { - if (super.canView(requester, container)) - return true; - - return hasPermissions(requester.getContainerPermissions().getJoinedGroups(), Permission.ENTER); - } - - @Override - public boolean canRemove(SWGObject requester, SWGObject container) { - return super.canRemove(requester, container); - } - - @Override - public boolean canMove(SWGObject requester, SWGObject container) { - return super.canMove(requester, container); - } - - @Override - public boolean canAdd(SWGObject requester, SWGObject container) { - return super.canAdd(requester, container); - } -} diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 8572eedb9..7f80f4cbf 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -42,11 +42,8 @@ import resources.Terrain; import resources.buildout.BuildoutArea; import resources.client_info.visitors.ObjectData.ObjectDataAttribute; import resources.common.CRC; -import resources.containers.ContainerPermissions; -import resources.containers.ContainerPermissionsFactory; +import resources.containers.ContainerPermissionsType; import resources.containers.ContainerResult; -import resources.containers.DefaultPermissions; -import resources.containers.ContainerPermissions.Permission; import resources.encodables.StringId; import resources.network.BaselineBuilder; import resources.network.BaselineObject; @@ -66,42 +63,40 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; public abstract class SWGObject extends BaselineObject implements Comparable, Persistable { - private final Location location; - private final long objectId; - private final HashMap slots; // HashMap used for null value support - private final Set containedObjects; - private final Map attributes; - private final Map dataAttributes; - private transient Set objectsAware; - private transient Set customAware; - private transient BuildoutArea buildoutArea; - private transient Player owner; - private List > arrangement; - - private ObjectClassification classification = ObjectClassification.GENERATED; - private GameObjectType gameObjectType = GameObjectType.GOT_NONE; - private ContainerPermissions containerPermissions; - private SWGObject parent = null; - private StringId stringId = new StringId("", ""); - private StringId detailStringId = new StringId("", ""); - private String template = ""; - private int crc = 0; - private String objectName = ""; - private int volume = 0; - private float complexity = 1; - private int containerType = 0; - private double loadRange = 0; - private int areaId = -1; - - private int slotArrangement = -1; + private final long objectId; + private final Location location = new Location(); + private final Set containedObjects= new HashSet<>(); + private final Map attributes = new HashMap<>(); + private final Set objectsAware = new HashSet<>(); + private final Set customAware = new HashSet<>(); + private final HashMap slots = new HashMap<>(); // HashMap used for null value support + private final Map dataAttributes = new HashMap<>(); + + private ObjectClassification classification = ObjectClassification.GENERATED; + private GameObjectType gameObjectType = GameObjectType.GOT_NONE; + private ContainerPermissionsType permissions = ContainerPermissionsType.DEFAULT; + private List > arrangement = new ArrayList<>(); + private BuildoutArea buildoutArea = null; + private Player owner = null; + + private SWGObject parent = null; + private StringId stringId = new StringId("", ""); + private StringId detailStringId = new StringId("", ""); + private String template = ""; + private int crc = 0; + private String objectName = ""; + private int volume = 0; + private float complexity = 1; + private int containerType = 0; + private double loadRange = 0; + private int areaId = -1; + private int slotArrangement = -1; public SWGObject() { this(0, null); @@ -110,16 +105,8 @@ public abstract class SWGObject extends BaselineObject implements Comparable(); - this.customAware = new HashSet<>(); - this.slots = new HashMap<>(); - this.containedObjects = new HashSet<>(); - this.attributes = new LinkedHashMap<>(); - this.dataAttributes = new Hashtable<>(); - this.containerPermissions = new DefaultPermissions(); } - + /** * Adds the specified object to this object and places it in the appropriate slot if needed * @param object Object to add to this container, which will either be put into the appropriate slot(s) or become a contained object @@ -229,7 +216,7 @@ public abstract class SWGObject extends BaselineObject implements ComparableThis is the same as calling addPermissions(String.valueOf(permissionRequester.getObjectId() + getObjectId()), permissions) - * with the added benefit of adding the group to the permissionRequester's joined container groups - * @param permissionRequester The object that should be given unique permissions to this object - * @param permissions Permissions that the permissionRequester will have for this object - */ - public void addPermissions(SWGObject permissionRequester, ContainerPermissions.Permission... permissions) { - addPermissions(String.valueOf(permissionRequester.getObjectId() + getObjectId()), permissions); - permissionRequester.joinPermissionGroup(String.valueOf(getObjectId() + permissionRequester.getObjectId())); - } - - /** - * Removes all the unique permissions for the permissionRequester from this object. - * @param permissionRequester The object that should no longer have unique permissions to this object - */ - public void removePermissions(SWGObject permissionRequester) { - String group = String.valueOf(permissionRequester.getObjectId() + getObjectId()); - removePermissions(group); - permissionRequester.containerPermissions.getJoinedGroups().remove(group); - } - - /** - * Assigns this object to a permission group - * @param group - */ - public void joinPermissionGroup(String group) { - containerPermissions.getJoinedGroups().add(group); - } - - public void setContainerPermissions(ContainerPermissions permissions) { - this.containerPermissions = permissions; - } - + public void addAttribute(String attribute, String value) { attributes.put(attribute, value); } @@ -624,6 +522,14 @@ public abstract class SWGObject extends BaselineObject implements Comparable { stream.addAscii(e.getKey()); stream.addAscii(e.getValue()); }); } - stream.addAscii(classification.name()); - stream.addUnicode(objectName); - stream.addInt(volume); - stream.addFloat(complexity); - stream.addFloat((float) loadRange); Set contained; synchronized (containedObjects) { contained = new HashSet<>(containedObjects); @@ -1121,24 +1025,18 @@ public abstract class SWGObject extends BaselineObject implements Comparable= 1 && stream.getBoolean()) + if (stream.getBoolean()) parent = SWGObjectFactory.create(stream); - stream.getList((i) -> attributes.put(stream.getAscii(), stream.getAscii())); + permissions = ContainerPermissionsType.valueOf(stream.getAscii()); classification = ObjectClassification.valueOf(stream.getAscii()); objectName = stream.getUnicode(); volume = stream.getInt(); complexity = stream.getFloat(); loadRange = stream.getFloat(); - Set contained = new HashSet<>(); - stream.getList((i) -> contained.add(SWGObjectFactory.create(stream))); - for (SWGObject obj : contained) - obj.moveToContainer(this); + stream.getList((i) -> attributes.put(stream.getAscii(), stream.getAscii())); + stream.getList((i) -> SWGObjectFactory.create(stream).moveToContainer(this)); } public enum ObjectClassification { diff --git a/src/resources/objects/buildouts/TerrainBuildoutLoader.java b/src/resources/objects/buildouts/TerrainBuildoutLoader.java index b6885b6ae..a2ba07e34 100644 --- a/src/resources/objects/buildouts/TerrainBuildoutLoader.java +++ b/src/resources/objects/buildouts/TerrainBuildoutLoader.java @@ -37,7 +37,6 @@ import resources.Terrain; import resources.client_info.ClientFactory; import resources.client_info.visitors.CrcStringTableData; import resources.client_info.visitors.DatatableData; -import resources.containers.ContainerPermissions; import resources.objects.SWGObject; import resources.objects.SWGObject.ObjectClassification; import resources.objects.cell.CellObject; @@ -96,7 +95,6 @@ class TerrainBuildoutLoader { object.setBuildoutAreaId(area.getIndex()); setCellInformation(object, buildoutRow.getCellIndex()); addObject(area.getName(), object, buildoutRow.getContainerId()); - updatePermissions(object); } } @@ -132,8 +130,4 @@ class TerrainBuildoutLoader { cell.setNumber(cellIndex); } - private void updatePermissions(SWGObject object) { - object.setContainerPermissions(ContainerPermissions.WORLD); - } - } diff --git a/src/resources/objects/buildouts/TerrainSnapshotLoader.java b/src/resources/objects/buildouts/TerrainSnapshotLoader.java index 698103087..d02252f6a 100644 --- a/src/resources/objects/buildouts/TerrainSnapshotLoader.java +++ b/src/resources/objects/buildouts/TerrainSnapshotLoader.java @@ -37,7 +37,6 @@ import resources.Terrain; import resources.client_info.ClientFactory; import resources.client_info.visitors.WorldSnapshotData; import resources.client_info.visitors.WorldSnapshotData.Node; -import resources.containers.ContainerPermissions; import resources.objects.SWGObject; import resources.objects.SWGObject.ObjectClassification; import resources.objects.cell.CellObject; @@ -83,8 +82,7 @@ public class TerrainSnapshotLoader { object.setLoadRange(node.getRadius()); setCellInformation(object, node.getCellIndex()); addObject(object, node.getContainerId()); - updatePermissions(object); - + for (Node child : node.getChildren()) { createFromNode(templates, child); } @@ -117,8 +115,4 @@ public class TerrainSnapshotLoader { cell.setNumber(cellIndex); } - private void updatePermissions(SWGObject object) { - object.setContainerPermissions(ContainerPermissions.WORLD); - } - } diff --git a/src/resources/objects/creature/CreatureObjectSharedNP.java b/src/resources/objects/creature/CreatureObjectSharedNP.java index 57a3c5eaa..503520061 100644 --- a/src/resources/objects/creature/CreatureObjectSharedNP.java +++ b/src/resources/objects/creature/CreatureObjectSharedNP.java @@ -66,10 +66,10 @@ class CreatureObjectSharedNP implements Persistable { private boolean shownOnRadar = true; private boolean beast = false; - private SWGList attributes = new SWGList(6, 21); - private SWGList maxAttributes = new SWGList(6, 22); - private SWGList equipmentList = new SWGList(6, 23); - private SWGList appearanceList = new SWGList(6, 33); + private SWGList attributes = new SWGList<>(6, 21); + private SWGList maxAttributes = new SWGList<>(6, 22); + private SWGList equipmentList = new SWGList<>(6, 23); + private SWGList appearanceList = new SWGList<>(6, 33); private SWGMap buffs = new SWGMap<>(6, 26); diff --git a/src/services/player/CharacterCreationService.java b/src/services/player/CharacterCreationService.java index 26fc6dca8..065e470b7 100644 --- a/src/services/player/CharacterCreationService.java +++ b/src/services/player/CharacterCreationService.java @@ -58,7 +58,7 @@ import resources.Race; import resources.client_info.ClientFactory; import resources.client_info.visitors.ProfTemplateData; import resources.config.ConfigFile; -import resources.containers.ContainerPermissions; +import resources.containers.ContainerPermissionsType; import resources.control.Service; import resources.objects.SWGObject; import resources.objects.building.BuildingObject; @@ -378,7 +378,7 @@ public class CharacterCreationService extends Service { private SWGObject createInventoryObject(ObjectManager objManager, CreatureObject creatureObj, String template) { SWGObject obj = ObjectCreator.createObjectFromTemplate(template); obj.moveToContainer(creatureObj); - obj.setContainerPermissions(ContainerPermissions.INVENTORY); + obj.setContainerPermissions(ContainerPermissionsType.INVENTORY); new ObjectCreatedIntent(obj).broadcast(); return obj; } @@ -413,8 +413,6 @@ public class CharacterCreationService extends Service { // Any character can perform the basic dance. creatureObj.addAbility("startDance+basic"); - - creatureObj.joinPermissionGroup("world"); } private void setPlayerObjectValues(PlayerObject playerObj, ClientCreateCharacter create) { From 958d8bca186206e17fd2bea61b69a0695b6783b2 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 2 Jun 2016 06:26:24 -0500 Subject: [PATCH 14/24] Sped up sdb read --- .../server_info/RelationalServerData.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/resources/server_info/RelationalServerData.java b/src/resources/server_info/RelationalServerData.java index 5e4796843..430944cf3 100644 --- a/src/resources/server_info/RelationalServerData.java +++ b/src/resources/server_info/RelationalServerData.java @@ -357,19 +357,40 @@ public class RelationalServerData extends RelationalDatabase { return; switch (lineNum) { case 1: - columnNames = line.split("\t"); + columnNames = fastTabSplit(line); break; case 2: - columnTypes = line.split("\t"); + columnTypes = fastTabSplit(line); createTable(); createPreparedStatement(); break; default: - generateInsert(line.split("\t"), lineNum); + generateInsert(fastTabSplit(line), lineNum); break; } } + private String [] fastTabSplit(String str) { + int count = 1; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == '\t') { + count++; + } + } + String [] tabs = new String[count]; + int tabInd = 0; + int prevInd = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == '\t') { + tabs[tabInd++] = str.substring(prevInd, i); + prevInd = i+1; + } + } + if (prevInd < str.length()) + tabs[tabInd++] = str.substring(prevInd); + return tabs; + } + private void createTable() { if (columnNames.length != columnTypes.length) throw new IllegalArgumentException("Names length and types length mismatch"); From 6534843fa4076bab946f0baaf579a261b1024a16 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Sun, 5 Jun 2016 13:20:02 -0500 Subject: [PATCH 15/24] Fixed null pointer using complicated owner/creature object code --- src/services/galaxy/travel/TravelService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/galaxy/travel/TravelService.java b/src/services/galaxy/travel/TravelService.java index 66a9b6237..9e8bba394 100644 --- a/src/services/galaxy/travel/TravelService.java +++ b/src/services/galaxy/travel/TravelService.java @@ -555,7 +555,7 @@ public class TravelService extends Service { } private boolean isTicketUsable(SWGObject ticket) { - Location worldLoc = ticket.getOwner().getCreatureObject().getWorldLocation(); + Location worldLoc = ticket.getWorldLocation(); TravelPoint nearest = getNearestTravelPoint(worldLoc); String departurePoint = ticket.getAttribute("@obj_attr_n:travel_departure_point"); String departurePlanet = ticket.getAttribute("@obj_attr_n:travel_departure_planet"); From 777b37af81de8e1a87923d79355bb91f66c05b70 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 07:58:11 -0500 Subject: [PATCH 16/24] Fixed friends list updating right away --- .../commands/callbacks/FindFriendCallback.java | 4 ++-- src/resources/objects/player/PlayerObject.java | 4 ++++ .../objects/player/PlayerObjectPrivateNP.java | 6 ++++++ src/services/chat/ChatManager.java | 10 ++++------ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/resources/commands/callbacks/FindFriendCallback.java b/src/resources/commands/callbacks/FindFriendCallback.java index ec42835fa..3d172775e 100644 --- a/src/resources/commands/callbacks/FindFriendCallback.java +++ b/src/resources/commands/callbacks/FindFriendCallback.java @@ -56,7 +56,7 @@ public class FindFriendCallback implements ICmdCallback { String friendName = args.split(" ")[0].toLowerCase(Locale.US); - if (!ghost.getFriendsList().contains(friendName)) { + if (!ghost.isFriend(friendName)) { new ChatBroadcastIntent(player, "@ui_cmnty:friend_location_failed_noname").broadcast(); return; } @@ -68,7 +68,7 @@ public class FindFriendCallback implements ICmdCallback { } PlayerObject friendGhost = friend.getPlayerObject(); - if (friendGhost == null || !friendGhost.getFriendsList().contains(player.getCharacterName().split(" ")[0].toLowerCase(Locale.US))) { + if (friendGhost == null || !friendGhost.isFriend(player.getCharacterName().split(" ")[0].toLowerCase(Locale.US))) { new ChatBroadcastIntent(player, new ProsePackage("@ui_cmnty:friend_location_failed", "TU", friendName)).broadcast(); return; } diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index daaa14374..d572762c1 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -283,6 +283,10 @@ public class PlayerObject extends IntangibleObject { play9.addFriend(friend, this); } + public boolean isFriend(String target) { + return play9.isFriend(target); + } + public List getFriendsList() { return play9.getFriendsList(); } diff --git a/src/resources/objects/player/PlayerObjectPrivateNP.java b/src/resources/objects/player/PlayerObjectPrivateNP.java index b79579968..2e7611f2f 100644 --- a/src/resources/objects/player/PlayerObjectPrivateNP.java +++ b/src/resources/objects/player/PlayerObjectPrivateNP.java @@ -72,6 +72,12 @@ class PlayerObjectPrivateNP implements Persistable { friendsList.sendDeltaMessage(target); } + public boolean isFriend(String friend) { + synchronized (friendsList) { + return friendsList.contains(friend); + } + } + public List getFriendsList() { return friendsList; } diff --git a/src/services/chat/ChatManager.java b/src/services/chat/ChatManager.java index 89f7cf9dc..adfdc9942 100644 --- a/src/services/chat/ChatManager.java +++ b/src/services/chat/ChatManager.java @@ -55,6 +55,7 @@ import resources.player.Player; import resources.player.PlayerState; import resources.server_info.RelationalServerData; import resources.server_info.RelationalServerFactory; +import services.CoreManager; import services.player.PlayerManager; import java.sql.PreparedStatement; @@ -214,7 +215,7 @@ public class ChatManager extends Manager { if (ghost == null) return; - if (!ghost.getFriendsList().contains(target)) { + if (!ghost.isFriend(target)) { sendSystemMessage(player, "@cmnty:friend_not_found", target); return; } @@ -237,7 +238,7 @@ public class ChatManager extends Manager { return; } - if (ghost.getFriendsList().contains(target)) { + if (ghost.isFriend(target)) { sendSystemMessage(player, "@cmnty:friend_duplicate", target); return; } @@ -250,10 +251,7 @@ public class ChatManager extends Manager { ghost.addFriend(target); sendSystemMessage(player, "@cmnty:friend_added", target); - Player targetPlayer = player.getPlayerManager().getPlayerByCreatureFirstName(target); - - if (targetPlayer != null && targetPlayer.getPlayerState() == PlayerState.ZONED_IN) - player.sendPacket(new ChatFriendsListUpdate(new ChatAvatar(0, target, targetPlayer.getGalaxyName()), true)); + player.sendPacket(new ChatFriendsListUpdate(new ChatAvatar(0, target, CoreManager.getGalaxy().getName()), true)); } /* Ignore List */ From e7f4616f9aeca748dd4137d54427ddfcf472b49d Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 08:00:56 -0500 Subject: [PATCH 17/24] Made intent factory broadcasts sequential and added additional awareness debug to details.js --- scripts/commands/helper/qatool/details.js | 18 +++++++++++++++--- src/utilities/IntentFactory.java | 6 ++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/scripts/commands/helper/qatool/details.js b/scripts/commands/helper/qatool/details.js index fe6f24560..71d6b0983 100644 --- a/scripts/commands/helper/qatool/details.js +++ b/scripts/commands/helper/qatool/details.js @@ -1,13 +1,25 @@ function sendDetails(player, object, args) { if (object == null) { - intentFactory.sendSystemMessage(player, "Null target"); - return; + object = player.getCreatureObject(); } if (args.length >= 2 && args[1].equalsIgnoreCase("observers")) { - intentFactory.sendSystemMessage(player, "Aware: " + object.getObjectsAware()); intentFactory.sendSystemMessage(player, "Observers: " + object.getObservers()); return; } + if (args.length >= 3 && args[1].equalsIgnoreCase("aware-of")) { + aware = object.getObjectsAware(); + count = 0; + for (var iterator = aware.iterator(); iterator.hasNext();) { + var obj = iterator.next(); + if (obj.getObjectId() == parseInt(args[2]) || obj.getTemplate().contains(args[2])) { + intentFactory.sendSystemMessage(player, "True: " + obj); + return; + } + count++; + } + intentFactory.sendSystemMessage(player, "False. Checked " + count + " in aware"); + return; + } intentFactory.sendSystemMessage(player, object.getName() + " - " + object.getClass().getSimpleName() + " [" + object.getObjectId() + "]"); intentFactory.sendSystemMessage(player, " STR: " + object.getStringId() + " / " + object.getDetailStringId()); intentFactory.sendSystemMessage(player, " Template: " + object.getTemplate()); diff --git a/src/utilities/IntentFactory.java b/src/utilities/IntentFactory.java index f83b191a9..5bc0ea8be 100644 --- a/src/utilities/IntentFactory.java +++ b/src/utilities/IntentFactory.java @@ -46,9 +46,11 @@ import resources.server_info.Log; * This class is to be used exclusively in cases where using the intents directly isn't practical. */ public final class IntentFactory { - + + private final IntentChain broadcastChain = new IntentChain(); + private void broadcast(String message, Player source, BroadcastType type) { - new ChatBroadcastIntent(message, source, source.getCreatureObject().getTerrain(), type).broadcast(); + broadcastChain.broadcastAfter(new ChatBroadcastIntent(message, source, source.getCreatureObject().getTerrain(), type)); } /** From 703f6f44f29fca8e6e14e21682745fa66c99096e Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 08:03:33 -0500 Subject: [PATCH 18/24] Fixed slots, moveToContainer, and simplified awareness functions --- src/resources/objects/SWGObject.java | 132 +++++++++++---------------- 1 file changed, 51 insertions(+), 81 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 7f80f4cbf..7008f31a5 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -70,7 +70,7 @@ import java.util.Set; public abstract class SWGObject extends BaselineObject implements Comparable, Persistable { private final long objectId; - private final Location location = new Location(); + private final Location location = new Location(0, 0, 0, null); private final Set containedObjects= new HashSet<>(); private final Map attributes = new HashMap<>(); private final Set objectsAware = new HashSet<>(); @@ -112,58 +112,43 @@ public abstract class SWGObject extends BaselineObject implements Comparable requiredSlots = object.getArrangement().get(arrangementId - 4); - // Note that some objects don't have a descriptor, meaning it has no slots - - // Add object to the slot - for (String requiredSlot : requiredSlots) { + for (String requiredSlot : object.getArrangement().get(object.getSlotArrangement() - 4)) { setSlot(requiredSlot, object); } } - object.parent = this; - object.slotArrangement = arrangementId; synchronized (object.objectsAware) { - object.objectsAware.clear(); + for (SWGObject obj : new ArrayList<>(object.objectsAware)) { + object.awarenessOutOfRange(obj, false); + } } } - + /** * Removes the specified object from this current object. * @param object Object to remove */ - public void removeObject(SWGObject object) { - synchronized (object.objectsAware) { - object.objectsAware.clear(); - object.objectsAware.addAll(getObjectsAware()); - object.objectsAware.remove(object); - } - // This object is a container object, so remove it from the container + protected void removeObject(SWGObject object) { if (object.getSlotArrangement() == -1) { synchronized (containedObjects) { containedObjects.remove(object); } } else { - for (String slot : (slotArrangement == -1 ? - object.getArrangement().get(0) : object.getArrangement().get(slotArrangement - 4))) { - setSlot(slot, null); + for (String requiredSlot : object.getArrangement().get(object.getSlotArrangement() - 4)) { + setSlot(requiredSlot, null); } } object.parent = null; object.slotArrangement = -1; } - + /** * Moves this object to the passed container if the requester has the MOVE permission for the container * @param requester Object that is requesting to move the object, used for permission checking @@ -171,38 +156,24 @@ public abstract class SWGObject extends BaselineObject implements Comparable oldObservers = getObservers(); - Player prevOwner = (getParent() != null) ? getParent().getOwner() : null; - if (prevOwner != null) - oldObservers.add(prevOwner.getCreatureObject()); - + Set oldObservers = getObserversAndParent(); SWGObject parent = this.parent; - // Remove this object from the old parent if one exists - if (parent != null) { + if (parent != null) parent.removeObject(this); - } - Player newOwner = null; if (container != null) { int arrangement = container.getArrangementId(this); if (arrangement != -1) container.handleSlotReplacement(parent, this, arrangement); container.addObject(this); - newOwner = container.getOwner(); - } + } else + recreateWorldAwareness(parent); - // Observer notification - Set containerObservers = getObservers(); - if (newOwner != null) - containerObservers.add(newOwner.getCreatureObject()); - sendUpdatedContainment(oldObservers, containerObservers); - + sendUpdatedContainment(oldObservers, getObserversAndParent()); return ContainerResult.SUCCESS; } @@ -216,6 +187,8 @@ public abstract class SWGObject extends BaselineObject implements Comparable getObserversAndParent() { + Set observers = getObservers(); + Player prevOwner = (getParent() != null) ? getParent().getOwner() : null; + if (prevOwner != null) + observers.add(prevOwner.getCreatureObject()); + return observers; + } + + private void recreateWorldAwareness(SWGObject oldParent) { + for (SWGObject obj : oldParent.getObjectsAware()) { + awarenessInRange(obj, false); + } + } + protected void handleSlotReplacement(SWGObject oldParent, SWGObject obj, int arrangement) { for (String slot : obj.getArrangement().get(arrangement-4)) { SWGObject slotObj = getSlottedObject(slot); @@ -370,7 +357,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable objects = getObjectsAware(); for (SWGObject o : objects) { - o.awarenessOutOfRange(this, true); - awarenessOutOfRange(o, updateSelf); + awarenessOutOfRange(o, true); } } @@ -662,20 +644,6 @@ public abstract class SWGObject extends BaselineObject implements Comparable copy; synchronized (customAware) { @@ -808,21 +770,29 @@ public abstract class SWGObject extends BaselineObject implements Comparable Date: Mon, 6 Jun 2016 08:06:58 -0500 Subject: [PATCH 19/24] Fixed players spawning back into buildings --- src/services/objects/ObjectManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 986a110f9..49ea15a8d 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -106,6 +106,9 @@ public class ObjectManager extends Manager { putObject(obj); new ObjectCreatedIntent(obj).broadcast(); } + synchronized (database) { + database.traverse((obj) -> loadObject(obj)); + } return super.initialize(); } @@ -115,7 +118,6 @@ public class ObjectManager extends Manager { synchronized (database) { if (!database.load() && database.fileExists()) return false; - database.traverse((obj) -> loadObject(obj)); } double loadTime = (System.nanoTime() - startLoad) / 1E6; Log.i("ObjectManager", "Finished loading %d objects. Time: %fms", database.size(), loadTime); From 79f7048a920dbb0a625eb56b0d868ac0c815e994 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 08:08:29 -0500 Subject: [PATCH 20/24] Fixed errors in GroupObject --- src/resources/objects/group/GroupObject.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/resources/objects/group/GroupObject.java b/src/resources/objects/group/GroupObject.java index 79475dcdd..e2a9bedd9 100644 --- a/src/resources/objects/group/GroupObject.java +++ b/src/resources/objects/group/GroupObject.java @@ -89,7 +89,6 @@ public class GroupObject extends SWGObject { // Extends INTO or TANO? groupMembers.sendDeltaMessage(this); - awarenessInRange(object, true); object.setGroupId(getObjectId()); if (object.getLevel() > level) @@ -101,16 +100,13 @@ public class GroupObject extends SWGObject { // Extends INTO or TANO? groupMembers.remove(new GroupMember(object.getObjectId(), object.getName())); object.setGroupId(0); - awarenessOutOfRange(object, true); groupMembers.sendDeltaMessage(this); } } public void updateMember(CreatureObject object) { - if (groupMembers.contains(new GroupMember(object.getObjectId(), object.getName()))) - awarenessInRange(object, true); - else awarenessOutOfRange(object, true); + } public long getLeader() { From 87cee94f2d9a2570f82b68910ce81b42e473cd78 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 09:09:34 -0500 Subject: [PATCH 21/24] Fixed respawning outside and added a location map for generated objects --- src/services/objects/ObjectAwareness.java | 116 +++++++++++----------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 810fea83c..061c6ddb9 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -52,6 +52,7 @@ import resources.buildout.BuildoutArea; import resources.control.Intent; import resources.control.Service; import resources.objects.SWGObject; +import resources.objects.SWGObject.ObjectClassification; import resources.objects.creature.CreatureObject; import resources.objects.quadtree.QuadTree; import resources.objects.tangible.TangibleObject; @@ -64,9 +65,11 @@ public class ObjectAwareness extends Service { private static final int DEFAULT_LOAD_RANGE = (int) square(200); // Squared for speed private final Map > quadTree; + private final Map locations; public ObjectAwareness() { - quadTree = new HashMap>(); + quadTree = new HashMap<>(); + locations = new HashMap<>(); registerForIntent(PlayerEventIntent.TYPE); registerForIntent(ObjectCreatedIntent.TYPE); registerForIntent(ObjectTeleportIntent.TYPE); @@ -136,12 +139,11 @@ public class ObjectAwareness extends Service { private void processObjectTeleportIntent(ObjectTeleportIntent oti) { SWGObject object = oti.getObject(); Player owner = object.getOwner(); - Location old = object.getLocation(); object.setLocation(oti.getNewLocation()); if (oti.getParent() != null) { move(object, oti.getParent(), oti.getNewLocation()); } else { - moveFromOld(object, old, false); + move(object, oti.getNewLocation(), false); } object.clearAware(); if (object instanceof CreatureObject && ((CreatureObject) object).isLoggedInPlayer()) @@ -175,9 +177,7 @@ public class ObjectAwareness extends Service { SWGObject obj = i.getObject(); Location newLocation = i.getNewLocation(); BuildoutArea area = obj.getBuildoutArea(); - if (area == null) - Log.e(this, "Unknown buildout area at: " + obj.getWorldLocation()); - else + if (area != null) newLocation = area.adjustLocation(newLocation); move(obj, newLocation, true); if (area != null) @@ -210,20 +210,10 @@ public class ObjectAwareness extends Service { transform = new DataTransform(transform); Location newLocation = transform.getLocation(); newLocation.setTerrain(obj.getTerrain()); - double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; - obj.updateLastTransformTime(); - Location l = obj.getWorldLocation(); - double speed = Math.sqrt(square(l.getX()-newLocation.getX()) + square(l.getZ()-newLocation.getZ())) / time; - if (speed > obj.getMovementScale()*7.3) { - double angle = (newLocation.getX() == l.getX() ? 0 : Math.atan2(newLocation.getZ()-l.getZ(), newLocation.getX()-l.getX())); - newLocation.setX(l.getX()+obj.getMovementScale()*7.3*time*Math.cos(angle)); - newLocation.setZ(l.getZ()+obj.getMovementScale()*7.3*time*Math.sin(angle)); - transform.setSpeed((float) (obj.getMovementScale()*7.3)); - } + moveObjectSpeedChecks(obj, newLocation); + transform.setSpeed((float) (obj.getMovementScale()*7.3)); BuildoutArea area = obj.getBuildoutArea(); - if (area == null) - Log.e(this, "Unknown buildout area at: " + obj.getWorldLocation()); - else + if (area != null) newLocation = area.adjustLocation(newLocation); new PlayerTransformedIntent(obj, obj.getParent(), null, obj.getLocation(), newLocation).broadcast(); move(obj, newLocation, true); @@ -239,6 +229,26 @@ public class ObjectAwareness extends Service { Log.e("ObjectManager", "Could not find parent for transform! Cell: %d Object: %s", transformWithParent.getCellId(), obj); return; } + moveObjectSpeedChecks(obj, parent, newLocation); + transformWithParent.setSpeed((float) (obj.getMovementScale()*7.3)); + new PlayerTransformedIntent((CreatureObject) obj, obj.getParent(), parent, obj.getLocation(), newLocation).broadcast(); + move(obj, parent, newLocation); + obj.sendParentDataTransforms(transformWithParent); + } + + private void moveObjectSpeedChecks(CreatureObject obj, Location newLocation) { + double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; + obj.updateLastTransformTime(); + Location l = obj.getWorldLocation(); + double speed = Math.sqrt(square(l.getX()-newLocation.getX()) + square(l.getZ()-newLocation.getZ())) / time; + if (speed > obj.getMovementScale()*7.3) { + double angle = (newLocation.getX() == l.getX() ? 0 : Math.atan2(newLocation.getZ()-l.getZ(), newLocation.getX()-l.getX())); + newLocation.setX(l.getX()+obj.getMovementScale()*7.3*time*Math.cos(angle)); + newLocation.setZ(l.getZ()+obj.getMovementScale()*7.3*time*Math.sin(angle)); + } + } + + private void moveObjectSpeedChecks(CreatureObject obj, SWGObject parent, Location newLocation) { double time = ((CreatureObject) obj).getTimeSinceLastTransform() / 1000; obj.updateLastTransformTime(); Location l = obj.getWorldLocation(); @@ -249,11 +259,7 @@ public class ObjectAwareness extends Service { double angle = (nWorld.getX() == l.getX() ? 0 : Math.atan2(nWorld.getZ()-l.getZ(), nWorld.getX()-l.getX())) + Math.PI; newLocation.setX(newLocation.getX()+obj.getMovementScale()*7.3*time*invertNormalizedValue(Math.cos(angle))); newLocation.setZ(newLocation.getZ()+obj.getMovementScale()*7.3*time*invertNormalizedValue(Math.sin(angle))); - transformWithParent.setSpeed((float) (obj.getMovementScale()*7.3)); } - new PlayerTransformedIntent((CreatureObject) obj, obj.getParent(), parent, obj.getLocation(), newLocation).broadcast(); - move(obj, parent, newLocation); - obj.sendParentDataTransforms(transformWithParent); } private void loadQuadTree() { @@ -265,9 +271,15 @@ public class ObjectAwareness extends Service { private boolean isInAwareness(SWGObject object) { if (object instanceof CreatureObject && ((CreatureObject) object).isLoggedOutPlayer()) return false; + if (object.getTerrain() == null) + return false; return object.getParent() == null && object instanceof TangibleObject; } + private boolean isInMap(SWGObject object) { + return object.getClassification() == ObjectClassification.GENERATED; + } + private double invertNormalizedValue(double x) { if (x < 0) return -1 - x; @@ -281,13 +293,16 @@ public class ObjectAwareness extends Service { public void add(SWGObject object) { if (!isInAwareness(object)) return; + remove(object); Location l = object.getLocation(); - if (invalidLocation(l)) - return; + if (isInMap(object)) { + synchronized (locations) { + locations.put(object.getObjectId(), l); + } + } QuadTree tree = getTree(l); synchronized (tree) { - if (!tree.contains(l.getX(), l.getZ(), object)) - tree.put(l.getX(), l.getZ(), object); + tree.put(l.getX(), l.getZ(), object); } } @@ -296,7 +311,20 @@ public class ObjectAwareness extends Service { * @param object the object to remove */ public void remove(SWGObject object) { - removeFromLocation(object, object.getLocation()); + Location l; + if (isInMap(object)) { + synchronized (locations) { + l = locations.remove(object.getObjectId()); + } + } else { + l = object.getLocation(); + } + if (l == null) + return; + QuadTree tree = getTree(l); + synchronized (tree) { + tree.remove(l.getX(), l.getZ(), object); + } } /** @@ -329,12 +357,10 @@ public class ObjectAwareness extends Service { */ private void move(SWGObject object, SWGObject nParent, Location nLocation) { SWGObject parent = object.getParent(); - if (parent != null && nParent != parent) { - object.moveToContainer(null); - } else if (parent == null) { + if (parent == null) { remove(object); // Moving from world to cell } - if (object.getParent() == null) { // Should have been updated in removeObject() + if (nParent != parent) { // Intentional. Just in case the ID matches or one is null object.moveToContainer(nParent); } object.setLocation(nLocation); @@ -349,8 +375,6 @@ public class ObjectAwareness extends Service { if (!obj.isGenerated() || !isInAwareness(obj)) return; Location l = obj.getWorldLocation(); - if (invalidLocation(l)) - return; Set objectAware = new HashSet(); QuadTree tree = getTree(l); List range; @@ -364,34 +388,10 @@ public class ObjectAwareness extends Service { obj.updateObjectAwareness(objectAware); } - private void moveFromOld(SWGObject object, Location oldLocation, boolean update) { - if (object.getParent() != null) { - object.moveToContainer(null); - } else { - removeFromLocation(object, oldLocation); // World to World - } - add(object); - if (update) - update(object); - } - - private void removeFromLocation(SWGObject object, Location l) { - if (invalidLocation(l)) - return; - QuadTree tree = getTree(l); - synchronized (tree) { - tree.remove(l.getX(), l.getZ(), object); - } - } - private QuadTree getTree(Location l) { return quadTree.get(l.getTerrain()); } - private boolean invalidLocation(Location l) { - return l == null || l.getTerrain() == null; - } - private boolean isValidInRange(SWGObject obj, SWGObject inRange, Location objLoc) { if (inRange.getObjectId() == obj.getObjectId()) return false; From 9b5f66fdec8912123e53b529e4f9b7fc06cdbe1d Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 10:21:41 -0500 Subject: [PATCH 22/24] Fixed zoning in to buildings --- src/services/objects/ObjectAwareness.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 061c6ddb9..be79196e9 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -123,6 +123,13 @@ public class ObjectAwareness extends Service { creature.resetAwareness(); add(creature); update(creature); + if (creature.getParent() != null && creature.getOwner() != null) { + for (SWGObject observer : creature.getObservers()) + creature.createObject(observer.getOwner()); + for (SWGObject object : creature.getObjectsAware()) { + object.createObject(creature.getOwner()); + } + } p.sendPacket(new CmdSceneReady()); break; default: From ee311700884d3bba2b4005b4df8917f417e416b0 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Mon, 6 Jun 2016 10:54:54 -0500 Subject: [PATCH 23/24] Improved DataTransform code in SWGObject --- src/resources/objects/SWGObject.java | 38 ++++++++++------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 7008f31a5..46031cdd5 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -813,39 +813,29 @@ public abstract class SWGObject extends BaselineObject implements Comparable Date: Mon, 6 Jun 2016 11:22:52 -0500 Subject: [PATCH 24/24] Removed override of client's data transform speed --- src/services/objects/ObjectAwareness.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index be79196e9..fc24b2a23 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -218,7 +218,6 @@ public class ObjectAwareness extends Service { Location newLocation = transform.getLocation(); newLocation.setTerrain(obj.getTerrain()); moveObjectSpeedChecks(obj, newLocation); - transform.setSpeed((float) (obj.getMovementScale()*7.3)); BuildoutArea area = obj.getBuildoutArea(); if (area != null) newLocation = area.adjustLocation(newLocation); @@ -237,7 +236,6 @@ public class ObjectAwareness extends Service { return; } moveObjectSpeedChecks(obj, parent, newLocation); - transformWithParent.setSpeed((float) (obj.getMovementScale()*7.3)); new PlayerTransformedIntent((CreatureObject) obj, obj.getParent(), parent, obj.getLocation(), newLocation).broadcast(); move(obj, parent, newLocation); obj.sendParentDataTransforms(transformWithParent);