Buildout overhaul

This commit is contained in:
Obique
2018-09-01 17:17:06 -05:00
parent 95dab44489
commit eb137e110c
33 changed files with 102452 additions and 105150 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,4 +25,4 @@ tansarii dungeon1 du1_npe_dungeon hangarbay1 76.70 0.80 55.70 5
heroic_ek dungeon1 du1_heroic_ek r1 -11.70 0.20 -116.50 5
heroic_isd dungeon1 du1_heroic_isd mainhangar 0.10 172.30 326.30 5
nova_orion dungeon1 du1_nova_orion hangarbay1 76.70 0.80 55.70 5
dev_area dev_area 3525 4 -4807 5
dev_area dev_area 3525 4 -4807 5

View File

@@ -1,117 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.data.server_info.loader;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
import com.projectswg.holocore.resources.support.objects.buildout.BuildoutArea;
import com.projectswg.holocore.resources.support.objects.buildout.BuildoutArea.BuildoutAreaBuilder;
import me.joshlarson.jlcommon.log.Log;
import java.io.File;
import java.io.IOException;
import java.util.*;
public final class AreaLoader {
private final Map<String, BuildoutArea> areasByName;
private final Map<Integer, BuildoutArea> areasById;
private final List<BuildoutArea> areaList;
private final Collection<String> events;
private AreaLoader(Collection<String> events) {
this.areasByName = new HashMap<>();
this.areasById = new HashMap<>();
this.areaList = new ArrayList<>();
this.events = events;
}
public BuildoutArea getArea(String areaName) {
return areasByName.get(areaName);
}
public BuildoutArea getArea(int areaId) {
return areasById.get(areaId);
}
public List<BuildoutArea> getAreaList() {
return areaList;
}
public Map<String, BuildoutArea> getAreasByName() {
return areasByName;
}
public Map<Integer, BuildoutArea> getAreasById() {
return areasById;
}
private void loadFromFile() {
BuildoutArea area;
try (SdbResultSet set = SdbLoader.load(new File("serverdata/buildout/areas.sdb"))) {
while (set.next()) {
area = new BuildoutAreaBuilder()
.setId((int) set.getInt(0))
.setTerrain(Terrain.getTerrainFromName(set.getText(1)))
.setName(set.getText(2))
.setEvent(set.getText(3))
.setX1(set.getReal(4))
.setZ1(set.getReal(5))
.setX2(set.getReal(6))
.setZ2(set.getReal(7))
.setAdjustCoordinates(set.getInt(8) != 0)
.setTranslationX(set.getReal(9))
.setTranslationX(set.getReal(10))
.build();
BuildoutArea replaced = areasByName.get(area.getName());
if ((replaced == null && area.getEvent().isEmpty()) || (!area.getEvent().isEmpty() && events.contains(area.getEvent()))) {
areasByName.put(area.getName(), area);
areasById.put(area.getId(), area);
areaList.add(area);
}
}
} catch (IOException e) {
Log.e(e);
}
}
static AreaLoader load() {
return load(Collections.emptySet());
}
static AreaLoader load(String ... events) {
return load(Arrays.asList(events));
}
static AreaLoader load(Collection<String> events) {
AreaLoader loader = new AreaLoader(events);
loader.loadFromFile();
return loader;
}
}

View File

@@ -31,10 +31,8 @@ import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildingLoader.BuildingLoaderInfo;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.ObjectCreator.ObjectCreationException;
import com.projectswg.holocore.resources.support.objects.buildout.BuildoutArea;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
@@ -42,22 +40,22 @@ import me.joshlarson.jlcommon.log.Log;
import java.io.File;
import java.io.IOException;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
public final class BuildoutLoader {
private static final CrcDatabase CRC_DATABASE = CrcDatabase.getInstance();
private final Map<Long, SWGObject> objectMap;
private final Map<String, BuildingObject> buildingMap;
private final EnumMap<Terrain, Map<Long, SWGObject>> terrainMap;
private final AreaLoader areaLoader;
private final Set<String> events;
private BuildoutLoader(AreaLoader areaLoader) {
private BuildoutLoader(Collection<String> events) {
this.objectMap = new HashMap<>();
this.buildingMap = new HashMap<>();
this.terrainMap = new EnumMap<>(Terrain.class);
this.areaLoader = areaLoader;
this.events = new HashSet<>(events);
for (Terrain terrain : Terrain.values()) {
terrainMap.put(terrain, new HashMap<>());
@@ -65,7 +63,11 @@ public final class BuildoutLoader {
}
public Map<Long, SWGObject> getObjects() {
return objectMap;
return Collections.unmodifiableMap(objectMap);
}
public Map<String, BuildingObject> getBuildings() {
return Collections.unmodifiableMap(buildingMap);
}
public Map<Long, SWGObject> getObjects(Terrain terrain) {
@@ -78,32 +80,29 @@ public final class BuildoutLoader {
}
private void loadStandardBuildouts() {
int areaId;
AreaLoader areaLoader = this.areaLoader;
BuildoutArea currentArea = areaLoader.getAreaList().get(0);
Set<String> events = this.events;
try (SdbResultSet set = SdbLoader.load(new File("serverdata/buildout/objects.sdb"))) {
while (set.next()) {
areaId = (int) set.getInt(1);
if (currentArea.getId() != areaId) {
BuildoutArea area = areaLoader.getArea(areaId);
if (area == null) { // usually for events
continue;
}
currentArea = area;
}
// "id", "template_crc", "container_id", "event", "terrain", "x", "y", "z", "orientation_x", "orientation_y", "orientation_z", "orientation_w", "cell_index", "tag"
String event = set.getText(3);
if (!event.isEmpty() && !events.contains(event))
continue;
SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getInt(0), CRC_DATABASE.getString((int) set.getInt(2)));
SWGObject obj = ObjectCreator.createObjectFromTemplate(set.getInt(0), CRC_DATABASE.getString((int) set.getInt(1)));
obj.setGenerated(false);
obj.setLocation(Location.builder().setPosition(set.getReal(4), set.getReal(5), set.getReal(6)).setOrientation(set.getReal(7), set.getReal(8), set.getReal(9), set.getReal(10))
.setTerrain(currentArea.getTerrain()).build());
obj.setLocation(Location.builder().setPosition(set.getReal(5), set.getReal(6), set.getReal(7)).setOrientation(set.getReal(8), set.getReal(9), set.getReal(10), set.getReal(11))
.setTerrain(Terrain.valueOf(set.getText(4))).build());
obj.setBuildoutTag(set.getText(13));
if (set.getInt(12) != 0) {
BuildingObject building = (BuildingObject) objectMap.get(set.getInt(3));
BuildingObject building = (BuildingObject) objectMap.get(set.getInt(2));
CellObject cell = building.getCellByNumber((int) set.getInt(12));
obj.systemMove(cell);
} else if (obj instanceof BuildingObject) {
((BuildingObject) obj).populateCells();
for (SWGObject cell : obj.getContainedObjects())
objectMap.put(cell.getObjectId(), cell);
if (!obj.getBuildoutTag().isEmpty())
buildingMap.put(obj.getBuildoutTag(), (BuildingObject) obj);
}
objectMap.put(set.getInt(0), obj);
}
@@ -144,25 +143,15 @@ public final class BuildoutLoader {
}
private void checkParent(SWGObject obj, String buildingName, int cellId) {
BuildingLoaderInfo building = DataLoader.buildings().getBuilding(buildingName);
if (buildingName.endsWith("_world"))
return;
BuildingObject building = buildingMap.get(buildingName);
if (building == null) {
Log.e("Building not found in map: %s", buildingName);
return;
}
long buildingId = building.getId();
if (buildingId == 0)
return; // World
SWGObject buildingUncasted = objectMap.get(buildingId);
if (buildingUncasted == null) {
Log.e("Building not found in map: %s", buildingName);
return;
}
if (!(buildingUncasted instanceof BuildingObject)) {
Log.e("Building is not an instance of BuildingObject: %s", buildingName);
return;
}
CellObject cell = ((BuildingObject) buildingUncasted).getCellByNumber(cellId);
CellObject cell = building.getCellByNumber(cellId);
if (cell == null) {
Log.e("Cell is not found! Building: %s Cell: %d", buildingName, cellId);
return;
@@ -170,8 +159,8 @@ public final class BuildoutLoader {
obj.systemMove(cell);
}
static BuildoutLoader load(AreaLoader areaLoader) {
BuildoutLoader loader = new BuildoutLoader(areaLoader);
static BuildoutLoader load(Collection<String> events) {
BuildoutLoader loader = new BuildoutLoader(events);
loader.loadFromFile();
return loader;
}

View File

@@ -9,7 +9,6 @@ import java.util.function.Supplier;
enum CachedLoader {
BUILDING_CELLS (BuildingCellLoader::new),
BUILDOUT_BUILDINGS (BuildingLoader::new),
NPC_LOADER (NpcLoader::new),
NPC_PATROL_ROUTES (NpcPatrolRouteLoader::new),
NPC_STATS (NpcStatLoader::new),
@@ -18,7 +17,8 @@ enum CachedLoader {
STATIC_SPAWNS (NpcStaticSpawnLoader::new),
OBJECT_DATA (ObjectDataLoader::new),
COMMANDS (CommandLoader::new),
SLOT_DEFINITIONS (SlotDefinitionLoader::new);
SLOT_DEFINITIONS (SlotDefinitionLoader::new),
ZONE_INSERTIONS (TerrainZoneInsertionLoader::new);
private final AtomicReference<SoftReference<DataLoader>> cachedLoader;
private final Supplier<DataLoader> supplier;

View File

@@ -2,6 +2,7 @@ package com.projectswg.holocore.resources.support.data.server_info.loader;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
public abstract class DataLoader {
@@ -18,19 +19,15 @@ public abstract class DataLoader {
}
public static BuildoutLoader buildouts() {
return BuildoutLoader.load(AreaLoader.load());
return BuildoutLoader.load(List.of());
}
public static BuildoutLoader buildouts(String ... events) {
return BuildoutLoader.load(AreaLoader.load(events));
return BuildoutLoader.load(List.of(events));
}
public static BuildoutLoader buildouts(Collection<String> events) {
return BuildoutLoader.load(AreaLoader.load(events));
}
public static BuildingLoader buildings() {
return (BuildingLoader) CachedLoader.BUILDOUT_BUILDINGS.load();
return BuildoutLoader.load(events);
}
public static BuildingCellLoader buildingCells() {
@@ -73,4 +70,8 @@ public abstract class DataLoader {
return (SlotDefinitionLoader) CachedLoader.SLOT_DEFINITIONS.load();
}
public static TerrainZoneInsertionLoader zoneInsertions() {
return (TerrainZoneInsertionLoader) CachedLoader.ZONE_INSERTIONS.load();
}
}

View File

@@ -26,6 +26,7 @@
***********************************************************************************/
package com.projectswg.holocore.resources.support.data.server_info.loader;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
import com.projectswg.holocore.resources.support.objects.swg.custom.AIBehavior;
@@ -65,6 +66,7 @@ public final class NpcStaticSpawnLoader extends DataLoader {
public static class StaticSpawnInfo {
private final int id;
private final Terrain terrain;
private final double x;
private final double y;
private final double z;
@@ -84,6 +86,7 @@ public final class NpcStaticSpawnLoader extends DataLoader {
private StaticSpawnInfo(SdbResultSet set) {
this.id = (int) set.getInt("spawn_id");
this.terrain = Terrain.valueOf(set.getText("terrain"));
this.x = set.getReal("x");
this.y = set.getReal("y");
this.z = set.getReal("z");
@@ -107,6 +110,10 @@ public final class NpcStaticSpawnLoader extends DataLoader {
return id;
}
public Terrain getTerrain() {
return terrain;
}
public double getX() {
return x;
}

View File

@@ -36,14 +36,14 @@ import java.util.Map;
public final class SlotDefinitionLoader extends DataLoader {
private final Map<String, SlotDefinition> buildingMap;
private final Map<String, SlotDefinition> slotDefinitions;
SlotDefinitionLoader() {
this.buildingMap = new HashMap<>();
this.slotDefinitions = new HashMap<>();
}
public SlotDefinition getSlotDefinition(String slotName) {
return buildingMap.get(slotName);
return slotDefinitions.get(slotName);
}
@Override
@@ -51,7 +51,7 @@ public final class SlotDefinitionLoader extends DataLoader {
try (SdbResultSet set = SdbLoader.load(new File("serverdata/abstract/slot_definitions.sdb"))) {
while (set.next()) {
SlotDefinition def = new SlotDefinition(set);
buildingMap.put(def.getName(), def);
slotDefinitions.put(def.getName(), def);
}
}
}

View File

@@ -24,6 +24,7 @@
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.data.server_info.loader;
import com.projectswg.common.data.location.Terrain;
@@ -33,46 +34,55 @@ import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbR
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public final class BuildingLoader extends DataLoader {
public class TerrainZoneInsertionLoader extends DataLoader {
private final Map<String, BuildingLoaderInfo> buildingMap;
private final Map<String, ZoneInsertion> zoneInsertions;
BuildingLoader() {
this.buildingMap = new HashMap<>();
TerrainZoneInsertionLoader() {
this.zoneInsertions = new HashMap<>();
}
public BuildingLoaderInfo getBuilding(String buildingName) {
return buildingMap.get(buildingName);
public ZoneInsertion getInsertion(String id) {
return zoneInsertions.get(id);
}
@Override
public final void load() throws IOException {
try (SdbResultSet set = SdbLoader.load(new File("serverdata/building/buildings.sdb"))) {
try (SdbResultSet set = SdbLoader.load(new File("serverdata/player/player_spawns.sdb"))) {
while (set.next()) {
buildingMap.put(set.getText(0), new BuildingLoaderInfo(set));
ZoneInsertion def = new ZoneInsertion(set);
zoneInsertions.put(def.getId(), def);
}
}
}
public static class BuildingLoaderInfo {
public static class ZoneInsertion {
private final String name;
private final long id;
private final String id;
private final Terrain terrain;
private final String buildingId;
private final String cell;
private final double x;
private final double y;
private final double z;
private final double radius;
public BuildingLoaderInfo(SdbResultSet set) {
this.name = set.getText(0).intern();
this.id = set.getInt(2);
this.terrain = Terrain.valueOf(set.getText(1));
private ZoneInsertion(SdbResultSet set) {
// id terrain building_id cell x y z radius
this.id = set.getText("id");
this.terrain = Terrain.valueOf(set.getText("terrain").toUpperCase(Locale.US));
this.buildingId = set.getText("building_id");
this.cell = set.getText("cell");
this.x = set.getReal("x");
this.y = set.getReal("y");
this.z = set.getReal("z");
this.radius = set.getReal("radius");
}
public String getName() {
return name;
}
public long getId() {
public String getId() {
return id;
}
@@ -80,6 +90,40 @@ public final class BuildingLoader extends DataLoader {
return terrain;
}
public String getBuildingId() {
return buildingId;
}
public String getCell() {
return cell;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public double getRadius() {
return radius;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof ZoneInsertion && ((ZoneInsertion) o).id.equals(id);
}
}
}

View File

@@ -28,15 +28,13 @@ package com.projectswg.holocore.resources.support.global.commands.callbacks.admi
import com.projectswg.common.data.location.Location;
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildingLoader.BuildingLoaderInfo;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.global.commands.ICmdCallback;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.Portal;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.ObjectLookup;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.BuildingLookup;
import me.joshlarson.jlcommon.log.Log;
import org.jetbrains.annotations.NotNull;
@@ -52,7 +50,7 @@ public class CmdGoto implements ICmdCallback {
String [] parts = args.split(" ");
if (parts.length == 0 || parts[0].trim().isEmpty())
return;
BuildingLoaderInfo building = DataLoader.buildings().getBuilding(parts[0].trim());
BuildingObject building = BuildingLookup.getBuildingByTag(parts[0].trim());
if (building == null) {
SystemMessageIntent.broadcastPersonal(player, "Unknown building: " + parts[0]);
return;
@@ -69,16 +67,10 @@ public class CmdGoto implements ICmdCallback {
new SystemMessageIntent(player, err).broadcast();
}
private String teleportToGoto(SWGObject obj, BuildingLoaderInfo building, int cellNumber) {
SWGObject parent = ObjectLookup.getObjectById(building.getId());
if (!(parent instanceof BuildingObject)) {
String err = String.format("Invalid parent! Either null or not a building: %s BUID: %d", parent, building.getId());
Log.e(err);
return err;
}
CellObject cell = ((BuildingObject) parent).getCellByNumber(cellNumber);
private String teleportToGoto(SWGObject obj, BuildingObject building, int cellNumber) {
CellObject cell = building.getCellByNumber(cellNumber);
if (cell == null) {
String err = String.format("Building '%s' does not have cell %d", building.getName(), cellNumber);
String err = String.format("Building '%s' does not have cell %d", building, cellNumber);
Log.e(err);
return err;
}
@@ -91,7 +83,7 @@ public class CmdGoto implements ICmdCallback {
z = (portal.getFrame1().getZ() + portal.getFrame2().getZ()) / 2;
}
obj.moveToContainer(cell, Location.builder().setPosition(x, y, z).setTerrain(building.getTerrain()).build());
return "Successfully teleported "+obj.getObjectName()+" to "+building.getId();
return "Successfully teleported "+obj.getObjectName()+" to "+building.getBuildoutTag();
}
}

View File

@@ -1,91 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.global.zone;
import com.projectswg.common.data.info.RelationalServerData;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Location.LocationBuilder;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.holocore.ProjectSWG;
import me.joshlarson.jlcommon.log.Log;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TerrainZoneInsertion {
private final RelationalServerData insertions;
public TerrainZoneInsertion() {
insertions = RelationalServerFactory.getServerData("player/player_spawns.db", "building/buildings", "player_spawns");
if (insertions == null)
throw new ProjectSWG.CoreException("Failed to load SDBs for TerrainZoneInsertion");
}
public SpawnInformation generateSpawnLocation(String id) {
final String whereClause = "(player_spawns.id = ?) AND (player_spawns.building_id = '' OR buildings.building_id = player_spawns.building_id)";
try (ResultSet set = insertions.selectFromTable("player_spawns, buildings", new String[]{"player_spawns.*", "buildings.object_id"}, whereClause, id)) {
if (!set.next())
return null;
String building = set.getString("building_id");
Location l = generateRandomLocation(Terrain.getTerrainFromName(set.getString("terrain")), set.getDouble("x"), set.getDouble("y"), set.getDouble("z"), set.getDouble("radius"));
return new SpawnInformation(!building.isEmpty(), l, set.getLong("object_id"), set.getString("cell"));
} catch (SQLException e) {
Log.e(e);
}
return null;
}
private static Location generateRandomLocation(Terrain terrain, double x, double y, double z, double delta) {
LocationBuilder location = Location.builder();
location.setTerrain(terrain);
location.setX(x + (Math.random()-.5) * delta);
location.setY(y);
location.setZ(z + (Math.random()-.5) * delta);
location.setOrientationX(0);
location.setOrientationY(0);
location.setOrientationZ(0);
location.setOrientationW(1);
return location.build();
}
public static class SpawnInformation {
public final boolean building;
public final Location location;
public final long buildingId;
public final String cell;
public SpawnInformation(boolean building, Location location, long buildingId, String cell) {
this.building = building;
this.location = location;
this.buildingId = buildingId;
this.cell = cell;
}
}
}

View File

@@ -29,13 +29,14 @@ package com.projectswg.holocore.resources.support.global.zone.creation;
import com.projectswg.common.data.customization.CustomizationString;
import com.projectswg.common.data.encodables.tangible.PvpFlag;
import com.projectswg.common.data.encodables.tangible.Race;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.ProfTemplateData;
import com.projectswg.common.network.packets.swg.login.creation.ClientCreateCharacter;
import com.projectswg.holocore.intents.gameplay.player.experience.skills.GrantSkillIntent;
import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent;
import com.projectswg.holocore.resources.support.data.server_info.loader.TerrainZoneInsertionLoader.ZoneInsertion;
import com.projectswg.holocore.resources.support.global.player.AccessLevel;
import com.projectswg.holocore.resources.support.global.zone.TerrainZoneInsertion.SpawnInformation;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
@@ -45,7 +46,7 @@ import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject
import com.projectswg.holocore.resources.support.objects.swg.tangible.TangibleObject;
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponObject;
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponType;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.ObjectLookup;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.BuildingLookup;
import me.joshlarson.jlcommon.utilities.Arguments;
import org.jetbrains.annotations.NotNull;
@@ -61,7 +62,7 @@ public class CharacterCreation {
this.create = create;
}
public CreatureObject createCharacter(AccessLevel accessLevel, SpawnInformation info) {
public CreatureObject createCharacter(AccessLevel accessLevel, ZoneInsertion info) {
Race race = Race.getRaceByFile(create.getRace());
CreatureObject creatureObj = createCreature(race.getFilename(), info);
PlayerObject playerObj = createPlayer(creatureObj);
@@ -76,26 +77,26 @@ public class CharacterCreation {
}
@NotNull
private CreatureObject createCreature(String template, SpawnInformation info) {
if (info.building)
private CreatureObject createCreature(String template, ZoneInsertion info) {
if (!info.getBuildingId().isEmpty())
return createCreatureBuilding(template, info);
SWGObject obj = ObjectCreator.createObjectFromTemplate(template);
assert obj instanceof CreatureObject;
obj.setLocation(info.location);
obj.setLocation(generateRandomLocation(info));
return (CreatureObject) obj;
}
@NotNull
private CreatureObject createCreatureBuilding(String template, SpawnInformation info) {
SWGObject parent = ObjectLookup.getObjectById(info.buildingId);
Arguments.validate(parent instanceof BuildingObject, String.format("Invalid parent! Either null or not a building: %s BUID: %d", parent, info.buildingId));
private CreatureObject createCreatureBuilding(String template, ZoneInsertion info) {
BuildingObject building = BuildingLookup.getBuildingByTag(info.getBuildingId());
Arguments.validate(building != null, String.format("Invalid building: %s", info.getBuildingId()));
CellObject cell = ((BuildingObject) parent).getCellByName(info.cell);
Arguments.validate(cell != null, String.format("Invalid cell! Cell does not exist: %s B-Template: %s BUID: %d", info.cell, parent.getTemplate(), info.buildingId));
CellObject cell = building.getCellByName(info.getCell());
Arguments.validate(cell != null, String.format("Invalid cell! Cell does not exist: %s Building: %s", info.getCell(), building));
SWGObject obj = ObjectCreator.createObjectFromTemplate(template);
assert obj instanceof CreatureObject;
obj.moveToContainer(cell, info.location);
obj.moveToContainer(cell, generateRandomLocation(info));
return (CreatureObject) obj;
}
@@ -178,4 +179,17 @@ public class CharacterCreation {
createDefaultObject(inventory, "object/tangible/npe/shared_npe_uniform_box.iff");
}
private static Location generateRandomLocation(ZoneInsertion info) {
return Location.builder()
.setTerrain(info.getTerrain())
.setX(info.getX() + (Math.random()-.5) * info.getRadius())
.setY(info.getY())
.setZ(info.getZ() + (Math.random()-.5) * info.getRadius())
.setOrientationX(0)
.setOrientationY(0)
.setOrientationZ(0)
.setOrientationW(1)
.build();
}
}

View File

@@ -28,7 +28,6 @@ package com.projectswg.holocore.resources.support.npc.spawn;
import com.projectswg.common.data.encodables.tangible.PvpFaction;
import com.projectswg.common.data.location.Location;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildingLoader.BuildingLoaderInfo;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.NpcLoader.*;
import com.projectswg.holocore.resources.support.data.server_info.loader.NpcPatrolRouteLoader.PatrolRouteWaypoint;
@@ -41,7 +40,7 @@ import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty;
import com.projectswg.holocore.resources.support.objects.swg.custom.AIBehavior;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.ObjectLookup;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.BuildingLookup;
import me.joshlarson.jlcommon.log.Log;
import org.jetbrains.annotations.NotNull;
@@ -69,10 +68,8 @@ public final class Spawner {
this.npcStat = DataLoader.npcStats().getNpcStats(npc.getCombatLevel());
Objects.requireNonNull(npcStat, "Invalid npc combat lebel: " + npc.getCombatLevel());
BuildingLoaderInfo building = DataLoader.buildings().getBuilding(spawn.getBuildingId());
Objects.requireNonNull(building, "Invalid building id: " + spawn.getBuildingId());
this.location = Location.builder()
.setTerrain(building.getTerrain())
.setTerrain(spawn.getTerrain())
.setPosition(spawn.getX(), spawn.getY(), spawn.getZ())
.setHeading(spawn.getHeading())
.build();
@@ -383,29 +380,18 @@ public final class Spawner {
}
private static SWGObject getPatrolWaypointParent(PatrolRouteWaypoint waypoint) {
if (waypoint.getBuildingId().isEmpty()) {
Log.w("PatrolRouteWaypoint: Undefined building id for patrol id: %d and group id: %d", waypoint.getPatrolId(), waypoint.getGroupId());
if (waypoint.getBuildingId().isEmpty() || waypoint.getBuildingId().endsWith("_world"))
return null;
}
BuildingLoaderInfo buildingInfo = DataLoader.buildings().getBuilding(waypoint.getBuildingId());
if (buildingInfo == null) {
BuildingObject building = BuildingLookup.getBuildingByTag(waypoint.getBuildingId());
if (building == null) {
Log.w("PatrolRouteWaypoint: Invalid building id for patrol id: %d and group id: %d", waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
if (buildingInfo.getId() == 0)
return null;
SWGObject building = ObjectLookup.getObjectById(buildingInfo.getId());
if (!(building instanceof BuildingObject)) {
Log.w("PatrolRouteWaypoint: Invalid building [%d] for patrol id: %d and group id: %d", buildingInfo.getId(), waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
SWGObject cell = ((BuildingObject) building).getCellByNumber(waypoint.getCellId());
SWGObject cell = building.getCellByNumber(waypoint.getCellId());
if (cell == null) {
Log.w("PatrolRouteWaypoint: Invalid cell [%d] for building: %d, patrol id: %d and group id: %d", waypoint.getCellId(), buildingInfo.getId(), waypoint.getPatrolId(), waypoint.getGroupId());
Log.w("PatrolRouteWaypoint: Invalid cell [%d] for building: %s, patrol id: %d and group id: %d", waypoint.getCellId(), waypoint.getBuildingId(), waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}

View File

@@ -61,7 +61,7 @@ import java.util.concurrent.atomic.AtomicLong;
public final class ObjectCreator {
private static final AtomicLong OBJECT_ID = new AtomicLong(0);
private static final AtomicLong OBJECT_ID = new AtomicLong(150000);
/*
Misc helper methods

View File

@@ -101,6 +101,8 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
private float complexity = 1;
private int containerType = 0;
private int areaId = -1;
private String buildoutEvent = "";
private String buildoutTag = "";
private int slotArrangement = -1;
private boolean observeWithParent = true;
private boolean generated = true;
@@ -556,6 +558,14 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
this.areaId = areaId;
}
public void setBuildoutEvent(String event) {
this.buildoutEvent = event;
}
public void setBuildoutTag(String tag) {
this.buildoutTag = tag;
}
public void setArrangement(List<List<String>> arrangement) {
this.arrangement = arrangement;
}
@@ -681,6 +691,14 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
return areaId;
}
public String getBuildoutEvent() {
return buildoutEvent;
}
public String getBuildoutTag() {
return buildoutTag;
}
public Object getServerAttribute(ServerAttribute key) {
return serverAttributes.get(key);
}

View File

@@ -357,9 +357,9 @@ public class CreatureObject extends TangibleObject {
public void setPosture(Posture posture) {
this.posture = posture;
sendDelta(3, 13, posture.getId());
if (isPlayer())
sendObservers(new PostureUpdate(getObjectId(), posture));
sendDelta(3, 13, posture.getId());
}
public void setRace(Race race) {

View File

@@ -89,11 +89,11 @@ public class AIObject extends CreatureObject {
return;
}
CreatureObject player = (CreatureObject) aware;
if (!player.isLoggedInPlayer() || player.getPosture() == Posture.INCAPACITATED || player.getPosture() == Posture.DEAD)
if (!player.isLoggedInPlayer())
return;
double distance = getLocation().flatDistanceTo(aware.getLocation());
NpcMode activeMode = this.activeMode;
if (distance <= 100) {
if (distance <= 100 && player.getPosture() != Posture.INCAPACITATED && player.getPosture() != Posture.DEAD) {
if (playersNearby.add(player)) {
if (activeMode != null)
activeMode.onPlayerEnterAware(player, distance);

View File

@@ -110,8 +110,8 @@ public class CombatDeathblowService extends Service {
}
private void incapacitatePlayer(CreatureObject incapacitator, CreatureObject incapacitated) {
incapacitated.setPosture(Posture.INCAPACITATED);
incapacitated.setCounter(INCAP_TIMER);
incapacitated.setPosture(Posture.INCAPACITATED);
StandardLog.onPlayerEvent(this, incapacitated, "was incapacitated by %s", incapacitator);

View File

@@ -4,6 +4,7 @@ import com.projectswg.holocore.intents.gameplay.combat.CreatureRevivedIntent;
import com.projectswg.holocore.intents.gameplay.combat.EnterCombatIntent;
import com.projectswg.holocore.intents.gameplay.combat.ExitCombatIntent;
import com.projectswg.holocore.intents.support.global.command.ExecuteCommandIntent;
import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent;
import com.projectswg.holocore.resources.support.global.commands.CombatCommand;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool;
@@ -35,8 +36,22 @@ public class CombatRegenerationService extends Service {
@Override
public boolean stop() {
executor.stop();
executor.awaitTermination(1000);
return true;
return executor.awaitTermination(1000);
}
@IntentHandler
private void handlePlayerEventIntent(PlayerEventIntent pei) {
CreatureObject creature = pei.getPlayer().getCreatureObject();
switch (pei.getEvent()) {
case PE_ZONE_IN_SERVER:
if (!creature.isInCombat()) {
startHealthRegeneration(creature);
startActionRegeneration(creature);
}
break;
default:
break;
}
}
@IntentHandler

View File

@@ -36,6 +36,7 @@ import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent;
import com.projectswg.holocore.resources.gameplay.combat.buff.BuffData;
import com.projectswg.holocore.resources.gameplay.combat.buff.BuffMap;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.swg.creature.Buff;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import me.joshlarson.jlcommon.concurrency.BasicScheduledThread;
@@ -286,7 +287,11 @@ public class BuffService extends Service {
// TODO stack counts upon add/remove need to be defined on a per-buff basis due to skillmod influence. Scripts might not be a bad idea.
int stackCount = 1;
int buffDuration = (int) buffData.getDefaultDuration();
Log.d("buff %s applied to %s from %s; applyTime: %d, buffDuration: %d", buffData.getName(), receiver.getObjectName(), buffer.getObjectName(), applyTime, buffDuration);
{
Player bufferPlayer = buffer.getOwner();
String bufferUsername = bufferPlayer == null ? "NULL" : bufferPlayer.getUsername();
StandardLog.onPlayerTrace(this, receiver, "received buff '%s' from %s/%s; applyTime: %d, buffDuration: %d", buffData.getName(), bufferUsername, buffer.getObjectName(), applyTime, buffDuration);
}
Buff buff = new Buff(buffData.getCrc(), applyTime + buffDuration, buffData.getEffectValue(0), buffDuration, buffer.getObjectId(), stackCount);
checkSkillMods(buffData, receiver, 1);

View File

@@ -20,7 +20,6 @@ import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent;
import com.projectswg.holocore.intents.support.objects.swg.DestroyObjectIntent;
import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.global.zone.sui.SuiButtons;
import com.projectswg.holocore.resources.support.global.zone.sui.SuiListBox;
@@ -29,7 +28,7 @@ import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.ObjectLookup;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.BuildingLookup;
import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
@@ -391,8 +390,7 @@ public class CloningService extends Service {
}
private static BuildingObject getDefaultCloner() {
long clonerId = DataLoader.buildings().getBuilding("tat_moseisley_cloning1").getId();
BuildingObject defaultCloner = (clonerId == 0) ? null : (BuildingObject) ObjectLookup.getObjectById(clonerId);
BuildingObject defaultCloner = BuildingLookup.getBuildingByTag("tat_moseisley_cloning1");
if (defaultCloner == null)
Log.e("No default cloner found with building id: 'tat_moseisley_cloning1'");

View File

@@ -39,13 +39,13 @@ import com.projectswg.holocore.intents.support.objects.swg.DestroyObjectIntent;
import com.projectswg.holocore.resources.support.data.config.ConfigFile;
import com.projectswg.holocore.resources.support.data.server_info.DataManager;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.TerrainZoneInsertionLoader.ZoneInsertion;
import com.projectswg.holocore.resources.support.data.server_info.mongodb.users.PswgUserDatabase;
import com.projectswg.holocore.resources.support.data.server_info.mongodb.users.PswgUserDatabase.CharacterMetadata;
import com.projectswg.holocore.resources.support.global.player.AccessLevel;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.global.player.PlayerState;
import com.projectswg.holocore.resources.support.global.zone.TerrainZoneInsertion;
import com.projectswg.holocore.resources.support.global.zone.TerrainZoneInsertion.SpawnInformation;
import com.projectswg.holocore.resources.support.global.zone.creation.CharacterCreation;
import com.projectswg.holocore.resources.support.global.zone.creation.CharacterCreationRestriction;
import com.projectswg.holocore.resources.support.global.zone.name_filter.NameFilter;
@@ -69,7 +69,6 @@ public class CharacterCreationService extends Service {
private final NameFilter nameFilter;
private final SWGNameGenerator nameGenerator;
private final CharacterCreationRestriction creationRestriction;
private final TerrainZoneInsertion insertion;
private final PswgUserDatabase userDatabase;
public CharacterCreationService() {
@@ -79,7 +78,6 @@ public class CharacterCreationService extends Service {
this.nameFilter = new NameFilter(getClass().getResourceAsStream("/namegen/bad_word_list.txt"), getClass().getResourceAsStream("/namegen/reserved_words.txt"), getClass().getResourceAsStream("/namegen/fiction_reserved.txt"));
this.nameGenerator = new SWGNameGenerator(nameFilter);
this.creationRestriction = new CharacterCreationRestriction(2);
this.insertion = new TerrainZoneInsertion();
this.userDatabase = new PswgUserDatabase();
}
@@ -270,7 +268,7 @@ public class CharacterCreationService extends Service {
private CreatureObject createCharacter(Player player, ClientCreateCharacter create) {
String spawnLocation = DataManager.getConfig(ConfigFile.PRIMARY).getString("PRIMARY-SPAWN-LOCATION", "tat_moseisley");
SpawnInformation info = insertion.generateSpawnLocation(spawnLocation);
ZoneInsertion info = DataLoader.zoneInsertions().getInsertion(spawnLocation);
if (info == null) {
Log.e("Failed to get spawn information for location: " + spawnLocation);
return null;

View File

@@ -32,7 +32,6 @@ import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent;
import com.projectswg.holocore.resources.support.data.config.ConfigFile;
import com.projectswg.holocore.resources.support.data.server_info.DataManager;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildingLoader.BuildingLoaderInfo;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.NpcPatrolRouteLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.NpcPatrolRouteLoader.PatrolRouteWaypoint;
@@ -45,7 +44,7 @@ import com.projectswg.holocore.resources.support.objects.permissions.AdminPermis
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.ObjectLookup;
import com.projectswg.holocore.services.support.objects.ObjectStorageService.BuildingLookup;
import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
@@ -118,33 +117,25 @@ public final class SpawnerService extends Service {
private static SWGObject createEgg(StaticSpawnInfo spawn) {
SpawnerType spawnerType = SpawnerType.valueOf(spawn.getSpawnerType());
BuildingLoaderInfo building = DataLoader.buildings().getBuilding(spawn.getBuildingId());
SWGObject egg = ObjectCreator.createObjectFromTemplate(spawnerType.getObjectTemplate());
egg.setContainerPermissions(AdminPermissions.getPermissions());
egg.systemMove(getCell(spawn.getId(), spawn.getCellId(), building), Location.builder().setTerrain(building.getTerrain()).setPosition(spawn.getX(), spawn.getY(), spawn.getZ()).setHeading(spawn.getHeading()).build());
egg.systemMove(getCell(spawn.getId(), spawn.getCellId(), spawn.getBuildingId()), Location.builder().setTerrain(spawn.getTerrain()).setPosition(spawn.getX(), spawn.getY(), spawn.getZ()).setHeading(spawn.getHeading()).build());
ObjectCreatedIntent.broadcast(egg);
return egg;
}
private static SWGObject getCell(int spawnId, int cellId, BuildingLoaderInfo buildingInfo) {
if (buildingInfo.getId() != 0 && cellId == 0) {
Log.e("No cell ID specified for spawner with ID %d", spawnId);
private static SWGObject getCell(int spawnId, int cellId, String buildingTag) {
if (buildingTag.isEmpty() || buildingTag.endsWith("_world"))
return null;
} else if (buildingInfo.getId() == 0) {
if (cellId != 0)
Log.w("Unnecessary cell ID specified for spawner with ID %d", spawnId);
return null; // No cell to find
}
SWGObject building = ObjectLookup.getObjectById(buildingInfo.getId());
if (!(building instanceof BuildingObject)) {
Log.w("Skipping spawner with ID %d - building_id %d didn't reference a BuildingObject!", spawnId, buildingInfo.getId());
BuildingObject building = BuildingLookup.getBuildingByTag(buildingTag);
if (building == null) {
Log.w("Skipping spawner with ID %d - building_id %s didn't reference a BuildingObject!", spawnId, buildingTag);
return null;
}
SWGObject cellObject = ((BuildingObject) building).getCellByNumber(cellId);
SWGObject cellObject = building.getCellByNumber(cellId);
if (cellObject == null) {
Log.e("Spawner with ID %d - building %d didn't have cell ID %d!", spawnId, buildingInfo.getId(), cellId);
Log.e("Spawner with ID %d - building %s didn't have cell ID %d!", spawnId, buildingTag, cellId);
}
return cellObject;
}
@@ -170,261 +161,22 @@ public final class SpawnerService extends Service {
}
private static SWGObject getPatrolWaypointParent(PatrolRouteWaypoint waypoint) {
if (waypoint.getBuildingId().isEmpty()) {
Log.w("PatrolRouteWaypoint: Undefined building id for patrol id: %d and group id: %d", waypoint.getPatrolId(), waypoint.getGroupId());
if (waypoint.getBuildingId().isEmpty() || waypoint.getBuildingId().endsWith("_world"))
return null;
BuildingObject building = BuildingLookup.getBuildingByTag(waypoint.getBuildingId());
if (building == null) {
Log.w("PatrolRouteWaypoint: Invalid building [%s] for patrol id: %d and group id: %d", waypoint.getBuildingId(), waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
BuildingLoaderInfo buildingInfo = DataLoader.buildings().getBuilding(waypoint.getBuildingId());
if (buildingInfo == null) {
Log.w("PatrolRouteWaypoint: Invalid building id for patrol id: %d and group id: %d", waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
if (buildingInfo.getId() == 0)
return null;
SWGObject building = ObjectLookup.getObjectById(buildingInfo.getId());
if (!(building instanceof BuildingObject)) {
Log.w("PatrolRouteWaypoint: Invalid building [%d] for patrol id: %d and group id: %d", buildingInfo.getId(), waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
SWGObject cell = ((BuildingObject) building).getCellByNumber(waypoint.getCellId());
SWGObject cell = building.getCellByNumber(waypoint.getCellId());
if (cell == null) {
Log.w("PatrolRouteWaypoint: Invalid cell [%d] for building: %d, patrol id: %d and group id: %d", waypoint.getCellId(), buildingInfo.getId(), waypoint.getPatrolId(), waypoint.getGroupId());
Log.w("PatrolRouteWaypoint: Invalid cell [%d] for building: %s, patrol id: %d and group id: %d", waypoint.getCellId(), waypoint.getBuildingId(), waypoint.getPatrolId(), waypoint.getGroupId());
return null;
}
return cell;
}
//
// private static class SpawnLoader {
//
// private final Consumer<Spawner> npcSpawner;
//
// // Loaders
// private BuildingLoader buildingLoader;
// private NpcStatLoader npcStatLoader;
// private NpcLoader npcLoader;
// private NpcStaticSpawnLoader npcStaticSpawnLoader;
// private NpcPatrolRouteLoader npcPatrolRouteLoader;
//
// // Spawn info
// private BuildingLoaderInfo building;
// private NpcInfo npc;
// private NpcStatInfo npcStat;
// private List<ResolvedPatrolWaypoint> waypoints;
//
// public SpawnLoader(Consumer<Spawner> npcSpawner) {
// this.npcSpawner = npcSpawner;
// this.buildingLoader = null;
// this.npcStatLoader = null;
// this.npcLoader = null;
// this.npcStaticSpawnLoader = null;
// this.npcPatrolRouteLoader = null;
//
// this.building = null;
// this.npc = null;
// this.npcStat = null;
// this.waypoints = null;
// }
//
// public void load() {
// buildingLoader = DataLoader.buildings();
// npcStatLoader = DataLoader.npcStats();
// npcLoader = DataLoader.npcs();
// npcStaticSpawnLoader = DataLoader.npcStaticSpawns();
// npcPatrolRouteLoader = DataLoader.npcPatrolRoutes();
//
// npcStaticSpawnLoader.iterate(this::loadStaticSpawn);
// }
//
// private void loadStaticSpawn(StaticSpawnInfo spawn) {
// building = buildingLoader.getBuilding(spawn.getBuildingId());
// if (building == null) {
// Log.e("Invalid entry for spawn id [%d] - unknown building: '%s'", spawn.getId(), spawn.getBuildingId());
// return;
// }
//
// npc = npcLoader.getNpc(spawn.getNpcId());
// if (npc == null) {
// Log.w("Invalid entry for spawn id [%d] - unknown NPC: '%s'", spawn.getId(), spawn.getNpcId());
// return;
// }
//
// npcStat = npcStatLoader.getNpcStats(npc.getCombatLevel());
// if (npcStat == null) {
// Log.w("Invalid entry for spawn id [%d], NPC id [%d] - unknown NPC stat for level: %d", spawn.getId(), npc.getId(), npc.getCombatLevel());
// return;
// }
//
// if (spawn.getPatrolId() < 1000) {
// waypoints = null;
// } else {
// waypoints = npcPatrolRouteLoader.getPatrolRoute(spawn.getPatrolId())
// .stream()
// .map(route -> new ResolvedPatrolWaypoint(getPatrolWaypointParent(route), getPatrolWaypointLocation(route), route.getDelay(), route.getPatrolType()))
// .collect(Collectors.toList());
// }
//
// loadSpawner(spawn);
// }
//
// private void loadSpawner(StaticSpawnInfo spawn) {
// Spawner spawner = new Spawner(spawn.getId());
// spawner.setCreatureId(npc.getId());
// spawner.setIffTemplates(createTemplateList(npc.getIff()));
// spawner.setCreatureName(npc.getName());
// spawner.setCombatLevel((short) npc.getCombatLevel());
// spawner.setSpawnerFlag(npc.getSpawnerFlag());
// spawner.setPatrolRoute(waypoints);
// spawner.setFormation(spawn.getPatrolFormation());
// spawner.setAttackSpeed(npc.getAttackSpeed());
// spawner.setMovementSpeed(npc.getMovementSpeed());
// setRespawnDelay(spawner, spawn);
// setDifficulty(spawner);
// setMoodAnimation(spawner, spawn);
// setAiBehavior(spawner, spawn);
// setLocation(spawner, spawn);
// setFaction(spawner);
// createEgg(spawner, spawn);
//
// for (int i = 0; i < spawn.getAmount(); i++) {
// npcSpawner.accept(spawner);
// }
// }
//
// private void createEgg(Spawner spawner, StaticSpawnInfo spawn) {
// SpawnerType spawnerType = SpawnerType.valueOf(spawn.getSpawnerType());
// SWGObject egg = ObjectCreator.createObjectFromTemplate(spawnerType.getObjectTemplate());
// egg.setContainerPermissions(ContainerPermissionsType.ADMIN);
// egg.setLocation(spawner.getLocation());
// egg.moveToContainer(getCell(spawner.getSpawnerId(), spawn.getCellId(), building));
// spawner.setSpawnerObject(egg);
// ObjectCreatedIntent.broadcast(egg);
// }
//
// private void setRespawnDelay(Spawner spawner, StaticSpawnInfo spawn) {
// int minRespawnDelay = spawn.getMinSpawnTime();
// int maxRespawnDelay = spawn.getMaxSpawnTime();
//
// if (minRespawnDelay > maxRespawnDelay) {
// Log.e("Spawner with ID %d has a minimum respawn time larger than the maximum respawn time", spawner.getSpawnerId());
// maxRespawnDelay = minRespawnDelay;
// }
// spawner.setMinRespawnDelay(minRespawnDelay);
// spawner.setMaxRespawnDelay(maxRespawnDelay);
// }
//
// private void setDifficulty(Spawner spawner) {
// char difficultyChar = npc.getDifficulty().charAt(0);
//
// CreatureDifficulty difficulty;
// DetailNpcStatInfo detailInfo; // undefined to trigger warnings if not defined below
// switch (difficultyChar) {
// default:
// Log.w("Unknown creature difficulty: %s", difficultyChar);
// case 'N':
// difficulty = CreatureDifficulty.NORMAL;
// detailInfo = npcStat.getNormalDetailStat();
// break;
// case 'E':
// difficulty = CreatureDifficulty.ELITE;
// detailInfo = npcStat.getEliteDetailStat();
// break;
// case 'B':
// difficulty = CreatureDifficulty.BOSS;
// detailInfo = npcStat.getBossDetailStat();
// break;
// }
// spawner.setMaxHealth(detailInfo.getHealth());
// spawner.setMaxAction(detailInfo.getAction());
// spawner.setCreatureDifficulty(difficulty);
// }
//
// private void setLocation(Spawner spawner, StaticSpawnInfo spawn) {
// Location loc = Location.builder()
// .setTerrain(building.getTerrain())
// .setPosition(spawn.getX(), spawn.getY(), spawn.getZ())
// .setHeading(spawn.getHeading())
// .build();
// spawner.setLocation(loc);
// }
//
// private void setFaction(Spawner spawner) {
// PvpFaction faction;
//
// switch (npc.getFaction()) {
// case "rebel": faction = PvpFaction.REBEL; break;
// case "imperial": faction = PvpFaction.IMPERIAL; break;
// default: return;
// }
//
// spawner.setFaction(faction, npc.isSpecForce());
// }
//
// private void setMoodAnimation(Spawner spawner, StaticSpawnInfo spawn) {
// String moodAnimation = spawn.getMood();
//
// if (moodAnimation.equals(IDLE_MOOD))
// moodAnimation = "neutral";
//
// spawner.setMoodAnimation(moodAnimation);
// }
//
// private void setAiBehavior(Spawner spawner, StaticSpawnInfo spawn) {
// AIBehavior aiBehavior = AIBehavior.valueOf(spawn.getBehavior());
// spawner.setAIBehavior(aiBehavior);
// if (aiBehavior == AIBehavior.LOITER) {
// spawner.setFloatRadius(spawn.getLoiterRadius());
// }
// }
//
// private SWGObject getCell(int spawnId, int cellId, BuildingLoaderInfo buildingInfo) {
// if (buildingInfo.getId() != 0 && cellId == 0) {
// Log.e("No cell ID specified for spawner with ID %d", spawnId);
// return null;
// } else if (buildingInfo.getId() == 0) {
// if (cellId != 0)
// Log.w("Unnecessary cell ID specified for spawner with ID %d", spawnId);
// return null; // No cell to find
// }
//
// SWGObject building = ObjectLookup.getObjectById(buildingInfo.getId());
// if (!(building instanceof BuildingObject)) {
// Log.w("Skipping spawner with ID %d - building_id %d didn't reference a BuildingObject!", spawnId, buildingInfo.getId());
// return null;
// }
//
// SWGObject cellObject = ((BuildingObject) building).getCellByNumber(cellId);
// if (cellObject == null) {
// Log.e("Spawner with ID %d - building %d didn't have cell ID %d!", spawnId, buildingInfo.getId(), cellId);
// }
// return cellObject;
// }
//
// private String [] createTemplateList(String templates) {
// int count = 0;
// int ind = -1;
// while (ind < templates.length()) {
// ind = templates.indexOf(';', ind + 1);
// count++;
// if (ind == -1)
// break;
// }
//
// ind = 0;
// String[] templateList = new String[count];
// for (int i = 0; i < count; i++) {
// int next = templates.indexOf(';', ind);
// if (next == -1)
// next = templates.length();
// templateList[i] = ClientFactory.formatToSharedFile("object/mobile/" + templates.substring(ind, next));
// ind = next + 1;
// }
// return templateList;
// }
//
// }
}

View File

@@ -11,6 +11,7 @@ import com.projectswg.holocore.resources.support.data.server_info.CachedObjectDa
import com.projectswg.holocore.resources.support.data.server_info.DataManager;
import com.projectswg.holocore.resources.support.data.server_info.ObjectDatabase;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildoutLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
@@ -21,10 +22,7 @@ import me.joshlarson.jlcommon.control.Service;
import me.joshlarson.jlcommon.log.Log;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -35,18 +33,21 @@ public class ObjectStorageService extends Service {
private final ObjectDatabase<SWGObject> database;
private final Map<Long, SWGObject> objectMap;
private final Map<Long, SWGObject> buildouts;
private final Map<String, BuildingObject> buildingLookup;
private final AtomicBoolean started;
public ObjectStorageService() {
this.database = new CachedObjectDatabase<>("odb/objects.db", SWGObjectFactory::create, SWGObjectFactory::save);
this.objectMap = new ConcurrentHashMap<>(256*1024, 0.8f, Runtime.getRuntime().availableProcessors());
this.buildouts = new ConcurrentHashMap<>(256*1024, 0.8f, 1);
this.buildingLookup = new HashMap<>();
this.started = new AtomicBoolean(false);
}
@Override
public boolean initialize() {
ObjectLookup.setObjectAuthority(this::getObjectById);
BuildingLookup.setBuildingAuthority(buildingLookup::get);
{
long startTime = StandardLog.onStartLoad("players");
@@ -59,8 +60,10 @@ public class ObjectStorageService extends Service {
{
long startTime = StandardLog.onStartLoad("client objects");
buildouts.putAll(DataLoader.buildouts(createEventList()).getObjects());
BuildoutLoader loader = DataLoader.buildouts(createEventList());
buildouts.putAll(loader.getObjects());
objectMap.putAll(buildouts);
buildingLookup.putAll(loader.getBuildings());
StandardLog.onEndLoad(buildouts.size(), "client objects", startTime);
}
return true;
@@ -206,4 +209,19 @@ public class ObjectStorageService extends Service {
}
public static class BuildingLookup {
private static final AtomicReference<Function<String, BuildingObject>> AUTHORITY = new AtomicReference<>(null);
static void setBuildingAuthority(Function<String, BuildingObject> authority) {
AUTHORITY.set(authority);
}
@Nullable
public static BuildingObject getBuildingByTag(String buildoutTag) {
return AUTHORITY.get().apply(buildoutTag);
}
}
}

View File

@@ -5,7 +5,7 @@ import com.projectswg.utility.clientdata.Converters;
public class ClientdataConvertSpecific {
public static void main(String [] args) {
Converters.OBJECTS_OBJECT_DATA.load();
Converters.BUILDOUT_OBJECTS.load();
}
}

View File

@@ -44,9 +44,10 @@ public class ConvertBuildingList implements Converter {
System.out.println("Converting building list...");
Collection<SWGObject> objects = DataLoader.buildouts().getObjects().values();
try (SdbGenerator gen = new SdbGenerator(new File("serverdata/building/buildings.sdb"))) {
gen.writeColumnNames("building_id", "terrain_name", "object_id", "iff", "building_name", "total_cells", "x", "y", "z");
gen.writeColumnNames("building_id", "terrain_name", "object_id");
for (SWGObject obj : objects) {
if (obj instanceof BuildingObject) {
String template = obj.getTemplate().substring(obj.getTemplate().lastIndexOf('/') + 1);
Terrain terrain = obj.getTerrain();
String name = terrain.name().charAt(0) + terrain.name().toLowerCase(Locale.US).substring(1);

View File

@@ -32,33 +32,45 @@ import com.projectswg.common.data.location.Quaternion;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import com.projectswg.holocore.utilities.SdbGenerator;
import com.projectswg.utility.clientdata.buildouts.BuildoutLoader;
import com.projectswg.utility.clientdata.buildouts.SnapshotLoader;
import com.projectswg.utility.clientdata.buildouts.SwgBuildoutArea;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicLong;
@SuppressWarnings({ "UseOfSystemOutOrSystemErr", "CallToPrintStackTrace" }) // Converter class that's not meant to be used by Holocore
public class ConvertBuildouts implements Converter{
private static final String [][] AREA_COLUMNS = {
{"id", "terrain", "area_name", "event", "min_x", "min_z", "max_x", "max_z", "adjust_coordinates", "translate_x", "translate_z"}
};
private static final String [][] OBJECT_COLUMNS = {
{"id", "area_id", "template_crc", "container_id", "x", "y", "z", "orientation_x", "orientation_y", "orientation_z", "orientation_w", "radius", "cell_index"}
{"id", "template_crc", "container_id", "event", "terrain", "x", "y", "z", "orientation_x", "orientation_y", "orientation_z", "orientation_w", "cell_index", "tag"}
};
private final List<GenBuildoutArea> areas;
private final List<GenBuildoutArea> fallbackAreas;
private final Map<Long, String> objectTagMap;
private final BuildoutLoader buildoutLoader;
private final SnapshotLoader snapshotLoader;
public ConvertBuildouts() {
this.areas = new ArrayList<>();
this.fallbackAreas = new ArrayList<>(Terrain.values().length);
this.objectTagMap = new HashMap<>();
AtomicLong objectIdGenerator = new AtomicLong(1);
AtomicLong cellIdGenerator = new AtomicLong(1000000);
this.buildoutLoader = new BuildoutLoader(objectIdGenerator, cellIdGenerator);
this.snapshotLoader = new SnapshotLoader(objectIdGenerator, cellIdGenerator);
int areaId = -1;
for (Terrain t : Terrain.values()) {
fallbackAreas.add(new GenBuildoutArea(null, t, -8196, -8196, 8196, 8196, areaId, false));
@@ -85,6 +97,11 @@ public class ConvertBuildouts implements Converter{
}
private void createObjects() throws IOException {
try (SdbResultSet set = SdbLoader.load(new File("serverdata/buildout/object_tag_map.sdb"))) {
while (set.next()) {
objectTagMap.put(set.getInt(1), set.getText(0));
}
}
System.out.println("Generating objects...");
List<SWGObject> objects = new LinkedList<>();
System.out.println(" Creating buildouts...");
@@ -96,70 +113,33 @@ public class ConvertBuildouts implements Converter{
}
private void createBuildouts(List <SWGObject> objects) {
BuildoutLoader loader = new BuildoutLoader();
loader.loadAllBuildouts();
for (Entry<String, List<SWGObject>> areaObjects : loader.getObjects().entrySet()) {
GenBuildoutArea area = null;
for (GenBuildoutArea a : areas) {
if (a.area.getName().equals(areaObjects.getKey())) {
area = a;
break;
}
}
if (area == null) {
System.err.println("Unknown area! Name: " + areaObjects.getKey());
continue;
}
for (SWGObject obj : areaObjects.getValue()) {
obj.setBuildoutAreaId(area.id);
addClientObject(objects, obj);
}
}
buildoutLoader.loadAllBuildouts();
objects.addAll(buildoutLoader.getObjects());
}
private void createSnapshots(List<SWGObject> objects) {
SnapshotLoader snapLoader = new SnapshotLoader();
snapLoader.loadAllSnapshots();
List<SWGObject> snapshots = new LinkedList<>();
for (SWGObject obj : snapLoader.getObjects()) {
addClientObject(snapshots, obj);
}
setSnapshotData(snapshots, objects);
}
private void setSnapshotData(List<SWGObject> snapshots, List<SWGObject> objects) {
for (SWGObject snap : snapshots) {
GenBuildoutArea area = getAreaForObject(snap);
snapshotLoader.loadAllSnapshots();
for (SWGObject snap : snapshotLoader.getObjects()) {
GenBuildoutArea area = fallbackAreas.stream().filter(a -> a.terrain.equals(snap.getTerrain())).findFirst().orElse(null);
if (area != null)
snap.setBuildoutAreaId(area.id);
else
System.err.println("No area for: " + snap.getObjectId() + " / " + snap.getTerrain());
objects.add(snap);
}
objects.addAll(snapshots);
}
private void generateObjectFile(List<SWGObject> objects) throws IOException {
isValidBuildoutAreas(objects);
try (SdbGenerator gen = new SdbGenerator(new File("serverdata/buildout/objects.sdb"))) {
gen.writeColumnNames(OBJECT_COLUMNS[0]);
int objNum = 0;
int percent = 0;
objects.sort((o1, o2) -> {
int comp;
comp = Integer.compare(o1.getBuildoutAreaId(), o2.getBuildoutAreaId());
if (comp != 0)
return comp;
comp = Long.compare(o1.getSuperParent() != null ? o1.getSuperParent().getObjectId() : o1.getObjectId(), o2.getSuperParent() != null ? o2.getSuperParent().getObjectId() : o2.getObjectId());
if (comp != 0)
return comp;
comp = Integer.compare(getBuildoutDepth(o1), getBuildoutDepth(o2));
if (comp != 0)
return comp;
return 0;
});
isValidBuildoutAreas(objects);
objects.sort(Comparator.comparingLong(SWGObject::getObjectId));
for (SWGObject obj : objects) {
if (obj instanceof CellObject)
continue;
writeObject(gen, obj);
while (percent / 100.0 * objects.size() <= objNum) {
System.out.print(".");
@@ -171,29 +151,24 @@ public class ConvertBuildouts implements Converter{
}
}
private int getBuildoutDepth(SWGObject object) {
if (object.getParent() == null)
return 0;
return getBuildoutDepth(object.getParent()) + 1;
}
private void addClientObject(List<SWGObject> objects, SWGObject obj) {
objects.add(obj);
for (SWGObject child : obj.getContainedObjects()) {
addClientObject(objects, child);
}
for (SWGObject child : obj.getSlots().values()) {
if (child != null)
addClientObject(objects, child);
}
}
private void writeAreas(SdbGenerator gen) throws IOException {
DatatableData table = (DatatableData) ClientFactory.getInfoFromFile("datatables/buildout/buildout_scenes.iff");
areas.clear();
for (int sceneRow = 0; sceneRow < table.getRowCount(); sceneRow++) {
Terrain t = Terrain.getTerrainFromName((String) table.getCell(sceneRow, 0));
getArea(t, sceneRow, (Boolean) table.getCell(sceneRow, 1));
{
DatatableData table = (DatatableData) ClientFactory.getInfoFromFile("datatables/buildout/buildout_scenes.iff");
int areaId = 1;
for (int sceneRow = 0; sceneRow < table.getRowCount(); sceneRow++) {
Terrain t = Terrain.getTerrainFromName((String) table.getCell(sceneRow, 0));
boolean adjust = (Boolean) table.getCell(sceneRow, 1);
String file = "datatables/buildout/areas_"+t.getName()+".iff";
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(file);
for (int row = 0; row < areaTable.getRowCount(); row++) {
SwgBuildoutArea area = new SwgBuildoutArea();
area.load(areaTable.getRow(row), sceneRow, row);
areas.add(new GenBuildoutArea(area, t, area.getX1(), area.getZ1(), area.getX2(), area.getZ2(), areaId, adjust));
areaId++;
}
}
}
Collections.sort(areas);
for (int i = fallbackAreas.size()-1; i >= 0; i--) {
@@ -217,16 +192,6 @@ public class ConvertBuildouts implements Converter{
System.out.println();
}
private void getArea(Terrain t, int sceneRow, boolean adjust) {
String file = "datatables/buildout/areas_"+t.getName()+".iff";
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(file);
for (int row = 0; row < areaTable.getRowCount(); row++) {
SwgBuildoutArea area = new SwgBuildoutArea();
area.load(areaTable.getRow(row), sceneRow, row);
areas.add(new GenBuildoutArea(area, t, area.getX1(), area.getZ1(), area.getX2(), area.getZ2(), sceneRow*100+row, adjust));
}
}
private void writeArea(SdbGenerator gen, GenBuildoutArea area, String substituteName) throws IOException {
if (substituteName == null)
substituteName = area.area.getName();
@@ -249,53 +214,28 @@ public class ConvertBuildouts implements Converter{
private void writeObject(SdbGenerator gen, SWGObject object) throws IOException {
long id = object.getObjectId();
long originalId = buildoutLoader.getPreviousId(id);
if (originalId == 0)
originalId = snapshotLoader.getPreviousId(id);
int crc = CRC.getCrc(object.getTemplate());
long container = (object.getParent() != null) ? object.getParent().getObjectId() : 0;
if (object.getParent() instanceof CellObject)
if (object.getParent() instanceof CellObject) {
assert object.getParent().getParent() != null;
container = object.getParent().getParent().getObjectId();
}
String event = object.getBuildoutEvent();
Location l = object.getLocation();
Quaternion q = l.getOrientation();
double radius = object.getLoadRange();
int cellIndex = (object.getParent() instanceof CellObject) ? ((CellObject) object.getParent()).getNumber() : 0;
Terrain terrain = l.getTerrain();
float x = (float) l.getX(), y = (float) l.getY(), z = (float) l.getZ();
float oX = (float) q.getX(), oY = (float) q.getY(), oZ = (float) q.getZ(), oW = (float) q.getW();
gen.writeLine(id, object.getBuildoutAreaId(), crc, container, x, y, z, oX, oY, oZ, oW, radius, cellIndex);
}
private GenBuildoutArea getAreaForObject(SWGObject obj) {
SWGObject superParent = obj.getSuperParent();
Location l = superParent == null ? obj.getLocation() : superParent.getLocation();
double x = l.getX();
double z = l.getZ();
int ind = Collections.binarySearch(areas, new GenBuildoutArea(null, obj.getTerrain(), x, z, x, z, 0, false), (area1, area2) -> {
int comp = area1.terrain.getName().compareTo(area2.terrain.getName());
if (comp != 0)
return comp;
if (area2.x1 < area1.x1)
return 1;
if (area2.x2 > area1.x2)
return -1;
if (area2.z1 < area1.z1)
return 1;
if (area2.z2 > area1.z2)
return -1;
return Integer.compare(area1.getSorting(), area2.getSorting());
});
if (ind < 0) {
for (GenBuildoutArea fallback : fallbackAreas) {
if (fallback.terrain == obj.getTerrain())
return fallback;
}
return null;
}
return areas.get(ind);
gen.writeLine(id, crc, container, event, terrain.name(), x, y, z, oX, oY, oZ, oW, cellIndex, objectTagMap.getOrDefault(originalId, ""));
}
private void isValidBuildoutAreas(List<SWGObject> objects) {
for (SWGObject obj : objects) {
GenBuildoutArea area = getAreaForObject(obj);
assert area != null : "no buildout area found for object: " + obj;
assert obj.getBuildoutAreaId() == area.id : "invalid buildout area for object " + obj;
assert fallbackAreas.stream().mapToInt(area -> area.id).anyMatch(id -> obj.getBuildoutAreaId() == id) || areas.stream().mapToInt(area -> area.id).anyMatch(id -> obj.getBuildoutAreaId() == id) : "no area found: " + obj.getBuildoutAreaId();
}
}
@@ -313,10 +253,7 @@ public class ConvertBuildouts implements Converter{
public GenBuildoutArea(SwgBuildoutArea area, Terrain terrain, double x1, double z1, double x2, double z2, int id, boolean adjust) {
this.area = area;
this.terrain = terrain;
if (area != null)
this.index = area.getIndex();
else
this.index = -1;
this.index = area != null ? area.getIndex() : -1;
this.x1 = (int) x1;
this.z1 = (int) z1;
this.x2 = (int) x2;
@@ -326,7 +263,7 @@ public class ConvertBuildouts implements Converter{
}
@Override
public int compareTo(GenBuildoutArea area) {
public int compareTo(@NotNull GenBuildoutArea area) {
int comp = Integer.compare(index, area.index);
if (comp != 0)
return comp;

View File

@@ -26,66 +26,99 @@
***********************************************************************************/
package com.projectswg.utility.clientdata.buildouts;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.CrcStringTableData;
import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import me.joshlarson.jlcommon.log.Log;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
public class BuildoutLoader {
private static final CrcStringTableData crcTable = (CrcStringTableData) ClientFactory.getInfoFromFile("misc/object_template_crc_string_table.iff");
private static final String BASE_PATH = "datatables/buildout/";
private final Map <Long, SWGObject> objectTable;
private final Map<String, List <SWGObject>> objects;
private final Map<Long, Long> idMapping;
private final Set<SWGObject> objects;
private final AtomicLong objectIdGenerator;
private final AtomicLong cellIdGenerator;
public BuildoutLoader() {
objectTable = new HashMap<>();
objects = new Hashtable<>();
public BuildoutLoader(AtomicLong objectIdGenerator, AtomicLong cellIdGenerator) {
this.idMapping = new HashMap<>();
this.objects = new HashSet<>();
this.objectIdGenerator = objectIdGenerator;
this.cellIdGenerator = cellIdGenerator;
}
public void loadAllBuildouts() {
for (Terrain t : getTerrainsToLoad())
loadBuildoutsForTerrain(t);
}
public void loadBuildoutsForTerrain(Terrain terrain) {
DatatableData table = (DatatableData) ClientFactory.getInfoFromFile("datatables/buildout/buildout_scenes.iff");
for (int row = 0; row < table.getRowCount(); row++) {
if (table.getCell(row, 0).equals(terrain.name().toLowerCase(Locale.ENGLISH))) {
TerrainBuildoutLoader loader = new TerrainBuildoutLoader(crcTable, terrain);
loader.load(row);
objects.putAll(loader.getObjects());
objectTable.putAll(loader.getObjectTable());
return;
DatatableData table = (DatatableData) ClientFactory.getInfoFromFile(BASE_PATH+"buildout_scenes.iff");
int areaId = 1;
for (int sceneRow = 0; sceneRow < table.getRowCount(); sceneRow++) {
Terrain t = Terrain.getTerrainFromName((String) table.getCell(sceneRow, 0));
String file = "datatables/buildout/areas_"+t.getName()+".iff";
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(file);
for (int row = 0; row < areaTable.getRowCount(); row++) {
SwgBuildoutArea area = new SwgBuildoutArea();
area.load(areaTable.getRow(row), sceneRow, row);
loadArea(area, t, areaId);
areaId++;
}
}
System.err.println("Could not find buildouts for terrain: " + terrain);
Log.e("Could not find buildouts for terrain: %s", terrain);
}
public Map <Long, SWGObject> getObjectTable() {
return objectTable;
public long getPreviousId(long id) {
return idMapping.getOrDefault(id, 0L);
}
public Map<String, List <SWGObject>> getObjects() {
return objects;
public Set<SWGObject> getObjects() {
return Collections.unmodifiableSet(objects);
}
private static List <Terrain> getTerrainsToLoad() {
DatatableData table = (DatatableData) ClientFactory.getInfoFromFile("datatables/buildout/buildout_scenes.iff");
List <Terrain> terrains = new LinkedList<>();
for (int row = 0; row < table.getRowCount(); row++) {
Terrain t = Terrain.getTerrainFromName((String) table.getCell(row, 0));
if (t != null)
terrains.add(t);
else
System.err.println("Couldn't find terrain: " + table.getCell(row, 0));
private void loadArea(SwgBuildoutArea area, Terrain terrain, int areaId) {
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(BASE_PATH+terrain.getName()+"/"+area.getName().replace("server", "client")+".iff");
SwgBuildoutRow buildoutRow = new SwgBuildoutRow(area);
Map<Long, SWGObject> officialBuildoutTable = new HashMap<>();
for (int row = 0; row < areaTable.getRowCount(); row++) {
buildoutRow.load(areaTable.getRow(row), crcTable);
long id = buildoutRow.getTemplate().equals("object/cell/shared_cell.iff") ? cellIdGenerator.getAndIncrement() : objectIdGenerator.getAndIncrement();
SWGObject object = ObjectCreator.createObjectFromTemplate(id, buildoutRow.getTemplate());
Location l = buildoutRow.getLocation();
object.setPosition(terrain, l.getX(), l.getY(), l.getZ());
object.setOrientation(l.getOrientationX(), l.getOrientationY(), l.getOrientationZ(), l.getOrientationW());
object.setBuildoutAreaId(areaId);
object.setBuildoutEvent(area.getEventRequired());
setCellInformation(object, buildoutRow.getCellIndex());
addObject(officialBuildoutTable, object, buildoutRow.getObjectId(), buildoutRow.getContainerId());
}
}
private void setCellInformation(SWGObject object, int cellIndex) {
if (!(object instanceof CellObject))
return;
CellObject cell = (CellObject) object;
cell.setNumber(cellIndex);
}
private void addObject(Map<Long, SWGObject> objectTable, SWGObject object, long objectId, long containerId) {
objects.add(object);
idMapping.put(object.getObjectId(), objectId);
objectTable.put(objectId, object);
if (containerId != 0) {
SWGObject container = objectTable.get(containerId);
object.systemMove(container);
if (container == null)
Log.e("Failed to load object: " + object.getTemplate());
}
return terrains;
}
}

View File

@@ -26,10 +26,19 @@
***********************************************************************************/
package com.projectswg.utility.clientdata.buildouts;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.WorldSnapshotData;
import com.projectswg.common.data.swgfile.visitors.WorldSnapshotData.Node;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import me.joshlarson.jlcommon.log.Log;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
public class SnapshotLoader {
@@ -39,34 +48,87 @@ public class SnapshotLoader {
Terrain.NABOO, Terrain.RORI, Terrain.TALUS,
Terrain.TATOOINE, Terrain.YAVIN4
);
private static final String BASE_PATH = "snapshot/";
private final Map <Long, SWGObject> objectTable;
private final List <SWGObject> objects;
private final Map<Long, SWGObject> snapshotTable;
private final Map<Long, Long> idMapping;
private final List<SWGObject> objects;
private final AtomicLong objectIdGenerator;
private final AtomicLong cellIdGenerator;
public SnapshotLoader() {
objectTable = new HashMap<>();
objects = new LinkedList<>();
public SnapshotLoader(AtomicLong objectIdGenerator, AtomicLong cellIdGenerator) {
this.snapshotTable = new HashMap<>();
this.idMapping = new HashMap<>();
this.objects = new ArrayList<>();
this.objectIdGenerator = objectIdGenerator;
this.cellIdGenerator = cellIdGenerator;
}
public void loadAllSnapshots() {
for (Terrain t : TERRAINS) {
loadSnapshotsForTerrain(t);
loadTerrain(t);
}
}
public void loadSnapshotsForTerrain(Terrain t) {
TerrainSnapshotLoader loader = new TerrainSnapshotLoader(t);
loader.load();
objects.addAll(loader.getObjects());
objectTable.putAll(loader.getObjectTable());
public long getPreviousId(long id) {
return idMapping.getOrDefault(id, 0L);
}
public Map<Long, SWGObject> getObjectTable() {
return objectTable;
public List<SWGObject> getObjects() {
return Collections.unmodifiableList(objects);
}
public List <SWGObject> getObjects() {
return objects;
private void loadTerrain(Terrain terrain) {
String path = BASE_PATH + terrain.getName() + ".ws";
WorldSnapshotData data = (WorldSnapshotData) ClientFactory.getInfoFromFile(path);
Map <Integer, String> templates = data.getObjectTemplateNames();
for (Node node : data.getNodes()) {
createFromNode(templates, terrain, node);
}
}
private void createFromNode(Map<Integer, String> templates, Terrain terrain, Node node) {
SWGObject object = createObject(templates, terrain, node);
object.setBuildoutAreaId(-1);
setCellInformation(object, node.getCellIndex());
addObject(object, node.getId(), node.getContainerId());
for (Node child : node.getChildren()) {
createFromNode(templates, terrain, child);
}
}
private SWGObject createObject(Map <Integer, String> templateMap, Terrain terrain, Node row) {
String template = templateMap.get(row.getObjectTemplateNameIndex());
long id = template.equals("object/cell/shared_cell.iff") ? cellIdGenerator.getAndIncrement() : objectIdGenerator.getAndIncrement();
SWGObject object = ObjectCreator.createObjectFromTemplate(id, template);
Location l = row.getLocation();
object.setPosition(terrain, l.getX(), l.getY(), l.getZ());
object.setOrientation(l.getOrientationX(), l.getOrientationY(), l.getOrientationZ(), l.getOrientationW());
return object;
}
private void addObject(SWGObject object, long objectId, long containerId) {
objects.add(object);
snapshotTable.put(objectId, object);
idMapping.put(object.getObjectId(), objectId);
if (containerId != 0) {
SWGObject container = snapshotTable.get(containerId);
if (!(object instanceof CellObject) && container instanceof BuildingObject) {
Log.w("Not adding: %s to %s - invalid type for BuildingObject", object, container);
return;
}
object.systemMove(container);
if (container == null)
Log.e("Failed to load object: " + object.getTemplate());
}
}
private void setCellInformation(SWGObject object, int cellIndex) {
if (!(object instanceof CellObject))
return;
CellObject cell = (CellObject) object;
cell.setNumber(cellIndex);
}
}

View File

@@ -1,125 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.utility.clientdata.buildouts;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.CrcStringTableData;
import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import me.joshlarson.jlcommon.log.Log;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
class TerrainBuildoutLoader {
private static final String BASE_PATH = "datatables/buildout/";
private final CrcStringTableData crcTable;
private final Terrain terrain;
private final Map <Long, SWGObject> objectTable;
private final Map<String, List <SWGObject>> objects;
public TerrainBuildoutLoader(CrcStringTableData crcTable, Terrain terrain) {
this.crcTable = crcTable;
this.terrain = terrain;
this.objectTable = new Hashtable<>(512);
this.objects = new Hashtable<>();
}
public void load(int sceneNumber) {
objects.clear();
loadAreas(sceneNumber);
}
public Map <Long, SWGObject> getObjectTable() {
return objectTable;
}
public Map<String, List <SWGObject>> getObjects() {
return objects;
}
private void loadAreas(int sceneNumber) {
String file = BASE_PATH+"areas_"+terrain.getName()+".iff";
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(file);
for (int row = 0; row < areaTable.getRowCount(); row++) {
SwgBuildoutArea area = new SwgBuildoutArea();
area.load(areaTable.getRow(row), sceneNumber, row);
loadArea(area);
}
}
private void loadArea(SwgBuildoutArea area) {
String file = BASE_PATH+terrain.getName()+"/"+area.getName().replace("server", "client")+".iff";
DatatableData areaTable = (DatatableData) ClientFactory.getInfoFromFile(file);
SwgBuildoutRow buildoutRow = new SwgBuildoutRow(area);
objectTable.clear();
for (int row = 0; row < areaTable.getRowCount(); row++) {
buildoutRow.load(areaTable.getRow(row), crcTable);
SWGObject object = createObject(buildoutRow);
object.setBuildoutAreaId(area.getIndex());
setCellInformation(object, buildoutRow.getCellIndex());
addObject(area.getName(), object, buildoutRow.getContainerId());
}
}
private SWGObject createObject(SwgBuildoutRow row) {
SWGObject object = ObjectCreator.createObjectFromTemplate(row.getObjectId(), row.getTemplate());
Location l = row.getLocation();
object.setPosition(terrain, l.getX(), l.getY(), l.getZ());
object.setOrientation(l.getOrientationX(), l.getOrientationY(), l.getOrientationZ(), l.getOrientationW());
return object;
}
private void addObject(String areaName, SWGObject object, long containerId) {
objectTable.put(object.getObjectId(), object);
if (containerId != 0) {
SWGObject container = objectTable.get(containerId);
object.systemMove(container);
if (container == null)
Log.e("Failed to load object: " + object.getTemplate());
} else {
List<SWGObject> list = objects.computeIfAbsent(areaName, k -> new LinkedList<>());
list.add(object);
}
}
private void setCellInformation(SWGObject object, int cellIndex) {
if (!(object instanceof CellObject))
return;
CellObject cell = (CellObject) object;
cell.setNumber(cellIndex);
}
}

View File

@@ -1,119 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.utility.clientdata.buildouts;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.data.swgfile.ClientFactory;
import com.projectswg.common.data.swgfile.visitors.WorldSnapshotData;
import com.projectswg.common.data.swgfile.visitors.WorldSnapshotData.Node;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import me.joshlarson.jlcommon.log.Log;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class TerrainSnapshotLoader {
private static final String BASE_PATH = "snapshot/";
private final Terrain terrain;
private final Map <Long, SWGObject> objectTable;
private final List <SWGObject> objects;
public TerrainSnapshotLoader(Terrain terrain) {
this.terrain = terrain;
this.objectTable = new Hashtable<>(12 * 1024);
this.objects = new LinkedList<>();
}
public Map <Long, SWGObject> getObjectTable() {
return objectTable;
}
public List <SWGObject> getObjects() {
return objects;
}
public void load() {
objects.clear();
String path = BASE_PATH + terrain.getName() + ".ws";
WorldSnapshotData data = (WorldSnapshotData) ClientFactory.getInfoFromFile(path);
Map <Integer, String> templates = data.getObjectTemplateNames();
for (Node node : data.getNodes()) {
createFromNode(templates, node);
}
}
private void createFromNode(Map<Integer, String> templates, Node node) {
SWGObject object = createObject(templates, node);
object.setBuildoutAreaId(-1);
setCellInformation(object, node.getCellIndex());
addObject(object, node.getContainerId());
for (Node child : node.getChildren()) {
createFromNode(templates, child);
}
}
private SWGObject createObject(Map <Integer, String> templateMap, Node row) {
SWGObject object = ObjectCreator.createObjectFromTemplate(row.getId(), templateMap.get(row.getObjectTemplateNameIndex()));
Location l = row.getLocation();
object.setPosition(terrain, l.getX(), l.getY(), l.getZ());
object.setOrientation(l.getOrientationX(), l.getOrientationY(), l.getOrientationZ(), l.getOrientationW());
return object;
}
private void addObject(SWGObject object, long containerId) {
objectTable.put(object.getObjectId(), object);
if (containerId != 0) {
SWGObject container = objectTable.get(containerId);
if (!(object instanceof CellObject) && container instanceof BuildingObject) {
Log.w("Not adding: %s to %s - invalid type for BuildingObject", object, container);
return;
}
object.systemMove(container);
if (container == null)
Log.e("Failed to load object: " + object.getTemplate());
} else {
objects.add(object);
}
}
private void setCellInformation(SWGObject object, int cellIndex) {
if (!(object instanceof CellObject))
return;
CellObject cell = (CellObject) object;
cell.setNumber(cellIndex);
}
}