diff --git a/ngengine_public.jar b/ngengine_public.jar index ffa4476f..ddeff30b 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/scripts/commands/giveitem.py b/scripts/commands/giveitem.py index 8279dc05..2d5aba72 100644 --- a/scripts/commands/giveitem.py +++ b/scripts/commands/giveitem.py @@ -13,6 +13,9 @@ def run(core, actor, target, commandString): object = core.objectService.createObject(commandString, actor.getPlanet()) + #object.setCustomizationVariable('/private/index_color_blade', 0x02) + #object.setCustomizationVariable('private/alternate_shader_blade', 0x02) + if not object: return diff --git a/scripts/commands/pvp.py b/scripts/commands/pvp.py index e7c27d07..8fbdc155 100644 --- a/scripts/commands/pvp.py +++ b/scripts/commands/pvp.py @@ -47,30 +47,30 @@ def run(core, actor, target, commandString): if factionStatus == FactionStatus.OnLeave: actor.sendSystemMessage('@faction_recruiter:on_leave_to_covert', 0) - actor.setPvpStatus(PvpStatus.GoingCovert, True) + #actor.setPvpStatus(PvpStatus.GoingCovert, True) time.sleep(1) actor.setFactionStatus(FactionStatus.Combatant) - actor.setPvpStatus(PvpStatus.GoingCovert, False) + #actor.setPvpStatus(PvpStatus.GoingCovert, False) actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) actor.updatePvpStatus() return if factionStatus == FactionStatus.Combatant: actor.sendSystemMessage('@faction_recruiter:covert_to_overt', 0) - actor.setPvpStatus(PvpStatus.GoingOvert, True) + #actor.setPvpStatus(PvpStatus.GoingOvert, True) time.sleep(30) actor.setFactionStatus(FactionStatus.SpecialForces) - actor.setPvpStatus(PvpStatus.GoingOvert, False) + #actor.setPvpStatus(PvpStatus.GoingOvert, False) actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) actor.updatePvpStatus() return if factionStatus == FactionStatus.SpecialForces: actor.sendSystemMessage('@faction_recruiter:overt_to_covert', 0) - actor.setPvpStatus(PvpStatus.GoingCovert, True) + #actor.setPvpStatus(PvpStatus.GoingCovert, True) time.sleep(300) actor.setFactionStatus(FactionStatus.Combatant) - actor.setPvpStatus(PvpStatus.GoingCovert, False) + #actor.setPvpStatus(PvpStatus.GoingCovert, False) actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) actor.updatePvpStatus() return diff --git a/scripts/commands/setgodmode.py b/scripts/commands/setgodmode.py index e051aebe..35e55686 100644 --- a/scripts/commands/setgodmode.py +++ b/scripts/commands/setgodmode.py @@ -1,10 +1,7 @@ import sys from engine.resources.scene import Point3D -from protocol.swg import CommPlayerMessage -from protocol.swg.objectControllerObjects import ShowLootBox from protocol.swg import ObjControllerMessage from engine.resources.objects import SWGObject -from jarray import array def setup(): return @@ -59,25 +56,11 @@ def run(core, actor, target, commandString): elif command == 'changeBio' and arg1: actor.getSlottedObject('ghost').setBiography(arg1) - - elif command == 'rewardMe': - testObject = core.objectService.createObject('object/weapon/ranged/rifle/shared_rifle_t21.iff', actor.getPlanet()) - testObject.setCustomName('Crush4r') - testObject.setStringAttribute('crafter', 'Wavescrub') - dGun = core.objectService.createObject('object/weapon/ranged/rifle/shared_rifle_tc22_blaster.iff', actor.getPlanet()) - dGun.setCustomName('Supertoms Gun') - dGun.setStringAttribute('crafter', 'Wavescrub') - core.playerService.giveItems(actor, testObject, dGun) - return - - elif command == 'comm': - comm = CommPlayerMessage(actor.getObjectId()) - actor.getClient().getSession().write(comm.serialize()) elif command == 'spawn' and arg1 and arg2: pos = actor.getWorldPosition() + core.spawnService.spawnCreature(arg1, actor.getPlanet().getName(), 0, pos.x, pos.y, pos.z, 1, 0, 1, 0, int(arg2)) - core.spawnService.spawnCreature(arg1, actor.getPlanet().getName(), 0, pos.x, pos.y, pos.z, 1, 0, 1, 0, int(arg2)) elif command == 'instance' and arg1: core.instanceService.queue(arg1, actor) @@ -89,5 +72,14 @@ def run(core, actor, target, commandString): elif command == 'id': actor.sendSystemMessage('Your id is: ' + str(actor.getObjectId()), 0) - + + elif command == 'stealth': + if (actor.isInStealth()): + actor.setInStealth(False) + actor.setRadarVisible(True) + actor.sendSystemMessage('You are now visible to other players.', 0) + else: + actor.setInStealth(True) + actor.setRadarVisible(False) + actor.sendSystemMessage('You are now hidden from players. "Stealth Effect" is not implemented, however players still won\'t be able to see you. Type /setgodmode stealth again to be visible.', 0) return diff --git a/scripts/commands/teleporttarget.py b/scripts/commands/teleporttarget.py new file mode 100644 index 00000000..f497fe25 --- /dev/null +++ b/scripts/commands/teleporttarget.py @@ -0,0 +1,29 @@ +import sys +from engine.resources.scene import Point3D + +def setup(): + return + +def run(core, actor, target, commandString): + + playerObject = actor.getSlottedObject('ghost') + + if not playerObject: + return + + commandArgs = commandString.split(' ') + if len(commandArgs) > 0: + arg1 = commandArgs[0] + if len(commandArgs) > 1: + arg2 = commandArgs[1] + if len(commandArgs) > 2: + arg3 = commandArgs[2] + if len(commandArgs) > 3: + arg4 = commandArgs[3] + + if arg1 and arg2 and arg3 and arg4 target: + position = Point3D(float(arg2), float(arg3), float(arg4)) + core.simulationService.transferToPlanet(target, core.terrainService.getPlanetByName(arg1), position, actor.getOrientation(), None) + + + return diff --git a/scripts/mobiles/canon/jedi_master.py b/scripts/mobiles/canon/jedi_master.py new file mode 100644 index 00000000..9770c507 --- /dev/null +++ b/scripts/mobiles/canon/jedi_master.py @@ -0,0 +1,26 @@ +import sys +from services.spawn import MobileTemplate +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + templates = Vector() + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_twk_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_twk_02.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_zab_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_zab_02.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_04.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_05.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_06.iff') + mobileTemplate.setTemplates(templates) + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(2) + mobileTemplate.setCustomWeaponTemplate('object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff') + attacks = Vector() + mobileTemplate.setDefaultAttack('saberHit') + mobileTemplate.setAttacks(attacks) + mobileTemplate.setCreatureName('eow_dark_jedi_sentinel_uber') + mobileTemplate.setAttackRange(6) + core.spawnService.addMobileTemplate('jedi_master', mobileTemplate) + \ No newline at end of file diff --git a/src/protocol/swg/ChatCreateRoom.java b/src/protocol/swg/ChatCreateRoom.java new file mode 100644 index 00000000..5f63614a --- /dev/null +++ b/src/protocol/swg/ChatCreateRoom.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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; + +import org.apache.mina.core.buffer.IoBuffer; + +public class ChatCreateRoom extends SWGMessage { + + @Override + public void deserialize(IoBuffer data) { + + } + + @Override + public IoBuffer serialize() { + return null; + } + +} diff --git a/src/protocol/swg/ChatEnterRoomById.java b/src/protocol/swg/ChatEnterRoomById.java new file mode 100644 index 00000000..29fd69cd --- /dev/null +++ b/src/protocol/swg/ChatEnterRoomById.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * 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; + +import org.apache.mina.core.buffer.IoBuffer; + +public class ChatEnterRoomById extends SWGMessage { + + private int roomId; + + public ChatEnterRoomById() { } + + @Override + public void deserialize(IoBuffer data) { + setRoomId(data.getInt()); + } + + @Override + public IoBuffer serialize() { + return null; + } + + public int getRoomId() { + return roomId; + } + + public void setRoomId(int roomId) { + this.roomId = roomId; + } + +} diff --git a/src/protocol/swg/ChatOnSendRoomMessage.java b/src/protocol/swg/ChatOnSendRoomMessage.java index 4ab43d6c..0d7729e5 100644 --- a/src/protocol/swg/ChatOnSendRoomMessage.java +++ b/src/protocol/swg/ChatOnSendRoomMessage.java @@ -28,9 +28,11 @@ import org.apache.mina.core.buffer.IoBuffer; public class ChatOnSendRoomMessage extends SWGMessage { private int errorCode; + private int msgId; - public ChatOnSendRoomMessage(int errorCode) { + public ChatOnSendRoomMessage(int errorCode, int msgId) { this.errorCode = errorCode; + this.msgId = msgId; } @Override @@ -43,7 +45,7 @@ public class ChatOnSendRoomMessage extends SWGMessage { buffer.putShort((short) 3); buffer.putInt(0xE7B61633); buffer.putInt(errorCode); - buffer.putInt(1); // msg id + buffer.putInt(msgId); // msg id return buffer.flip(); } diff --git a/src/protocol/swg/ChatSendToRoom.java b/src/protocol/swg/ChatSendToRoom.java new file mode 100644 index 00000000..c3a07dac --- /dev/null +++ b/src/protocol/swg/ChatSendToRoom.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; + +import org.apache.mina.core.buffer.IoBuffer; + +public class ChatSendToRoom extends SWGMessage { + + private String message; + private int roomId; + private int msgId; + + public ChatSendToRoom() { } + + @Override + public void deserialize(IoBuffer data) { + setMessage(getUnicodeString(data)); + data.getInt(); + setRoomId(data.getInt()); + setMsgId(data.getInt()); + } + + @Override + public IoBuffer serialize() { + return null; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getRoomId() { + return roomId; + } + + public void setRoomId(int roomId) { + this.roomId = roomId; + } + + public int getMsgId() { + return msgId; + } + + public void setMsgId(int msgId) { + this.msgId = msgId; + } + +} diff --git a/src/resources/common/Opcodes.java b/src/resources/common/Opcodes.java index 9f906000..4ac4d5ad 100644 --- a/src/resources/common/Opcodes.java +++ b/src/resources/common/Opcodes.java @@ -25,6 +25,8 @@ import engine.resources.common.CRC; public class Opcodes { + public static int ChatEnterRoomById = CRC.StringtoCRC("ChatEnterRoomById"); + public static int ChatSendToRoom = CRC.StringtoCRC("ChatSendToRoom"); public static int ChatDeletePersistentMessage = 0x8F251641; public static int ChatInstantMessageToCharacter = 0x84BB21F7; public static int ChatPersistentMessageToServer = 0x25A29FA6; diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index c543a344..5ebafb62 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -342,7 +342,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putShort((short) 0); // costume //buffer.put(getAsciiString("appearance/gungan_m.sat")); - buffer.put((byte) 1); // visible boolean. default: true. cloaked if false. + buffer.put((byte) (creature.isInStealth() ? 0 : 1)); if(creature.getBuffList().isEmpty()) { buffer.putInt(0); @@ -362,8 +362,11 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { PlayerObject player = (PlayerObject) creature.getSlottedObject("ghost"); for(Buff buff : creature.getBuffList().get()) { - - buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + + if(player != null) + buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + else + buff.setTotalPlayTime(0); buffer.put((byte) 1); buffer.putInt(0); buffer.putInt(CRC.StringtoCRC(buff.getBuffName())); @@ -385,7 +388,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { } - buffer.put((byte) 0); // performing? boolean + buffer.put((byte) (creature.isStationary() ? 1 : 0)); // if the server accepts transforms from the object buffer.put(creature.getDifficulty()); if(creature.isHologram()) @@ -393,7 +396,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { else buffer.putInt(0xFFFFFFFF); - buffer.put((byte) 1); // visibleOnRadar? boolean + buffer.put((byte) (creature.isRadarVisible() ? 1 : 0)); buffer.put((byte) 0); // no effect for 1? buffer.put((byte) 0); // no effect for 1? @@ -777,7 +780,10 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { IoBuffer buffer = bufferPool.allocate(37, false).order(ByteOrder.LITTLE_ENDIAN); buffer.putInt(1); buffer.putInt(creature.getBuffListCounter()); - buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + if(player != null) + buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + else + buff.setTotalPlayTime(0); buffer.put((byte) 0); buffer.put(buff.getBytes()); int size = buffer.position(); @@ -813,7 +819,10 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { IoBuffer buffer = bufferPool.allocate(37, false).order(ByteOrder.LITTLE_ENDIAN); buffer.putInt(1); buffer.putInt(creature.getBuffListCounter()); - buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + if(player != null) + buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + else + buff.setTotalPlayTime(0); buffer.put((byte) 2); buffer.put(buff.getBytes()); int size = buffer.position(); @@ -1188,6 +1197,24 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer = createDelta("CREO", (byte) 3, (short) 1, (short) 0x0D, buffer, size + 4); return buffer; } + + public IoBuffer buildStealthFlagDelta(boolean flag) { + IoBuffer buffer = bufferPool.allocate(8, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.put((byte) (flag ? 0 : 1)); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x19, buffer, size + 4); + return buffer; + } + + public IoBuffer buildRadarVisibleFlagDelta(boolean flag) { + IoBuffer buffer = bufferPool.allocate(1, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.put((byte) (flag ? 1 : 0)); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x1E, buffer, size + 4); + return buffer; + } public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { switch (viewType) { diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index d861e5a5..de703925 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -59,7 +59,7 @@ import engine.resources.scene.Quaternion; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; -@Entity(version=3) +@Entity(version=4) public class CreatureObject extends TangibleObject implements IPersistent { @NotPersistent @@ -147,7 +147,11 @@ public class CreatureObject extends TangibleObject implements IPersistent { private SWGList appearanceEquipmentList; @NotPersistent private int appearanceEquipmentListUpdateCounter = 0; - + + private boolean inStealth = false; + private boolean radarVisible = true; // radar + private boolean stationary = false; + // non-baseline vars @NotPersistent private List duelList = Collections.synchronizedList(new ArrayList()); @@ -1709,4 +1713,42 @@ public class CreatureObject extends TangibleObject implements IPersistent { this.performingFlourish = performingFlourish; } } + + public boolean isInStealth() { + synchronized(objectMutex) { + return inStealth; + } + } + + public void setInStealth(boolean inStealth) { + synchronized(objectMutex) { + this.inStealth = inStealth; + } + notifyObservers(messageBuilder.buildStealthFlagDelta(inStealth), false); + } + + public boolean isRadarVisible() { + synchronized(objectMutex) { + return radarVisible; + } + } + + public void setRadarVisible(boolean radarVisible) { + synchronized(objectMutex) { + this.radarVisible = radarVisible; + } + notifyObservers(messageBuilder.buildRadarVisibleFlagDelta(radarVisible), false); + } + + public boolean isStationary() { + synchronized(objectMutex) { + return stationary; + } + } + + public void setStationary(boolean stationary) { + synchronized(objectMutex) { + this.stationary = stationary; + } + } } diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index b00537a1..dce95545 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -21,35 +21,40 @@ ******************************************************************************/ package resources.objects.tangible; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Vector; -import main.NGECore; +import javax.xml.bind.DatatypeConverter; +import main.NGECore; import protocol.swg.ObjControllerMessage; import protocol.swg.PlayClientEffectObjectMessage; import protocol.swg.StopClientEffectObjectByLabel; import protocol.swg.UpdatePVPStatusMessage; import protocol.swg.objectControllerObjects.ShowFlyText; - import resources.common.RGB; import resources.objects.creature.CreatureObject; +import resources.visitors.IDManagerVisitor; import services.ai.AIActor; import com.sleepycat.persist.model.NotPersistent; import com.sleepycat.persist.model.Persistent; +import engine.clientdata.ClientFileManager; import engine.clients.Client; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=0) +@Persistent(version=1) public class TangibleObject extends SWGObject { // TODO: Thread safety @@ -59,6 +64,7 @@ public class TangibleObject extends SWGObject { protected int pvpBitmask = 0; protected byte[] customization; private List componentCustomizations = new ArrayList(); + private Map customizationVariables = new HashMap(); protected int optionsBitmask = 0; private int maxDamage = 1000; private boolean staticObject = true; @@ -241,6 +247,50 @@ public class TangibleObject extends SWGObject { } } + public void setCustomizationVariable(String type, byte value) + { + if(customizationVariables.containsKey(type)) customizationVariables.replace(type, value); + else customizationVariables.put(type, value); + + buildCustomizationBytes(); + } + + public void removeCustomizationVariable(String type) + { + if(customizationVariables.containsKey(type)) + { + customizationVariables.remove(type); + buildCustomizationBytes(); + } + } + + private void buildCustomizationBytes() + { + //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); + } + customization = stream.toByteArray(); + } + catch (Exception e) { e.printStackTrace(); } + } + public String getFaction() { synchronized(objectMutex) { return faction; diff --git a/src/resources/visitors/IDManagerVisitor.java b/src/resources/visitors/IDManagerVisitor.java index 2ad1ad46..3c7a1617 100644 --- a/src/resources/visitors/IDManagerVisitor.java +++ b/src/resources/visitors/IDManagerVisitor.java @@ -31,11 +31,11 @@ import engine.clientdata.VisitorInterface; public class IDManagerVisitor implements VisitorInterface { - private ConcurrentHashMap customizationMap; + private ConcurrentHashMap customizationMap; private CharsetDecoder charsetDecoder; public IDManagerVisitor() { - customizationMap = new ConcurrentHashMap(); + customizationMap = new ConcurrentHashMap(); charsetDecoder = Charset.forName("US-ASCII").newDecoder(); } @@ -46,21 +46,28 @@ public class IDManagerVisitor implements VisitorInterface { return; while(data.hasRemaining()) { - short designNumber = data.getShort(); + + byte designNumber = data.get(); + data.get(); String customizationType = data.getString(charsetDecoder); charsetDecoder.reset(); - + customizationMap.put(customizationType, designNumber); //System.out.println(designNumber + ": " + customizationType); } } + + public byte getAttributeIndex(String type) + { + return customizationMap.get(type); + } @Override public void notifyFolder(String node, int depth) throws Exception { } - public ConcurrentHashMap getCustomizationMap() { + public ConcurrentHashMap getCustomizationMap() { return this.customizationMap; } } diff --git a/src/services/DevService.java b/src/services/DevService.java index 6359957d..f9689348 100644 --- a/src/services/DevService.java +++ b/src/services/DevService.java @@ -93,6 +93,7 @@ public class DevService implements INetworkDispatch { break; case 4: // [Items] Misc Items suiOptions.put((long) 40, "Unity Ring"); + break; } final SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "Character Builder Terminal", "Select the desired option and click OK.", suiOptions, creature, null, 10); @@ -231,27 +232,33 @@ public class DevService implements INetworkDispatch { return; // [Items] Weapons case 30: // Jedi Weapons - SWGObject lightsaber1 = core.objectService.createObject("object/weapon/melee/sword/crafted_saber/shared_sword_lightsaber_one_handed_gen5.iff", planet); + TangibleObject lightsaber1 = (TangibleObject) core.objectService.createObject("object/weapon/melee/sword/crafted_saber/shared_sword_lightsaber_one_handed_gen5.iff", planet); lightsaber1.setIntAttribute("required_combat_level", 90); lightsaber1.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber1.setStringAttribute("class_required", "Jedi"); lightsaber1.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber1.setStringAttribute("cat_wpn_damage.damage", "689-1379"); - SWGObject lightsaber2 = core.objectService.createObject("object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff", planet); + TangibleObject lightsaber2 = (TangibleObject) core.objectService.createObject("object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff", planet); lightsaber2.setIntAttribute("required_combat_level", 90); lightsaber2.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber2.setStringAttribute("class_required", "Jedi"); lightsaber2.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber2.setStringAttribute("cat_wpn_damage.damage", "689-1379"); - SWGObject lightsaber3 = core.objectService.createObject("object/weapon/melee/polearm/crafted_saber/shared_sword_lightsaber_polearm_gen5.iff", planet); + TangibleObject lightsaber3 = (TangibleObject) core.objectService.createObject("object/weapon/melee/polearm/crafted_saber/shared_sword_lightsaber_polearm_gen5.iff", planet); lightsaber3.setIntAttribute("required_combat_level", 90); lightsaber3.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber3.setStringAttribute("class_required", "Jedi"); lightsaber3.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber3.setStringAttribute("cat_wpn_damage.damage", "689-1379"); + Random random = new Random(); + + lightsaber1.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + lightsaber2.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + lightsaber3.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + inventory.add(lightsaber1); inventory.add(lightsaber2); inventory.add(lightsaber3); @@ -275,6 +282,15 @@ public class DevService implements INetworkDispatch { rifle1.setStringAttribute("cat_wpn_damage.damage", "800-1250"); inventory.add(rifle1); + + SWGObject pistol = core.objectService.createObject("object/weapon/ranged/pistol/shared_pistol_cdef.iff", planet); + pistol.setIntAttribute("required_combat_level", 90); + pistol.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); + pistol.setStringAttribute("class_required", "None"); + pistol.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); + pistol.setStringAttribute("cat_wpn_damage.damage", "400-559"); + + inventory.add(pistol); return; case 40: TangibleObject ring = (TangibleObject) core.objectService.createObject("object/tangible/wearables/ring/shared_ring_s01.iff", planet); diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 8b64175e..0457d94a 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -65,9 +65,9 @@ public class EntertainmentService implements INetworkDispatch { private ConcurrentHashMap performancesByIndex = new ConcurrentHashMap(); private ConcurrentHashMap danceMap = new ConcurrentHashMap(); - private ConcurrentHashMap designMap = new ConcurrentHashMap(); + private ConcurrentHashMap designMap = new ConcurrentHashMap(); - private Random ranWorkshop = new Random(); + //private Random ranWorkshop = new Random(); private Map performanceEffects = new ConcurrentHashMap(); @@ -932,7 +932,7 @@ public class EntertainmentService implements INetworkDispatch { public String getCustomizationString(int number){ synchronized (designMap) { - for (Entry entry : designMap.entrySet()) { + for (Entry entry : designMap.entrySet()) { if (entry.getValue().intValue() == number) { return entry.getKey(); } @@ -943,7 +943,7 @@ public class EntertainmentService implements INetworkDispatch { public int getCustomizationValue(String customizationString) { synchronized(designMap){ - for(Entry entry : designMap.entrySet()) { + for(Entry entry : designMap.entrySet()) { if (entry.getKey().equals(customizationString)) { return entry.getValue().intValue(); } diff --git a/src/services/GroupService.java b/src/services/GroupService.java index dc2cf39b..472c4f80 100644 --- a/src/services/GroupService.java +++ b/src/services/GroupService.java @@ -153,7 +153,7 @@ public class GroupService implements INetworkDispatch { addGroupBuffsToMember(group, leader); addGroupBuffsToMember(group, invited); - //ChatRoom groupChat = core.chatService.createChatRoom(leader.getCustomName() + group.getObjectID(), "GroupChat", leader.getCustomName(), true); + //ChatRoom groupChat = core.chatService.createChatRoom("GroupChat", "group." + group.getObjectID(), leader.getCustomName(), true); //group.setChatRoomId(groupChat.getRoomId()); //core.chatService.joinChatRoom(leader, groupChat.getRoomId()); diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 15b784d7..80680ae1 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -87,6 +87,7 @@ import toxi.geom.Line3D; import toxi.geom.Ray3D; import toxi.geom.Vec3D; import toxi.geom.mesh.TriangleMesh; +import wblut.geom.WB_AABB; import wblut.geom.WB_AABBNode; import wblut.geom.WB_AABBTree; import wblut.geom.WB_Distance; @@ -166,6 +167,7 @@ public class SimulationService implements INetworkDispatch { core.commandService.registerCommand("requestbiography"); core.commandService.registerCommand("eject"); core.commandService.registerGmCommand("broadcast"); + core.commandService.registerGmCommand("teleporttarget"); } @@ -689,7 +691,6 @@ public class SimulationService implements INetworkDispatch { float endZ = (float) (modelSpace.m31 * end.x + modelSpace.m32 * end.y + modelSpace.m33 * end.z + modelSpace.m34); end = new Point3D(endX, endY, endZ); - Vector3D direction = new Vector3D(end.x - origin.x, end.y - origin.y, end.z - origin.z); if(direction.getX() > 0 && direction.getY() > 0 && direction.getZ() > 0) direction.normalize(); @@ -719,7 +720,6 @@ public class SimulationService implements INetworkDispatch { return new Point3D(x, y, z); } - /* * Moved this to ConnectionService which will disconnect them * from the server if they don't send packets for 5 minutes or more @@ -902,7 +902,7 @@ public class SimulationService implements INetworkDispatch { } public boolean checkLineOfSight(SWGObject obj1, SWGObject obj2) { - + long startTime = System.nanoTime(); if(obj1.getPlanet() != obj2.getPlanet()) return false; @@ -931,7 +931,7 @@ public class SimulationService implements INetworkDispatch { Point3D end = new Point3D(position2.x, position2.y + heightDirection, position2.z); float distance = position1.getDistance2D(position2); - List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, 150); + List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, (int) (distance + 10)); for(SWGObject object : inRangeObjects) { @@ -959,6 +959,7 @@ public class SimulationService implements INetworkDispatch { for(Mesh3DTriangle tri : tris) { if(ray.intersectsTriangle(tri, distance) != null) { + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (collided)"); // System.out.println("Collided with " + object.getTemplate() + " X: " + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); return false; } @@ -981,8 +982,8 @@ public class SimulationService implements INetworkDispatch { return checkLineOfSightWorldToCell(obj1, obj2, cell); } - /*List segments = new ArrayList(); - Line3D.splitIntoSegments(new Vec3D(position1.x, position1.y + 1, position1.z), new Vec3D(position2.x, position2.y + 1, position2.z), (float) 0.5, segments, true); + List segments = new ArrayList(); + Line3D.splitIntoSegments(new Vec3D(position1.x, position1.y + 1, position1.z), new Vec3D(position2.x, position2.y + 1, position2.z), (float) 1, segments, true); for(Vec3D segment : segments) { float y = segment.y; @@ -990,11 +991,12 @@ public class SimulationService implements INetworkDispatch { int height = (int) core.terrainService.getHeight(obj1.getPlanetId(), segment.x, segment.z); // round down to int if(height > y) { - System.out.println("Collision with terrain"); + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (terrain collision)"); return false; } - }*/ - + } + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (did not collide)"); + return true; } @@ -1031,6 +1033,7 @@ public class SimulationService implements INetworkDispatch { MeshVisitor meshVisitor; if(!cellMeshes.containsKey(cell.mesh)) { meshVisitor = ClientFileManager.loadFile(cell.mesh, MeshVisitor.class); + meshVisitor.getTriangles(); cellMeshes.put(cell.mesh, meshVisitor); } else { meshVisitor = cellMeshes.get(cell.mesh); diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index c5b5bb5e..562686dc 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -49,6 +49,7 @@ import resources.common.*; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import protocol.swg.AddIgnoreMessage; +import protocol.swg.ChatEnterRoomById; import protocol.swg.ChatOnChangeFriendStatus; import protocol.swg.ChatDeletePersistentMessage; import protocol.swg.ChatFriendsListUpdate; @@ -64,6 +65,7 @@ import protocol.swg.ChatPersistentMessageToServer; import protocol.swg.ChatRequestPersistentMessage; import protocol.swg.ChatRoomList; import protocol.swg.ChatRoomMessage; +import protocol.swg.ChatSendToRoom; import protocol.swg.ChatSystemMessage; import protocol.swg.ObjControllerMessage; import protocol.swg.objectControllerObjects.PlayerEmote; @@ -367,9 +369,53 @@ public class ChatService implements INetworkDispatch { }); swgOpcodes.put(Opcodes.ChatCreateRoom, (session, data) -> { + //System.out.println("CREATE:"); + //StringUtilities.printBytes(data.array()); }); swgOpcodes.put(Opcodes.ChatQueryRoom, (session, data) -> { + //System.out.println("QUERY: "); + //StringUtilities.printBytes(data.array()); + }); + + swgOpcodes.put(Opcodes.ChatSendToRoom, (session, data) -> { + Client client = core.getClient(session); + + if(client == null) + return; + + SWGObject obj = client.getParent(); + + if (obj == null) + return; + + ChatSendToRoom sentPacket = new ChatSendToRoom(); + sentPacket.deserialize(data); + + //ChatRoom room = getChatRoom(sentPacket.getRoomId()); + + sendChatRoomMessage((CreatureObject) obj, sentPacket.getRoomId(), sentPacket.getMsgId(), sentPacket.getMessage()); + + }); + + swgOpcodes.put(Opcodes.ChatEnterRoomById, (session, data) -> { + Client client = core.getClient(session); + + if(client == null) + return; + + SWGObject obj = client.getParent(); + + if (obj == null) + return; + + ChatEnterRoomById sentPacket = new ChatEnterRoomById(); + sentPacket.deserialize(data); + + joinChatRoom((CreatureObject) obj, sentPacket.getRoomId()); + + //System.out.println("Entering room..."); + }); } @@ -687,10 +733,12 @@ public class ChatService implements INetworkDispatch { return; ChatOnEnteredRoom enterRoom = new ChatOnEnteredRoom(playerName, 0, roomId, true); - player.getClient().getSession().write(enterRoom.serialize()); if (!room.getUserList().contains(player)) room.getUserList().add(player); + + room.getUserList().stream().forEach(user -> user.getClient().getSession().write(enterRoom.serialize())); + } public void leaveChatRoom(CreatureObject player, int roomId) { @@ -711,7 +759,7 @@ public class ChatService implements INetworkDispatch { room.getUserList().remove(player); } - public void sendChatRoomMessage(CreatureObject sender, int roomId, String message) { + public void sendChatRoomMessage(CreatureObject sender, int roomId, int msgId, String message) { String senderName = sender.getCustomName().toLowerCase(); if (senderName.contains(" ")) @@ -720,17 +768,14 @@ public class ChatService implements INetworkDispatch { ChatRoom room = getChatRoom(roomId); if (room == null) return; - - ChatOnSendRoomMessage onSend = new ChatOnSendRoomMessage(ChatOnSendRoomMessage.SUCCESS); + + ChatOnSendRoomMessage onSend = new ChatOnSendRoomMessage(0, msgId); sender.getClient().getSession().write(onSend.serialize()); ChatRoomMessage roomMessage = new ChatRoomMessage(roomId, senderName, message); Vector users = room.getUserList(); for (CreatureObject user : users) { - if (user == sender) - continue; - user.getClient().getSession().write(roomMessage.serialize()); } } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 53022efc..6115344a 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -193,7 +193,15 @@ public class CombatService implements INetworkDispatch { creature.removeDefender(defender); } } - } + } + else if(target instanceof TangibleObject) + { + if(target.getConditionDamage() == target.getMaxDamage()) + { + for(TangibleObject defender : target.getDefendersList()) defender.removeDefender(target); + core.objectService.destroyObject(target); + } + } } private void doAreaCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { @@ -979,6 +987,8 @@ public class CombatService implements INetworkDispatch { target.sendSystemMessage("@base_player:victim_dead", (byte) 0); attacker.removeDefender(target); target.removeDefender(attacker); + target.setSpeedMultiplierBase(0); + target.setTurnRadius(0); if(target.getDuelList().contains(attacker)) handleEndDuel(target, attacker, false); diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index c2c42166..9b1cb401 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -23,6 +23,7 @@ package services.spawn; import java.util.Vector; +import main.NGECore; import resources.datatables.Options; import resources.datatables.PvpStatus; import resources.objects.weapon.WeaponObject; @@ -43,6 +44,7 @@ public class MobileTemplate { private float scale = 1; // this is a custom attack Range setting to use for large mobs like krayts private int attackRange; + private String customWeaponTemplate; public Vector getTemplates() { return templates; @@ -155,5 +157,14 @@ public class MobileTemplate { public void setAttackRange(int attackRange) { this.attackRange = attackRange; } - + + public void setCustomWeaponTemplate(String template) + { + this.customWeaponTemplate = template; + } + + public String getCustomWeaponTemplate() + { + return customWeaponTemplate; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index eede805a..c26defae 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -112,7 +112,7 @@ public class SpawnService { creature.setLevel(level); else creature.setLevel(mobileTemplate.getLevel()); - WeaponObject defaultWeapon = (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", creature.getPlanet()); + WeaponObject defaultWeapon = (mobileTemplate.getCustomWeaponTemplate() != null) ? (WeaponObject) core.objectService.createObject(mobileTemplate.getCustomWeaponTemplate(), creature.getPlanet()) : (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", creature.getPlanet()); defaultWeapon.setAttackSpeed(2); defaultWeapon.setDamageType("@obj_attr_n:armor_eff_kinetic"); defaultWeapon.setStringAttribute("cat_wpn_damage.damage", "0-0");