diff --git a/.gitignore b/.gitignore index f897d83d..16fd367a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ /clientdata /.settings /odb +/serverdata/**/*.iff packets.txt log.txt diff --git a/serverdata/map/map_locations.iff b/serverdata/map/map_locations.iff deleted file mode 100644 index 092392e9..00000000 Binary files a/serverdata/map/map_locations.iff and /dev/null differ diff --git a/serverdata/map/map_locations.sdf b/serverdata/map/map_locations.sdf new file mode 100644 index 00000000..38583651 --- /dev/null +++ b/serverdata/map/map_locations.sdf @@ -0,0 +1,107 @@ +Template Name Category Subcategory Type Flag +s s s[unknown] s I[0] I[0] +object/building/tatooine/cloning_facility_tatooine.iff cloningfacility +object/building/tatooine/cloning_facility_tatooine_small.iff cloningfacility +object/building/tatooine/bank_tatooine.iff bank +object/building/naboo/bank_naboo.iff bank +object/building/corellia/bank_corellia.iff bank +object/building/tatooine/cantina_tatooine.iff cantina 1 +object/building/tatooine/capitol_tatooine.iff capitol +object/building/tatooine/guild_combat_tatooine_style_01.iff guild guild_combat +object/building/tatooine/guild_commerce_tatooine_style_01.iff guild guild_commerce +object/building/tatooine/guild_theater_tatooine_style_01.iff guild guild_theater 1 +object/building/tatooine/guild_university_tatooine_style_01.iff guild guild_university +object/building/tatooine/hospital_tatooine_style01.iff medicalcenter 1 +object/building/tatooine/hospital_tatooine_style02.iff medicalcenter 1 +object/building/tatooine/hotel_tatooine_style_01.iff hotel +object/building/tatooine/hotel_tatooine_general.iff hotel +object/building/tatooine/junkshop_watto.iff @map_loc_n:junkshop_watto junkshop +object/building/tatooine/lucky_despot.iff @map_loc_n:lucky_despot cantina 1 +object/building/tatooine/shuttleport_tatooine.iff shuttleport +object/building/tatooine/starport_tatooine.iff starport +object/building/corellia/cantina_corellia.iff cantina 1 +object/building/corellia/cloning_corellia.iff cloningfacility +object/building/corellia/guild_combat_corellia_style_01.iff guild guild_combat +object/building/corellia/guild_commerce_corellia_style_01.iff guild guild_commerce +object/building/corellia/guild_theater_corellia_s01.iff guild guild_theater 1 +object/building/corellia/guild_university_corellia_style_01.iff guild guild_university +object/building/corellia/hospital_corellia.iff medicalcenter 1 +object/building/corellia/hospital_corellia_s02.iff medicalcenter 1 +object/building/corellia/hotel_corellia.iff hotel +object/building/corellia/shuttleport_corellia.iff shuttleport +object/building/corellia/starport_corellia.iff starport +object/building/naboo/cantina_naboo.iff cantina 1 +object/building/naboo/capitol_naboo_theed.iff capitol +object/building/naboo/cloning_facility_naboo.iff cloningfacility +object/building/naboo/guild_combat_naboo_style_01.iff guild guild_combat +object/building/naboo/guild_commerce_naboo_style_01.iff guild guild_commerce +object/building/naboo/guild_theater_naboo_s01.iff guild guild_theater 1 +object/building/naboo/guild_university_naboo_style_01.iff guild guild_university +object/building/naboo/hangar_naboo_theed.iff starport +object/building/naboo/hospital_naboo_style01.iff medicalcenter 1 +object/building/naboo/hospital_naboo_style02.iff medicalcenter 1 +object/building/naboo/hotel_naboo_theed.iff hotel +object/building/naboo/palace_naboo_theed.iff @map_loc_n:theed_palace capitol +object/building/naboo/shuttleport_naboo.iff shuttleport +object/building/naboo/starport_naboo.iff starport +object/building/military/outpost_cloning_facility.iff cloningfacility +object/building/military/outpost_cloning_facility_s02.iff cloningfacility +object/building/military/outpost_cloning_facility_s03.iff cloningfacility +object/building/military/outpost_starport.iff starport +object/building/military/small_imperial_cloning_facility.iff cloningfacility +object/building/military/small_imperial_cloning_facility_s02.iff cloningfacility +object/building/corellia/capitol_corellia.iff capitol +object/building/poi/scout_camp_s4.iff camp 1 +object/building/poi/scout_camp_s5.iff camp 1 +object/building/player/city/cloning_naboo.iff cloningfacility +object/building/player/city/cloning_corellia.iff cloningfacility +object/building/player/city/cloning_tatooine.iff cloningfacility +object/building/player/city/hospital_naboo.iff medicalcenter +object/building/player/city/hospital_corellia.iff medicalcenter +object/building/player/city/hospital_tatooine.iff medicalcenter +object/building/player/city/cityhall_tatooine.iff city +object/building/player/city/cityhall_naboo.iff city +object/building/player/city/cityhall_corellia.iff city +object/building/player/city/theater_tatooine.iff theater +object/building/player/city/theater_naboo.iff theater +object/building/player/city/theater_corellia.iff theater +object/building/player/city/shuttleport_tatooine.iff shuttleport +object/building/player/city/shuttleport_naboo.iff shuttleport +object/building/player/city/shuttleport_corellia.iff shuttleport +object/building/player/city/bank_corellia.iff bank +object/building/player/city/bank_tatooine.iff bank +object/building/player/city/bank_naboo.iff bank +object/building/player/city/cantina_tatooine.iff cantina +object/building/player/city/cantina_naboo.iff cantina +object/building/player/city/cantina_corellia.iff cantina +object/building/corellia/garage_corellia.iff garage +object/building/naboo/parking_garage_naboo_style_1.iff garage +object/building/tatooine/parking_garage_tatooine_style_1.iff garage +object/building/player/player_garage_tatooine_style_01.iff garage +object/building/player/player_garage_corellia_style_01.iff garage +object/building/player/player_garage_naboo_style_01.iff garage +object/building/tatooine/salon_tatooine.iff salon +object/building/corellia/salon_corellia.iff salon +object/building/naboo/salon_naboo.iff salon +object/building/faction_perk/hq/hq_s01_rebel_pvp.iff rebel sf_rebel_forward_base 1 +object/building/faction_perk/hq/hq_s01_imp_pvp.iff imperial sf_imperial_forward_base 1 +object/building/faction_perk/hq/hq_s02_rebel_pvp.iff rebel sf_rebel_minor_base 1 +object/building/faction_perk/hq/hq_s02_imp_pvp.iff imperial sf_imperial_minor_base 1 +object/building/faction_perk/hq/hq_s03_rebel_pvp.iff rebel sf_rebel_major_base 1 +object/building/faction_perk/hq/hq_s03_imp_pvp.iff imperial sf_imperial_major_base 1 +object/building/faction_perk/hq/hq_s04_rebel_pvp.iff rebel sf_rebel_hq 1 +object/building/faction_perk/hq/hq_s04_imp_pvp.iff imperial sf_imperial_hq 1 +object/building/faction_perk/hq/hq_s05_rebel_pvp.iff rebel sf_rebel_hq 1 +object/building/faction_perk/hq/hq_s05_imp_pvp.iff imperial sf_imperial_hq 1 +object/building/faction_perk/hq/hq_s04_rebel.iff rebel rebel_hq +object/building/faction_perk/hq/hq_s04_imp.iff imperial imperial_hq +object/building/faction_perk/hq/hq_s05_rebel.iff rebel rebel_hq +object/building/faction_perk/hq/hq_s05_imp.iff imperial imperial_hq +object/building/kashyyyk/mun_kachirho_starport.iff starport +object/building/mustafar/structures/must_new_mining_facility.iff cantina +object/building/mustafar/structures/must_mining_cantina_marker.iff starport +object/building/mustafar/structures/must_mining_clone_marker.iff cloningfacility +object/building/naboo/rori_restuss_starport.iff starport +object/building/naboo/rori_restuss_shuttleport.iff shuttleport +object/building/dathomir/dathomir_quarantine_zone_starport.iff starport +object/building/dathomir/dathomir_quarantine_zone_cantina.iff cantina diff --git a/serverdata/map/static_city_points.iff b/serverdata/map/static_city_points.iff deleted file mode 100644 index ae9f9332..00000000 Binary files a/serverdata/map/static_city_points.iff and /dev/null differ diff --git a/serverdata/map/static_city_points.sdf b/serverdata/map/static_city_points.sdf new file mode 100644 index 00000000..8b293e0a --- /dev/null +++ b/serverdata/map/static_city_points.sdf @@ -0,0 +1,37 @@ +planet city x z +s s f f +tatooine Mos Eisley 3528 -4804 +tatooine Bestine -1290 -3590 +tatooine Mos Espa -2902 2130 +tatooine Mos Entha 1291 3138 +tatooine Wayfar -5124 -6530 +tatooine Anchorhead 40 -5348 +tatooine Mos Taike 3813 2354 +corellia Coronet -178 -4504 +corellia Tyrena -5140 -2450 +corellia Bela Vistal 6766 -5692 +corellia Kor Vella -3420 3146 +corellia Doaba Guerfel 3274 5582 +corellia Vreni Island -5538 -6176 +naboo Theed -5488 4380 +naboo Keren 1888 2700 +naboo Moenia 4836 -4830.5 +naboo Dee'ja Peak 4686 -1375 +naboo Kaddara 5288 6687 +rori Narmle -5140 -2368 +rori Restuss 5318 5680 +rori Rebel Outpost 3677 -6447 +endor Research Outpost 3222 -3467 +endor Smuggler Outpost -898 1587 +talus Dearic 422 -3004 +talus Nashal 4163 5220 +yavin4 Mining Outpost -312 4865 +yavin4 Labor Outpost -6925 -5707 +dantooine Mining Outpost -640 2486 +dantooine Pirate Outpost 1588 -6399 +dantooine Imperial Outpost -4224 -2400 +dathomir Trade Outpost 599 3071 +dathomir Quarentine Zone -6358 930 +dathomir Science Outpost -85 -1600 +lok Nym's Stronghold 440 5029 +lok Imperial Outpost -1920 -3084 diff --git a/src/resources/client_info/DataFactory.java b/src/resources/client_info/DataFactory.java index 464bf83c..37ed07eb 100644 --- a/src/resources/client_info/DataFactory.java +++ b/src/resources/client_info/DataFactory.java @@ -27,21 +27,14 @@ package resources.client_info; -import utilities.ByteUtilities; - import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; /** * Created by Waverunner on 6/9/2015 */ public abstract class DataFactory { - // readFile only called if dataMap doesn't contain the file as a key or it's value is null protected ClientData readFile(String file) { if (file == null || file.isEmpty()) { System.err.println("File cannot be null or empty!"); @@ -64,6 +57,27 @@ public abstract class DataFactory { return clientData; } + protected File writeFile(SWGFile swgFile, ClientData data) { + if (swgFile == null || data == null) { + System.err.println("File or data objects cannot be null or empty!"); + return null; + } + + File save = new File(swgFile.getFileName()); + data.writeIff(swgFile); + try { + swgFile.save(save); + } catch (IOException e) { + e.printStackTrace(); + } + + return save; + } + protected abstract ClientData createDataObject(String type); + protected ClientData createDataObject(SWGFile swgFile) { + return createDataObject(swgFile.getType()); + } + protected abstract String getFolder(); } diff --git a/src/resources/client_info/IffNode.java b/src/resources/client_info/IffNode.java index d859b8fe..f8afaf13 100644 --- a/src/resources/client_info/IffNode.java +++ b/src/resources/client_info/IffNode.java @@ -67,26 +67,46 @@ public class IffNode { return bb.get(); } + public void writeByte(byte val) { + bb.order(ByteOrder.LITTLE_ENDIAN).put(val); + } + public short readShort() { initBuffer(); return bb.order(ByteOrder.LITTLE_ENDIAN).getShort(); } + public void writeShort(short val) { + bb.order(ByteOrder.LITTLE_ENDIAN).putShort(val); + } + public int readInt() { initBuffer(); return bb.order(ByteOrder.LITTLE_ENDIAN).getInt(); } + public void writeInt(int val) { + bb.order(ByteOrder.LITTLE_ENDIAN).putInt(val); + } + public float readFloat() { initBuffer(); return bb.getFloat(); } + public void writeFloat(float val) { + bb.putFloat(val); + } + public long readLong() { initBuffer(); return bb.order(ByteOrder.LITTLE_ENDIAN).getLong(); } + public void writeLong(long val) { + bb.order(ByteOrder.LITTLE_ENDIAN).putLong(val); + } + public int readUInt() { initBuffer(); return bb.order(ByteOrder.BIG_ENDIAN).getInt(); @@ -119,6 +139,11 @@ public class IffNode { return string; } + public void writeString(String s) { + bb.put(s.getBytes(Charset.forName("US-ASCII"))); + writeByte((byte) 0); + } + public void readChunk(ChunkReader reader) { initBuffer(); while(bb.hasRemaining()) { @@ -198,6 +223,14 @@ public class IffNode { if (bb == null) bb = ByteBuffer.wrap(getChunkData()); } + public void initWriteBuffer(int size) { + bb = ByteBuffer.allocate(size); + } + + public void updateChunk() { + chunkData = bb.array(); + } + private byte[] createForm() { List childrenData = new ArrayList<>(); int size = 0; diff --git a/src/resources/client_info/SWGFile.java b/src/resources/client_info/SWGFile.java index 3e4e6db3..de3c5068 100644 --- a/src/resources/client_info/SWGFile.java +++ b/src/resources/client_info/SWGFile.java @@ -45,6 +45,11 @@ public class SWGFile { public SWGFile() {} + public SWGFile(String fileName, String type) { + this(type); + this.fileName = fileName; + } + public SWGFile(String type) { this.type = type; this.master = new IffNode(type, true); diff --git a/src/resources/client_info/ServerFactory.java b/src/resources/client_info/ServerFactory.java index a829705a..097e0e30 100644 --- a/src/resources/client_info/ServerFactory.java +++ b/src/resources/client_info/ServerFactory.java @@ -29,6 +29,17 @@ package resources.client_info; import resources.client_info.visitors.DatatableData; +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * Created by Waverunner on 6/9/2015 @@ -42,6 +53,138 @@ public final class ServerFactory extends DataFactory { return (data != null ? (DatatableData) data : null); } + public void updateServerIffs() throws IOException { + File root = new File(getFolder()); + + Files.walkFileTree(root.toPath(), new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException { + if (path.toString().endsWith("sdf")) { + String name = path.toString(); + name = name.substring(0, name.length() - 4) + ".iff"; + + File iff = new File(name); + + if (!iff.exists()) { + convertSif(path, name); + System.out.println("Created Server Datatable: " + name); + } else { + File sif = path.toFile(); + if (sif.lastModified() > iff.lastModified()) { + convertSif(path, name); + System.out.println("Updated Server Datatable: " + name); + } + } + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException { + return FileVisitResult.CONTINUE; + } + }); + } + + private void convertSif(Path sif, String newPath) { + SWGFile swgFile = new SWGFile(newPath, "DTII"); + + DatatableData data = (DatatableData) createDataObject(swgFile); + + String[] columnTypes = null; + String[] columnNames = null; + Object[][] table = null; + + List defaultValues = new ArrayList<>(); + try { + int lineNum = -1; + + List rows = Files.readAllLines(sif); + Iterator itr = rows.iterator(); + while (itr.hasNext()) { + String row = itr.next(); + if (row == null || row.isEmpty() || row.startsWith("#") || row.startsWith("//")) { + itr.remove(); + continue; + } + + // Don't break out of the loop, make sure we remove all the commented/null/empty rows + if (!(lineNum <= 1)) + continue; + + lineNum++; + if (lineNum == 0) { + columnNames = row.split("\t"); + } else if (lineNum == 1) { + columnTypes = row.split("\t"); + for (int i = 0; i < columnTypes.length; i++) { + String columnType = columnTypes[i]; + if (columnType.contains("[")) { + String[] split = columnType.split("\\["); + columnTypes[i] = split[0].toLowerCase(); + defaultValues.add(split[1].replace("]", "")); + } else { + columnTypes[i] = columnType.toLowerCase(); + defaultValues.add(""); + } + } + } + itr.remove(); + } + + if (columnNames == null || columnTypes == null) { + System.err.println("Failed to convert sif " + sif.getFileName()); + return; + } + + table = new Object[rows.size()][columnTypes.length]; + + for (int i = 0; i < rows.size(); i++) { + createDatatableRow(i, rows.get(i), columnTypes, table, defaultValues); + } + + } catch (IOException e) { + e.printStackTrace(); + } + + data.setColumnNames(columnNames); + data.setColumnTypes(columnTypes); + data.setTable(table); + + writeFile(swgFile, data); + } + + private void createDatatableRow(int rowNum, String line, String[] columnTypes, Object[][] table, List defValues) { + String[] values = line.split("\t", -1); + + for (int t = 0; t < columnTypes.length; t++) { + String type = columnTypes[t]; + String val = values[t]; + + if (val.isEmpty() && !defValues.get(t).isEmpty()) + val = defValues.get(t); + + switch(type) { + case "b": table[rowNum][t] = Boolean.valueOf(val); break; + case "h": + case "i": table[rowNum][t] = Integer.valueOf(val); break; + case "f": table[rowNum][t] = Float.valueOf(val); break; + case "s": table[rowNum][t] = val; break; + default: System.err.println("Don't know how to parse type " + type); break; + } + } + } + @Override protected ClientData createDataObject(String type) { switch(type) { @@ -55,7 +198,7 @@ public final class ServerFactory extends DataFactory { return "./serverdata/"; } - private static ServerFactory getInstance() { + public static ServerFactory getInstance() { if (instance == null) instance = new ServerFactory(); return instance; diff --git a/src/resources/client_info/visitors/DatatableData.java b/src/resources/client_info/visitors/DatatableData.java index 500e3f5a..c856a3b3 100644 --- a/src/resources/client_info/visitors/DatatableData.java +++ b/src/resources/client_info/visitors/DatatableData.java @@ -62,6 +62,79 @@ public class DatatableData extends ClientData { } } + @Override + public void writeIff(SWGFile iff) { + iff.addForm("0001"); + writeColumns(iff.addChunk("COLS")); + writeTypes(iff.addChunk("TYPE")); + writeRows(iff.addChunk("ROWS")); + } + + private void writeColumns(IffNode chunk) { + int size = getTableStringSize(columnNames); + + chunk.initWriteBuffer(size + 4); + + chunk.writeInt(columnNames.length); + for (String columnName : columnNames) { + chunk.writeString(columnName); + } + + chunk.updateChunk(); + } + + private void writeTypes(IffNode chunk) { + int size = getTableStringSize(columnTypes); + + chunk.initWriteBuffer(size); + + for (String columnType : columnTypes) { + chunk.writeString(columnType); + } + + chunk.updateChunk(); + } + + private void writeRows(IffNode chunk) { + int size = 0; + int rows = table.length; + + for (int i = 0; i < columnTypes.length; i++) { + String type = columnTypes[i]; + switch(type) { + case "b": + case "f": + case "h": + case "i": size += 4 * rows; break; + case "s": { + for (int r = 0; r < rows; r++) { + size += ((String) table[r][i]).length() + 1; + } + break; + } + default: System.err.println("Cannot write row type " + type); + } + } + chunk.initWriteBuffer(size + 4); + + chunk.writeInt(rows); + + for (int r = 0; r < rows; r++) { + for (int t = 0; t < columnTypes.length; t++) { + String type = columnTypes[t]; + switch(type) { + case "b": + case "h": + case "i": chunk.writeInt((Integer) table[r][t]); break; + case "f": chunk.writeFloat((Float) table[r][t]); break; + case "s": chunk.writeString((String) table[r][t]); break; + default: System.err.println("Cannot write datatable to type " + type); + } + } + } + chunk.updateChunk(); + } + private void parseTypes(IffNode chunk) { columnTypes = new String[columnNames.length]; @@ -190,4 +263,23 @@ public class DatatableData extends ClientData { return columnTypes[column]; } + public void setColumnNames(String[] columnNames) { + this.columnNames = columnNames; + } + + public void setColumnTypes(String[] columnTypes) { + this.columnTypes = columnTypes; + } + + public void setTable(Object[][] table) { + this.table = table; + } + + private int getTableStringSize(String[] table) { + int size = 0; + for (String s : table) { + size += s.length() + 1; + } + return size; + } } diff --git a/src/services/EngineManager.java b/src/services/EngineManager.java index d3968baa..08961089 100644 --- a/src/services/EngineManager.java +++ b/src/services/EngineManager.java @@ -28,8 +28,10 @@ package services; import java.io.File; +import java.io.IOException; import resources.Galaxy; +import resources.client_info.ServerFactory; import resources.config.ConfigFile; import resources.control.Manager; import resources.server_info.Config; @@ -46,6 +48,8 @@ public class EngineManager extends Manager { addChildService(networkManager); addChildService(shutdownService); + + initializeServerFactory(); } @Override @@ -56,7 +60,7 @@ public class EngineManager extends Manager { wipeCharacterDatabase(); if (config.getInt("WIPE-ODB-FILES", 0) == 1) wipeOdbFiles(); - + return super.initialize(); } @@ -73,5 +77,13 @@ public class EngineManager extends Manager { } } } - + + + private void initializeServerFactory() { + try { + ServerFactory.getInstance().updateServerIffs(); + } catch (IOException e) { + e.printStackTrace(); + } + } }