diff --git a/src/resources/objects/building/BuildingObject.java b/src/resources/objects/building/BuildingObject.java index ed6adb3c..f1b95da7 100644 --- a/src/resources/objects/building/BuildingObject.java +++ b/src/resources/objects/building/BuildingObject.java @@ -59,7 +59,7 @@ public class BuildingObject extends TangibleObject implements IPersistent, Seria private Vector banList = new Vector(); public BuildingObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { - super(objectID, planet, Template, position, orientation); + super(objectID, planet, position, orientation, Template); messageBuilder = new BuildingMessageBuilder(this); this.setConditionDamage(100); } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 84e0bf2c..6f55ab4f 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -187,7 +187,7 @@ public class CreatureObject extends TangibleObject implements Serializable { private transient SWGObject useTarget; public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { - super(objectID, planet, Template, position, orientation); + super(objectID, planet, position, orientation, Template); messageBuilder = new CreatureMessageBuilder(this); loadTemplateData(); skills = new ArrayList(); @@ -234,12 +234,6 @@ public class CreatureObject extends TangibleObject implements Serializable { } - public void setCustomName2(String customName) { - setCustomName(customName); - - notifyObservers(messageBuilder.buildCustomNameDelta(customName), true); - } - public int getBankCredits() { synchronized(objectMutex) { return bankCredits; @@ -351,25 +345,6 @@ public class CreatureObject extends TangibleObject implements Serializable { } - @Override - public int getOptionsBitmask() { - synchronized(objectMutex) { - return optionsBitmask; - } - } - - @Override - public void setOptionsBitmask(int optionBitmask) { - synchronized(objectMutex) { - this.optionsBitmask = optionBitmask; - } - - IoBuffer optionDelta = messageBuilder.buildOptionMaskDelta(optionBitmask); - - notifyObservers(optionDelta, true); - - } - public void setOptions(int options, boolean add) { synchronized(objectMutex) { if (options != 0) { @@ -485,15 +460,9 @@ public class CreatureObject extends TangibleObject implements Serializable { this.inspirationTick = inspirationTick; } } - - @Override + public void setFaction(String faction) { - synchronized(objectMutex) { - this.faction = faction; - } - - notifyObservers(messageBuilder.buildFactionDelta(faction), true); - + super.setFaction(faction); CreatureObject companion = NGECore.getInstance().mountService.getCompanion(this); @@ -502,13 +471,8 @@ public class CreatureObject extends TangibleObject implements Serializable { } } - @Override public void setFactionStatus(int factionStatus) { - synchronized(objectMutex) { - this.factionStatus = factionStatus; - } - - notifyObservers(messageBuilder.buildFactionStatusDelta(factionStatus), true); + super.setFactionStatus(factionStatus); CreatureObject companion = NGECore.getInstance().mountService.getCompanion(this); @@ -812,21 +776,6 @@ public class CreatureObject extends TangibleObject implements Serializable { return missionCriticalObjects; } - public byte getCombatFlag() { - synchronized(objectMutex) { - return combatFlag; - } - } - - public void setCombatFlag(byte combatFlag) { - synchronized(objectMutex) { - this.combatFlag = combatFlag; - } - IoBuffer combatDelta = messageBuilder.buildCombatFlagDelta(combatFlag); - - notifyObservers(combatDelta, true); - } - public short getLevel() { synchronized(objectMutex) { return level; diff --git a/src/resources/objects/factorycrate/FactoryCrateObject.java b/src/resources/objects/factorycrate/FactoryCrateObject.java index 8c82e824..b735ece8 100644 --- a/src/resources/objects/factorycrate/FactoryCrateObject.java +++ b/src/resources/objects/factorycrate/FactoryCrateObject.java @@ -69,8 +69,8 @@ public class FactoryCrateObject extends TangibleObject implements Serializable { } - public FactoryCrateObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation) { - super(objectID, planet, template, position, orientation); + public FactoryCrateObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); this.messageBuilder = new FactoryCrateMessageBuilder(this); this.contents = new Vector(); this.contentObjectQuantity = 0; diff --git a/src/resources/objects/harvester/HarvesterObject.java b/src/resources/objects/harvester/HarvesterObject.java index d53eb991..50f87e23 100644 --- a/src/resources/objects/harvester/HarvesterObject.java +++ b/src/resources/objects/harvester/HarvesterObject.java @@ -118,8 +118,8 @@ public class HarvesterObject extends InstallationObject implements Serializable private int specRate; - public HarvesterObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation){ - super(objectID, planet, template, position, orientation); + public HarvesterObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); this.setConditionDamage(100); messageBuilder = new HarvesterMessageBuilder(this); installationMessageBuilder = new InstallationMessageBuilder((InstallationObject)this); diff --git a/src/resources/objects/installation/InstallationObject.java b/src/resources/objects/installation/InstallationObject.java index c6269dc3..b9cc98d6 100644 --- a/src/resources/objects/installation/InstallationObject.java +++ b/src/resources/objects/installation/InstallationObject.java @@ -39,8 +39,8 @@ public class InstallationObject extends TangibleObject implements Serializable { private static final long serialVersionUID = 1L; private transient InstallationMessageBuilder messageBuilder; - public InstallationObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation){ - super(objectID, planet, template, position, orientation); + public InstallationObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); messageBuilder = new InstallationMessageBuilder(this); } diff --git a/src/resources/objects/resource/ResourceContainerObject.java b/src/resources/objects/resource/ResourceContainerObject.java index 66ac4a80..aef9ce0e 100644 --- a/src/resources/objects/resource/ResourceContainerObject.java +++ b/src/resources/objects/resource/ResourceContainerObject.java @@ -144,8 +144,8 @@ public class ResourceContainerObject extends TangibleObject implements Serializa } - public ResourceContainerObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation){ - super(objectID, planet, template, position, orientation); + public ResourceContainerObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ + super(objectID, planet, position, orientation, template); messageBuilder = new ResourceContainerMessageBuilder(this); this.setAttachment("radial_filename", "resourceContainer"); } diff --git a/src/resources/objects/tangible/TangibleMessageBuilder.java b/src/resources/objects/tangible/TangibleMessageBuilder.java index befaeddf..b6f4e4b8 100644 --- a/src/resources/objects/tangible/TangibleMessageBuilder.java +++ b/src/resources/objects/tangible/TangibleMessageBuilder.java @@ -21,11 +21,8 @@ ******************************************************************************/ package resources.objects.tangible; -import java.nio.ByteOrder; import java.util.Map; -import org.apache.mina.core.buffer.IoBuffer; - import resources.objects.ObjectMessageBuilder; import engine.resources.objects.Builder; @@ -39,177 +36,6 @@ public class TangibleMessageBuilder extends ObjectMessageBuilder { super(); } - public IoBuffer buildBaseline3() { - TangibleObject tangible = (TangibleObject) object; - IoBuffer buffer = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.setAutoExpand(true); - - buffer.putShort((short) 0x0D); - buffer.putFloat(object.getComplexity()); - buffer.put(getAsciiString(object.getStfFilename())); - buffer.putInt(0); - buffer.put(getAsciiString(object.getStfName())); - - if(object.getCustomName() == null || object.getCustomName().length() < 1) - buffer.putInt(0); - else - buffer.put(getUnicodeString(object.getCustomName())); - buffer.putInt(object.getVolume()); - buffer.putInt(0); - buffer.putInt(tangible.getFactionStatus()); // faction vars - - if(tangible.getCustomization() == null || tangible.getCustomization().length <= 0) - buffer.putShort((short) 0); - else { - buffer.putShort((short) tangible.getCustomization().length); - buffer.put(tangible.getCustomization()); - } - - buffer.putInt(0); - buffer.putInt(0); - - //buffer.putInt(0); - if(tangible.getOptionsBitmask() == 0) - tangible.setOptionsBitmask(0x100); - buffer.putInt(tangible.getOptionsBitmask()); - buffer.putInt(tangible.getUses()); // number of item uses - buffer.putInt(tangible.getConditionDamage()); - buffer.putInt(tangible.getMaxDamage()); - buffer.put((byte) (tangible.isStaticObject() ? 1 : 0)); - - int size = buffer.position(); - buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); - - buffer.flip(); - buffer = createBaseline("TANO", (byte) 3, buffer, size); - - return buffer; - } - - public IoBuffer buildBaseline6() { - TangibleObject tangible = (TangibleObject) object; - IoBuffer buffer = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.setAutoExpand(true); - buffer.putShort((short) 8); - buffer.putInt(0x43); - buffer.put(getAsciiString(tangible.getDetailFilename())); - buffer.putInt(0); - buffer.put(getAsciiString(tangible.getDetailName())); - buffer.putLong(0); - buffer.putLong(0); - buffer.putLong(0); // unks - buffer.putLong(0); - buffer.putInt(0); - buffer.put((byte) 0); - - int size = buffer.position(); - buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); - - buffer.flip(); - buffer = createBaseline("TANO", (byte) 6, buffer, size); - - return buffer; - } - - public IoBuffer buildBaseline8() { - IoBuffer buffer = bufferPool.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putShort((short) 0); - int size = buffer.position(); - buffer = IoBuffer.allocate(size).put(buffer.array(), 0, size); - buffer.flip(); - buffer = createBaseline("TANO", (byte) 8, buffer, size); - - return buffer; - } - - public IoBuffer buildBaseline9() { - IoBuffer buffer = bufferPool.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putShort((short) 0); - int size = buffer.position(); - buffer = IoBuffer.allocate(size).put(buffer.array(), 0, size); - buffer.flip(); - buffer = createBaseline("TANO", (byte) 9, buffer, size); - - return buffer; - } - - public IoBuffer buildConditionDamageDelta(int conditionDamage) { - - IoBuffer buffer = bufferPool.allocate(4, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putInt(conditionDamage); - int size = buffer.position(); - buffer.flip(); - buffer = createDelta("TANO", (byte) 3, (short) 1, (short) 0x0A, buffer, size + 4); - - return buffer; - - } - - public IoBuffer buildCustomNameDelta(String customName) { - IoBuffer buffer = bufferPool.allocate(getUnicodeString(customName).length, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.put(getUnicodeString(customName)); - int size = buffer.position(); - buffer.flip(); - buffer = createDelta("TANO", (byte) 3, (short) 1, (short) 2, buffer, size + 4); - return buffer; - - } - - public IoBuffer buildCustomizationDelta(byte[] customization) { - IoBuffer buffer = bufferPool.allocate(customization.length + 2, false).order(ByteOrder.LITTLE_ENDIAN); - - buffer.putShort((short) customization.length); - buffer.put(customization); - - int size = buffer.position(); - buffer.flip(); - buffer = createDelta("TANO", (byte) 3, (short) 1, (short) 6, buffer, size + 4); - return buffer; - } - - public IoBuffer buildDelta3() { - IoBuffer buffer = bufferPool.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.setAutoExpand(true); - buffer.putShort((short)5); - buffer.putInt(0x12862153); - buffer.putLong(getObject().getObjectID()); - buffer.putInt(0x54414E4F); - buffer.put((byte)3); - buffer.putInt(8);//buffer.putInt(8+6); - - buffer.putShort((short) 2); - buffer.putShort((short)8); - buffer.put((byte)0); - buffer.putShort((short) 0x21); - buffer.put((byte)0); - -// buffer.putShort((short) 0); -// buffer.putFloat(4.0F); - - int size = buffer.position(); - buffer.flip(); - return IoBuffer.allocate(size).put(buffer.array(), 0, size).flip(); - } - - public IoBuffer buildAssemblyDelta3() { - IoBuffer buffer = bufferPool.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.setAutoExpand(true); - buffer.putShort((short)5); - buffer.putInt(0x12862153); - buffer.putLong(getObject().getObjectID()); - buffer.putInt(0x54414E4F); - buffer.put((byte)3); - buffer.putInt(8);//buffer.putInt(8+6); - - buffer.putShort((short) 1); - buffer.putShort((short)0x0B); - buffer.putInt(0x000003E8); // ? - - int size = buffer.position(); - buffer.flip(); - return IoBuffer.allocate(size).put(buffer.array(), 0, size).flip(); - } - @Override public void buildBaseline3(Map baselineBuilders, Map deltaBuilders) { super.buildBaseline3(baselineBuilders, deltaBuilders); diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 9da87652..3d529b47 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -45,74 +45,50 @@ import resources.datatables.Options; import resources.datatables.PvpStatus; import resources.loot.LootGroup; import resources.objects.ObjectMessageBuilder; +import resources.objects.SWGList; +import resources.objects.SWGSet; import resources.objects.creature.CreatureObject; -import com.sleepycat.persist.model.NotPersistent; -import com.sleepycat.persist.model.Persistent; - import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.IDManagerVisitor; import engine.clients.Client; +import engine.resources.common.CRC; import engine.resources.common.RGB; +import engine.resources.objects.Baseline; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=12) +@SuppressWarnings("unchecked") public class TangibleObject extends SWGObject implements Serializable { private static final long serialVersionUID = 1L; - // TODO: Thread safety - protected int incapTimer = 10; - private int conditionDamage = 0; - protected int pvpBitmask = 0; - protected byte[] customization; - private List componentCustomizations = new ArrayList(); - private Map customizationVariables = new HashMap(); - protected int optionsBitmask = 0; - private int uses = 0; - private int maxDamage = 1000; - private boolean staticObject = true; - protected String faction = ""; // Says you're "Imperial Special Forces" if it's 0 for some reason - protected int factionStatus = 0; - @NotPersistent - protected transient Vector defendersList = new Vector(); // unused in packets but useful for the server - @NotPersistent private transient TangibleMessageBuilder messageBuilder; + private Map customizationVariables = new HashMap(); + + protected transient Vector defendersList = new Vector(); + + private transient int pvpBitmask = 0; + //private TreeSet> lootSpecification = new TreeSet>(); private transient List lootGroups = new ArrayList(); - - @NotPersistent - private transient boolean looted = false; // These 4 should not need to be persisted, since a looted corpse will get wiped with server restart - @NotPersistent + private transient boolean looted = false; private transient boolean lootLock = false; - @NotPersistent private transient boolean creditRelieved = false; - @NotPersistent private transient boolean lootItem = false; - - private boolean stackable = false; - private int stackCount = 1; - private boolean noSell = false; - private byte junkType = -1; - private int junkDealerPrice = 0; - - private String serialNumber; - - @NotPersistent private transient TangibleObject killer = null; - public TangibleObject(long objectID, Planet planet, String template) { - super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0), template); + public TangibleObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); messageBuilder = new TangibleMessageBuilder(this); if (this.getClass().getSimpleName().equals("TangibleObject")) setIntAttribute("volume", 1); } - public TangibleObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation) { - super(objectID, planet, position, orientation, template); + public TangibleObject(long objectID, Planet planet, String template) { + super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0), template); messageBuilder = new TangibleMessageBuilder(this); if (this.getClass().getSimpleName().equals("TangibleObject")) setIntAttribute("volume", 1); } @@ -122,136 +98,264 @@ public class TangibleObject extends SWGObject implements Serializable { messageBuilder = new TangibleMessageBuilder(this); } - @Override public void initAfterDBLoad() { super.init(); defendersList = new Vector(); messageBuilder = new TangibleMessageBuilder(this); } - @Deprecated - public void setCustomName2(String customName) { - setCustomName(customName); - System.err.println("setCustomName2 is now deprecated - please use setCustomName"); - } - - public int getIncapTimer() { - return incapTimer; - } - - public void setIncapTimer(int incapTimer) { - this.incapTimer = incapTimer; + public Baseline getOtherVariables() { + Baseline baseline = super.getOtherVariables(); + baseline.put("stackable", false); + baseline.put("noSell", false); + baseline.put("junkType", (byte) -1); + baseline.put("junkDealerPrice", 0); + return baseline; } - public int getUses() { - return uses; + public Baseline getBaseline3() { + Baseline baseline = super.getBaseline3(); + baseline.put("faction", 0); + baseline.put("factionStatus", 0); + baseline.put("customization", new byte[] { }); + baseline.put("componentCustomizations", new SWGList(this, 3, 7, false)); + baseline.put("optionsBitmask", 0); + baseline.put("uses", 0); + baseline.put("conditionDamage", 0); + baseline.put("maximumCondition", 100); + baseline.put("staticObject", false); + return baseline; } - public void setUses(int uses) { - this.uses = uses; - setIntAttribute("uses", uses); + public Baseline getBaseline6() { + Baseline baseline = super.getBaseline6(); + baseline.put("inCombat", false); + baseline.put("defendersList", new SWGSet(this, 6, 3, false)); + baseline.put("4", 0); + baseline.put("5", new SWGList(this, 6, 5, false)); + baseline.put("6", new SWGList(this, 6, 6, false)); + baseline.put("7", (long) 0); // Unknown List (HUGE structure inside) + return baseline; } - - public synchronized int getConditionDamage() { - return conditionDamage; + + public Baseline getBaseline8() { + Baseline baseline = super.getBaseline8(); + return baseline; } - - public synchronized void setConditionDamage(int conditionDamage) { - if(conditionDamage < 0) - conditionDamage = 0; - else if(conditionDamage > getMaxDamage()) - conditionDamage = getMaxDamage(); - this.conditionDamage = conditionDamage; - notifyObservers(messageBuilder.buildConditionDamageDelta(conditionDamage), true); - if (maxDamage > 0) { - this.setStringAttribute("condition", (maxDamage + "/" + (maxDamage - conditionDamage))); - } + + public Baseline getBaseline9() { + Baseline baseline = super.getBaseline9(); + return baseline; } - + + public String getFaction() { + return NGECore.getInstance().factionService.getName((int) getBaseline(3).get("faction")); + } + + public void setFaction(String faction) { + notifyClients(getBaseline(3).set("faction", CRC.StringtoCRC(faction)), true); + updatePvpStatus(); + } + + public int getFactionStatus() { + return (int) getBaseline(3).get("factionStatus"); + } + + public void setFactionStatus(int factionStatus) { + notifyClients(getBaseline(3).set("factionStatus", factionStatus), true); + } + public byte[] getCustomization() { - return customization; + return (byte[]) baseline3.get("customization"); } - + public void setCustomization(byte[] customization) { - synchronized(objectMutex) { - this.customization = customization; + notifyClients(getBaseline(3).set("customization", customization), true); + } + + public SWGList getComponentCustomizations() { + return (SWGList) getBaseline(3).get("componentCustomizations"); + } + + public void setComponentCustomizations(List componentCustomizations) { + getComponentCustomizations().addAll(componentCustomizations); + } + + public Byte getCustomizationVariable(String type) { + if (customizationVariables.containsKey(type)) { + return customizationVariables.get(type); + } else { + System.err.println("Error: object doesn't have customization variable " + type); } - notifyObservers(messageBuilder.buildCustomizationDelta(customization), true); + return null; } - - public List getComponentCustomizations() { - return componentCustomizations; + + public void setCustomizationVariable(String type, byte value) { + if (customizationVariables.containsKey(type)) { + customizationVariables.replace(type, value); + } else { + customizationVariables.put(type, value); + } + + setCustomization(getCustomizationBytes()); } - - public void setComponentCustomizations(List componentCustomizations) { - this.componentCustomizations = componentCustomizations; + + public void removeCustomizationVariable(String type) { + if (customizationVariables.containsKey(type)) { + customizationVariables.remove(type); + setCustomization(getCustomizationBytes()); + } } - + + private byte[] getCustomizationBytes() { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + try { + IDManagerVisitor visitor = ClientFileManager.loadFile("customization/customization_id_manager.iff", IDManagerVisitor.class); + + stream.write((byte) 0x02); // Unk + stream.write((byte) customizationVariables.size()); // Number of customization attributes + + for (String type : customizationVariables.keySet()) { + stream.write(visitor.getAttributeIndex(type)); // Index of palette type within "customization/customization_id_manager.iff" + stream.write(customizationVariables.get(type)); // Value/Index within palette + + // Seperator/Footer + stream.write((byte) 0xC3); + stream.write((byte) 0xBF); + stream.write((byte) 0x03); + } + + return stream.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + public int getOptionsBitmask() { - return optionsBitmask; + return (int) getBaseline(3).get("optionsBitmask"); } - + public void setOptionsBitmask(int optionsBitmask) { - this.optionsBitmask = optionsBitmask; + notifyClients(getBaseline(3).set("optionsBitmask", optionsBitmask), true); } public void setOptions(int options, boolean add) { - synchronized(objectMutex) { - if (options != 0) { - if (add) { - addOption(options); - } else { - removeOption(options); - } + if (options != 0) { + if (add) { + setOptionsBitmask(getOptionsBitmask() | options); + } else { + setOptionsBitmask(getOptionsBitmask() & ~options);; } } } public boolean getOption(int option) { - synchronized(objectMutex) { - return ((optionsBitmask & option) == option); + return ((getOptionsBitmask() & option) == option); + } + + public int getUses() { + return (int) getBaseline(3).get("uses"); + } + + public void setUses(int uses) { + notifyClients(getBaseline(3).set("uses", uses), true); + setIntAttribute("uses", uses); + } + + public int getIncapTimer() { + return getUses(); + } + + public void setIncapTimer(int incapTimer) { + notifyClients(getBaseline(3).set("uses", incapTimer), true); + } + + public int getConditionDamage() { + return (int) getBaseline(3).get("conditionDamage"); + } + + public void setConditionDamage(int conditionDamage) { + int maximumCondition = getMaximumCondition(); + + if (conditionDamage < 0) { + conditionDamage = 0; + } else if (conditionDamage > maximumCondition) { + conditionDamage = maximumCondition; + } + + notifyClients(getBaseline(3).set("conditionDamage", conditionDamage), true); + + if (getMaximumCondition() > 0) { + setStringAttribute("condition", (maximumCondition + "/" + (maximumCondition - conditionDamage))); } } - public void addOption(int option) { - setOptionsBitmask(getOptionsBitmask() | option); + public int getMaximumCondition() { + return (int) getBaseline(3).get("maximumCondition"); } - public void removeOption(int option) { - setOptionsBitmask(getOptionsBitmask() & ~option); + public void setMaximumCondition(int maximumCondition) { + notifyClients(getBaseline(3).set("maximumCondition", maximumCondition), true); + setStringAttribute("condition", (maximumCondition + "/" + (maximumCondition - getConditionDamage()))); } - public int getMaxDamage() { - return maxDamage; - } - - public void setMaxDamage(int maxDamage) { - this.maxDamage = maxDamage; - - this.setStringAttribute("condition", (maxDamage + "/" + (maxDamage - conditionDamage))); - } - public boolean isStaticObject() { - return staticObject; - } - - public void setStaticObject(boolean staticObject) { - this.staticObject = staticObject; + return (boolean) getBaseline(3).get("staticObject"); } - public int getPvPBitmask() { + public void setStaticObject(boolean staticObject) { + notifyClients(getBaseline(3).set("staticObject", staticObject), true); + } + + public boolean isInCombat() { + return (boolean) getBaseline(6).get("inCombat"); + } + + public void setInCombat(boolean inCombat) { + notifyClients(getBaseline(6).set("inCombat", inCombat), true); + } + + // All objects can be in combat (terminal mission flag bases, tutorial target box) + + public List getDefendersList() { + synchronized(objectMutex) { + return defendersList; + } + } + + public void addDefender(TangibleObject defender) { + defendersList.add(defender); + + if (!isInCombat()) { + setInCombat(true); + } + } + + public void removeDefender(TangibleObject defender) { + defendersList.remove(defender); + + if (defendersList.isEmpty() && isInCombat()) { + setInCombat(false); + } + } + + public int getPvpBitmask() { synchronized(objectMutex) { return pvpBitmask; } } - - public void setPvPBitmask(int pvpBitmask) { + + public void setPvpBitmask(int pvpBitmask) { synchronized(objectMutex) { this.pvpBitmask = pvpBitmask; } } + public boolean getPvpStatus(int pvpStatus) { synchronized(objectMutex) { return ((pvpBitmask & pvpStatus) != 0); @@ -268,8 +372,6 @@ public class TangibleObject extends SWGObject implements Serializable { } } } - - //updatePvpStatus(); } public void updatePvpStatus() { @@ -295,162 +397,9 @@ public class TangibleObject extends SWGObject implements Serializable { } } - public Byte getCustomizationVariable(String type) - { - if(customizationVariables.containsKey(type)) return customizationVariables.get(type); - System.err.println("Error: object doesn't have customization variable " + type); - return null; - } - - public void setCustomizationVariable(String type, byte value) - { - if(customizationVariables.containsKey(type)) customizationVariables.replace(type, value); - else customizationVariables.put(type, value); - - byte[] customizationBytes = getCustomizationBytes(); - customization = customizationBytes; - notifyObservers(messageBuilder.buildCustomizationDelta(customizationBytes), true); - } - - public void removeCustomizationVariable(String type) - { - if(customizationVariables.containsKey(type)) - { - customizationVariables.remove(type); - byte[] customizationBytes = getCustomizationBytes(); - customization = customizationBytes; - notifyObservers(messageBuilder.buildCustomizationDelta(customizationBytes), true); - } - } - - private byte[] getCustomizationBytes() - { - //if(customizationVariables.size() == 0) customization = { 0x00 }; - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try - { - IDManagerVisitor visitor = ClientFileManager.loadFile("customization/customization_id_manager.iff", IDManagerVisitor.class); - - stream.write((byte)0x02); // Unk - stream.write((byte)customizationVariables.size()); // Number of customization attributes - - for(String type : customizationVariables.keySet()) - { - stream.write(visitor.getAttributeIndex(type)); // Index of palette type within "customization/customization_id_manager.iff" - stream.write(customizationVariables.get(type)); // Value/Index within palette - - // Seperator/Footer - stream.write((byte) 0xC3); - stream.write((byte) 0xBF); - stream.write((byte) 0x03); - } - return stream.toByteArray(); - } - catch (Exception e) { e.printStackTrace(); } - return null; - } - - public String getFaction() { - synchronized(objectMutex) { - return faction; - } - } - - public void setFaction(String faction) { - synchronized(objectMutex) { - this.faction = faction; - } - - updatePvpStatus(); - } - - public int getFactionStatus() { - synchronized(objectMutex) { - return factionStatus; - } - } - - public void setFactionStatus(int factionStatus) { - synchronized(objectMutex) { - this.factionStatus = factionStatus; - } - } - - public Vector getDefendersList() { - synchronized(objectMutex) { - return defendersList; - } - } - - public void addDefender(TangibleObject defender) { - - defendersList.add(defender); - - if(this instanceof CreatureObject) { - CreatureObject creature = (CreatureObject) this; - - if(creature.getCombatFlag() == 0) - creature.setCombatFlag((byte) 1); - } - - } - - public void removeDefender(TangibleObject defender) { - - defendersList.remove(defender); - - if(this instanceof CreatureObject) { - CreatureObject creature = (CreatureObject) this; - - if(creature.getCombatFlag() == 1 && defendersList.isEmpty()) - creature.setCombatFlag((byte) 0); - } - - } - public boolean isAttackableBy(CreatureObject attacker) { int pvpStatus = NGECore.getInstance().factionService.calculatePvpStatus(attacker, this); return (((pvpStatus & PvpStatus.Attackable) == PvpStatus.Attackable) || ((pvpStatus & PvpStatus.Aggressive) == PvpStatus.Aggressive)); - - /* - CreatureObject creature; - - if(this instanceof CreatureObject) { - creature = (CreatureObject) this; - if(creature.getDuelList().contains(attacker) && attacker.getDuelList().contains(this)) - return true; - } - - if(faction.equals("rebel") && attacker.getFaction().equals("rebel")) - return false; - else if(faction.equals("imperial") && attacker.getFaction().equals("imperial")) - return false; - else if(attacker.getSlottedObject("ghost") != null) { - - if(this instanceof CreatureObject && getSlottedObject("ghost") != null) { - - creature = (CreatureObject) this; - - if(creature.getFactionStatus() == 2 && attacker.getFactionStatus() == 2) - return true; - else - return false; - - } - - if((faction.equals("rebel") || faction.equals("imperial")) && attacker.getFactionStatus() >= 1) - return true; - else if((faction.equals("rebel") || faction.equals("imperial")) && attacker.getFactionStatus() == 0) - return false; - - return getPvPBitmask() == 1 || getPvPBitmask() == 2; - - } else if(attacker.getSlottedObject("ghost") == null) - return true; - - return getPvPBitmask() == 1 || getPvPBitmask() == 2; - */ } public void showFlyText(OutOfBand outOfBand, float scale, RGB color, int displayType, boolean notifyObservers) { @@ -491,6 +440,15 @@ public class TangibleObject extends SWGObject implements Serializable { notifyObservers(new StopClientEffectObjectByLabel(getObjectID(), commandString), true); } + public String getSerialNumber() { + return getStringAttribute("serial_number"); + } + + public void setSerialNumber(String serialNumber) { + setStringAttribute("serial_number", serialNumber); + setOptions(Options.SERIAL, true); + } + public TangibleObject getKiller() { synchronized(objectMutex) { return killer; @@ -504,167 +462,208 @@ public class TangibleObject extends SWGObject implements Serializable { } public List getLootGroups() { - return lootGroups; + synchronized(objectMutex) { + return lootGroups; + } } public void setLootGroups(List lootGroups) { - this.lootGroups = lootGroups; + synchronized(objectMutex) { + this.lootGroups = lootGroups; + } } public void addToLootGroups(String[] lootPoolNames, double[] lootPoolChances, double lootGroupChance) { - //System.out.println("lootPoolNames[0] " + lootPoolNames[0]); - LootGroup lootGroup = new LootGroup(lootPoolNames, lootPoolChances, lootGroupChance); - this.lootGroups.add(lootGroup); + synchronized(objectMutex) { + //System.out.println("lootPoolNames[0] " + lootPoolNames[0]); + LootGroup lootGroup = new LootGroup(lootPoolNames, lootPoolChances, lootGroupChance); + lootGroups.add(lootGroup); + } } public void addToLootGroups(LootGroup lootGroup) { - this.lootGroups.add(lootGroup); + synchronized(objectMutex) { + lootGroups.add(lootGroup); + } } - public boolean isLooted() { - return looted; + synchronized(objectMutex) { + return looted; + } } - + public void setLooted(boolean looted) { - this.looted = looted; + synchronized(objectMutex) { + this.looted = looted; + } } public boolean isLootLock() { - return lootLock; + synchronized(objectMutex) { + return lootLock; + } } - + public void setLootLock(boolean lootLock) { - this.lootLock = lootLock; + synchronized(objectMutex) { + this.lootLock = lootLock; + } } public boolean isLootItem() { - return lootItem; + synchronized(objectMutex) { + return lootItem; + } } - + public void setLootItem(boolean lootItem) { - this.lootItem = lootItem; + synchronized(objectMutex) { + this.lootItem = lootItem; + } } public boolean isStackable() { - return stackable; - } - - public void setStackable(boolean stackable) { - this.stackable = stackable; + return (boolean) otherVariables.get("stackable"); } - public int getStackCount() { - return stackCount; - } - - public void setStackCount(int stackCount) { - this.stackCount = stackCount; + public void setStackable(boolean stackable) { + otherVariables.set("stackable", stackable); } public boolean isNoSell() { - return noSell; + return (boolean) otherVariables.get("noSell"); } - + public void setNoSell(boolean noSell) { - this.noSell = noSell; + otherVariables.set("noSell", noSell); } public byte getJunkType() { - return junkType; + return (byte) otherVariables.get("junkType"); } - + public void setJunkType(byte junkType) { - this.junkType = junkType; + otherVariables.set("junkType", junkType); } - + public int getJunkDealerPrice() { - return junkDealerPrice; + return (int) otherVariables.get("junkDealerPrice"); } - + public void setJunkDealerPrice(int junkDealerPrice) { - this.junkDealerPrice = junkDealerPrice; + otherVariables.set("junkDealerPrice", junkDealerPrice); } public boolean isCreditRelieved() { - return creditRelieved; + synchronized(objectMutex) { + return creditRelieved; + } } - + public void setCreditRelieved(boolean creditRelieved) { - if (creditRelieved) - this.creditRelieved = creditRelieved; // only allow one state change to prevent hacking + synchronized(objectMutex) { + if (creditRelieved) { + this.creditRelieved = creditRelieved; // only allow one state change to prevent hacking + } + } } - public String getSerialNumber() { - return getStringAttribute("serial_number"); - } - - public void setSerialNumber(String serialNumber) { - setStringAttribute("serial_number", serialNumber); - setOptions(Options.SERIAL, true); - } - - public void sendDelta3(Client destination) { - destination.getSession().write(messageBuilder.buildDelta3()); - //tools.CharonPacketUtils.printAnalysis(messageBuilder.buildDelta3(),"TANO3 Delta"); - } - - public void sendAssemblyDelta3(Client destination) { - destination.getSession().write(messageBuilder.buildAssemblyDelta3()); - //tools.CharonPacketUtils.printAnalysis(messageBuilder.buildAssemblyDelta3(),"TANO3 Assembly Delta"); - } - - public void sendCustomizationDelta3(Client destination, String enteredName){ - destination.getSession().write(messageBuilder.buildCustomNameDelta(enteredName)); - //tools.CharonPacketUtils.printAnalysis(messageBuilder.buildCustomNameDelta(enteredName),"TANO3 Customization Delta"); - } - - - @Override - public void sendBaselines(Client destination) { - - - if(destination == null || destination.getSession() == null) { - System.out.println("NULL destination"); - return; + public boolean isFull() { + if (getTemplateData().getAttribute("containerVolumeLimit") == null) { + return false; } - destination.getSession().write(messageBuilder.buildBaseline3()); - destination.getSession().write(messageBuilder.buildBaseline6()); - destination.getSession().write(messageBuilder.buildBaseline8()); - destination.getSession().write(messageBuilder.buildBaseline9()); + int containerVolumeLimit = (int) getTemplateData().getAttribute("containerVolumeLimit") >> 8; // Shifting because it seems to be returning an extra byte before it should - if(getPvPBitmask() != 0) { - UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); - upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Neutral); - upvpm.setStatus(getPvPBitmask()); - destination.getSession().write(upvpm.serialize()); + if (containerVolumeLimit == 0) { + return false; } - - } - - public ObjectMessageBuilder getMessageBuilder() { - return messageBuilder; - } - - public boolean isFull() - { - if(getTemplateData().getAttribute("containerVolumeLimit") == null) return false; + if (NGECore.getInstance().objectService.objsInContainer(this, this) >= containerVolumeLimit) { + return true; + } - int containerVolumeLimit = (int)getTemplateData().getAttribute("containerVolumeLimit") >> 8; // Shifting because it seems to be returning an extra byte before it should - - if(containerVolumeLimit == 0) return false; - - if(NGECore.getInstance().objectService.objsInContainer(this, this) >= containerVolumeLimit) return true; - return false; } - @Override - public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { - // TODO Auto-generated method stub - + public void notifyClients(IoBuffer buffer, boolean notifySelf) { + notifyObservers(buffer, false); } + public ObjectMessageBuilder getMessageBuilder() { + synchronized(objectMutex) { + if (messageBuilder == null) { + messageBuilder = new TangibleMessageBuilder(this); + } + + return messageBuilder; + } + } + + public void sendBaselines(Client destination) { + if (destination != null && destination.getSession() != null) { + destination.getSession().write(getBaseline(3).getBaseline()); + destination.getSession().write(getBaseline(6).getBaseline()); + + Client parent = ((getGrandparent() == null) ? null : getGrandparent().getClient()); + + if (parent != null && destination == parent) { + destination.getSession().write(getBaseline(8).getBaseline()); + destination.getSession().write(getBaseline(9).getBaseline()); + } + + if (destination.getParent() != this) { + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); + upvpm.setFaction(CRC.StringtoCRC(getFaction())); + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this)); + destination.getSession().write(upvpm.serialize()); + } + } + } + + public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { + switch (viewType) { + case 3: + { + switch (updateType) { + case 7: + { + buffer = getBaseline(3).createDelta(7, buffer.array()); + notifyClients(buffer, true); + break; + } + } + } + } + } + + @Deprecated public void setCustomName2(String customName) { setCustomName(customName); } + + @Deprecated public void sendDelta3(Client destination) { setOptions(Options.SERIAL | Options.INVULNERABLE, true); } + + @Deprecated public void sendAssemblyDelta3(Client destination) { setMaximumCondition(1000); } + + @Deprecated public void sendCustomizationDelta3(Client destination, String enteredName){ setCustomName(enteredName); } + + @Deprecated public void addOption(int option) { setOptionsBitmask(getOptionsBitmask() | option); } + + @Deprecated public void removeOption(int option) { setOptionsBitmask(getOptionsBitmask() & ~option); } + + @Deprecated public int getMaxDamage() { return getMaximumCondition(); } + + @Deprecated public void setMaxDamage(int maxDamage) { setMaximumCondition(maxDamage); } + + @Deprecated public byte getCombatFlag() { return (byte) ((isInCombat()) ? 1 : 0); } //Baseline.getBoolean(isInCombat()); } + + @Deprecated public void setCombatFlag(byte combatFlag) { setInCombat(combatFlag > 0); } //setInCombat(Baseline.getBoolean(combatFlag)); } + + @Deprecated public int getPvPBitmask() { return getPvpBitmask(); } + + @Deprecated public void setPvPBitmask(int pvpBitmask) { setPvpBitmask(pvpBitmask); } + + @Deprecated public int getStackCount() { if (getUses() == 0) setUses(1); return getUses(); } + + @Deprecated public void setStackCount(int stackCount) { setUses(stackCount); } + } diff --git a/src/resources/objects/tool/SurveyTool.java b/src/resources/objects/tool/SurveyTool.java index e9337445..464c8534 100644 --- a/src/resources/objects/tool/SurveyTool.java +++ b/src/resources/objects/tool/SurveyTool.java @@ -95,8 +95,8 @@ public class SurveyTool extends TangibleObject implements Serializable { defendersList = new Vector(); } - public SurveyTool(long objectID, Planet planet, String template, Point3D position, Quaternion orientation){ - super(objectID, planet, template, position, orientation); + public SurveyTool(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); surveyEffectString = ""; sampleEffectString = ""; this.tanoID = objectID; diff --git a/src/resources/objects/weapon/WeaponObject.java b/src/resources/objects/weapon/WeaponObject.java index a4ef7b31..4fca13d7 100644 --- a/src/resources/objects/weapon/WeaponObject.java +++ b/src/resources/objects/weapon/WeaponObject.java @@ -44,14 +44,14 @@ public class WeaponObject extends TangibleObject implements Serializable { private transient WeaponMessageBuilder messageBuilder; public WeaponObject(long objectID, Planet planet, String template) { - super(objectID, planet, template, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0)); + super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0), template); messageBuilder = new WeaponMessageBuilder(this); if (this.getClass().getSimpleName().equals("WeaponObject")) setIntAttribute("volume", 1); setStringAttribute("cat_wpn_damage.damage", "0-0"); } - public WeaponObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation) { - super(objectID, planet, template, position, orientation); + public WeaponObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String template) { + super(objectID, planet, position, orientation, template); messageBuilder = new WeaponMessageBuilder(this); if (this.getClass().getSimpleName().equals("WeaponObject")) setIntAttribute("volume", 1); setStringAttribute("cat_wpn_damage.damage", "0-0"); @@ -68,38 +68,12 @@ public class WeaponObject extends TangibleObject implements Serializable { messageBuilder = new WeaponMessageBuilder(this); defendersList = new Vector(); } - - public int getIncapTimer() { - return incapTimer; - } - - public void setIncapTimer(int incapTimer) { - this.incapTimer = incapTimer; - } - - - public byte[] getCustomization() { - return customization; - } - - public void setCustomization(byte[] customization) { - this.customization = customization; - } - - public int getOptionsBitmask() { - return optionsBitmask; - } - - public void setOptionsBitmask(int optionsBitmask) { - this.optionsBitmask = optionsBitmask; - } - + public int getMaxDamage() { return Integer.parseInt(getStringAttribute("cat_wpn_damage.damage").split("-")[1]); } - + public void setMaxDamage(int maxDamage) { - setStringAttribute("cat_wpn_damage.damage", String.valueOf(getMinDamage()) + "-" + String.valueOf(maxDamage)); setIntAttribute("cat_wpn_damage.dps", getDamagePerSecond()); } diff --git a/src/services/gcw/FactionService.java b/src/services/gcw/FactionService.java index f46d4f2f..c5bafb16 100644 --- a/src/services/gcw/FactionService.java +++ b/src/services/gcw/FactionService.java @@ -246,11 +246,11 @@ public class FactionService implements INetworkDispatch { target = (TangibleObject) core.objectService.getObject(((CreatureObject) target).getOwnerId()); } - if ((target.getPvPBitmask() & PvpStatus.GoingCovert) == PvpStatus.GoingCovert) { + if ((target.getPvpBitmask() & PvpStatus.GoingCovert) == PvpStatus.GoingCovert) { pvpBitmask |= PvpStatus.GoingCovert; } - if ((target.getPvPBitmask() & PvpStatus.GoingOvert) == PvpStatus.GoingOvert) { + if ((target.getPvpBitmask() & PvpStatus.GoingOvert) == PvpStatus.GoingOvert) { pvpBitmask |= PvpStatus.GoingOvert; } @@ -383,12 +383,12 @@ public class FactionService implements INetworkDispatch { return; } - if (actor.getPvPBitmask() == PvpStatus.GoingCovert) { + if (actor.getPvpBitmask() == PvpStatus.GoingCovert) { actor.sendSystemMessage("@faction_recruiter:pvp_status_changing", DisplayType.Broadcast); return; } - if (actor.getPvPBitmask() == PvpStatus.GoingOvert) { + if (actor.getPvpBitmask() == PvpStatus.GoingOvert) { actor.sendSystemMessage("@faction_recruiter:pvp_status_changing", DisplayType.Broadcast); return; } @@ -428,7 +428,7 @@ public class FactionService implements INetworkDispatch { final String finalMessage = message; scheduler.schedule(() -> { - actor.setPvPBitmask(0); + actor.setPvpBitmask(0); actor.setFactionStatus(factionStatus); actor.updatePvpStatus(); actor.sendSystemMessage("@faction_recruiter:" + finalMessage, DisplayType.Broadcast); @@ -436,12 +436,12 @@ public class FactionService implements INetworkDispatch { } public void resign(CreatureObject actor) { - if (actor.getPvPBitmask() == PvpStatus.GoingCovert) { + if (actor.getPvpBitmask() == PvpStatus.GoingCovert) { actor.sendSystemMessage("@faction_recruiter:pvp_status_changing", DisplayType.Broadcast); return; } - if (actor.getPvPBitmask() == PvpStatus.GoingOvert) { + if (actor.getPvpBitmask() == PvpStatus.GoingOvert) { actor.sendSystemMessage("@faction_recruiter:pvp_status_changing", DisplayType.Broadcast); return; } @@ -461,7 +461,7 @@ public class FactionService implements INetworkDispatch { } scheduler.schedule(() -> { - actor.setPvPBitmask(0); + actor.setPvpBitmask(0); actor.setFactionStatus(FactionStatus.OnLeave); actor.setFaction(""); actor.updatePvpStatus(); diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index a1b6b79b..05f19b24 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -129,7 +129,6 @@ import services.bazaar.AuctionItem; import services.chat.ChatRoom; @SuppressWarnings("unused") - public class ObjectService implements INetworkDispatch { private Map objectList = new ConcurrentHashMap(); @@ -241,11 +240,11 @@ public class ObjectService implements INetworkDispatch { } else if(Template.startsWith("object/tangible/survey_tool")) { - object = new SurveyTool(objectID, planet, Template, position, orientation); + object = new SurveyTool(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/tangible")) { - object = new TangibleObject(objectID, planet, Template, position, orientation); + object = new TangibleObject(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/intangible")) { @@ -253,7 +252,7 @@ public class ObjectService implements INetworkDispatch { } else if(Template.startsWith("object/weapon")) { - object = new WeaponObject(objectID, planet, Template, position, orientation); + object = new WeaponObject(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/building") || Template.startsWith("object/static/worldbuilding/structures") || Template.startsWith("object/static/structure")){ @@ -297,11 +296,11 @@ public class ObjectService implements INetworkDispatch { } else if(Template.startsWith("object/resource_container")) { - object = new ResourceContainerObject(objectID, planet, Template, position, orientation); + object = new ResourceContainerObject(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/factory/shared_factory_crate")) { - object = new FactoryCrateObject(objectID, planet, Template, position, orientation); + object = new FactoryCrateObject(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/draft_schematic")) { @@ -315,7 +314,7 @@ public class ObjectService implements INetworkDispatch { float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1f; Point3D newpoint = new Point3D(position.x,positionY,position.z); - object = new InstallationObject(objectID, planet, Template, newpoint, orientation); + object = new InstallationObject(objectID, planet, newpoint, orientation, Template); } else if(Template.startsWith("object/installation/mining_ore") || Template.startsWith("object/installation/mining_liquid") || Template.startsWith("object/installation/mining_gas") || Template.startsWith("object/installation/mining_organic") || @@ -323,7 +322,7 @@ public class ObjectService implements INetworkDispatch { float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1f; Point3D newpoint = new Point3D(position.x,positionY,position.z); - object = new HarvesterObject(objectID, planet, Template, newpoint, orientation); + object = new HarvesterObject(objectID, planet, newpoint, orientation, Template); } else { return null;