From 75b2dcc3b375e5bf2850c4108d845eab2dbc15fc Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Wed, 4 Jan 2017 12:14:18 -0600 Subject: [PATCH 01/14] Flipped invite names --- src/services/group/GroupService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/group/GroupService.java b/src/services/group/GroupService.java index 100ec4099..5cf623634 100644 --- a/src/services/group/GroupService.java +++ b/src/services/group/GroupService.java @@ -393,8 +393,8 @@ public class GroupService extends Service { } private void sendInvite(Player groupLeader, CreatureObject invitee, long groupId) { - sendSystemMessage(invitee.getOwner(), "invite_target", "TT", invitee.getName()); - sendSystemMessage(groupLeader, "invite_leader", "TT", groupLeader.getCharacterName()); + sendSystemMessage(invitee.getOwner(), "invite_target", "TT", groupLeader.getCharacterName()); + sendSystemMessage(groupLeader, "invite_leader", "TT", invitee.getName()); // Set the invite data to the current group ID if (groupId == 0) From 5c5e683a4aa047633e9ce832894eb3508bf34567 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Wed, 4 Jan 2017 12:25:52 -0600 Subject: [PATCH 02/14] Fixed invite with more than 2 people --- src/services/group/GroupService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/group/GroupService.java b/src/services/group/GroupService.java index 5cf623634..99fc47931 100644 --- a/src/services/group/GroupService.java +++ b/src/services/group/GroupService.java @@ -196,7 +196,7 @@ public class GroupService extends Service { return false; } - if (target.getInviterData().getId() != -1) { + if (target.getInviterData().getId() != 0) { if (target.getInviterData().getId() != inviter.getCreatureObject().getGroupId()) sendSystemMessage(inviter, "considering_other_group", "TT", target.getObjectId()); else From 73e1cc82e6bc17560a67b26731849b6c2d87f060 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:26:23 -0600 Subject: [PATCH 03/14] Removed invalid item from building object --- serverdata/buildout/objects.sdb | 1 - 1 file changed, 1 deletion(-) diff --git a/serverdata/buildout/objects.sdb b/serverdata/buildout/objects.sdb index aa7e5fead..2e97a3290 100644 --- a/serverdata/buildout/objects.sdb +++ b/serverdata/buildout/objects.sdb @@ -103999,7 +103999,6 @@ INTEGER PRIMARY KEY INTEGER NOT NULL INTEGER NOT NULL INTEGER NOT NULL INTEGER N 103996 1392858 1 1427 206832110 1392854 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 4 103997 1392859 1 1427 206832110 1392854 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 5 103998 1392860 1 1427 206832110 1392854 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 6 -103999 1725384 1 1427 963242043 1725383 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0 104000 1725400 1 1427 206832110 1725383 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1 104001 1725401 1 1427 206832110 1725383 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 2 104002 1725402 1 1427 206832110 1725383 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 3 From d6ca7b36e02a48967622b7b68d65152d5b083552 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:26:42 -0600 Subject: [PATCH 04/14] Removed an unused function in SWGObject --- src/resources/objects/SWGObject.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index c5bba9366..07689918f 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -306,21 +306,12 @@ public abstract class SWGObject extends BaselineObject implements Comparable Date: Thu, 5 Jan 2017 02:27:39 -0600 Subject: [PATCH 05/14] Fixed a bug with BuildoutArea's adjust and readjust location functions --- src/resources/buildout/BuildoutArea.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/resources/buildout/BuildoutArea.java b/src/resources/buildout/BuildoutArea.java index 5712a2fe4..544a2e832 100644 --- a/src/resources/buildout/BuildoutArea.java +++ b/src/resources/buildout/BuildoutArea.java @@ -144,10 +144,9 @@ public class BuildoutArea implements Comparable { } public void adjustLocation(Location l, Location adjusted) { - if (!isAdjustCoordinates()) { - adjusted.mergeWith(l); + adjusted.mergeWith(l); + if (!isAdjustCoordinates()) return; - } adjusted.translatePosition(-translationX, 0, -translationZ); } @@ -158,10 +157,9 @@ public class BuildoutArea implements Comparable { } public void readjustLocation(Location l, Location adjusted) { - if (!isAdjustCoordinates()) { - adjusted.mergeWith(l); + adjusted.mergeWith(l); + if (!isAdjustCoordinates()) return; - } adjusted.translatePosition(translationX, 0, translationZ); } From b9152aed4b9ab3bb77cde179be65aa06549c9341 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:28:05 -0600 Subject: [PATCH 06/14] Stopped invalid snapshots from being loaded --- src/resources/objects/buildouts/TerrainSnapshotLoader.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/resources/objects/buildouts/TerrainSnapshotLoader.java b/src/resources/objects/buildouts/TerrainSnapshotLoader.java index ddb920edb..f30056c6f 100644 --- a/src/resources/objects/buildouts/TerrainSnapshotLoader.java +++ b/src/resources/objects/buildouts/TerrainSnapshotLoader.java @@ -39,6 +39,7 @@ import resources.client_info.visitors.WorldSnapshotData; import resources.client_info.visitors.WorldSnapshotData.Node; import resources.objects.SWGObject; import resources.objects.SWGObject.ObjectClassification; +import resources.objects.building.BuildingObject; import resources.objects.cell.CellObject; import resources.server_info.Log; import services.objects.ObjectCreator; @@ -100,6 +101,10 @@ public class TerrainSnapshotLoader { objectTable.put(object.getObjectId(), object); if (containerId != 0) { SWGObject container = objectTable.get(containerId); + if (!(object instanceof CellObject) && container instanceof BuildingObject) { + Log.w(this, "Not adding: %s to %s - invalid type for BuildingObject", object, container); + return; + } object.moveToContainer(container); if (container == null) Log.e("TerrainSnapshotLoader", "Failed to load object: " + object.getTemplate()); From 6fe5b2efa86954c1a597d95f40f6968dd08678f6 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:29:06 -0600 Subject: [PATCH 07/14] Made the cell number persistable in CellObject --- src/resources/objects/cell/CellObject.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/resources/objects/cell/CellObject.java b/src/resources/objects/cell/CellObject.java index 377b0d87d..43fd8b465 100644 --- a/src/resources/objects/cell/CellObject.java +++ b/src/resources/objects/cell/CellObject.java @@ -124,8 +124,9 @@ public class CellObject extends SWGObject { @Override public void save(NetBufferStream stream) { super.save(stream); - stream.addByte(0); + stream.addByte(1); stream.addBoolean(isPublic); + stream.addInt(number); stream.addAscii(label); stream.addFloat((float) labelX); stream.addFloat((float) labelZ); @@ -134,8 +135,10 @@ public class CellObject extends SWGObject { @Override public void read(NetBufferStream stream) { super.read(stream); - stream.getByte(); + int ver = stream.getByte(); isPublic = stream.getBoolean(); + if (ver >= 1) + number = stream.getInt(); label = stream.getAscii(); labelX = stream.getFloat(); labelZ = stream.getFloat(); From f18cde3dd9cbf9e96fd5641dddcfaa4f6233587d Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:30:12 -0600 Subject: [PATCH 08/14] Streamlined BuildingObject and added maps for id/name -> cell lookup --- .../objects/building/BuildingObject.java | 118 +++++++++--------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/src/resources/objects/building/BuildingObject.java b/src/resources/objects/building/BuildingObject.java index 271e9c455..943c31d20 100644 --- a/src/resources/objects/building/BuildingObject.java +++ b/src/resources/objects/building/BuildingObject.java @@ -32,93 +32,96 @@ import resources.Location; import resources.client_info.ClientFactory; import resources.client_info.visitors.PortalLayoutData; import resources.client_info.visitors.ObjectData.ObjectDataAttribute; +import resources.control.Assert; import resources.network.NetBufferStream; import resources.objects.SWGObject; import resources.objects.cell.CellObject; import resources.objects.tangible.TangibleObject; +import resources.server_info.SynchronizedMap; import services.objects.ObjectCreator; import intents.object.ObjectCreatedIntent; -import java.util.Collections; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; +import java.util.Map; public class BuildingObject extends TangibleObject { + private final Map nameToCell; + private final Map idToCell; + public BuildingObject(long objectId) { super(objectId, BaselineType.BUIO); + nameToCell = new SynchronizedMap<>(); + idToCell = new SynchronizedMap<>(); } public CellObject getCellByName(String cellName) { - for (SWGObject cont : getContainedObjects()) { - if (cont instanceof CellObject) { - if (((CellObject) cont).getCellName().equals(cellName)) { - return (CellObject) cont; - } - } - } - return null; + return nameToCell.get(cellName); } public CellObject getCellByNumber(int cellNumber) { - for (SWGObject cont : getContainedObjects()) { - if (cont instanceof CellObject) { - if (((CellObject) cont).getNumber() == cellNumber) { - return (CellObject) cont; - } - } - } - return null; + return idToCell.get(cellNumber); } - + public List getCells() { - List cells = new LinkedList<>(); - for (SWGObject object : getContainedObjects()) { - if (object instanceof CellObject) - cells.add((CellObject) object); - } - return Collections.unmodifiableList(cells); + return new ArrayList<>(idToCell.values()); } - + @Override public void addObject(SWGObject object) { super.addObject(object); - if (!(object instanceof CellObject)) - return; - - String portalFile = (String) getDataAttribute(ObjectDataAttribute.PORTAL_LAYOUT_FILENAME); - if (portalFile == null || portalFile.isEmpty()) - return; - - PortalLayoutData portalLayoutData = (PortalLayoutData) ClientFactory.getInfoFromFile(portalFile, true); - if (portalLayoutData == null || portalLayoutData.getCells() == null || portalLayoutData.getCells().size() == 0) - return; - - populateCellData((CellObject) object, portalLayoutData.getCells().get(((CellObject) object).getNumber())); + Assert.test(object instanceof CellObject); + + CellObject cell = (CellObject) object; + Assert.test(cell.getNumber() > 0); + Assert.test(cell.getNumber() < getCellCount()); + cell.setCellName(getCellName(cell.getNumber())); + synchronized (idToCell) { + Assert.isNull(idToCell.get(cell.getNumber())); + idToCell.put(cell.getNumber(), cell); + nameToCell.put(cell.getName(), cell); // Can be multiple cells with the same name + } } public void populateCells() { - String portalFile = (String) getDataAttribute(ObjectDataAttribute.PORTAL_LAYOUT_FILENAME); - if (portalFile == null || portalFile.isEmpty()) - return; - - PortalLayoutData portalLayoutData = (PortalLayoutData) ClientFactory.getInfoFromFile(portalFile, true); - if (portalLayoutData == null || portalLayoutData.getCells() == null || portalLayoutData.getCells().size() == 0) - return; - - for (int i = 0; i < portalLayoutData.getCells().size() - 1; i++) { - CellObject cell = (CellObject) ObjectCreator.createObjectFromTemplate("object/cell/shared_cell.iff"); - cell.setNumber(i+1); - cell.setLocation(new Location(0, 0, 0, getTerrain())); - populateCellData(cell, portalLayoutData.getCells().get(i+1)); - cell.moveToContainer(this); - new ObjectCreatedIntent(cell).broadcast(); + int cells = getCellCount(); + synchronized (idToCell) { + for (int i = 1; i < cells; i++) { // 0 is world + if (idToCell.get(i) != null) + continue; + CellObject cell = (CellObject) ObjectCreator.createObjectFromTemplate("object/cell/shared_cell.iff"); + Assert.notNull(cell); + cell.setNumber(i); + cell.setLocation(new Location(0, 0, 0, getTerrain())); + addObject(cell); + new ObjectCreatedIntent(cell).broadcast(); + } } } - - private void populateCellData(CellObject cellObject, PortalLayoutData.Cell cellData) { - cellObject.setCellName(cellData.getName()); -// System.out.println(cellObject + " cell name " + cellObject.getCellName()); + + private int getCellCount() { + PortalLayoutData data = getPortalLayoutData(); + if (data == null) + return 0; + return data.getCells().size(); + } + + private String getCellName(int cell) { + PortalLayoutData data = getPortalLayoutData(); + if (data == null) + return ""; + return data.getCells().get(cell).getName(); + } + + private PortalLayoutData getPortalLayoutData() { + String portalFile = (String) getDataAttribute(ObjectDataAttribute.PORTAL_LAYOUT_FILENAME); + if (portalFile == null || portalFile.isEmpty()) + return null; + + PortalLayoutData portalLayoutData = (PortalLayoutData) ClientFactory.getInfoFromFile(portalFile, true); + Assert.test(portalLayoutData != null && portalLayoutData.getCells() != null && portalLayoutData.getCells().size() > 0); + return portalLayoutData; } @Override @@ -132,4 +135,5 @@ public class BuildingObject extends TangibleObject { super.read(stream); stream.getByte(); } + } From 2422fd15e94d4156426669d19d8608e2841496eb Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:30:55 -0600 Subject: [PATCH 09/14] Added kinder error message for unknown parent in datatransformwithparent --- src/services/objects/ObjectAwareness.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/services/objects/ObjectAwareness.java b/src/services/objects/ObjectAwareness.java index 148d5f529..4d5724f23 100644 --- a/src/services/objects/ObjectAwareness.java +++ b/src/services/objects/ObjectAwareness.java @@ -229,6 +229,10 @@ public class ObjectAwareness extends Service implements TerrainMapCallback { SWGObject obj = i.getObjectManager().getObjectById(trans.getObjectId()); SWGObject parent = i.getObjectManager().getObjectById(trans.getCellId()); Assert.test(obj instanceof CreatureObject); + if (parent == null) { + Log.w(this, "Unknown data transform parent! Obj: %d/%s Parent: %d", trans.getObjectId(), obj, trans.getCellId()); + return; + } Location requestedLocation = new Location(trans.getLocation()); requestedLocation.setTerrain(obj.getTerrain()); moveObjectWithTransform(obj, parent, requestedLocation, trans.getSpeed(), trans.getUpdateCounter()); From d14d8b452e58d72f646d5d3b0c4018fbd52f43e2 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:31:15 -0600 Subject: [PATCH 10/14] Optimized mergeLocation in Location --- src/resources/Location.java | 67 +++++++++++-------------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/src/resources/Location.java b/src/resources/Location.java index 52ad9f13f..2397e45af 100644 --- a/src/resources/Location.java +++ b/src/resources/Location.java @@ -159,58 +159,31 @@ public class Location implements Encodable, Persistable { orientation.rotateDegrees(angle, axisX, axisY, axisZ); } - public boolean mergeWith(Location l) { - boolean changed = false; - if (terrain == null || terrain != l.getTerrain()) { + public void mergeWith(Location l) { + if (terrain == null || terrain != l.getTerrain()) terrain = l.getTerrain(); - changed = true; - } - changed = mergeLocation(l.getX(), l.getY(), l.getZ()) || true; - changed = mergeOrientation(l) || true; - return changed; + mergeLocation(l.getX(), l.getY(), l.getZ()); + mergeOrientation(l); } - public boolean mergeLocation(double lX, double lY, double lZ) { - boolean changed = false; - if (Double.isNaN(getX()) || !isEqual(getX(), lX)) { - setX(lX); - changed = true; - } - if (Double.isNaN(getY()) || !isEqual(getY(), lY)) { - setY(lY); - changed = true; - } - if (Double.isNaN(getZ()) || !isEqual(getZ(), lZ)) { - setZ(lZ); - changed = true; - } - return changed; + public void mergeLocation(double lX, double lY, double lZ) { + if (!isEqual(getX(), lX)) + point.setX(lX); + if (!isEqual(getY(), lY)) + point.setY(lY); + if (!isEqual(getZ(), lZ)) + point.setZ(lZ); } - private boolean mergeOrientation(Location l) { - double oX = getOrientationX(); - double oY = getOrientationY(); - double oZ = getOrientationZ(); - double oW = getOrientationW(); - boolean changed = false; - if (!Double.isNaN(l.getOrientationX()) && (Double.isNaN(oX) || !isEqual(oX, l.getOrientationX()))) { - oX = l.getOrientationX(); - changed = true; - } - if (!Double.isNaN(l.getOrientationY()) && (Double.isNaN(oY) || !isEqual(oY, l.getOrientationY()))) { - oY = l.getOrientationY(); - changed = true; - } - if (!Double.isNaN(l.getOrientationZ()) && (Double.isNaN(oZ) || !isEqual(oZ, l.getOrientationZ()))) { - oZ = l.getOrientationZ(); - changed = true; - } - if (!Double.isNaN(l.getOrientationW()) && (Double.isNaN(oW) || !isEqual(oW, l.getOrientationW()))) { - oW = l.getOrientationW(); - changed = true; - } - orientation.set(oX, oY, oZ, oW); - return changed; + private void mergeOrientation(Location l) { + if (!isEqual(getOrientationX(), l.getOrientationX())) + orientation.setX(l.getOrientationX()); + if (!isEqual(getOrientationY(), l.getOrientationY())) + orientation.setY(l.getOrientationY()); + if (!isEqual(getOrientationZ(), l.getOrientationZ())) + orientation.setZ(l.getOrientationZ()); + if (!isEqual(getOrientationW(), l.getOrientationW())) + orientation.setW(l.getOrientationW()); } public double getSpeed(Location l, double deltaTime) { From b136d545bcb0b598b720ecd046fe8f858af6e313 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:31:26 -0600 Subject: [PATCH 11/14] Optimized buildout loading --- .../objects/ClientBuildoutService.java | 334 ++++++++++-------- 1 file changed, 194 insertions(+), 140 deletions(-) diff --git a/src/services/objects/ClientBuildoutService.java b/src/services/objects/ClientBuildoutService.java index e4ef47d4a..e51a0b512 100644 --- a/src/services/objects/ClientBuildoutService.java +++ b/src/services/objects/ClientBuildoutService.java @@ -27,11 +27,17 @@ ***********************************************************************************/ package services.objects; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.List; @@ -60,17 +66,6 @@ import resources.server_info.RelationalServerFactory; public class ClientBuildoutService extends Service { private static final String GET_BUILDOUT_AREAS = "SELECT * FROM areas ORDER BY area_name ASC, event ASC"; - private static final String GET_CLIENT_OBJECTS_SQL = "SELECT objects.id, objects.snapshot, objects.area_id, objects.template_crc, objects.container_id, " - + "objects.x, objects.y, objects.z, objects.orientation_x, objects.orientation_y, objects.orientation_z, objects.orientation_w, " - + "objects.radius, objects.cell_index " - + "FROM objects " - + "ORDER BY buildout_id ASC"; - private static final String GET_CLIENT_OBJECTS_BY_AREA_SQL = "SELECT objects.id, objects.snapshot, objects.area_id, objects.template_crc, objects.container_id, " - + "objects.x, objects.y, objects.z, objects.orientation_x, objects.orientation_y, objects.orientation_z, objects.orientation_w, " - + "objects.radius, objects.cell_index " - + "FROM objects " - + "WHERE objects.area_id = ? " - + "ORDER BY buildout_id ASC"; private static final String GET_ADDITIONAL_OBJECTS_SQL = "SELECT terrain, template, x, y, z, heading, cell_id, radius, building_name " + "FROM additional_buildouts WHERE active = 1"; private static final String GET_BUILDING_INFO_SQL = "SELECT object_id FROM buildings WHERE building_id = ?"; @@ -133,11 +128,15 @@ public class ClientBuildoutService extends Service { } private Collection loadObjects() throws SQLException { - Map objects = new Hashtable<>(); + Map objects = new HashMap<>(112660); try (CrcDatabase strings = new CrcDatabase()) { - try (RelationalServerData data = RelationalServerFactory.getServerData("buildout/buildouts.db", "objects")) { - try (ResultSet set = data.executeQuery(GET_CLIENT_OBJECTS_SQL)) { - readAllObjects(objects, strings, set); + strings.loadStrings(); + try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { + while (loader.loadNextEntry()) { + if (!loader.isValidNextEntry()) + continue; + SWGObject obj = loader.createObject(); + objects.put(obj.getObjectId(), obj); } } } @@ -147,38 +146,21 @@ public class ClientBuildoutService extends Service { } private Collection loadObjects(int areaId) throws SQLException { - Map objects = new Hashtable<>(); + Map objects = new HashMap<>(112660); try (CrcDatabase strings = new CrcDatabase()) { - try (RelationalServerData data = RelationalServerFactory.getServerData("buildout/buildouts.db", "objects")) { - PreparedStatement ps = data.prepareStatement(GET_CLIENT_OBJECTS_BY_AREA_SQL); - ps.setInt(1, areaId); - try (ResultSet set = ps.executeQuery()) { - readAllObjects(objects, strings, set); + strings.loadStrings(); + try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { + while (loader.loadNextEntry()) { + if (!loader.isAreaId(areaId)) + continue; + SWGObject obj = loader.createObject(); + objects.put(obj.getObjectId(), obj); } } } return new ArrayList<>(objects.values()); } - private void readAllObjects(Map objects, CrcDatabase strings, ResultSet set) throws SQLException { - set.setFetchSize(4*1024); - BuildoutArea area = null; - ObjectInformation info = new ObjectInformation(set); - int prevAreaId = Integer.MAX_VALUE; - int areaId = 0; - while (set.next()) { - areaId = info.getAreaIdNoLoad(); - if (prevAreaId != areaId) { - area = areasById.get(areaId); - prevAreaId = areaId; - } - if (area == null) - continue; - info.load(strings); - createObject(objects, area, info); - } - } - private Collection getAdditionalObjects(Map buildouts) throws SQLException { Map objects = new Hashtable<>(); try (CrcDatabase strings = new CrcDatabase()) { @@ -194,18 +176,6 @@ public class ClientBuildoutService extends Service { return new ArrayList<>(objects.values()); } - private void createObject(Map objects, BuildoutArea area, ObjectInformation info) throws SQLException { - SWGObject obj = ObjectCreator.createObjectFromTemplate(info.getId(), info.getTemplate()); - Location l = info.getLocation(); - l.setTerrain(area.getTerrain()); - obj.setLocation(l); - obj.setClassification(info.isSnapshot() ? ObjectClassification.SNAPSHOT : ObjectClassification.BUILDOUT); - obj.setPrefLoadRange(info.getRadius()); - checkCell(obj, info.getCell()); - checkChild(objects, obj, info.getContainer()); - objects.put(obj.getObjectId(), obj); - } - private void createAdditionalObject(Map objects, Map buildouts, ResultSet set) throws SQLException { try { SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getString("template")); @@ -257,16 +227,6 @@ public class ClientBuildoutService extends Service { } } - private void checkCell(SWGObject obj, int cell) { - if (cell != 0 && obj instanceof CellObject) - ((CellObject) obj).setNumber(cell); - } - - private void checkChild(Map objects, SWGObject obj, long container) { - if (container != 0) - obj.moveToContainer(objects.get(container)); - } - private List getEvents() { List events = new ArrayList<>(); String eventStr = getConfig(ConfigFile.FEATURES).getString("EVENTS", ""); @@ -359,6 +319,178 @@ public class ClientBuildoutService extends Service { return area.getTerrain() == t && x >= area.getX1() && x <= area.getX2() && z >= area.getZ1() && z <= area.getZ2(); } + private static class BuildoutLoader implements AutoCloseable { + + private final Map areas; + private final Map objects; + private final CrcDatabase strings; + private final SdbLoader loader; + private final Location location; + private final ObjectCreationData creationData; + private BuildoutArea previousArea; + private String line; + + public BuildoutLoader(Map areas, Map objects, CrcDatabase strings, File file) { + this.areas = areas; + this.objects = objects; + this.strings = strings; + this.loader = new SdbLoader(file); + this.location = new Location(); + this.creationData = new ObjectCreationData(); + this.previousArea = areas.values().iterator().next(); + this.line = ""; + loader.loadNextLine(); // Skip column names + loader.loadNextLine(); // Skip data types + } + + public void close() { + loader.close(); + } + + public boolean loadNextEntry() { + line = loader.loadNextLine(); + if (line != null) { + parse(); + return true; + } + return false; + } + + public boolean isAreaId(int areaId) { + return creationData.areaId == areaId; + } + + public boolean isValidNextEntry() { + return areas.containsKey(creationData.areaId); + } + + public SWGObject createObject() { + SWGObject obj = ObjectCreator.createObjectFromTemplate(creationData.id, strings.getString(creationData.templateCrc)); + obj.setClassification(creationData.snapshot ? ObjectClassification.SNAPSHOT : ObjectClassification.BUILDOUT); + obj.setPrefLoadRange(creationData.radius); + setObjectLocation(obj); + setCellNumber(obj); + setContainer(obj); + return obj; + } + + private void setObjectLocation(SWGObject obj) { + location.setPosition(creationData.x, creationData.y, creationData.z); + location.setOrientation(creationData.orientationX, creationData.orientationY, creationData.orientationZ, creationData.orientationW); + if (previousArea.getId() != creationData.areaId) + location.setTerrain(areas.get(creationData.areaId).getTerrain()); + obj.setLocation(location); + } + + private void setCellNumber(SWGObject obj) { + if (creationData.cellIndex != 0) + ((CellObject) obj).setNumber(creationData.cellIndex); + } + + private void setContainer(SWGObject obj) { + if (creationData.containerId != 0) + obj.moveToContainer(objects.get(creationData.containerId)); + } + + private void parse() { + int prevIndex = 0; + int nextIndex = 0; + for (int i = 0; i < 15; i++) { // 14 expected variables + nextIndex = line.indexOf('\t', prevIndex); + parseValue(getNextValue(prevIndex, nextIndex), i); + prevIndex = nextIndex+1; + } + } + + private void parseValue(Number n, int index) { + switch (index) { + case 1: creationData.id = n.longValue(); break; + case 2: creationData.snapshot = n.longValue() != 0; break; + case 3: creationData.areaId = n.intValue(); break; + case 4: creationData.templateCrc = n.intValue(); break; + case 5: creationData.containerId = n.longValue(); break; + case 6: creationData.x = n.doubleValue(); break; + case 7: creationData.y = n.doubleValue(); break; + case 8: creationData.z = n.doubleValue(); break; + case 9: creationData.orientationX = n.doubleValue(); break; + case 10: creationData.orientationY = n.doubleValue(); break; + case 11: creationData.orientationZ = n.doubleValue(); break; + case 12: creationData.orientationW = n.doubleValue(); break; + case 13: creationData.radius = n.doubleValue(); break; + case 14: creationData.cellIndex = n.intValue(); break; + } + } + + private Number getNextValue(int prevIndex, int nextIndex) { + if (nextIndex == -1) + return parse(line.substring(prevIndex)); + else + return parse(line.substring(prevIndex, nextIndex)); + } + + private Number parse(String str) { + if (str.indexOf('.') == -1) + return Long.valueOf(str); + return Double.valueOf(str); + } + + } + + private static class ObjectCreationData { + + public long id; + public boolean snapshot; + public int areaId; + public int templateCrc; + public long containerId; + public double x; + public double y; + public double z; + public double orientationX; + public double orientationY; + public double orientationZ; + public double orientationW; + public double radius; + public int cellIndex; + + } + + private static class SdbLoader implements AutoCloseable { + + private final BufferedReader reader; + + public SdbLoader(File file) { + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(file)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + br = null; + } + this.reader = br; + } + + public void close() { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public String loadNextLine() { + try { + return reader.readLine(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + } + private static class AreaIndexes { private int id; @@ -385,82 +517,4 @@ public class ClientBuildoutService extends Service { } - private static class ObjectInformation { - - private final ColumnIndexes index; - private final ResultSet set; - private final Location l; - private long id; - private boolean snapshot; - private String template; - private float radius; - private long container; - private int cell; - - public ObjectInformation(ResultSet set) throws SQLException { - this.set = set; - index = new ColumnIndexes(set); - l = new Location(); - } - - public void load(CrcDatabase strings) throws SQLException { - id = set.getLong(index.idInd); - snapshot = set.getBoolean(index.snapInd); - template = strings.getString(set.getInt(index.crcInd)); - l.setPosition(set.getDouble(index.xInd), set.getDouble(index.yInd), set.getDouble(index.zInd)); - l.setOrientation(set.getDouble(index.oxInd), set.getDouble(index.oyInd), set.getDouble(index.ozInd), set.getDouble(index.owInd)); - radius = set.getInt(index.radiusInd); - container = set.getLong(index.contInd); - cell = set.getInt(index.cellInd); - } - - public int getAreaIdNoLoad() throws SQLException { - return set.getInt(index.areaInd); - } - - public long getId() { return id; } - public boolean isSnapshot() { return snapshot; } - public String getTemplate() { return template; } - public Location getLocation() { return l; } - public double getRadius() { return radius; } - public long getContainer() { return container; } - public int getCell() { return cell; } - } - - private static class ColumnIndexes { - - public final int idInd; - public final int snapInd; - public final int crcInd; - public final int areaInd; - public final int xInd; - public final int yInd; - public final int zInd; - public final int oxInd; - public final int oyInd; - public final int ozInd; - public final int owInd; - public final int radiusInd; - public final int contInd; - public final int cellInd; - - public ColumnIndexes(ResultSet set) throws SQLException { - idInd = set.findColumn("id"); - snapInd = set.findColumn("snapshot"); - crcInd = set.findColumn("template_crc"); - areaInd = set.findColumn("area_id"); - xInd = set.findColumn("x"); - yInd = set.findColumn("y"); - zInd = set.findColumn("z"); - oxInd = set.findColumn("orientation_x"); - oyInd = set.findColumn("orientation_y"); - ozInd = set.findColumn("orientation_z"); - owInd = set.findColumn("orientation_w"); - radiusInd = set.findColumn("radius"); - contInd = set.findColumn("container_id"); - cellInd = set.findColumn("cell_index"); - } - - } - } From db8936fc6720cbf2f50a0a6eec0150079b33dfe2 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:48:27 -0600 Subject: [PATCH 12/14] Changed return type of ClientBuildoutService to load faster --- .../objects/ClientBuildoutService.java | 48 ++++++++++--------- src/services/objects/ObjectManager.java | 9 ++-- .../buildouts/BuildingListGenerator.java | 2 +- .../awareness/TestAwarenessHandler.java | 4 +- .../objects/awareness/TestTerrainMap.java | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/services/objects/ClientBuildoutService.java b/src/services/objects/ClientBuildoutService.java index e51a0b512..f89882d1f 100644 --- a/src/services/objects/ClientBuildoutService.java +++ b/src/services/objects/ClientBuildoutService.java @@ -36,9 +36,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Locale; @@ -97,8 +95,8 @@ public class ClientBuildoutService extends Service { } } - public Collection loadClientObjects() { - Collection objects; + public Map loadClientObjects() { + Map objects; long startLoad = System.nanoTime(); Log.i(this, "Loading client objects..."); try { @@ -106,9 +104,9 @@ public class ClientBuildoutService extends Service { if (getConfig(ConfigFile.PRIMARY).getBoolean("LOAD-OBJECTS", true)) objects = loadObjects(); else - objects = new HashSet<>(); + objects = new HashMap<>(); } catch (SQLException e) { - objects = new HashSet<>(); + objects = new HashMap<>(); Log.e(this, e); } double loadTime = (System.nanoTime() - startLoad) / 1E6; @@ -116,67 +114,70 @@ public class ClientBuildoutService extends Service { return objects; } - public Collection loadClientObjectsByArea(int areaId) { + public Map loadClientObjectsByArea(int areaId) { try { if (areasById.isEmpty()) loadAreas(new ArrayList<>()); return loadObjects(areaId); } catch (SQLException e) { Log.e(this, e); - return new ArrayList<>(); + return new HashMap<>(); } } - private Collection loadObjects() throws SQLException { + private Map loadObjects() throws SQLException { Map objects = new HashMap<>(112660); try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { + SWGObject obj; while (loader.loadNextEntry()) { if (!loader.isValidNextEntry()) continue; - SWGObject obj = loader.createObject(); - objects.put(obj.getObjectId(), obj); + obj = loader.createObject(); + new ObjectCreatedIntent(obj).broadcast(); } } } - List ret = new ArrayList<>(objects.values()); - ret.addAll(getAdditionalObjects(objects)); - return ret; + objects.putAll(getAdditionalObjects(objects)); + return objects; } - private Collection loadObjects(int areaId) throws SQLException { + private Map loadObjects(int areaId) throws SQLException { Map objects = new HashMap<>(112660); try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { + SWGObject obj; while (loader.loadNextEntry()) { if (!loader.isAreaId(areaId)) continue; - SWGObject obj = loader.createObject(); - objects.put(obj.getObjectId(), obj); + obj = loader.createObject(); + new ObjectCreatedIntent(obj).broadcast(); } } } - return new ArrayList<>(objects.values()); + return objects; } - private Collection getAdditionalObjects(Map buildouts) throws SQLException { + private Map getAdditionalObjects(Map buildouts) throws SQLException { Map objects = new Hashtable<>(); try (CrcDatabase strings = new CrcDatabase()) { try (RelationalServerData data = RelationalServerFactory.getServerData("buildout/additional_buildouts.db", "additional_buildouts")) { try (ResultSet set = data.executeQuery(GET_ADDITIONAL_OBJECTS_SQL)) { set.setFetchSize(4*1024); + SWGObject obj; while (set.next()) { - createAdditionalObject(objects, buildouts, set); + obj = createAdditionalObject(objects, buildouts, set); + new ObjectCreatedIntent(obj).broadcast(); } } } } - return new ArrayList<>(objects.values()); + return objects; } - private void createAdditionalObject(Map objects, Map buildouts, ResultSet set) throws SQLException { + private SWGObject createAdditionalObject(Map objects, Map buildouts, ResultSet set) throws SQLException { try { SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getString("template")); Location l = new Location(); @@ -190,8 +191,10 @@ public class ClientBuildoutService extends Service { obj.setPrefLoadRange(set.getFloat("radius")); checkParent(buildouts, obj, set.getString("building_name"), set.getInt("cell_id")); objects.put(obj.getObjectId(), obj); + return obj; } catch (NullPointerException e) { Log.e(this, "File: %s", set.getString("template")); + return null; } } @@ -371,6 +374,7 @@ public class ClientBuildoutService extends Service { setObjectLocation(obj); setCellNumber(obj); setContainer(obj); + objects.put(obj.getObjectId(), obj); return obj; } diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 4b7fd3d45..9ce9939f4 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -27,7 +27,6 @@ ***********************************************************************************/ package services.objects; -import java.util.Collection; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.Executors; @@ -102,13 +101,11 @@ public class ObjectManager extends Manager { @Override public boolean initialize() { - Collection buildouts = clientBuildoutService.loadClientObjects(); + synchronized (objectMap) { + objectMap.putAll(clientBuildoutService.loadClientObjects()); + } if (!loadObjects()) return false; - for (SWGObject obj : buildouts) { - putObject(obj); - new ObjectCreatedIntent(obj).broadcast(); - } synchronized (database) { database.traverse((obj) -> loadObject(obj)); } diff --git a/src/utilities/buildouts/BuildingListGenerator.java b/src/utilities/buildouts/BuildingListGenerator.java index 8892e2ad1..df08b5369 100644 --- a/src/utilities/buildouts/BuildingListGenerator.java +++ b/src/utilities/buildouts/BuildingListGenerator.java @@ -44,7 +44,7 @@ public class BuildingListGenerator { public static void main(String [] args) throws IOException { ClientBuildoutService buildouts = new ClientBuildoutService(); - Collection objects = buildouts.loadClientObjects(); + Collection objects = buildouts.loadClientObjects().values(); System.out.println("Organizing data..."); List buildings = new ArrayList<>(); SdbGenerator gen = new SdbGenerator(new File("buildings.sdb")); diff --git a/test/resources/objects/awareness/TestAwarenessHandler.java b/test/resources/objects/awareness/TestAwarenessHandler.java index bd4cbce81..603c78a84 100644 --- a/test/resources/objects/awareness/TestAwarenessHandler.java +++ b/test/resources/objects/awareness/TestAwarenessHandler.java @@ -60,10 +60,10 @@ public class TestAwarenessHandler { public static void initTatooine() { ClientBuildoutService buildoutService = new ClientBuildoutService(); double loadDistance = 1024*1.414*2; // 1024 * sqrt(2) - for (SWGObject obj : buildoutService.loadClientObjectsByArea(843)) { // mos eisley's area id + for (SWGObject obj : buildoutService.loadClientObjectsByArea(843).values()) { // mos eisley's area id initObject(obj, loadDistance); } - for (SWGObject obj : buildoutService.loadClientObjectsByArea(-59)) { // general tatooine's area id + for (SWGObject obj : buildoutService.loadClientObjectsByArea(-59).values()) { // general tatooine's area id initObject(obj, loadDistance); } CREATURE2.setLocation(CREATURE2_LOCATION); diff --git a/test/resources/objects/awareness/TestTerrainMap.java b/test/resources/objects/awareness/TestTerrainMap.java index f38dabeba..4a17f4090 100644 --- a/test/resources/objects/awareness/TestTerrainMap.java +++ b/test/resources/objects/awareness/TestTerrainMap.java @@ -111,7 +111,7 @@ public class TestTerrainMap { @Test public void testTatooine() { ClientBuildoutService buildoutService = new ClientBuildoutService(); - Collection allObjects = buildoutService.loadClientObjectsByArea(843); // mos eisley's area id + Collection allObjects = buildoutService.loadClientObjectsByArea(843).values(); // mos eisley's area id List tatObjects = allObjects.stream().filter((obj) -> { return obj.getTerrain() == Terrain.TATOOINE && obj.getParent() == null; }).collect(Collectors.toList()); From 782be86f797b411226153aa2c3e1a8da9c688c98 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 02:58:53 -0600 Subject: [PATCH 13/14] Improved object map data type to speed up loading further --- src/services/objects/ClientBuildoutService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/objects/ClientBuildoutService.java b/src/services/objects/ClientBuildoutService.java index f89882d1f..7e2a560c3 100644 --- a/src/services/objects/ClientBuildoutService.java +++ b/src/services/objects/ClientBuildoutService.java @@ -126,7 +126,7 @@ public class ClientBuildoutService extends Service { } private Map loadObjects() throws SQLException { - Map objects = new HashMap<>(112660); + Map objects = new Hashtable<>(112660); try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { @@ -144,7 +144,7 @@ public class ClientBuildoutService extends Service { } private Map loadObjects(int areaId) throws SQLException { - Map objects = new HashMap<>(112660); + Map objects = new Hashtable<>(); try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { From 322ae8b305dae6c3f4fe24779470fd283d1e97e6 Mon Sep 17 00:00:00 2001 From: Obique PSWG Date: Thu, 5 Jan 2017 03:13:26 -0600 Subject: [PATCH 14/14] Externalized the ObjectCreatedIntent from ClientBuildoutService --- .../objects/ClientBuildoutService.java | 39 +++++++------------ src/services/objects/ObjectManager.java | 7 +++- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/services/objects/ClientBuildoutService.java b/src/services/objects/ClientBuildoutService.java index 7e2a560c3..adfd047d5 100644 --- a/src/services/objects/ClientBuildoutService.java +++ b/src/services/objects/ClientBuildoutService.java @@ -126,20 +126,18 @@ public class ClientBuildoutService extends Service { } private Map loadObjects() throws SQLException { - Map objects = new Hashtable<>(112660); + Map objects = new Hashtable<>(115000); try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { - SWGObject obj; while (loader.loadNextEntry()) { if (!loader.isValidNextEntry()) continue; - obj = loader.createObject(); - new ObjectCreatedIntent(obj).broadcast(); + loader.createObject(); } } + addAdditionalObjects(strings, objects); } - objects.putAll(getAdditionalObjects(objects)); return objects; } @@ -148,36 +146,28 @@ public class ClientBuildoutService extends Service { try (CrcDatabase strings = new CrcDatabase()) { strings.loadStrings(); try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { - SWGObject obj; while (loader.loadNextEntry()) { if (!loader.isAreaId(areaId)) continue; - obj = loader.createObject(); - new ObjectCreatedIntent(obj).broadcast(); + loader.createObject(); } } } return objects; } - private Map getAdditionalObjects(Map buildouts) throws SQLException { - Map objects = new Hashtable<>(); - try (CrcDatabase strings = new CrcDatabase()) { - try (RelationalServerData data = RelationalServerFactory.getServerData("buildout/additional_buildouts.db", "additional_buildouts")) { - try (ResultSet set = data.executeQuery(GET_ADDITIONAL_OBJECTS_SQL)) { - set.setFetchSize(4*1024); - SWGObject obj; - while (set.next()) { - obj = createAdditionalObject(objects, buildouts, set); - new ObjectCreatedIntent(obj).broadcast(); - } + private void addAdditionalObjects(CrcDatabase strings, Map buildouts) throws SQLException { + try (RelationalServerData data = RelationalServerFactory.getServerData("buildout/additional_buildouts.db", "additional_buildouts")) { + try (ResultSet set = data.executeQuery(GET_ADDITIONAL_OBJECTS_SQL)) { + set.setFetchSize(4*1024); + while (set.next()) { + createAdditionalObject(buildouts, set); } } } - return objects; } - private SWGObject createAdditionalObject(Map objects, Map buildouts, ResultSet set) throws SQLException { + private void createAdditionalObject(Map buildouts, ResultSet set) throws SQLException { try { SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getString("template")); Location l = new Location(); @@ -190,11 +180,9 @@ public class ClientBuildoutService extends Service { obj.setClassification(ObjectClassification.BUILDOUT); obj.setPrefLoadRange(set.getFloat("radius")); checkParent(buildouts, obj, set.getString("building_name"), set.getInt("cell_id")); - objects.put(obj.getObjectId(), obj); - return obj; + buildouts.put(obj.getObjectId(), obj); } catch (NullPointerException e) { Log.e(this, "File: %s", set.getString("template")); - return null; } } @@ -367,7 +355,7 @@ public class ClientBuildoutService extends Service { return areas.containsKey(creationData.areaId); } - public SWGObject createObject() { + public void createObject() { SWGObject obj = ObjectCreator.createObjectFromTemplate(creationData.id, strings.getString(creationData.templateCrc)); obj.setClassification(creationData.snapshot ? ObjectClassification.SNAPSHOT : ObjectClassification.BUILDOUT); obj.setPrefLoadRange(creationData.radius); @@ -375,7 +363,6 @@ public class ClientBuildoutService extends Service { setCellNumber(obj); setContainer(obj); objects.put(obj.getObjectId(), obj); - return obj; } private void setObjectLocation(SWGObject obj) { diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 9ce9939f4..d5ba7a1d6 100644 --- a/src/services/objects/ObjectManager.java +++ b/src/services/objects/ObjectManager.java @@ -109,6 +109,11 @@ public class ObjectManager extends Manager { synchronized (database) { database.traverse((obj) -> loadObject(obj)); } + synchronized (objectMap) { + for (SWGObject obj : objectMap.values()) { + new ObjectCreatedIntent(obj).broadcast(); + } + } return super.initialize(); } @@ -140,7 +145,7 @@ public class ObjectManager extends Manager { } private void addChildrenObjects(SWGObject obj) { - new ObjectCreatedIntent(obj).broadcast(); + putObject(obj); for (SWGObject child : obj.getSlots().values()) { if (child != null) addChildrenObjects(child);