diff --git a/src/services/spawn/StaticService.java b/src/services/spawn/StaticService.java index 0dadcc21..ead254a1 100644 --- a/src/services/spawn/StaticService.java +++ b/src/services/spawn/StaticService.java @@ -29,9 +29,14 @@ package services.spawn; import intents.object.ObjectCreatedIntent; +import java.lang.ref.SoftReference; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import resources.Location; import resources.control.Intent; @@ -41,26 +46,26 @@ import resources.objects.building.BuildingObject; import resources.server_info.Log; import resources.server_info.RelationalServerData; import resources.server_info.RelationalServerFactory; -import services.objects.ObjectManager; +import services.objects.ObjectCreator; public class StaticService extends Service { private static final String GET_SUPPORTING_SQL = "SELECT spawns.* FROM spawns, types WHERE types.iff = ? AND spawns.iff_type = types.iff_type"; private final Object databaseMutex; - private final ObjectManager objectManager; + private final Map>> spawnableObjects; private RelationalServerData spawnDatabase; private PreparedStatement getSupportingStatement; - public StaticService(ObjectManager objectManager) { + public StaticService() { this.databaseMutex = new Object(); - this.objectManager = objectManager; spawnDatabase = RelationalServerFactory.getServerData("static/spawns.db", "spawns", "types"); if (spawnDatabase == null) throw new main.ProjectSWG.CoreException("Unable to load sdb files for StaticService"); getSupportingStatement = spawnDatabase.prepareStatement(GET_SUPPORTING_SQL); + spawnableObjects = new HashMap<>(); registerForIntent(ObjectCreatedIntent.TYPE); } @@ -76,47 +81,88 @@ public class StaticService extends Service { } private void createSupportingObjects(SWGObject object) { + List objects = null; + synchronized (spawnableObjects) { + SoftReference> ref = spawnableObjects.get(object.getTemplate()); + if (ref != null) + objects = ref.get(); + if (objects == null) { + objects = fetchFromDatabase(object.getTemplate()); + spawnableObjects.put(object.getTemplate(), new SoftReference>(objects)); + } + } + Location world = object.getWorldLocation(); + for (SpawnedObject spawn : objects) { + spawn.createObject(object, world); + } + } + + private List fetchFromDatabase(String template) { + List objects = new ArrayList<>(); synchronized (databaseMutex) { try { - getSupportingStatement.setString(1, object.getTemplate()); + getSupportingStatement.setString(1, template); try (ResultSet set = getSupportingStatement.executeQuery()) { - Location world = object.getWorldLocation(); while (set.next()) { - String iff = set.getString("child_iff"); - String cell = set.getString("cell"); - double x = set.getDouble("x"); - double y = set.getDouble("y"); - double z = set.getDouble("z"); - double heading = set.getDouble("heading"); - if (cell.isEmpty()) { - createObject(iff, world, x, y, z, heading); - } else if (object instanceof BuildingObject) { - BuildingObject buio = (BuildingObject) object; - createObject(iff, buio.getCellByName(cell), x, y, z, heading); - } else { - Log.e("StaticService", "Parent object with cell specified is not a BuildingObject!"); - } + objects.add(new SpawnedObject(set)); } } } catch (SQLException e) { e.printStackTrace(); } } + return objects; } - private SWGObject createObject(String iff, SWGObject parent, double x, double y, double z, double heading) { - if (parent == null) - return null; - Location loc = new Location(x, y, z, parent.getTerrain()); - loc.setHeading(heading); - return objectManager.createObject(parent, iff, loc, false); - } - - private SWGObject createObject(String iff, Location parentLoc, double x, double y, double z, double heading) { - Location loc = new Location(x, y, z, parentLoc.getTerrain()); - loc.setHeading(heading); - loc.translateLocation(parentLoc); - return objectManager.createObject(iff, loc, false); + private static class SpawnedObject { + + private final String iff; + private final String cell; + private final double x; + private final double y; + private final double z; + private final double heading; + + public SpawnedObject(ResultSet set) throws SQLException { + this.iff = set.getString("child_iff"); + this.cell = set.getString("cell"); + this.x = set.getDouble("x"); + this.y = set.getDouble("y"); + this.z = set.getDouble("z"); + this.heading = set.getDouble("heading"); + } + + public void createObject(SWGObject building, Location parentLocation) { + if (cell.isEmpty()) + createObject(parentLocation); + else if (building instanceof BuildingObject) + createObjectInParent(((BuildingObject) building).getCellByName(cell)); + else + Log.e("StaticService", "Parent object with cell specified is not a BuildingObject!"); + } + + private SWGObject createObjectInParent(SWGObject parent) { + if (parent == null) + return null; + Location loc = new Location(x, y, z, parent.getTerrain()); + loc.setHeading(heading); + SWGObject obj = ObjectCreator.createObjectFromTemplate(iff); + obj.setParent(parent); + obj.setLocation(loc); + new ObjectCreatedIntent(obj).broadcast(); + return obj; + } + + private SWGObject createObject(Location parentLocation) { + Location loc = new Location(x, y, z, parentLocation.getTerrain()); + loc.setHeading(heading); + loc.translateLocation(parentLocation); + SWGObject obj = ObjectCreator.createObjectFromTemplate(iff); + obj.setLocation(loc); + new ObjectCreatedIntent(obj).broadcast(); + return obj; + } + } }