From addc4bc2b0ca8aec85b7de7a23495e03ebc7c8a7 Mon Sep 17 00:00:00 2001 From: Obique Date: Tue, 19 Jun 2018 12:56:24 -0500 Subject: [PATCH] Fixed gitignore blocking out clientdata directory in src/utility --- .gitignore | 8 +- .../clientdata/ConvertBuildingList.java | 69 ++++ .../utility/clientdata/ConvertBuildouts.java | 382 ++++++++++++++++++ .../utility/clientdata/ConvertObjectData.java | 116 ++++++ .../clientdata/ConvertRawDatatable.java | 31 ++ .../clientdata/ConvertSlotDefinition.java | 34 ++ .../utility/clientdata/Converter.java | 36 ++ .../utility/clientdata/Converters.java | 21 + .../clientdata/buildouts/BuildoutLoader.java | 91 +++++ .../clientdata/buildouts/SnapshotLoader.java | 72 ++++ .../clientdata/buildouts/SwgBuildoutArea.java | 252 ++++++++++++ .../clientdata/buildouts/SwgBuildoutRow.java | 164 ++++++++ .../buildouts/TerrainBuildoutLoader.java | 125 ++++++ .../buildouts/TerrainSnapshotLoader.java | 119 ++++++ 14 files changed, 1516 insertions(+), 4 deletions(-) create mode 100644 src/utility/java/com/projectswg/utility/clientdata/ConvertBuildingList.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/ConvertBuildouts.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/ConvertObjectData.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/ConvertRawDatatable.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/ConvertSlotDefinition.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/Converter.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/Converters.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/BuildoutLoader.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/SnapshotLoader.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutArea.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutRow.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainBuildoutLoader.java create mode 100644 src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainSnapshotLoader.java diff --git a/.gitignore b/.gitignore index 5388c84ce..2ff1580a4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,9 @@ build .gradle # Holocore -clientdata/ -log/ -cfg/ -odb/ +/clientdata/ +/log/ +/cfg/ +/odb/ *.db *.iff diff --git a/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildingList.java b/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildingList.java new file mode 100644 index 000000000..a86c76d22 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildingList.java @@ -0,0 +1,69 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata; + +import com.projectswg.common.data.location.Terrain; +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; +import com.projectswg.utility.SdbGenerator; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Locale; + +public class ConvertBuildingList implements Converter { + + @Override + public void convert() { + System.out.println("Converting building list..."); + Collection 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"); + 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); + int cells = ((BuildingObject) obj).getCells().size(); + if (cells <= 0) + continue; + gen.writeLine("", terrain, obj.getObjectId(), template, name, cells, obj.getX(), obj.getY(), obj.getZ()); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void convertFile(SdbGenerator sdb, File file) { + + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildouts.java b/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildouts.java new file mode 100644 index 000000000..8d1d2b208 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/ConvertBuildouts.java @@ -0,0 +1,382 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata; + +import com.projectswg.common.data.CRC; +import com.projectswg.common.data.location.Location; +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.objects.swg.SWGObject; +import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject; +import com.projectswg.utility.SdbGenerator; +import com.projectswg.utility.clientdata.buildouts.BuildoutLoader; +import com.projectswg.utility.clientdata.buildouts.SnapshotLoader; +import com.projectswg.utility.clientdata.buildouts.SwgBuildoutArea; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +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"} + }; + + private final List areas; + private final List fallbackAreas; + + public ConvertBuildouts() { + this.areas = new ArrayList<>(); + this.fallbackAreas = new ArrayList<>(Terrain.values().length); + int areaId = -1; + for (Terrain t : Terrain.values()) { + fallbackAreas.add(new GenBuildoutArea(null, t, -8196, -8196, 8196, 8196, areaId, false)); + areaId--; + } + } + + @Override + public void convert() { + try { + createAreas(); + createObjects(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void createAreas() throws IOException { + System.out.println("Generating areas..."); + try (SdbGenerator gen = new SdbGenerator(new File("serverdata/buildout/areas.sdb"))) { + gen.writeColumnNames(AREA_COLUMNS[0]); + writeAreas(gen); + } + } + + private void createObjects() throws IOException { + System.out.println("Generating objects..."); + List objects = new LinkedList<>(); + System.out.println(" Creating buildouts..."); + createBuildouts(objects); + System.out.println(" Creating snapshots..."); + createSnapshots(objects); + System.out.println(" Generating file..."); + generateObjectFile(objects); + } + + private void createBuildouts(List objects) { + BuildoutLoader loader = new BuildoutLoader(); + loader.loadAllBuildouts(); + for (Entry> 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); + } + } + } + + private void createSnapshots(List objects) { + SnapshotLoader snapLoader = new SnapshotLoader(); + snapLoader.loadAllSnapshots(); + List snapshots = new LinkedList<>(); + for (SWGObject obj : snapLoader.getObjects()) { + addClientObject(snapshots, obj); + } + setSnapshotData(snapshots, objects); + } + + private void setSnapshotData(List snapshots, List objects) { + for (SWGObject snap : snapshots) { + GenBuildoutArea area = getAreaForObject(snap); + if (area != null) + snap.setBuildoutAreaId(area.id); + else + System.err.println("No area for: " + snap.getObjectId() + " / " + snap.getTerrain()); + } + objects.addAll(snapshots); + } + + private void generateObjectFile(List objects) throws IOException { + 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); + for (SWGObject obj : objects) { + if (obj instanceof CellObject) + continue; + writeObject(gen, obj); + while (percent / 100.0 * objects.size() <= objNum) { + System.out.print("."); + percent++; + } + objNum++; + } + System.out.println(); + } + } + + private int getBuildoutDepth(SWGObject object) { + if (object.getParent() == null) + return 0; + return getBuildoutDepth(object.getParent()) + 1; + } + + private void addClientObject(List 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)); + } + Collections.sort(areas); + for (int i = fallbackAreas.size()-1; i >= 0; i--) { + GenBuildoutArea fallback = fallbackAreas.get(i); + String name = fallback.terrain.name().toLowerCase(Locale.US); + gen.writeLine(fallback.id, name, name + "_global", "", -8196, -8196, 8196, 8196, "0", 0, 0); + } + int percent = 0; + for (int i = 0; i < areas.size(); i++) { + GenBuildoutArea area = areas.get(i); + writeArea(gen, area, null); + for (int j = i+1; j < areas.size() && area.equals(areas.get(j)); j++) { + writeArea(gen, areas.get(j), area.area.getName()); + i++; + } + while (percent / 100.0 * areas.size() <= i) { + System.out.print("."); + percent++; + } + } + 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(); + String terrain = area.terrain.getName(); + double x1 = area.area.getX1(); + double z1 = area.area.getZ1(); + double x2 = area.area.getX2(); + double z2 = area.area.getZ2(); + double transX = 0; + double transZ = 0; + boolean adjust = area.adjust || !area.area.getCompositeName().isEmpty(); + if (!area.area.getCompositeName().isEmpty()) { + transX = area.area.getCompositeX1() + (area.area.getCompositeX2() - area.area.getCompositeX1()) / 2; + transZ = area.area.getCompositeZ1() + (area.area.getCompositeZ2() - area.area.getCompositeZ1()) / 2; + } + transX -= area.area.getX1() + (area.area.getX2() - area.area.getX1()) / 2; + transZ -= area.area.getZ1() + (area.area.getZ2() - area.area.getZ1()) / 2; + gen.writeLine(area.id, terrain, substituteName, area.area.getEventRequired(), x1, z1, x2, z2, adjust?"1":"0", transX, transZ); + } + + private void writeObject(SdbGenerator gen, SWGObject object) throws IOException { + long id = object.getObjectId(); + int crc = CRC.getCrc(object.getTemplate()); + long container = (object.getParent() != null) ? object.getParent().getObjectId() : 0; + if (object.getParent() instanceof CellObject) + container = object.getParent().getParent().getObjectId(); + Location l = object.getLocation(); + Quaternion q = l.getOrientation(); + double radius = object.getLoadRange(); + int cellIndex = (object.getParent() instanceof CellObject) ? ((CellObject) object.getParent()).getNumber() : 0; + 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); + } + + private void isValidBuildoutAreas(List 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; + } + } + + private static class GenBuildoutArea implements Comparable { + public final SwgBuildoutArea area; + public final Terrain terrain; + public final int index; + public final int x1; + public final int z1; + public final int x2; + public final int z2; + public final int id; + public final boolean adjust; + + 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.x1 = (int) x1; + this.z1 = (int) z1; + this.x2 = (int) x2; + this.z2 = (int) z2; + this.id = id; + this.adjust = adjust; + } + + @Override + public int compareTo(GenBuildoutArea area) { + int comp = Integer.compare(index, area.index); + if (comp != 0) + return comp; + comp = Integer.compare(x1, area.x1); + if (comp != 0) + return comp; + comp = Integer.compare(z1, area.z1); + if (comp != 0) + return comp; + comp = Integer.compare(x2, area.x2); + if (comp != 0) + return comp; + comp = Integer.compare(z2, area.z2); + if (comp != 0) + return comp; + return Integer.compare(getSorting(), area.getSorting()); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof GenBuildoutArea)) + return false; + GenBuildoutArea area = (GenBuildoutArea) o; + return terrain.equals(area.terrain) && x1 == area.x1 && z1 == area.z1; + } + + @Override + public int hashCode() { + return terrain.hashCode() ^ Integer.hashCode(x1) ^ Integer.hashCode(z1); + } + + private int getSorting() { + if (area == null) + return 1; + String [] parts = area.getName().split("_"); + if (parts.length != 3) + return 2; + if (isNumber(parts[1]) && isNumber(parts[2])) + return 1; + return 2; + } + + private boolean isNumber(String str) { + try { + Integer.parseInt(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/ConvertObjectData.java b/src/utility/java/com/projectswg/utility/clientdata/ConvertObjectData.java new file mode 100644 index 000000000..e888cc2d2 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/ConvertObjectData.java @@ -0,0 +1,116 @@ +package com.projectswg.utility.clientdata; + +import com.projectswg.common.data.swgfile.ClientFactory; +import com.projectswg.common.data.swgfile.visitors.ObjectData; +import com.projectswg.common.data.swgfile.visitors.ObjectData.ObjectDataAttribute; +import com.projectswg.utility.SdbGenerator; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +class ConvertObjectData implements Converter { + + private static final ObjectDataAttribute[] ATTRIBUTES = Arrays.stream(ObjectDataAttribute.values()).filter(a -> a != ObjectDataAttribute.UNKNOWN).collect(Collectors.toList()).toArray(new ObjectDataAttribute[0]); + private static final File CLIENTDATA = new File("clientdata"); + + private final Object [] line; + + public ConvertObjectData() { + this.line = new Object[ATTRIBUTES.length+1]; + } + + @Override + public void convert() { + System.out.println("Converting object data..."); + try (SdbGenerator sdb = new SdbGenerator(new File("serverdata/objects/object_data.sdb"))) { + { + List columns = new ArrayList<>(); + columns.add("iff"); + columns.addAll(Arrays.stream(ATTRIBUTES).map(ObjectDataAttribute::getName).collect(Collectors.toList())); + sdb.writeColumnNames(columns); + } + Converter.traverseFiles(this, new File(CLIENTDATA, "object"), sdb, file -> file.getName().endsWith(".iff")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void convertFile(SdbGenerator sdb, File file) throws IOException { + ObjectData objectData = (ObjectData) ClientFactory.getInfoFromFile(file); + if (objectData == null) { + System.err.println("Failed to load object: " + file); + return; + } + if (file.getName().equals("")) + System.out.println(objectData.getAttribute(ObjectDataAttribute.OBJECT_NAME)); + line[0] = file.getAbsolutePath().replace(CLIENTDATA.getAbsolutePath()+'/', ""); + for (int i = 0; i < ATTRIBUTES.length; i++) { + ObjectDataAttribute attr = ATTRIBUTES[i]; + line[i+1] = initializeDataType(attr, objectData.getAttribute(attr)); + } + sdb.writeLine(line); + } + + private static Object initializeDataType(ObjectDataAttribute attribute, Object o) { + switch (attribute) { + case ATTACK_TYPE: + case COLLISION_MATERIAL_BLOCK_FLAGS: + case COLLISION_MATERIAL_FLAGS: + case COLLISION_MATERIAL_PASS_FLAGS: + case COLLISION_ACTION_BLOCK_FLAGS: + case COLLISION_ACTION_FLAGS: + case COLLISION_ACTION_PASS_FLAGS: + case CONTAINER_TYPE: + case CONTAINER_VOLUME_LIMIT: + case GAME_OBJECT_TYPE: + case GENDER: + case NICHE: + case RACE: + case SPECIES: + case SURFACE_TYPE: + case WEAPON_EFFECT_INDEX: + case ACCELERATION: + case CAMERA_HEIGHT: + case CLEAR_FLORA_RADIUS: + case COLLISION_HEIGHT: + case COLLISION_LENGTH: + case COLLISION_OFFSET_X: + case COLLISION_OFFSET_Z: + case COLLISION_RADIUS: + case LOCATION_RESERVATION_RADIUS: + case NO_BUILD_RADIUS: + case SCALE: + case SCALE_THRESHOLD_BEFORE_EXTENT_TEST: + case SLOPE_MOD_ANGLE: + case SLOPE_MOD_PERCENT: + case SPEED: + case STEP_HEIGHT: + case SWIM_HEIGHT: + case TURN_RADIUS: + case WARP_TOLERANCE: + case WATER_MOD_PERCENT: + if (o == null) + return "0"; + return o; + case CLIENT_VISIBILITY_FLAG: + case FORCE_NO_COLLISION: + case HAS_WINGS: + case ONLY_VISIBLE_IN_TOOLS: + case PLAYER_CONTROLLED: + case POSTURE_ALIGN_TO_TERRAIN: + case SEND_TO_CLIENT: + case SNAP_TO_TERRAIN: + case TARGETABLE: + case USE_STRUCTURE_FOOTPRINT_OUTLINE: + if (o == null) + return "false"; + return o; + default: + return o; + } + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/ConvertRawDatatable.java b/src/utility/java/com/projectswg/utility/clientdata/ConvertRawDatatable.java new file mode 100644 index 000000000..776f0fb32 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/ConvertRawDatatable.java @@ -0,0 +1,31 @@ +package com.projectswg.utility.clientdata; + +import com.projectswg.utility.SdbGenerator; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; + +public abstract class ConvertRawDatatable implements Converter { + + public ConvertRawDatatable() { + + } + + protected void convert(File input, File output) { + try (BufferedReader in = new BufferedReader(new FileReader(input))) { + String [] columnNames = in.readLine().split("\t"); + String [] columnTypes = in.readLine().split("\t"); + System.out.println(List.of(columnNames)); + System.out.println(List.of(columnTypes)); + try (SdbGenerator gen = new SdbGenerator(output)) { + + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/ConvertSlotDefinition.java b/src/utility/java/com/projectswg/utility/clientdata/ConvertSlotDefinition.java new file mode 100644 index 000000000..04bfb06af --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/ConvertSlotDefinition.java @@ -0,0 +1,34 @@ +package com.projectswg.utility.clientdata; + +import com.projectswg.common.data.swgfile.ClientFactory; +import com.projectswg.common.data.swgfile.visitors.SlotDefinitionData; +import com.projectswg.common.data.swgfile.visitors.SlotDefinitionData.SlotDefinition; +import com.projectswg.utility.SdbGenerator; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; + +class ConvertSlotDefinition implements Converter { + + @Override + public void convert() { + System.out.println("Converting slot definitions..."); + try (SdbGenerator sdb = new SdbGenerator(new File("serverdata/abstract/slot_definitions.sdb"))) { + sdb.writeColumnNames("slotName", "global", "modifiable", "observeWithParent", "exposeToWorld"); + convertFile(sdb, new File("clientdata/abstract/slot/slot_definition/slot_definitions.iff")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void convertFile(SdbGenerator sdb, File file) throws IOException { + SlotDefinitionData clientdata = (SlotDefinitionData) ClientFactory.getInfoFromFile(file); + Objects.requireNonNull(clientdata, "Failed to load clientdata"); + + for (SlotDefinition sd : clientdata.getDefinitions().values()) { + sdb.writeLine(sd.getName(), sd.isGlobal(), sd.isModifiable(), sd.isObserveWithParent(), sd.isExposeToWorld()); + } + } +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/Converter.java b/src/utility/java/com/projectswg/utility/clientdata/Converter.java new file mode 100644 index 000000000..b9d2f5560 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/Converter.java @@ -0,0 +1,36 @@ +package com.projectswg.utility.clientdata; + +import com.projectswg.utility.SdbGenerator; + +import java.io.File; +import java.io.IOException; +import java.util.function.Predicate; + +interface Converter { + + File HOLOCORE = new File("serverdata"); + File RAW = new File("/home/josh/devel/ProjectSWG/sauce/whitengold/dsrc/sku.0/sys.shared/compiled/game/"); + + void convert(); + default void convertFile(SdbGenerator sdb, File file) throws IOException {} + + static void traverseFiles(Converter converter, File directory, SdbGenerator sdb, Predicate filter) { + System.out.println(directory); + File [] children = directory.listFiles(); + assert children != null; + for (File child : children) { + if (child.isDirectory()) { + traverseFiles(converter, child, sdb, filter); + } else if (filter.test(child)) { + try { + converter.convertFile(sdb, child); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + System.out.println("Ignoring " + child); + } + } + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/Converters.java b/src/utility/java/com/projectswg/utility/clientdata/Converters.java new file mode 100644 index 000000000..baa882bd7 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/Converters.java @@ -0,0 +1,21 @@ +package com.projectswg.utility.clientdata; + +import java.util.function.Supplier; + +public enum Converters { + BUILDOUT_BUILDING_LIST (ConvertBuildingList::new), + BUILDOUT_OBJECTS (ConvertBuildouts::new), + OBJECTS_OBJECT_DATA (ConvertObjectData::new), + ABSTRACT_SLOT_DEFINITION(ConvertSlotDefinition::new); + + private final Supplier converter; + + Converters(Supplier converter) { + this.converter = converter; + } + + public void load() { + converter.get().convert(); + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/BuildoutLoader.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/BuildoutLoader.java new file mode 100644 index 000000000..3cf9cb0f4 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/BuildoutLoader.java @@ -0,0 +1,91 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata.buildouts; + +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.swg.SWGObject; +import me.joshlarson.jlcommon.log.Log; + +import java.util.*; + +public class BuildoutLoader { + + private static final CrcStringTableData crcTable = (CrcStringTableData) ClientFactory.getInfoFromFile("misc/object_template_crc_string_table.iff"); + + private final Map objectTable; + private final Map> objects; + + public BuildoutLoader() { + objectTable = new HashMap<>(); + objects = new Hashtable<>(); + } + + 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; + } + } + System.err.println("Could not find buildouts for terrain: " + terrain); + Log.e("Could not find buildouts for terrain: %s", terrain); + } + + public Map getObjectTable() { + return objectTable; + } + + public Map> getObjects() { + return objects; + } + + private static List getTerrainsToLoad() { + DatatableData table = (DatatableData) ClientFactory.getInfoFromFile("datatables/buildout/buildout_scenes.iff"); + List 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)); + } + return terrains; + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/SnapshotLoader.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SnapshotLoader.java new file mode 100644 index 000000000..d2d64df35 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SnapshotLoader.java @@ -0,0 +1,72 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata.buildouts; + +import com.projectswg.common.data.location.Terrain; +import com.projectswg.holocore.resources.support.objects.swg.SWGObject; + +import java.util.*; + +public class SnapshotLoader { + + private static final Set TERRAINS = EnumSet.of( + Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR, + Terrain.DUNGEON1, Terrain.ENDOR, Terrain.LOK, + Terrain.NABOO, Terrain.RORI, Terrain.TALUS, + Terrain.TATOOINE, Terrain.YAVIN4 + ); + + private final Map objectTable; + private final List objects; + + public SnapshotLoader() { + objectTable = new HashMap<>(); + objects = new LinkedList<>(); + } + + public void loadAllSnapshots() { + for (Terrain t : TERRAINS) { + loadSnapshotsForTerrain(t); + } + } + + public void loadSnapshotsForTerrain(Terrain t) { + TerrainSnapshotLoader loader = new TerrainSnapshotLoader(t); + loader.load(); + objects.addAll(loader.getObjects()); + objectTable.putAll(loader.getObjectTable()); + } + + public Map getObjectTable() { + return objectTable; + } + + public List getObjects() { + return objects; + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutArea.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutArea.java new file mode 100644 index 000000000..aac399bf1 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutArea.java @@ -0,0 +1,252 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata.buildouts; + +public class SwgBuildoutArea { + + // Datatable Information + private String name; + private float x1; + private float z1; + private float x2; + private float z2; + private boolean useClipRect; + private float clipRectX1; + private float clipRectZ1; + private float clipRectX2; + private float clipRectZ2; + private int envFlags; + private int envFlagsExclude; + private boolean useOrigin; + private float originX; + private float originZ; + private float compositeX1; + private float compositeZ1; + private float compositeX2; + private float compositeZ2; + private String compositeName; + private boolean isolated; + private boolean allowMap; + private boolean internal; + private boolean allowRadarTerrain; + private String eventRequired; + // Calculated + private int index; + // Used to calculate rows + private long currentBuilding; + private long currentCell; + private long buildingObjectId; + private long objectIdBase; + + public void load(Object [] datatableRow, int sceneNumber, int areaNumber) { + name = (String) datatableRow[0]; + x1 = (Float) datatableRow[1]; + z1 = (Float) datatableRow[2]; + x2 = (Float) datatableRow[3]; + z2 = (Float) datatableRow[4]; + useClipRect = (Boolean) datatableRow[5]; + clipRectX1 = (Float) datatableRow[6]; + clipRectZ1 = (Float) datatableRow[7]; + clipRectX2 = (Float) datatableRow[8]; + clipRectZ2 = (Float) datatableRow[9]; + envFlags = (Integer) datatableRow[10]; + envFlagsExclude = (Integer) datatableRow[11]; + useOrigin = (Boolean) datatableRow[12]; + originX = (Float) datatableRow[13]; + originZ = (Float) datatableRow[14]; + compositeX1 = (Float) datatableRow[15]; + compositeZ1 = (Float) datatableRow[16]; + compositeX2 = (Float) datatableRow[17]; + compositeZ2 = (Float) datatableRow[18]; + compositeName = (String) datatableRow[19]; + isolated = (Boolean) datatableRow[20]; + allowMap = (Boolean) datatableRow[21]; + internal = (Boolean) datatableRow[22]; + allowRadarTerrain = (Boolean) datatableRow[23]; + eventRequired = (String) datatableRow[24]; + reset(); + calculate(sceneNumber, areaNumber); + } + + private void reset() { + currentBuilding = 0; + currentCell = 0; + buildingObjectId = 0; + objectIdBase = 0; + } + + private void calculate(int sceneNumber, int areaNumber) { + index = sceneNumber * 100 + areaNumber; + buildingObjectId = -(index + 1) * 30000L; + objectIdBase = buildingObjectId + 2000; + } + + public void setCurrentBuilding(long currentBuilding) { + this.currentBuilding = currentBuilding; + } + + public void setCurrentCell(long currentCell) { + this.currentCell = currentCell; + } + + public void setBuildingObjectId(long buildingObjectId) { + this.buildingObjectId = buildingObjectId; + } + + public void setObjectIdBase(long objectIdBase) { + this.objectIdBase = objectIdBase; + } + + public void incrementBuildingObjectId() { + buildingObjectId++; + } + + public void incrementObjectIdBase() { + objectIdBase++; + } + + public String getName() { + return name; + } + + public float getX1() { + return x1; + } + + public float getZ1() { + return z1; + } + + public float getX2() { + return x2; + } + + public float getZ2() { + return z2; + } + + public boolean isUseClipRect() { + return useClipRect; + } + + public float getClipRectX1() { + return clipRectX1; + } + + public float getClipRectZ1() { + return clipRectZ1; + } + + public float getClipRectX2() { + return clipRectX2; + } + + public float getClipRectZ2() { + return clipRectZ2; + } + + public int getEnvFlags() { + return envFlags; + } + + public int getEnvFlagsExclude() { + return envFlagsExclude; + } + + public boolean isUseOrigin() { + return useOrigin; + } + + public float getOriginX() { + return originX; + } + + public float getOriginZ() { + return originZ; + } + + public float getCompositeX1() { + return compositeX1; + } + + public float getCompositeZ1() { + return compositeZ1; + } + + public float getCompositeX2() { + return compositeX2; + } + + public float getCompositeZ2() { + return compositeZ2; + } + + public String getCompositeName() { + return compositeName; + } + + public boolean isIsolated() { + return isolated; + } + + public boolean isAllowMap() { + return allowMap; + } + + public boolean isInternal() { + return internal; + } + + public boolean isAllowRadarTerrain() { + return allowRadarTerrain; + } + + public String getEventRequired() { + return eventRequired; + } + + public int getIndex() { + return index; + } + + public long getCurrentBuilding() { + return currentBuilding; + } + + public long getCurrentCell() { + return currentCell; + } + + public long getBuildingObjectId() { + return buildingObjectId; + } + + public long getObjectIdBase() { + return objectIdBase; + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutRow.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutRow.java new file mode 100644 index 000000000..8dc190726 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/SwgBuildoutRow.java @@ -0,0 +1,164 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +package com.projectswg.utility.clientdata.buildouts; + +import com.projectswg.common.data.CRC; +import com.projectswg.common.data.location.Location; +import com.projectswg.common.data.swgfile.visitors.CrcStringTableData; + +import java.util.concurrent.atomic.AtomicReference; + +public class SwgBuildoutRow { + + private static final int cellCrc = CRC.getCrc("object/cell/shared_cell.iff"); + + private final SwgBuildoutArea buildoutArea; + private final AtomicReference location; + private long objectId; + private long containerId; + private int type; + private int sharedTemplateCrc; + private int cellIndex; + private float radius; + private int portalLayoutCrc; + private String template; + + public SwgBuildoutRow(SwgBuildoutArea buildoutArea) { + this.buildoutArea = buildoutArea; + this.location = new AtomicReference<>(null); + } + + public void load(Object [] datatableRow, CrcStringTableData crcString) { + switch (datatableRow.length) { + case 11: + loadSmall(datatableRow, crcString); + break; + case 14: + loadLarge(datatableRow, crcString); + break; + default: + throw new IllegalArgumentException("Datatable row must be either 11 or 14 columns!"); + } + translateLocation(); + } + + private void loadSmall(Object [] datatableRow, CrcStringTableData crcString) { + loadEndColumns(datatableRow, crcString, 0); + if (portalLayoutCrc != 0) { // is building + objectId = buildoutArea.getBuildingObjectId(); + buildoutArea.incrementBuildingObjectId(); + buildoutArea.setCurrentBuilding(objectId); + containerId = 0; + } else if (sharedTemplateCrc == cellCrc) { + objectId = buildoutArea.getBuildingObjectId(); + buildoutArea.incrementBuildingObjectId(); + buildoutArea.setCurrentCell(objectId); + containerId = buildoutArea.getCurrentBuilding(); + } else if (cellIndex > 0) { // is in cell + objectId = buildoutArea.getObjectIdBase(); + buildoutArea.incrementObjectIdBase(); + containerId = buildoutArea.getCurrentCell(); + } else { // is somewhere else + objectId = buildoutArea.getObjectIdBase(); + buildoutArea.incrementObjectIdBase(); + containerId = 0; + } + } + + private void loadLarge(Object [] datatableRow, CrcStringTableData crcString) { + objectId = (Integer) datatableRow[0]; + containerId = (Integer) datatableRow[1]; + type = (Integer) datatableRow[2]; + loadEndColumns(datatableRow, crcString, 3); + final long indexShifted = (buildoutArea.getIndex() + 1L) << 48; + if (objectId < 0) + objectId ^= indexShifted; + if (containerId < 0) + containerId ^= indexShifted; + } + + private void loadEndColumns(Object [] datatableRow, CrcStringTableData crcString, int offset) { + sharedTemplateCrc = (Integer) datatableRow[offset]; + cellIndex = (Integer) datatableRow[offset + 1]; + Location loc = Location.builder() + .setX((Float) datatableRow[offset + 2]) + .setY((Float) datatableRow[offset + 3]) + .setZ((Float) datatableRow[offset + 4]) + .setOrientationW((Float) datatableRow[offset + 5]) + .setOrientationX((Float) datatableRow[offset + 6]) + .setOrientationY((Float) datatableRow[offset + 7]) + .setOrientationZ((Float) datatableRow[offset + 8]) + .build(); + location.set(loc); + radius = (Float) datatableRow[offset + 9]; + portalLayoutCrc = (Integer) datatableRow[offset + 10]; + template = crcString.getTemplateString(sharedTemplateCrc); + } + + private void translateLocation() { + if (cellIndex != 0) + return; + location.set(Location.builder(location.get()).translatePosition(buildoutArea.getX1(), 0, buildoutArea.getZ1()).build()); + } + + public Location getLocation() { + return location.get(); + } + + public long getObjectId() { + return objectId; + } + + public long getContainerId() { + return containerId; + } + + public int getType() { + return type; + } + + public int getSharedTemplateCrc() { + return sharedTemplateCrc; + } + + public int getCellIndex() { + return cellIndex; + } + + public float getRadius() { + return radius; + } + + public int getPortalLayoutCrc() { + return portalLayoutCrc; + } + + public String getTemplate() { + return template; + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainBuildoutLoader.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainBuildoutLoader.java new file mode 100644 index 000000000..171b8bd5f --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainBuildoutLoader.java @@ -0,0 +1,125 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +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 objectTable; + private final Map> 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 getObjectTable() { + return objectTable; + } + + public Map> 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 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); + } + +} diff --git a/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainSnapshotLoader.java b/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainSnapshotLoader.java new file mode 100644 index 000000000..bd0ac7130 --- /dev/null +++ b/src/utility/java/com/projectswg/utility/clientdata/buildouts/TerrainSnapshotLoader.java @@ -0,0 +1,119 @@ +/*********************************************************************************** + * 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 . * + ***********************************************************************************/ +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 objectTable; + private final List objects; + + public TerrainSnapshotLoader(Terrain terrain) { + this.terrain = terrain; + this.objectTable = new Hashtable<>(12 * 1024); + this.objects = new LinkedList<>(); + } + + public Map getObjectTable() { + return objectTable; + } + + public List getObjects() { + return objects; + } + + public void load() { + objects.clear(); + String path = BASE_PATH + terrain.getName() + ".ws"; + WorldSnapshotData data = (WorldSnapshotData) ClientFactory.getInfoFromFile(path); + Map templates = data.getObjectTemplateNames(); + for (Node node : data.getNodes()) { + createFromNode(templates, node); + } + } + + private void createFromNode(Map 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 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); + } + +}