diff --git a/src/resources/client_info/ChunkReader.java b/src/resources/client_info/ChunkReader.java new file mode 100644 index 00000000..e36ec06a --- /dev/null +++ b/src/resources/client_info/ChunkReader.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 /// 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 resources.client_info; + +/** + * @author Waverunner + */ +public interface ChunkReader { + void handleReadChunk(IffNode chunk); +} diff --git a/src/resources/client_info/IffNode.java b/src/resources/client_info/IffNode.java index 83e66b4f..c32323f5 100644 --- a/src/resources/client_info/IffNode.java +++ b/src/resources/client_info/IffNode.java @@ -112,10 +112,18 @@ public class IffNode { public String readString() { initBuffer(); String string = ByteUtilities.nextString(bb); - bb.get(); + if (!string.isEmpty()) + bb.get(); return string; } + public void readChunk(ChunkReader reader) { + initBuffer(); + while(bb.hasRemaining()) { + reader.handleReadChunk(this); + } + } + public byte[] getBytes() { return isForm ? createForm() : createChunk(); } @@ -174,7 +182,7 @@ public class IffNode { return parent; } - public int readBuffer(ByteBuffer bb) { + public int populateFromBuffer(ByteBuffer bb) { String nodeTag = getTag(bb); if (!nodeTag.equals("FORM")) { tag = nodeTag; @@ -212,7 +220,7 @@ public class IffNode { IffNode child = new IffNode(); child.parent = this; - read += child.readBuffer(bb); + read += child.populateFromBuffer(bb); addChild(child); } return 4 + size; diff --git a/src/resources/client_info/SWGFile.java b/src/resources/client_info/SWGFile.java index 02c9decf..fc86c14b 100644 --- a/src/resources/client_info/SWGFile.java +++ b/src/resources/client_info/SWGFile.java @@ -72,7 +72,7 @@ public class SWGFile { master = new IffNode("", true); currentForm = master; - master.readBuffer(bb); + master.populateFromBuffer(bb); type = master.getTag(); fileName = file.getAbsolutePath(); } diff --git a/src/resources/client_info/visitors/ProfTemplateData.java b/src/resources/client_info/visitors/ProfTemplateData.java index 171ad911..ed966abd 100644 --- a/src/resources/client_info/visitors/ProfTemplateData.java +++ b/src/resources/client_info/visitors/ProfTemplateData.java @@ -32,6 +32,8 @@ import java.util.ArrayList; import java.util.List; import resources.client_info.ClientData; +import resources.client_info.IffNode; +import resources.client_info.SWGFile; import utilities.ByteUtilities; public class ProfTemplateData extends ClientData { @@ -57,19 +59,35 @@ public class ProfTemplateData extends ClientData { } } - public void handleChunkData(String form, String node, ByteBuffer data) { - switch(node) { - - case "NAME": - templates.add(new Template(ByteUtilities.nextString(data))); - break; - - case "ITEM": - int index = templates.size() - 1; - data.getInt(); // empty int it seems for all items - templates.get(index).getItems().add(ByteUtilities.nextString(data)); - break; - + @Override + public void readIff(SWGFile iff) { + iff.enterNextForm(); // Version + + IffNode form; + while((form = iff.enterNextForm()) != null) { + if (!form.getTag().equals("PTMP")) { + iff.exitForm(); + continue; + } + + IffNode chunk; + while((chunk = iff.enterNextChunk()) != null) { + String tag = chunk.getTag(); + switch(tag) { + case "NAME": + templates.add(new Template(chunk.readString())); + break; + + case "ITEM": + int index = templates.size() - 1; + chunk.readInt(); // empty int it seems for all items + templates.get(index).getItems().add(chunk.readString()); + break; + + default: break; + } + } + iff.exitForm(); } } diff --git a/src/resources/client_info/visitors/SlotArrangementData.java b/src/resources/client_info/visitors/SlotArrangementData.java index a31bbb7e..771470ab 100644 --- a/src/resources/client_info/visitors/SlotArrangementData.java +++ b/src/resources/client_info/visitors/SlotArrangementData.java @@ -32,16 +32,31 @@ import java.util.ArrayList; import java.util.List; import resources.client_info.ClientData; +import resources.client_info.IffNode; +import resources.client_info.SWGFile; import utilities.ByteUtilities; public class SlotArrangementData extends ClientData { private List > occupiedSlots = new ArrayList<>(); - public void handleChunkData(String form, String chunk, ByteBuffer data) { - + @Override + public void readIff(SWGFile iff) { + iff.enterNextForm(); // Version + ArrayList slots = new ArrayList<>(); - + IffNode chunk; + while((chunk = iff.enterNextChunk()) != null) { + slots.add(chunk.readString()); + } + + occupiedSlots.add(slots); + } + + public void handleChunkData(String form, String chunk, ByteBuffer data) { + + ArrayList slots = new ArrayList<>(); + while(data.hasRemaining()) { slots.add(ByteUtilities.nextString(data)); data.get(); @@ -49,7 +64,7 @@ public class SlotArrangementData extends ClientData { occupiedSlots.add(slots); } - + public List > getArrangement() { return occupiedSlots; } diff --git a/src/resources/client_info/visitors/SlotDefinitionData.java b/src/resources/client_info/visitors/SlotDefinitionData.java index d5d6d5e1..dfc4666b 100644 --- a/src/resources/client_info/visitors/SlotDefinitionData.java +++ b/src/resources/client_info/visitors/SlotDefinitionData.java @@ -27,11 +27,11 @@ ***********************************************************************************/ package resources.client_info.visitors; -import java.nio.ByteBuffer; import java.util.HashMap; import resources.client_info.ClientData; -import utilities.ByteUtilities; +import resources.client_info.IffNode; +import resources.client_info.SWGFile; public class SlotDefinitionData extends ClientData { @@ -47,33 +47,32 @@ public class SlotDefinitionData extends ClientData { public int unk1; } - public void handleChunkData(String form, String node, ByteBuffer data) { - while (data.hasRemaining()) { + @Override + public void readIff(SWGFile iff) { + + IffNode data = iff.enterChunk("DATA"); + data.readChunk((chunk) -> { SlotDefinition def = new SlotDefinition(); - def.name = ByteUtilities.nextString(data); - def.isGlobal = (data.get() == (byte) 1); - def.isModdable = (data.get() == (byte) 1); - def.isExclusive = (data.get() == (byte) 1); - def.hasHardpoint = (data.get() == (byte) 1); + def.name = chunk.readString(); + def.isGlobal = chunk.readBoolean(); + def.isModdable = chunk.readBoolean(); + def.isExclusive = chunk.readBoolean(); + def.hasHardpoint = chunk.readBoolean(); if (def.hasHardpoint) { - data.mark(); - if (data.get() != (byte) 0) { - data.reset(); - def.hardpointName = ByteUtilities.nextString(data); - data.get(); + if (chunk.readByte() != 0) { + chunk.skip(-1); + def.hardpointName = chunk.readString(); } } else { - data.get(); + chunk.readByte(); } - def.unk1 = data.getInt(); // This seems to be a couple more booleans together, not sure what they would represent. + def.unk1 = chunk.readInt(); // This seems to be a couple more booleans together, not sure what they would represent. definitions.put(def.name, def); - - //System.out.println("Added slot definition: " + def.name + (def.hardpointName != null ? " - Hardpoint name: " + def.hardpointName : "")); - } + }); } public SlotDefinition getDefinition(String name) { diff --git a/src/resources/client_info/visitors/SlotDescriptorData.java b/src/resources/client_info/visitors/SlotDescriptorData.java index f31f193b..d2be585a 100644 --- a/src/resources/client_info/visitors/SlotDescriptorData.java +++ b/src/resources/client_info/visitors/SlotDescriptorData.java @@ -32,21 +32,25 @@ import java.util.ArrayList; import java.util.List; import resources.client_info.ClientData; +import resources.client_info.IffNode; +import resources.client_info.SWGFile; import utilities.ByteUtilities; public class SlotDescriptorData extends ClientData { private List slots = new ArrayList<>(); - public void handleChunkData(String form, String node, ByteBuffer data) { - if (!form.equals("0000") && !node.equals("DATA")) - return; - - while (data.hasRemaining()) { - slots.add(ByteUtilities.nextString(data)); - data.get(); + @Override + public void readIff(SWGFile iff) { + iff.enterNextForm(); // version + + IffNode chunk = iff.enterChunk("DATA"); + + String slot; + while((slot = chunk.readString()) != null && !slot.isEmpty()) { + slots.add(slot); } - + } public List getSlots() { diff --git a/src/services/player/CharacterCreationService.java b/src/services/player/CharacterCreationService.java index 8141bbeb..4f614392 100644 --- a/src/services/player/CharacterCreationService.java +++ b/src/services/player/CharacterCreationService.java @@ -312,6 +312,8 @@ public class CharacterCreationService extends Service { for (String template : profTemplates.get(profession).getItems(ClientFactory.formatToSharedFile(race))) { TangibleObject item = createTangible(objManager, template); + if (item == null) + return; // Move the new item to the player's clothing slots and add to equipment list item.moveToContainer(player, player); player.addEquipment(item);