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 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) { 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); } 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 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(); } + } 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()); 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(); diff --git a/src/services/group/GroupService.java b/src/services/group/GroupService.java index 100ec4099..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 @@ -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) diff --git a/src/services/objects/ClientBuildoutService.java b/src/services/objects/ClientBuildoutService.java index e4ef47d4a..adfd047d5 100644 --- a/src/services/objects/ClientBuildoutService.java +++ b/src/services/objects/ClientBuildoutService.java @@ -27,12 +27,16 @@ ***********************************************************************************/ 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.HashSet; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Locale; @@ -60,17 +64,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 = ?"; @@ -102,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 { @@ -111,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; @@ -121,92 +114,60 @@ 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 Hashtable<>(115000); + try (CrcDatabase strings = new CrcDatabase()) { + strings.loadStrings(); + try (BuildoutLoader loader = new BuildoutLoader(areasById, objects, strings, new File("serverdata/buildout/objects.sdb"))) { + while (loader.loadNextEntry()) { + if (!loader.isValidNextEntry()) + continue; + loader.createObject(); + } + } + addAdditionalObjects(strings, objects); + } + return objects; + } + + private Map loadObjects(int areaId) throws SQLException { Map objects = new Hashtable<>(); 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.isAreaId(areaId)) + continue; + loader.createObject(); } } } - List ret = new ArrayList<>(objects.values()); - ret.addAll(getAdditionalObjects(objects)); - return ret; + return objects; } - private Collection loadObjects(int areaId) throws SQLException { - Map objects = new Hashtable<>(); - 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); + 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 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()) { - 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(objects, buildouts, set); - } - } - } - } - 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 { + private void createAdditionalObject(Map buildouts, ResultSet set) throws SQLException { try { SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getString("template")); Location l = new Location(); @@ -219,7 +180,7 @@ 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); + buildouts.put(obj.getObjectId(), obj); } catch (NullPointerException e) { Log.e(this, "File: %s", set.getString("template")); } @@ -257,16 +218,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 +310,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 void 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); + objects.put(obj.getObjectId(), 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 +508,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"); - } - - } - } 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()); diff --git a/src/services/objects/ObjectManager.java b/src/services/objects/ObjectManager.java index 4b7fd3d45..d5ba7a1d6 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,16 +101,19 @@ 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)); } + synchronized (objectMap) { + for (SWGObject obj : objectMap.values()) { + new ObjectCreatedIntent(obj).broadcast(); + } + } return super.initialize(); } @@ -143,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); 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());