diff --git a/options.cfg b/options.cfg new file mode 100644 index 00000000..c35edf74 --- /dev/null +++ b/options.cfg @@ -0,0 +1 @@ +LOAD.SNAPSHOT_OBJECTS=0 diff --git a/scripts/commands/invite.py b/scripts/commands/invite.py new file mode 100644 index 00000000..1a109fe7 --- /dev/null +++ b/scripts/commands/invite.py @@ -0,0 +1,10 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + if actor and target: + core.groupService.handleGroupInvite(actor, target) + return + \ No newline at end of file diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index d7608031..7b22fd0d 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -737,6 +737,22 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { return buffer; } + + public IoBuffer buildGroupInviteDelta(long inviteSenderId, long inviteCounter, String leaderName) { + + IoBuffer buffer = bufferPool.allocate(18 + leaderName.length(), false).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putLong(inviteSenderId); + buffer.put(getAsciiString(leaderName)); + buffer.putLong(inviteCounter); + + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x0E, buffer, size + 4); + + return buffer; + + } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 2768623f..01fe8e79 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -936,6 +936,15 @@ public class CreatureObject extends TangibleObject implements IPersistent { } return null; } + + public void updateGroupInviteInfo() { + + if(getClient() == null || getClient().getSession() == null) + return; + + getClient().getSession().write(messageBuilder.buildGroupInviteDelta(getInviteSenderId(), getInviteCounter(), getInviteSenderName())); + + } } diff --git a/src/resources/objects/group/GroupMessageBuilder.java b/src/resources/objects/group/GroupMessageBuilder.java new file mode 100644 index 00000000..0d2ec6be --- /dev/null +++ b/src/resources/objects/group/GroupMessageBuilder.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * 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.objects.group; + +import java.nio.ByteOrder; +import org.apache.mina.core.buffer.IoBuffer; +import engine.resources.objects.SWGObject; +import resources.objects.ObjectMessageBuilder; + +public class GroupMessageBuilder extends ObjectMessageBuilder { + + public GroupMessageBuilder(GroupObject groupObject) { + setObject(groupObject); + } + + + public IoBuffer buildBaseline3() { + + IoBuffer buffer = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.setAutoExpand(true); + + buffer.putShort((short) 4); // Obj Operand Count + buffer.putFloat(1); // Complexity + + buffer.put(getAsciiString("string_id_table")); + + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + + buffer.putShort((short) 0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + buffer.put((byte) 0); + + int size = buffer.position(); + + buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); + + buffer.flip(); + buffer = createBaseline("GRUP", (byte) 3, buffer, size); + + return buffer; + + } + + public IoBuffer buildBaseline6() { + + GroupObject group = (GroupObject) object; + IoBuffer buffer = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.setAutoExpand(true); + + buffer.putShort((short) 0x0B); // Obj Operand Count + buffer.putInt(0x45); + + buffer.put(getAsciiString("string_id_table")); + + buffer.putInt(0); + buffer.putShort((short) 0); + + buffer.putInt(group.getMemberList().size()); + buffer.putInt(group.getMemberListUpdateCounter()); + + synchronized(group.getMemberList().getMutex()) { + for(SWGObject obj : group.getMemberList().get()) { + buffer.putLong(obj.getObjectID()); + buffer.put(getAsciiString(obj.getCustomName())); + } + } + + buffer.putInt(0); + buffer.putInt(0); + + + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(1); + buffer.putShort((short) 0); + buffer.putShort((short) 0x5A); + buffer.putInt(0); + buffer.putLong(group.getGroupLeader().getObjectID()); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + + + int size = buffer.position(); + + buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); + + buffer.flip(); + buffer = createBaseline("GRUP", (byte) 6, buffer, size); + + return buffer; + + } + + public IoBuffer buildAddMemberDelta(SWGObject member) { + + GroupObject group = (GroupObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(group.getMemberListUpdateCounter()); + + buffer.put((byte) 1); + buffer.putShort((short) group.getMemberList().indexOf(member)); + buffer.putLong(member.getObjectID()); + buffer.put(getAsciiString(member.getCustomName())); + + int size = buffer.position(); + buffer.flip(); + return buffer = createDelta("GRUP", (byte) 6, (short) 1, (short) 2, buffer, size + 4); + + } + + public IoBuffer buildRemoveMemberDelta(SWGObject member) { + + GroupObject group = (GroupObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(group.getMemberListUpdateCounter()); + + buffer.put((byte) 0); + buffer.putShort((short) group.getMemberList().indexOf(member)); + + int size = buffer.position(); + buffer.flip(); + return buffer = createDelta("GRUP", (byte) 6, (short) 1, (short) 2, buffer, size + 4); + + } + + + @Override + public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { + // TODO Auto-generated method stub + + } + + @Override + public void sendBaselines() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/resources/objects/group/GroupObject.java b/src/resources/objects/group/GroupObject.java index 2d4de4bd..e689ddc0 100644 --- a/src/resources/objects/group/GroupObject.java +++ b/src/resources/objects/group/GroupObject.java @@ -21,8 +21,9 @@ ******************************************************************************/ package resources.objects.group; -import java.util.Vector; +import org.apache.mina.core.buffer.IoBuffer; +import resources.objects.SWGList; import engine.clients.Client; import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; @@ -31,18 +32,20 @@ import engine.resources.scene.Quaternion; public class GroupObject extends SWGObject { - private Vector memberList = new Vector(); + private SWGList memberList = new SWGList(); private int memberListUpdateCounter; private SWGObject groupLeader; private SWGObject lootMaster; private short groupLevel; private int lootMode; + private GroupMessageBuilder messageBuilder; public GroupObject(long objectId) { super(objectId, null, new Point3D(0, 0, 0), new Quaternion(0, 0, 0, 1), "object/group/shared_group_object.iff"); + messageBuilder = new GroupMessageBuilder(this); } - public Vector getMemberList() { + public SWGList getMemberList() { return memberList; } @@ -105,10 +108,42 @@ public class GroupObject extends SWGObject { this.lootMode = lootMode; } } + + public void addMember(SWGObject member) { + + if(memberList.size() >= 8 || member.getClient() == null) + return; + + memberList.add(member); + + setMemberListUpdateCounter(getMemberListUpdateCounter() + 1); + notifyObservers(messageBuilder.buildAddMemberDelta(member), false); + + } + + public void removeMember(SWGObject member) { + + if(memberList.size() <= 0 || member.getClient() == null) + return; + + setMemberListUpdateCounter(getMemberListUpdateCounter() + 1); + notifyObservers(messageBuilder.buildRemoveMemberDelta(member), false); + + memberList.remove(member); + + } + @Override - public void sendBaselines(Client client) { - // TODO Auto-generated method stub + public void sendBaselines(Client destination) { + + if(destination == null || destination.getSession() == null) { + System.out.println("NULL session"); + return; + } + + destination.getSession().write(messageBuilder.buildBaseline3()); + destination.getSession().write(messageBuilder.buildBaseline6()); } diff --git a/src/services/GroupService.java b/src/services/GroupService.java new file mode 100644 index 00000000..f572a732 --- /dev/null +++ b/src/services/GroupService.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * 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.util.Map; + +import resources.objects.creature.CreatureObject; +import resources.objects.group.GroupObject; + +import main.NGECore; + +import engine.clients.Client; +import engine.resources.objects.SWGObject; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class GroupService implements INetworkDispatch { + + private NGECore core; + + public GroupService(NGECore core) { + this.core = core; + core.commandService.registerCommand("invite"); + core.commandService.registerCommand("join"); + core.commandService.registerCommand("disband"); + core.commandService.registerCommand("decline"); + } + + @Override + public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { + + } + + @Override + public void shutdown() { + + } + + public void handleGroupInvite(CreatureObject leader, CreatureObject member) { + + Client leaderClient = leader.getClient(); + Client memberClient = member.getClient(); + + if(leaderClient == null || memberClient == null) + return; + + long leaderGroupId = leader.getGroupId(); + long memberGroupId = member.getGroupId(); + + if(leader == member) { + leader.sendSystemMessage("@group:invite_no_target_self", (byte) 0); + return; + } + + if(memberGroupId != 0) { + leader.sendSystemMessage(member.getCustomName() + " is already in a group.", (byte) 0); + return; + } + + + if(leaderGroupId != 0) { + + GroupObject group = (GroupObject) core.objectService.getObject(leaderGroupId); + + if(group.getGroupLeader() != leader) { + leader.sendSystemMessage("@group:must_be_leader", (byte) 0); + return; + } + + if(group.getMemberList().size() >= 8) { + leader.sendSystemMessage("@group:full", (byte) 0); + return; + } + + } + + if(member.getInviteSenderId() != 0 && member.getInviteSenderId() != leader.getObjectID()) { + leader.sendSystemMessage(member.getCustomName() + " is considering joining another group.", (byte) 0); + return; + } + + if(member.getInviteSenderId() != 0 && member.getInviteSenderId() == leader.getObjectID()) { + leader.sendSystemMessage(member.getCustomName() + " has already been invited to join your group.", (byte) 0); + return; + } + + leader.sendSystemMessage("You invite " + member.getCustomName() + " to join the group.", (byte) 0); + member.setInviteCounter(member.getInviteCounter() + 1); + member.setInviteSenderId(member.getObjectId()); + member.setInviteSenderName(leader.getCustomName()); + + member.updateGroupInviteInfo(); + + } + + public void handleGroupDecline(CreatureObject invited) { + + CreatureObject leader = (CreatureObject) core.objectService.getObject(invited.getInviteSenderId()); + + invited.setInviteCounter(invited.getInviteCounter() + 1); + invited.setInviteSenderId(0); + invited.setInviteSenderName(""); + + invited.sendSystemMessage("You decline to join " + leader.getCustomName() + "'s group.", (byte) 0); + invited.updateGroupInviteInfo(); + + leader.sendSystemMessage(invited.getCustomName() + " declines to join your group.", (byte) 0); + + } + + + + +} diff --git a/src/services/TerrainService.java b/src/services/TerrainService.java index 7fb109a3..d1786eb0 100644 --- a/src/services/TerrainService.java +++ b/src/services/TerrainService.java @@ -26,11 +26,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TreeMap; +import engine.resources.config.Config; import engine.resources.scene.Planet; - import main.NGECore; public class TerrainService { @@ -127,7 +126,12 @@ public class TerrainService { @Override public void run() { - core.objectService.loadSnapshotObjects(planet); + Config config = new Config(); + config.setFilePath("options.cfg"); + + if (config.loadConfigFile() && config.getInt("LOAD.SNAPSHOT_OBJECTS") > 0) { + core.objectService.loadSnapshotObjects(planet); + } } }); diff --git a/src/services/trade/TradeService.java b/src/services/trade/TradeService.java index e1a7526e..95bc6e5f 100644 --- a/src/services/trade/TradeService.java +++ b/src/services/trade/TradeService.java @@ -370,7 +370,12 @@ public class TradeService implements INetworkDispatch{ { cleanTradeSession(client, tradePartner.getClient()); } - actingTraderInventory.transferTo(tradePartner, tradePartnerInventory, tradeObject); + //actingTraderInventory.transferTo(tradePartner, tradePartnerInventory, tradeObject); + + actingTraderInventory._remove(tradeObject); + actingTrader.makeUnaware(tradeObject); + tradePartnerInventory.add(tradeObject); + itr.remove(); }