diff --git a/scripts/conversation/missions/deliver.py b/scripts/conversation/missions/deliver.py new file mode 100644 index 00000000..5caef3fa --- /dev/null +++ b/scripts/conversation/missions/deliver.py @@ -0,0 +1,70 @@ +from resources.common import OutOfBand +from resources.common import ProsePackage +from resources.objectives import DeliveryMissionObjective +import sys + +def startConversation(core, actor, npc): + missionId = npc.getAttachment('assignedMission') + + if missionId is None: + return + + mission = core.objectService.getObject(missionId) + + if mission is None: + return + + objective = mission.getObjective() + + if mission.getGrandparent().getObjectId() != actor.getObjectId() or objective is None: + core.conversationService.sendStopConversation(actor, npc, 'mission/mission_generic', 'npc_job_request_no_job') + return + + if objective.getObjectivePhase() == 0: + handlePickupStage(core, actor, npc, objective, mission) + return + + elif objective.getObjectivePhase() == 1: + handleDeliveryStage(core, actor, npc, objective, mission) + return + + elif objective.getObjectivePhase() == 2: + handleCompletionStage(core, actor, npc, objective, mission) + return + return + +def endConversation(core, actor, npc): + core.conversationService.sendStopConversation(actor, npc, 'mission/mission_generic', 'npc_job_request_no_job') + return + +def handlePickupStage(core, actor, npc, objective, mission): + + if objective.getMissionGiver().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 'p') + objective.createDeliveryItem() + objective.update() + return + +def handleDeliveryStage(core, actor, npc, objective, mission): + + if objective.getDropOffNpc().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 'r') + core.objectService.destroyObject(objective.getDeliveryObject()) + objective.update() + return + +def handleCompletionStage(core, actor, npc, objective, mission): + + if objective.getMissionGiver().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 's') + objective.complete() + return \ No newline at end of file diff --git a/scripts/radial/object/conversation.py b/scripts/radial/object/conversation.py index ee774b7d..0603ecb1 100644 --- a/scripts/radial/object/conversation.py +++ b/scripts/radial/object/conversation.py @@ -9,7 +9,6 @@ def createRadial(core, owner, target, radials): def handleSelection(core, owner, target, option): if option == 26 and target: - print 'test' core.conversationService.handleStartConversation(owner, target) return \ No newline at end of file diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 25f8d117..e51fd562 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -61,7 +61,6 @@ import services.housing.HousingService; import services.InstanceService; import services.LoginService; import services.LootService; -import services.MissionService; import services.PlayerService; import services.ScriptService; import services.SimulationService; @@ -83,6 +82,7 @@ import services.gcw.GCWService; import services.guild.GuildService; import services.LoginService; import services.map.MapService; +import services.mission.MissionService; import services.object.ObjectService; import services.object.UpdateService; import services.pet.MountService; @@ -173,7 +173,7 @@ public class NGECore { public WeatherService weatherService; public SpawnService spawnService; public AIService aiService; - //public MissionService missionService; + public MissionService missionService; public InstanceService instanceService; public DevService devService; public SurveyService surveyService; @@ -322,7 +322,7 @@ public class NGECore { } spawnService = new SpawnService(this); aiService = new AIService(this); - //missionService = new MissionService(this); + missionService = new MissionService(this); if (optionsConfigLoaded && options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { surveyService = new SurveyService(this); @@ -359,7 +359,7 @@ public class NGECore { zoneDispatch.addService(playerService); zoneDispatch.addService(buffService); zoneDispatch.addService(entertainmentService); - //zoneDispatch.addService(missionService); + zoneDispatch.addService(missionService); zoneDispatch.addService(bazaarService); zoneDispatch.addService(lootService); zoneDispatch.addService(mountService); diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index a9f541b8..cb1ff04b 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -74,6 +74,8 @@ public class ObjControllerMessage extends SWGMessage { public static final int NEXT_CRAFTING_STAGE_RESULT = 0x01BE; public static final int DRAFT_SLOTS_QUERY_RESPONSE = 0x01BF; public static final int RESOURCE_WEIGHTS = 0x0207; + public static final int MISSION_ACCEPT_RESPONSE = 0x00FA; + public static final int MISSION_ABORT_RESPONSE = 0x0142; public ObjControllerMessage() { diff --git a/src/protocol/swg/objectControllerObjects/MissionAbort.java b/src/protocol/swg/objectControllerObjects/MissionAbort.java new file mode 100644 index 00000000..2195c511 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/MissionAbort.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; + +public class MissionAbort extends ObjControllerObject { + private long characterId; + private long missionId; + + public MissionAbort() { } + + @Override + public void deserialize(IoBuffer data) { + setCharacterId(data.getLong()); + data.getInt(); + setMissionId(data.getLong()); + } + + @Override + public IoBuffer serialize() { + IoBuffer buffer = IoBuffer.allocate(32).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(ObjControllerMessage.MISSION_ABORT_RESPONSE); + buffer.putLong(characterId); + buffer.putInt(0); + buffer.putLong(missionId); + return null; + } + + public long getMissionId() { return missionId; } + + public void setMissionId(long missionId) { this.missionId = missionId; } + + public long getCharacterId() { return characterId; } + + public void setCharacterId(long characterId) { this.characterId = characterId; } +} diff --git a/src/protocol/swg/objectControllerObjects/MissionAcceptRequest.java b/src/protocol/swg/objectControllerObjects/MissionAcceptRequest.java new file mode 100644 index 00000000..403861d3 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/MissionAcceptRequest.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg.objectControllerObjects; + +import org.apache.mina.core.buffer.IoBuffer; + +public class MissionAcceptRequest extends ObjControllerObject { + + private long missionObjId; + private long terminalObjId; + private byte terminalType; + + public MissionAcceptRequest() { } + + @Override + public void deserialize(IoBuffer data) { + data.getLong(); + data.getInt(); + setMissionObjId(data.getLong()); + setTerminalObjId(data.getLong()); + setTerminalType(data.get()); + } + + @Override + public IoBuffer serialize() { + return null; + } + + public long getMissionObjId() { + return missionObjId; + } + + public void setMissionObjId(long misssionObjId) { + this.missionObjId = misssionObjId; + } + + public long getTerminalObjId() { + return terminalObjId; + } + + public void setTerminalObjId(long terminalObjId) { + this.terminalObjId = terminalObjId; + } + + public void setTerminalType(byte terminalType) { + this.terminalType = terminalType; + } + + public byte getTerminalType() { + return terminalType; + } +} diff --git a/src/protocol/swg/objectControllerObjects/MissionAcceptResponse.java b/src/protocol/swg/objectControllerObjects/MissionAcceptResponse.java new file mode 100644 index 00000000..faad427b --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/MissionAcceptResponse.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; + +public class MissionAcceptResponse extends ObjControllerObject { + + private long objectId; + private long missionObjId; + private byte terminalType; + private byte flag; + + public MissionAcceptResponse(long objectId, long missionObjId, byte terminalType, byte flag) { + this.objectId = objectId; + this.missionObjId = missionObjId; + this.terminalType = terminalType; + this.flag = flag; + } + + @Override + public void deserialize(IoBuffer data) { + } + + @Override + public IoBuffer serialize() { + IoBuffer buffer = IoBuffer.allocate(27).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(ObjControllerMessage.MISSION_ACCEPT_RESPONSE); + buffer.putLong(objectId); + buffer.putInt(0); + + buffer.putLong(missionObjId); + buffer.put(flag); + buffer.put(terminalType); + + return buffer.flip(); + } + +} diff --git a/src/protocol/swg/objectControllerObjects/MissionListRequest.java b/src/protocol/swg/objectControllerObjects/MissionListRequest.java index aacf1bd0..5e7aa208 100644 --- a/src/protocol/swg/objectControllerObjects/MissionListRequest.java +++ b/src/protocol/swg/objectControllerObjects/MissionListRequest.java @@ -34,7 +34,7 @@ public class MissionListRequest extends ObjControllerObject { @Override public void deserialize(IoBuffer data) { - Console.println("MissionListRequest: " + StringUtilities.bytesToHex(data.array())); + //Console.println("MissionListRequest: " + StringUtilities.bytesToHex(data.array())); setObjectId(data.getLong()); data.getInt(); // unk data.get(); // unk byte diff --git a/src/resources/common/ObjControllerOpcodes.java b/src/resources/common/ObjControllerOpcodes.java index 8cc142fd..c38a6071 100644 --- a/src/resources/common/ObjControllerOpcodes.java +++ b/src/resources/common/ObjControllerOpcodes.java @@ -34,6 +34,8 @@ public class ObjControllerOpcodes { public static final int BUFF_BUILDER_CHANGE = 0x5A020000; public static final int BUFF_BUILDER_END = 0x5B020000; public static final int MISSION_LIST_REQUEST = 0xF5000000; + public static final int MISSION_GENERIC_REQUEST = 0xF9000000; + public static final int MISSION_ABORT = 0x42010000; public static final int ChangeRoleIconChoice = 0x4D040000; public static final int IMAGE_DESIGN_CHANGE = 0x38020000; public static final int IMAGE_DESIGN_END = 0x39020000; diff --git a/src/resources/objectives/DeliveryMissionObjective.java b/src/resources/objectives/DeliveryMissionObjective.java new file mode 100644 index 00000000..b5802390 --- /dev/null +++ b/src/resources/objectives/DeliveryMissionObjective.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.objectives; + +import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; +import main.NGECore; +import resources.common.OutOfBand; +import resources.common.ProsePackage; +import resources.objects.creature.CreatureObject; +import resources.objects.mission.MissionObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.waypoint.WaypointObject; +import services.mission.MissionObjective; + +public class DeliveryMissionObjective extends MissionObjective { + + private TangibleObject deliveryObject; + private CreatureObject missionGiver; + private CreatureObject dropOffNpc; + private NGECore core = NGECore.getInstance(); + + public DeliveryMissionObjective(MissionObject parent) { + super(parent); + } + + @Override + public void activate() { + + if (isActivated()) + return; + + String template = "object/mobile/shared_dressed_commoner_tatooine_sullustan_male_06.iff"; + + Point3D startLoc = parent.getStartLocation(); + Point3D destination = parent.getDestination(); + + // TODO: Randomize this process. + CreatureObject missionGiver = (CreatureObject) core.staticService.spawnObject(template, parent.getPlanet().name, 0, startLoc.x, startLoc.y, startLoc.z, 0, 1); + if (missionGiver == null) + return; + + missionGiver.setCustomName("a commoner"); + missionGiver.setAttachment("conversationFile", "missions/deliver"); + missionGiver.setAttachment("radial_filename", "object/conversation"); + missionGiver.setAttachment("assignedMission", getMissionObject().getObjectId()); + missionGiver.setOptionsBitmask(264); + setMissionGiver(missionGiver); + + CreatureObject dropOffNpc = (CreatureObject) core.staticService.spawnObject(template, parent.getPlanet().name, 0, destination.x, destination.y, destination.z, 0, 1); + if (dropOffNpc == null) + return; + + dropOffNpc.setCustomName("a commoner"); + dropOffNpc.setAttachment("conversationFile", "missions/deliver"); + dropOffNpc.setAttachment("radial_filename", "object/conversation"); + dropOffNpc.setAttachment("assignedMission", getMissionObject().getObjectId()); + dropOffNpc.setOptionsBitmask(264); + setDropOffNpc(dropOffNpc); + + if (getObjectivePhase() == 0) { + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + waypoint.setPosition(startLoc); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + waypoint.setColor(WaypointObject.ORANGE); + waypoint.setActive(true); + getMissionObject().setAttachedWaypoint(waypoint); + } else if (getObjectivePhase() == 1) { + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + waypoint.setPosition(parent.getDestination()); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + waypoint.setColor(WaypointObject.ORANGE); + waypoint.setActive(true); + getMissionObject().setAttachedWaypoint(waypoint); + } + + setActive(true); + } + + @Override + public void complete() { + CreatureObject completer = (CreatureObject) getMissionObject().getGrandparent(); + + if (completer == null) + return; + + int reward = getMissionObject().getCreditReward(); + + completer.addBankCredits(reward); + + completer.sendSystemMessage(new OutOfBand(new ProsePackage("@mission/mission_generic:success_w_amount", reward)), (byte) 0); + + abort(); + + core.objectService.destroyObject(getMissionObject()); + } + + @Override + public void abort() { + if (deliveryObject != null) + core.objectService.destroyObject(deliveryObject.getObjectId()); + + if (missionGiver != null) + core.objectService.destroyObject(missionGiver, 360); + + if (dropOffNpc != null) + core.objectService.destroyObject(dropOffNpc, 360); + } + + @Override + public void update() { + + setObjectivePhase(getObjectivePhase() + 1); + + switch(getObjectivePhase()) { + case 1: + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + waypoint.setPosition(parent.getDestination()); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + waypoint.setColor(WaypointObject.ORANGE); + waypoint.setActive(true); + getMissionObject().setMissionTargetName("Dropoff Location"); + getMissionObject().setAttachedWaypoint(waypoint); + System.out.println("Waypoint set to " + parent.getDestination().x + " and " + parent.getDestination().z); + break; + case 2: + WaypointObject returnWp = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + returnWp.setPosition(parent.getStartLocation()); + returnWp.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + returnWp.setColor(WaypointObject.ORANGE); + returnWp.setActive(true); + getMissionObject().setMissionTargetName("Return"); + getMissionObject().setAttachedWaypoint(returnWp); + break; + } + } + + public boolean createDeliveryItem() { + + SWGObject player = getMissionObject().getGrandparent(); + + if (player == null) + return false; + + TangibleObject inventory = (TangibleObject) player.getSlottedObject("inventory"); + + if (inventory == null) + return false; + + TangibleObject deliveryObject = (TangibleObject) core.objectService.createObject("object/tangible/mission/shared_mission_datadisk.iff", getMissionObject().getGrandparent().getPlanet()); + + if (deliveryObject != null && inventory.add(deliveryObject)) { + setDeliveryObject(deliveryObject); + return true; + } + else + return false; + } + + public TangibleObject getDeliveryObject() { return deliveryObject; } + + public void setDeliveryObject(TangibleObject object) { this.deliveryObject = object; } + + public CreatureObject getMissionGiver() { return missionGiver; } + + public void setMissionGiver(CreatureObject missionGiver) { this.missionGiver = missionGiver; } + + public CreatureObject getDropOffNpc() { return dropOffNpc; } + + public void setDropOffNpc(CreatureObject dropOffNpc) { this.dropOffNpc = dropOffNpc; } + +} diff --git a/src/resources/common/TerminalType.java b/src/resources/objectives/DestroyMissionObjective.java similarity index 63% rename from src/resources/common/TerminalType.java rename to src/resources/objectives/DestroyMissionObjective.java index 375d1e61..e4832756 100644 --- a/src/resources/common/TerminalType.java +++ b/src/resources/objectives/DestroyMissionObjective.java @@ -1,30 +1,57 @@ -/******************************************************************************* - * Copyright (c) 2013 - * - * This File is part of NGECore2. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. - * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. - ******************************************************************************/ -package resources.common; - -public class TerminalType { - public static int MISSION_GENERIC = 1; - public static int MISSION_BOUNTYHUNTER = 2; - public static int MISSION_ENTERTAINER = 3; - public static int MISSION_ARTISAN = 4; - public static int MISSION_EXPLORER = 5; -} +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.objectives; + +import resources.objects.mission.MissionObject; +import services.mission.MissionObjective; + +public class DestroyMissionObjective extends MissionObjective { + + public DestroyMissionObjective(MissionObject parent) { + super(parent); + } + + @Override + public void activate() { + // TODO Auto-generated method stub + + } + + @Override + public void complete() { + // TODO Auto-generated method stub + + } + + @Override + public void abort() { + // TODO Auto-generated method stub + + } + + @Override + public void update() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 7680d9bd..d6f2a861 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -251,12 +251,30 @@ public class CreatureObject extends TangibleObject implements IPersistent { getClient().getSession().write(messageBuilder.buildBankCreditsDelta(bankCredits)); } } + + public void addBankCredits(int amountToAdd) { + synchronized(objectMutex) { + this.bankCredits += amountToAdd; + } + if(getClient() != null && getClient().getSession() != null) { + getClient().getSession().write(messageBuilder.buildBankCreditsDelta(bankCredits)); + } + } public int getCashCredits() { synchronized(objectMutex) { return cashCredits; } } + + public void addCashCredits(int amountToAdd) { + synchronized(objectMutex) { + this.cashCredits += amountToAdd; + } + if(getClient() != null && getClient().getSession() != null) { + getClient().getSession().write(messageBuilder.buildCashCreditsDelta(cashCredits)); + } + } public void setCashCredits(int cashCredits) { synchronized(objectMutex) { diff --git a/src/resources/objects/mission/MissionMessageBuilder.java b/src/resources/objects/mission/MissionMessageBuilder.java index 190773ad..24c9aa07 100644 --- a/src/resources/objects/mission/MissionMessageBuilder.java +++ b/src/resources/objects/mission/MissionMessageBuilder.java @@ -26,6 +26,7 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import engine.resources.common.CRC; +import engine.resources.scene.Point3D; import resources.common.Console; import resources.common.StringUtilities; import resources.objects.ObjectMessageBuilder; @@ -42,109 +43,123 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { IoBuffer buffer = IoBuffer.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); buffer.setAutoExpand(true); - buffer.putShort((short) 17); + buffer.putShort((short) 16); - buffer.putFloat(1); // mission complexity ?? - buffer.put(getAsciiString(mission.getStfFilename())); + buffer.putFloat(object.getComplexity()); // mission complexity ?? + + buffer.put(getAsciiString(object.getStfFilename())); buffer.putInt(0); - buffer.put(getAsciiString(mission.getStfName())); - - if (mission.getCustomName() == null) { buffer.put(getUnicodeString("")); } + buffer.put(getAsciiString(object.getStfName())); + + if (mission.getCustomName() == null) { buffer.putInt(0); } else { buffer.put(getUnicodeString(mission.getCustomName())); } - buffer.putInt(0); // volume + buffer.putInt(object.getVolume()); // volume + buffer.putInt(0); // unused + buffer.putInt(mission.getMissionLevel()); - buffer.putFloat(mission.getMissionStartX()); - buffer.putFloat(0); // missionStartZ - buffer.putFloat(mission.getMissionStartY()); - - buffer.putLong(0); // ?? - - if (mission.getMissionStartPlanet() == null) { - buffer.putInt(0); + if (mission.getStartLocation() != null) { + buffer.putFloat(mission.getStartLocation().x); + buffer.putFloat(0); + buffer.putFloat(mission.getStartLocation().z); } else { + buffer.putFloat(0); + buffer.putFloat(0); + buffer.putFloat(0); + } + buffer.putLong(0); // Start Object ID + if (mission.getMissionStartPlanet() == null) + buffer.putInt(0); + else buffer.putInt(CRC.StringtoCRC(mission.getMissionStartPlanet())); - } - - buffer.put(getUnicodeString(mission.getMissionCreator())); - buffer.putInt(mission.getMissionCredits()); - buffer.putFloat(mission.getMissionDestinationX()); - buffer.putFloat(0); // missionDestinationZ - buffer.putFloat(mission.getMissionDestinationY()); - - buffer.putLong(0); // ?? - - if (mission.getMissionDestinationPlanet() == null) { + if (mission.getCreator() != null) + buffer.put(getUnicodeString(mission.getCreator())); + else buffer.putInt(0); + + buffer.putInt(mission.getCreditReward()); + + if (mission.getDestination() != null) { + buffer.putFloat(mission.getDestination().x); + buffer.putFloat(0); + buffer.putFloat(mission.getDestination().z); } else { + buffer.putFloat(0); + buffer.putFloat(0); + buffer.putFloat(0); + } + buffer.putLong(0); // Destination Object ID + if (mission.getMissionDestinationPlanet() == null) + buffer.putInt(0); + else buffer.putInt(CRC.StringtoCRC(mission.getMissionDestinationPlanet())); - } - if (mission.getTargetTemplateObject() == null) { - buffer.putInt(0); - } else { - buffer.putInt(CRC.StringtoCRC(mission.getTargetTemplateObject())); - } + buffer.putInt(mission.getMissionTemplateObject()); buffer.put(getAsciiString(mission.getMissionDescription())); buffer.putInt(0); - buffer.put(getAsciiString(mission.getMissionDescId())); + buffer.put(getAsciiString("m" + mission.getMissionId() + "d")); buffer.put(getAsciiString(mission.getMissionTitle())); buffer.putInt(0); - buffer.put(getAsciiString(mission.getMissionTitleId())); + buffer.put(getAsciiString("m" + mission.getMissionId() + "t")); buffer.putInt(0); // refresh counter - if(mission.getMissionType() == null) { + if(mission.getMissionType() == null) buffer.putInt(0); - } else { + else buffer.putInt(CRC.StringtoCRC(mission.getMissionType())); - } buffer.put(getAsciiString(mission.getMissionTargetName())); - WaypointObject wp = mission.getMissionAttachedWaypoint(); + WaypointObject wp = mission.getAttachedWaypoint(); if (wp == null) { - buffer.putInt(0); + buffer.putInt(0); // cell buffer.putFloat(0); // x buffer.putFloat(0); // z buffer.putFloat(0); // y buffer.putLong(0); // target id buffer.putInt(0); // planet crc - buffer.put(getUnicodeString("")); + buffer.putInt(0); // name buffer.putLong(0); // waypoint id buffer.put((byte) 0); // color buffer.put((byte) 0x01); //active } else { buffer.putInt(wp.getCellId()); buffer.putFloat(wp.getPosition().x); - buffer.putFloat(wp.getPosition().z); buffer.putFloat(wp.getPosition().y); + buffer.putFloat(wp.getPosition().z); buffer.putLong(0); buffer.putInt(CRC.StringtoCRC(wp.getPlanet().name)); - buffer.put((byte) 0); - buffer.put((byte) 0x01); + buffer.put(getUnicodeString(wp.getName())); + buffer.putLong(wp.getObjectId()); + buffer.put(wp.getColor()); + buffer.put((byte) (wp.isActive() ? 1 : 0)); } + int size = buffer.position(); buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); buffer.flip(); buffer = createBaseline("MISO", (byte) 3, buffer, size); - Console.println("Bytes: " + StringUtilities.bytesToHex(buffer.array())); + //Console.println("MISO3 Bytes: " + StringUtilities.bytesToHex(buffer.array())); return buffer; } public IoBuffer buildBaseline6() { - IoBuffer buffer = IoBuffer.allocate(4, false).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer buffer = IoBuffer.allocate(18, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putInt(121); // unk + buffer.putShort((short) 3); + buffer.putInt(76); // server id + buffer.putLong(0); // detail stf + buffer.putInt(0xFFFFFFFF); // unknown int size = buffer.position(); buffer.flip(); @@ -153,6 +168,30 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } + public IoBuffer buildBaseline8() { + IoBuffer buffer = IoBuffer.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putShort((short) 0); // unknown + + int size = buffer.position(); + buffer.flip(); + buffer = createBaseline("MISO", (byte) 8, buffer, size); + + return buffer; + } + + public IoBuffer buildBaseline9() { + IoBuffer buffer = IoBuffer.allocate(2, false).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putShort((short) 0); // unknown + + int size = buffer.position(); + buffer.flip(); + buffer = createBaseline("MISO", (byte) 9, buffer, size); + + return buffer; + } + public IoBuffer buildStfDelta(String stfFile, String stfName) { IoBuffer buffer = IoBuffer.allocate(4 + stfFile.length() + stfName.length(), false).order(ByteOrder.LITTLE_ENDIAN); @@ -181,18 +220,21 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } - public IoBuffer buildStartLocationDelta(float x, float z, float y, String planet) { + public IoBuffer buildStartLocationDelta(Point3D startLocation, String planet) { IoBuffer buffer = IoBuffer.allocate(24, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putFloat(x); - buffer.putFloat(z); - buffer.putFloat(y); + buffer.putFloat(startLocation.x); + buffer.putFloat(0); + buffer.putFloat(startLocation.z); buffer.putLong(0); - buffer.putInt(CRC.StringtoCRC(planet)); - + if (planet == null) { + buffer.putInt(CRC.StringtoCRC(object.getPlanet().name)); + } else { + buffer.putInt(CRC.StringtoCRC(planet)); + } int size = buffer.position(); buffer.flip(); buffer = createDelta("MISO", (byte) 3, (short) 1, (short) 0x06, buffer, size + 4); @@ -202,9 +244,9 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { public IoBuffer buildCreatorNameDelta(String creator) { - IoBuffer buffer = IoBuffer.allocate(4 + creator.length(), false).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer buffer = IoBuffer.allocate(4 + (creator.length() * 2), false).order(ByteOrder.LITTLE_ENDIAN); - buffer.put(getAsciiString(creator)); + buffer.put(getUnicodeString(creator)); int size = buffer.position(); buffer.flip(); @@ -226,17 +268,21 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } - public IoBuffer buildDestinationDelta(float x, float z, float y, String planet) { + public IoBuffer buildDestinationDelta(Point3D destination, String planet) { IoBuffer buffer = IoBuffer.allocate(24, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putFloat(x); - buffer.putFloat(z); - buffer.putFloat(y); + buffer.putFloat(destination.x); + buffer.putFloat(0); + buffer.putFloat(destination.z); buffer.putLong(0); // Destination Object ID - buffer.putInt(CRC.StringtoCRC(planet)); + if (planet == null) { + buffer.putInt(CRC.StringtoCRC(object.getPlanet().name)); + } else { + buffer.putInt(CRC.StringtoCRC(planet)); + } int size = buffer.position(); buffer.flip(); @@ -245,11 +291,11 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } - public IoBuffer buildTargetObjectIffDelta(String template) { + public IoBuffer buildTargetObjectIffDelta(int template) { IoBuffer buffer = IoBuffer.allocate(4, false).order(ByteOrder.LITTLE_ENDIAN); - buffer.putInt(CRC.StringtoCRC(template)); + buffer.putInt(template); int size = buffer.position(); buffer.flip(); @@ -258,13 +304,13 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } - public IoBuffer buildMissionDescriptionDelta(String desc, String id) { + public IoBuffer buildMissionDescriptionDelta(String desc, int id) { - IoBuffer buffer = IoBuffer.allocate(8 + desc.length() + id.length(), false).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer buffer = IoBuffer.allocate(12 + desc.length(), false).order(ByteOrder.LITTLE_ENDIAN); buffer.put(getAsciiString(desc)); buffer.putInt(0); - buffer.put(getAsciiString(id)); + buffer.put(getAsciiString("m" + id + "d")); int size = buffer.position(); buffer.flip(); @@ -273,13 +319,13 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } - public IoBuffer buildMissionTitleDelta(String title, String id) { + public IoBuffer buildMissionTitleDelta(String title, int id) { - IoBuffer buffer = IoBuffer.allocate(8 + title.length() + id.length(), false).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer buffer = IoBuffer.allocate(12 + title.length(), false).order(ByteOrder.LITTLE_ENDIAN); buffer.put(getAsciiString(title)); buffer.putInt(0); - buffer.put(getAsciiString(id)); + buffer.put(getAsciiString("m" + id + "t")); int size = buffer.position(); buffer.flip(); @@ -326,6 +372,28 @@ public class MissionMessageBuilder extends ObjectMessageBuilder { return buffer; } + + public IoBuffer buildWaypointDelta(WaypointObject wp) { + + IoBuffer buffer = IoBuffer.allocate(44 + (2 * wp.getName().length()), false).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(wp.getCellId()); + buffer.putFloat(wp.getPosition().x); + buffer.putFloat(wp.getPosition().y); + buffer.putFloat(wp.getPosition().z); + buffer.putLong(0); + buffer.putInt(CRC.StringtoCRC(wp.getPlanet().name)); + buffer.put(getUnicodeString(wp.getName())); + buffer.putLong(wp.getObjectId()); + buffer.put(wp.getColor()); + buffer.put((byte) (wp.isActive() ? 1 : 0)); + + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("MISO", (byte) 3, (short) 1, (short) 0x10, buffer, size + 4); + + return buffer; + } @Override public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { diff --git a/src/resources/objects/mission/MissionObject.java b/src/resources/objects/mission/MissionObject.java index 69562ef6..12ed3fa8 100644 --- a/src/resources/objects/mission/MissionObject.java +++ b/src/resources/objects/mission/MissionObject.java @@ -28,36 +28,32 @@ import com.sleepycat.persist.model.Persistent; import resources.objects.intangible.IntangibleObject; import resources.objects.waypoint.WaypointObject; +import services.mission.MissionObjective; import engine.clients.Client; import engine.resources.objects.IPersistent; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=0) +@Persistent(version=1) public class MissionObject extends IntangibleObject implements IPersistent { - private float missionDestinationX; - private float missionDestinationY; - private float missionDestinationZ; - private float missionStartX; - private float missionStartY; - private float missionStartZ; - private String missionStartPlanet; - private int missionLevel; // Difficulty level displayed in details - private String missionDestinationPlanet; - private int missionRepeatCounter; // increases for each player using the mission; used for redisplaying on mission term too - private int missionCredits; - private String missionCreator = ""; - private String missionDescription = ""; - private String missionTitle = ""; + private Point3D destination; + private Point3D startLocation; + private String startPlanet = ""; + private int difficultyLevel = 0; // Difficulty level displayed in details + private String destinationPlanet = ""; + private int repeatCount = 0; // increases for each player using the mission; used for redisplaying on mission term too + private int reward = 0; + private String creator = ""; + private String description = ""; + private String title = ""; private String missionTargetName = ""; // Target object I guess? - private String missionDescId = ""; - private String missionTitleId = ""; - private String missionType; - private WaypointObject missionAttachedWaypoint; - - private String missionTemplateObject; + private int missionId = 0; + private String type = ""; + private int missionTemplateObject = 0; + private WaypointObject attachedWaypoint; + private MissionObjective objective; @NotPersistent MissionMessageBuilder messageBuilder = new MissionMessageBuilder(this); @@ -73,150 +69,106 @@ public class MissionObject extends IntangibleObject implements IPersistent { super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 0, 0), template); } - public float getMissionStartX() { - synchronized(objectMutex) { - return missionStartX; - } - } - - public float getMissionStartY() { - synchronized(objectMutex) { - return missionStartY; - } - } - - public float getMissionStartZ() { - synchronized(objectMutex) { - return missionStartZ; - } - } - - public void setMissionStart(float x, float y, float z, String planet) { - synchronized(objectMutex) { - this.missionStartZ = z; - this.missionStartX = x; - this.missionStartY = y; - this.missionStartPlanet = planet; - } - - notifyObservers(messageBuilder.buildStartLocationDelta(x, z, y, planet), false); - } - - public float getMissionDestinationX() { - synchronized(objectMutex) { - return missionDestinationX; - } - } - - public float getMissionDestinationY() { - synchronized(objectMutex) { - return missionDestinationY; - } - } - - public float getMissionDestinationZ() { - synchronized(objectMutex) { - return missionDestinationZ; - } - } - - public void setMissionDestination(float x, float y, float z, String planet) { - synchronized(objectMutex) { - this.missionDestinationZ = z; - this.missionDestinationY = y; - this.missionDestinationZ = z; - this.missionDestinationPlanet = planet; - } - } - public String getMissionDestinationPlanet() { synchronized(objectMutex) { - return missionDestinationPlanet; + return destinationPlanet; } } public int getMissionLevel() { synchronized(objectMutex) { - return missionLevel; + return difficultyLevel; } } public void setMissionLevel(int missionLevel) { synchronized(objectMutex) { - this.missionLevel = missionLevel; + this.difficultyLevel = missionLevel; + } + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildDifficultyLevelDelta(missionLevel)); } } public String getMissionStartPlanet() { synchronized(objectMutex) { - return missionStartPlanet; + return startPlanet; } } public int getMissionRepeatCounter() { synchronized(objectMutex) { - return missionRepeatCounter; + return repeatCount; } } - public void setMissionRepeatCounter(int missionRepeatCounter) { + public void setRepeatCount(int missionRepeatCounter) { synchronized(objectMutex) { - this.missionRepeatCounter = missionRepeatCounter; + this.repeatCount = missionRepeatCounter; + } + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildRepeatCounterDelta(missionRepeatCounter)); } } - public int getMissionCredits() { + public int getCreditReward() { synchronized(objectMutex) { - return missionCredits; + return reward; } } - public void setMissionCredits(int missionCredits) { + public void setCreditReward(int missionCredits) { synchronized(objectMutex) { - this.missionCredits = missionCredits; + this.reward = missionCredits; } - notifyObservers(messageBuilder.buildCreditsRewardDelta(missionCredits), false); - } - - public String getMissionCreator() { - synchronized(objectMutex) { - return missionCreator; + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildCreditsRewardDelta(missionCredits)); } } - public void setMissionCreator(String missionCreator) { + public String getCreator() { synchronized(objectMutex) { - this.missionCreator = missionCreator; + return creator; + } + } + + public void setCreator(String missionCreator) { + synchronized(objectMutex) { + this.creator = missionCreator; + } + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildCreatorNameDelta(missionCreator)); } - notifyObservers(messageBuilder.buildCreatorNameDelta(missionCreator), false); } public String getMissionDescription() { synchronized(objectMutex) { - return missionDescription; + return description; } } - public void setMissionDescription(String missionDescription, String id) { + public void setMissionDescription(String missionDescription) { synchronized(objectMutex) { - this.missionDescription = missionDescription; - this.missionDescId = id; + this.description = missionDescription; + } + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildMissionDescriptionDelta(missionDescription, missionId)); } - notifyObservers(messageBuilder.buildMissionDescriptionDelta(missionDescription, id), false); } public String getMissionTitle() { synchronized(objectMutex) { - return missionTitle; + return title; } } - public void setMissionTitle(String missionTitle, String id) { + public void setMissionTitle(String missionTitle) { synchronized(objectMutex) { - this.missionTitle = missionTitle; - this.missionTitleId = id; + this.title = missionTitle; + } + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildMissionTitleDelta(missionTitle, missionId)); } - notifyObservers(messageBuilder.buildMissionTitleDelta(missionTitle, id), false); } public String getMissionTargetName() { @@ -229,57 +181,109 @@ public class MissionObject extends IntangibleObject implements IPersistent { synchronized(objectMutex) { this.missionTargetName = missionTargetName; } - notifyObservers(messageBuilder.buildTargetNameDelta(missionTargetName), false); - } - - public WaypointObject getMissionAttachedWaypoint() { - synchronized(objectMutex) { - return missionAttachedWaypoint; + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildTargetNameDelta(missionTargetName)); } } - public void setMissionAttachedWaypoint(WaypointObject missionAttachedWaypoint) { + public WaypointObject getAttachedWaypoint() { synchronized(objectMutex) { - this.missionAttachedWaypoint = missionAttachedWaypoint; + return attachedWaypoint; } } - public String getTargetTemplateObject() { + public void setAttachedWaypoint(WaypointObject waypoint) { + synchronized(objectMutex) { + this.attachedWaypoint = waypoint; + } + + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildWaypointDelta(waypoint)); + } + } + + public int getMissionTemplateObject() { synchronized(objectMutex) { return missionTemplateObject; } } - public void setTargetTemplateObject(String missionTemplateObject) { + public void setMissionTemplateObject(int missionTemplateObject) { synchronized(objectMutex) { this.missionTemplateObject = missionTemplateObject; } - notifyObservers(messageBuilder.buildTargetObjectIffDelta(missionTemplateObject), false); - } - - public String getMissionDescId() { - synchronized(objectMutex) { - return missionDescId; - } - } - - public String getMissionTitleId() { - synchronized(objectMutex) { - return missionTitleId; + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildTargetObjectIffDelta(missionTemplateObject)); } } public String getMissionType() { synchronized(objectMutex) { - return missionType; + return type; } } public void setMissionType(String missionType) { synchronized(objectMutex) { - this.missionType = missionType; + this.type = missionType; } - notifyObservers(messageBuilder.buildMissionTypeDelta(missionType), false); + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildMissionTypeDelta(missionType)); + } + } + + public MissionObjective getObjective() { + synchronized(objectMutex) { + return objective; + } + } + + public void setObjective(MissionObjective objective) { + synchronized(objectMutex) { + this.objective = objective; + } + } + + public Point3D getStartLocation() { + synchronized(objectMutex) { + return startLocation; + } + } + + public Point3D getDestination() { + synchronized(objectMutex) { + return destination; + } + } + + public void setStartLocation(Point3D startLocation, String planet) { + synchronized(objectMutex) { + this.startLocation = startLocation; + this.startPlanet = planet; + } + + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildStartLocationDelta(startLocation, planet)); + } + } + + public void setDestination(Point3D destination, String planet) { + synchronized(objectMutex) { + this.destination = destination; + this.destinationPlanet = planet; + } + + if (getGrandparent() != null && getGrandparent().getClient() != null && getGrandparent().getClient().getSession() != null) { + getGrandparent().getClient().getSession().write(messageBuilder.buildDestinationDelta(destination, planet)); + } + } + + public int getMissionId() { + return missionId; + } + + public void setMissionId(int missionId) { + this.missionId = missionId; } public Transaction getTransaction() { @@ -300,6 +304,8 @@ public class MissionObject extends IntangibleObject implements IPersistent { destination.getSession().write(messageBuilder.buildBaseline3()); destination.getSession().write(messageBuilder.buildBaseline6()); + destination.getSession().write(messageBuilder.buildBaseline8()); + destination.getSession().write(messageBuilder.buildBaseline9()); } } diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index 67c67f51..b11bd350 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -310,12 +310,11 @@ public class CharacterService implements INetworkDispatch { object._add(bank); object._add(missionBag); - /*for(int missionsAdded = 0; missionsAdded < 12; missionsAdded++) { + for(int missionsAdded = 1; missionsAdded <= 10; missionsAdded++) { MissionObject mission = (MissionObject) core.objectService.createObject("object/mission/shared_mission_object.iff", object.getPlanet()); missionBag._add(mission); - Console.println("Added empty mission " + missionsAdded); - }*/ + } // TODO: Race abilities if (client.isGM()) diff --git a/src/services/MissionService.java b/src/services/MissionService.java deleted file mode 100644 index 77e9dca7..00000000 --- a/src/services/MissionService.java +++ /dev/null @@ -1,213 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013 - * - * This File is part of NGECore2. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. - * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. - ******************************************************************************/ -package services; - -import java.nio.ByteOrder; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; - -import main.NGECore; - -import org.apache.mina.core.buffer.IoBuffer; -import org.apache.mina.core.session.IoSession; - -import protocol.swg.objectControllerObjects.MissionListRequest; -import resources.common.Console; -import resources.common.TerminalType; -import resources.common.ObjControllerOpcodes; -import resources.objects.creature.CreatureObject; -import resources.objects.mission.MissionObject; -import resources.objects.tangible.TangibleObject; -import engine.clientdata.ClientFileManager; -import engine.clientdata.visitors.DatatableVisitor; -import engine.clients.Client; -import engine.resources.container.Traverser; -import engine.resources.objects.SWGObject; -import engine.resources.service.INetworkDispatch; -import engine.resources.service.INetworkRemoteEvent; - -public class MissionService implements INetworkDispatch { - - private NGECore core; - - public MissionService(NGECore core) { - this.core = core; - } - - @Override - public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { - objControllerOpcodes.put(ObjControllerOpcodes.MISSION_LIST_REQUEST, new INetworkRemoteEvent() { - - @Override - public void handlePacket(IoSession session, IoBuffer data) throws Exception { - data.order(ByteOrder.LITTLE_ENDIAN); - - MissionListRequest request = new MissionListRequest(); - request.deserialize(data); - - Client client = core.getClient(session); - - if(client == null || client.getSession() == null) - return; - - SWGObject object = client.getParent(); - - if(object == null) - return; - - SWGObject terminal = core.objectService.getObject(request.getTerminalId()); - - int terminalType = (int) terminal.getAttachment("terminalType"); - - if (terminalType == TerminalType.MISSION_GENERIC) { - populateMissions(core.objectService.getObject(request.getObjectId()), TerminalType.MISSION_GENERIC); - } else if (terminalType == TerminalType.MISSION_BOUNTYHUNTER) { - - } else if (terminalType == TerminalType.MISSION_ENTERTAINER) { - - } else if (terminalType == TerminalType.MISSION_ARTISAN) { - - } else { - Console.println("ERROR: Unsupported terminal " + terminal.getObjectId()); - } - } - - }); - } - - private void populateMissions(final SWGObject player, int type) { - CreatureObject creature = (CreatureObject) player; - TangibleObject missionBag = (TangibleObject) creature.getSlottedObject("mission_bag"); - - final AtomicInteger deliveryCount = new AtomicInteger(); - final AtomicInteger destroyCount = new AtomicInteger(); - - final int deliveryEntries = 30; - - final Random ran = new Random(); - - final int bagSize = core.objectService.objsInContainer(creature, missionBag); - Console.println("Delivery Entries: " + deliveryEntries); - if (bagSize != 12) { - for(int missionsAdded = 0; missionsAdded < 12; missionsAdded++) { - MissionObject mission = (MissionObject) core.objectService.createObject("object/mission/shared_mission_object.iff", creature.getPlanet()); - - int textId = ran.nextInt(deliveryEntries); - - Console.println("Random Int Value: " + textId); - Console.println("Now the value is: " + textId); - - mission.setMissionLevel(5); - - mission.setMissionStart(0, 0, 0, player.getPlanet().name); - - mission.setMissionCreator("Waverunner"); - mission.setMissionCredits(9000); - - // TODO: Base this off of textId + f - mission.setTargetTemplateObject("object/tangible/mission/shared_mission_datadisk.iff"); - // TODO: Base this off of textId + l - mission.setMissionTargetName("Osskscosco"); - - mission.setMissionDescription("mission/mission_deliver_neutral_easy", "m" + textId + "d"); - mission.setMissionTitle("mission/mission_deliver_neutral_easy", "m" + textId + "t"); - - mission.setMissionType("deliver"); - - mission.setMissionDestination(-5962, 0, -6259, player.getPlanet().name); - deliveryCount.getAndIncrement(); - - - missionBag._add(mission); - Console.println("Added mission " + missionsAdded); - } - return; - } - - missionBag.viewChildren(player, false, false, new Traverser() { - - @Override - public void process(SWGObject child) { - if (deliveryCount.get() == 6) - return; - - MissionObject mission = (MissionObject) child; - int textId = ran.nextInt(deliveryEntries); - - Console.println("Random Int Value: " + textId); - Console.println("Now the value is: " + textId); - - mission.setMissionLevel(5); - - mission.setMissionStart(0, 0, 0, player.getPlanet().name); - - mission.setMissionCreator("Waverunner"); - mission.setMissionCredits(9000); - - // TODO: Base this off of textId + f - mission.setTargetTemplateObject("object/tangible/mission/shared_mission_datadisk.iff"); - // TODO: Base this off of textId + l - mission.setMissionTargetName("Osskscosco"); - - mission.setMissionDescription("mission/mission_deliver_neutral_easy", "m" + textId + "d"); - mission.setMissionTitle("mission/mission_deliver_neutral_easy", "m" + textId + "t"); - - mission.setMissionType("deliver"); - - mission.setMissionDestination(-5962, 0, -6259, player.getPlanet().name); - deliveryCount.getAndIncrement(); - } - - }); - - Console.println("Outside of the traverser now!"); - } - - // May want to create a map for the server with needed info - public int getNumberOfEntries(String stf) { - try { - DatatableVisitor stfFile = ClientFileManager.loadFile(stf, DatatableVisitor.class); - - for (int s = 0; s < stfFile.getRowCount(); s++) { - String name = ((String) stfFile.getObject(s, 3)); - Console.println("Name: " + name); - if (name.equals("number_of_entries")) { - int entryCount = ((int) stfFile.getObject(s, 4)); - Console.println("Entry Count: " + entryCount); - return entryCount; - } - } - } - catch (InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - } - - return 0; - } - - @Override - public void shutdown() { - - } - -} diff --git a/src/services/mission/MissionObjective.java b/src/services/mission/MissionObjective.java new file mode 100644 index 00000000..c81fcc0a --- /dev/null +++ b/src/services/mission/MissionObjective.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.mission; + +import com.sleepycat.persist.model.Persistent; + +import resources.objects.mission.MissionObject; + +@Persistent(version=0) +public abstract class MissionObjective { + + protected long startTime; + protected boolean activated; + protected MissionObject parent; + private int objectivePhase; + + public MissionObjective() { } + + public MissionObjective(MissionObject parent) { + this.startTime = System.currentTimeMillis(); + this.activated = false; + this.parent = parent; + this.objectivePhase = 0; + } + + public abstract void activate(); + public abstract void complete(); + public abstract void abort(); + public abstract void update(); + + public long getStartTime() { return startTime; } + + public boolean isActivated() { return activated; } + public void setActive(boolean isActive) { this.activated = isActive; } + + public MissionObject getMissionObject() { return parent; } + + public int getObjectivePhase() { return objectivePhase; } + public void setObjectivePhase(int phase) { this.objectivePhase = phase; } +} diff --git a/src/services/mission/MissionService.java b/src/services/mission/MissionService.java new file mode 100644 index 00000000..40b5abf0 --- /dev/null +++ b/src/services/mission/MissionService.java @@ -0,0 +1,419 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.mission; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteOrder; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import main.NGECore; + +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.session.IoSession; + +import protocol.swg.ObjControllerMessage; +import protocol.swg.objectControllerObjects.MissionAbort; +import protocol.swg.objectControllerObjects.MissionAcceptRequest; +import protocol.swg.objectControllerObjects.MissionAcceptResponse; +import protocol.swg.objectControllerObjects.MissionListRequest; +import resources.common.SpawnPoint; +import resources.common.ObjControllerOpcodes; +import resources.objectives.DeliveryMissionObjective; +import resources.objectives.DestroyMissionObjective; +import resources.objects.creature.CreatureObject; +import resources.objects.mission.MissionObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.waypoint.WaypointObject; +import engine.clientdata.StfTable; +import engine.clients.Client; +import engine.resources.common.CRC; +import engine.resources.common.NameGen; +import engine.resources.container.Traverser; +import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class MissionService implements INetworkDispatch { + + private NGECore core; + private NameGen nameGenerator; + // Use a HashMap for obtaining number of entries so we aren't using a visitor all the time. + private ConcurrentHashMap entryCounts = new ConcurrentHashMap(); + private Random ran = new Random(); + + public MissionService(NGECore core) { + this.core = core; + + try { nameGenerator = new NameGen("names.txt"); } + catch (IOException e) { e.printStackTrace(); } + + loadMissionEntryCounts(); + } + + @Override + public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { + + objControllerOpcodes.put(ObjControllerOpcodes.MISSION_ABORT, new INetworkRemoteEvent() { + + @Override + public void handlePacket(IoSession session, IoBuffer data) throws Exception { + Client client = core.getClient(session); + + if(client == null || client.getSession() == null) + return; + + CreatureObject creature = (CreatureObject) client.getParent(); + + if(creature == null) + return; + + data.order(ByteOrder.LITTLE_ENDIAN); + MissionAbort abort = new MissionAbort(); + abort.deserialize(data); + + MissionObject mission = (MissionObject) core.objectService.getObject(abort.getMissionId()); + + if (mission == null) + return; + + if (mission.getGrandparent().getObjectId() != creature.getObjectId()) + return; + + handleMissionAbort(creature, mission); + } + + }); + + objControllerOpcodes.put(ObjControllerOpcodes.MISSION_LIST_REQUEST, new INetworkRemoteEvent() { + + @Override + public void handlePacket(IoSession session, IoBuffer data) throws Exception { + Client client = core.getClient(session); + + if(client == null || client.getSession() == null) + return; + + SWGObject object = client.getParent(); + + if(object == null) + return; + + data.order(ByteOrder.LITTLE_ENDIAN); + + MissionListRequest request = new MissionListRequest(); + request.deserialize(data); + + SWGObject terminal = core.objectService.getObject(request.getTerminalId()); + + if (terminal.getAttachment("terminalType") == null) + return; + + int terminalType = (int) terminal.getAttachment("terminalType"); + + if (terminalType == TerminalType.GENERIC) { + handleMissionListRequest(core.objectService.getObject(request.getObjectId()), request.getTickCount(), TerminalType.GENERIC); + } else if (terminalType == TerminalType.BOUNTYHUNTER) { + + } else if (terminalType == TerminalType.ENTERTAINER) { + + } else if (terminalType == TerminalType.ARTISAN) { + + } else { + //Console.println("ERROR: Unsupported terminal " + terminal.getObjectId()); + } + } + + }); + + objControllerOpcodes.put(ObjControllerOpcodes.MISSION_GENERIC_REQUEST, new INetworkRemoteEvent() { + + @Override + public void handlePacket(IoSession session, IoBuffer data) throws Exception { + Client client = core.getClient(session); + + if(client == null || client.getSession() == null) + return; + + SWGObject object = client.getParent(); + + if(object == null) + return; + + CreatureObject creature = (CreatureObject) object; + + data.order(ByteOrder.LITTLE_ENDIAN); + + MissionAcceptRequest request = new MissionAcceptRequest(); + request.deserialize(data); + + MissionObject mission = (MissionObject) core.objectService.getObject(request.getMissionObjId()); + + if (mission == null) + return; + + if (handleMissionAccept(creature, mission)) { + MissionAcceptResponse response = new MissionAcceptResponse(object.getObjectId(), mission.getObjectId(), request.getTerminalType(), (byte) 1); + object.getClient().getSession().write(new ObjControllerMessage(0x0B, response).serialize()); + } else { + MissionAcceptResponse response = new MissionAcceptResponse(object.getObjectId(), mission.getObjectId(), request.getTerminalType(), (byte) 0); + object.getClient().getSession().write(new ObjControllerMessage(0x0B, response).serialize()); + } + } + }); + } + + public void handleMissionAbort(CreatureObject creature, MissionObject mission) { + MissionObjective objective = mission.getObjective(); + + if (objective != null) + objective.abort(); + + core.objectService.destroyObject(mission.getObjectId()); + } + + private void loadMissionEntryCounts() { + File missionFolder = new File("./clientdata/string/en/mission"); + File[] missionFiles = missionFolder.listFiles(); + + int missionStrings = 0; + for (int i = 0; i < missionFiles.length; i++) { + if (missionFiles[i].getName().contains("_easy") || missionFiles[i].getName().contains("_medium") || missionFiles[i].getName().contains("_hard")) { + + String missionStf = "clientdata" + missionFiles[i].getAbsolutePath().split("clientdata")[1].replace("\\", "/"); + try { + StfTable stf = new StfTable(missionStf); + boolean gotCount = false; + + for (int s = 1; s < stf.getRowCount(); s++) { + + if (stf.getStringById(s).getKey() != null && stf.getStringById(s).getKey().equals("number_of_entries")) { + String finalStr = missionStf.split("clientdata/string/en/")[1].replace(".stf", ""); + entryCounts.put(finalStr, Integer.parseInt(stf.getStringById(s).getValue())); + gotCount = true; + } + } + if (gotCount == false) { + //System.out.println("!NO ENTRY COUNT FOR " + missionStf); + continue; + } + } catch (Exception e) { e.printStackTrace(); } + missionStrings++; + } + } + System.out.println("Loaded " + missionStrings + " mission entry counts."); + } + + + private int getRandomStringEntry(String missionStf) { + int ranEntryNum = 1; + + if (entryCounts.get(missionStf) != null) { ranEntryNum = ran.nextInt(entryCounts.get(missionStf)); } + //else { System.out.println(missionStf + " was not found in entryCount and is using entry #1"); } + + if (ranEntryNum == 0) + return 1; + else + return ranEntryNum; + } + + private void handleMissionListRequest(final SWGObject player, int requestCounter, int type) { + CreatureObject creature = (CreatureObject) player; + + TangibleObject missionBag = (TangibleObject) creature.getSlottedObject("mission_bag"); + + if (missionBag == null || creature == null) + return; + + final AtomicInteger typeOneCount = new AtomicInteger(); + final AtomicInteger typeTwoCount = new AtomicInteger(); + + missionBag.viewChildren(creature, true, false, new Traverser() { + + @Override + public void process(SWGObject obj) { + + if (obj instanceof MissionObject == false) + return; + + MissionObject mission = (MissionObject) obj; + + if (typeOneCount.get() < 4) { + + if (type == TerminalType.GENERIC) + randomDeliveryMission(player, mission); + + else if (type == TerminalType.BOUNTYHUNTER) + randomBountyMission(player, mission); + + else if (type == TerminalType.ARTISAN) + return; + + else + return; + + mission.setRepeatCount(requestCounter); + typeOneCount.incrementAndGet(); + + } else if (typeTwoCount.get() < 4) { + + if (type == TerminalType.GENERIC) + randomDestroyMission(player, mission); + + else if (type == TerminalType.BOUNTYHUNTER) + return; + + else if (type == TerminalType.ARTISAN) + return; + + else + return; + + mission.setRepeatCount(requestCounter); + typeTwoCount.incrementAndGet(); + } + } + }); + } + + private boolean handleMissionAccept(CreatureObject creature, MissionObject mission) { + SWGObject missionBag = creature.getSlottedObject("mission_bag"); + + if (mission.getContainer() != missionBag) + return false; + + TangibleObject datapad = (TangibleObject) creature.getSlottedObject("datapad"); + + if (datapad == null) + return false; + + AtomicInteger missionCount = new AtomicInteger(); + AtomicBoolean hasBountyMission = new AtomicBoolean(false); + datapad.viewChildren(creature, true, false, new Traverser() { + + @Override + public void process(SWGObject obj) { + if (obj instanceof MissionObject) { + missionCount.incrementAndGet(); + + if (((MissionObject) obj).getMissionType().equals("bounty")) + hasBountyMission.set(true); + } + } + }); + + if (hasBountyMission.get() && mission.getMissionType().equals("bounty")) // Can only have 1 bounty mission + return false; + + if (missionCount.get() == 2) { + creature.sendSystemMessage("@mission/mission_generic:too_many_missions", (byte) 0); + return false; + } + missionBag.transferTo(creature, datapad, mission); + createMissionObjective(creature, mission); + return true; + } + + private void createMissionObjective(CreatureObject creature, MissionObject mission) { + switch(mission.getMissionType()) { + + case "deliver": + DeliveryMissionObjective deliveryObjective = new DeliveryMissionObjective(mission); + + mission.setObjective(deliveryObjective); + + deliveryObjective.activate(); + break; + + case "destroy": + DestroyMissionObjective destroyObjective = new DestroyMissionObjective(mission); + + mission.setObjective(destroyObjective); + + destroyObjective.activate(); + break; + default: + break; + } + } + + private void randomDeliveryMission(SWGObject player, MissionObject mission) { + mission.setMissionType("deliver"); + + String[] difficulties = { "easy", "medium", "hard" }; + + String missionStf = "mission/mission_deliver_neutral_" + difficulties[ran.nextInt(difficulties.length)]; + + mission.setMissionId(getRandomStringEntry(missionStf)); + mission.setMissionDescription(missionStf); + mission.setMissionTitle(missionStf); + + mission.setCreator(nameGenerator.compose(2) + " " + nameGenerator.compose(3)); + + mission.setMissionLevel(5); + + // TODO: Use pre-defined commoner locations + Point3D startLocation = SpawnPoint.getRandomPosition(player.getPosition(), (float) 50, (float) 300, player.getPlanetId()); + Point3D destination = SpawnPoint.getRandomPosition(startLocation, (float) 50, (float) 500, player.getPlanetId()); + + mission.setStartLocation(startLocation, player.getPlanet().name); + mission.setDestination(destination, player.getPlanet().name); + + mission.setCreditReward((int) (50 + ((startLocation.getDistance2D(destination) / 10)))); + + mission.setMissionTemplateObject(CRC.StringtoCRC("object/tangible/mission/shared_mission_datadisk.iff")); + mission.setMissionTargetName("Datadisk"); + + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", player.getPlanet()); + if (waypoint == null) + return; + + waypoint.setColor(WaypointObject.ORANGE); + + } + + private void randomDestroyMission(SWGObject player, MissionObject mission) { + + } + + private void randomBountyMission(SWGObject player, MissionObject mission) { + + } + + public enum TerminalType {; + public static final int GENERIC = 1; + public static final int BOUNTYHUNTER = 2; + public static final int ENTERTAINER = 3; + public static final int ARTISAN = 4; + public static final int EXPLORER = 5; + } + + @Override + public void shutdown() { + + } +}