diff --git a/src/resources/collections/SWGBitSet.java b/src/resources/collections/SWGBitSet.java index cca8dd4dd..0e65fc87c 100644 --- a/src/resources/collections/SWGBitSet.java +++ b/src/resources/collections/SWGBitSet.java @@ -1,59 +1,20 @@ -/******************************************************************************* - * Copyright (c) 2015 /// Project SWG /// www.projectswg.com - * - * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on - * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. - * Our goal is to create an emulator which will provide a server for players to - * continue playing a game similar to the one they used to play. We are basing - * it on the final publish of the game prior to end-game events. - * - * This file is part of Holocore. - * - * -------------------------------------------------------------------------------- - * - * Holocore is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * Holocore is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Holocore. If not, see - ******************************************************************************/ - package resources.collections; -import network.packets.swg.zone.baselines.Baseline; import resources.encodables.Encodable; import resources.objects.SWGObject; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.Arrays; import java.util.BitSet; - -/** - * @author Waverunner - */ public class SWGBitSet extends BitSet implements Encodable { - - private static final long serialVersionUID = 200L; - + + private static final long serialVersionUID = 1L; + private int view; private int updateType; - /** - * Creates a new {@link SWGBitSet} for the defined baseline with the given view and update. - * Note that this is an extension of {@link BitSet} - * @param baseline {@link Baseline.BaselineType} for this BitSet, should be the same as the parent class this list resides in - * @param view The baseline number this BitSet resides in - * @param updateType The update variable used for sending a delta, it's the operand count that this BitSet resides at within the baseline - */ + public SWGBitSet(int view, int updateType) { super(128); // Seems to be the default size for the bitmask sets in packets this.view = view; @@ -62,14 +23,12 @@ public class SWGBitSet extends BitSet implements Encodable { @Override public byte[] encode() { - int[] list = toList(); - ByteBuffer buffer = ByteBuffer.allocate(4 + (list.length * 4)).order(ByteOrder.LITTLE_ENDIAN); - - buffer.putInt(list.length); - for (int bits : list) { - buffer.putInt(bits); - } - + BitSet b = ((BitSet) this); + byte[] bytes = toByteArray(); + ByteBuffer buffer = ByteBuffer.allocate(8 + bytes.length).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(bytes.length); + buffer.putInt(b.length()); + buffer.put(bytes).array(); return buffer.array(); } @@ -78,19 +37,7 @@ public class SWGBitSet extends BitSet implements Encodable { // TODO: Decode method for SWGBitSet throw new UnsupportedOperationException("Unable to decode bitset!"); } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SWGBitSet)) - return super.equals(o); - return Arrays.equals(toList(), ((SWGBitSet)o).toList()); - } - - @Override - public int hashCode() { - return Arrays.hashCode(toList()); - } - + public void sendDeltaMessage(SWGObject target) { if (target.getOwner() == null) { return; @@ -99,24 +46,6 @@ public class SWGBitSet extends BitSet implements Encodable { target.sendDelta(view, updateType, encode()); } - public int[] toList() { - // TODO: This is working somehow, but position is wrong... - int[] integers = new int[4]; - int count = 0; - int position = 0; // Position within the bit set +} + - for (int i = 0; i < size(); i++) { - if (position >= 32) - count++; - - int setBitIndex = nextSetBit(i); - if (setBitIndex == -1) // No more bits after this one - break; - - integers[count] |= (0x00000001 << setBitIndex); - i += setBitIndex; - } - - return integers; - } -} diff --git a/src/resources/collections/SWGFlag.java b/src/resources/collections/SWGFlag.java new file mode 100644 index 000000000..1af1defa0 --- /dev/null +++ b/src/resources/collections/SWGFlag.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2015 /// Project SWG /// www.projectswg.com + * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. + * Our goal is to create an emulator which will provide a server for players to + * continue playing a game similar to the one they used to play. We are basing + * it on the final publish of the game prior to end-game events. + * + * This file is part of Holocore. + * + * -------------------------------------------------------------------------------- + * + * Holocore is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Holocore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Holocore. If not, see + ******************************************************************************/ + +package resources.collections; + +import network.packets.swg.zone.baselines.Baseline; +import resources.encodables.Encodable; +import resources.objects.SWGObject; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.BitSet; + + +/** + * @author Waverunner + */ +public class SWGFlag extends BitSet implements Encodable { + + private static final long serialVersionUID = 200L; + + private int view; + private int updateType; + + /** + * Creates a new {@link SWGFlag} for the defined baseline with the given view and update. + * Note that this is an extension of {@link BitSet} + * @param baseline {@link Baseline.BaselineType} for this BitSet, should be the same as the parent class this list resides in + * @param view The baseline number this BitSet resides in + * @param updateType The update variable used for sending a delta, it's the operand count that this BitSet resides at within the baseline + */ + public SWGFlag(int view, int updateType) { + super(128); // Seems to be the default size for the bitmask sets in packets + this.view = view; + this.updateType = updateType; + } + + @Override + public byte[] encode() { + int[] list = toList(); + ByteBuffer buffer = ByteBuffer.allocate(4 + (list.length * 4)).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(list.length); + for (int bits : list) { + buffer.putInt(bits); + } + + return buffer.array(); + } + + @Override + public void decode(ByteBuffer data) { + // TODO: Decode method for SWGBitSet + throw new UnsupportedOperationException("Unable to decode bitset!"); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof SWGFlag)) + return super.equals(o); + return Arrays.equals(toList(), ((SWGFlag)o).toList()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(toList()); + } + + public void sendDeltaMessage(SWGObject target) { + if (target.getOwner() == null) { + return; + } + + target.sendDelta(view, updateType, encode()); + } + + public int[] toList() { + // TODO: This is working somehow, but position is wrong... + int[] integers = new int[4]; + int count = 0; + int position = 0; // Position within the bit set + + for (int i = 0; i < size(); i++) { + if (position >= 32) + count++; + + int setBitIndex = nextSetBit(i); + if (setBitIndex == -1) // No more bits after this one + break; + + integers[count] |= (0x00000001 << setBitIndex); + i += setBitIndex; + } + + return integers; + } +} diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 4865d666c..616766b47 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -30,6 +30,7 @@ package resources.objects.player; import network.packets.swg.zone.UpdatePostureMessage; import network.packets.swg.zone.baselines.Baseline.BaselineType; import network.packets.swg.zone.chat.ChatSystemMessage; +import resources.collections.SWGFlag; import resources.collections.SWGBitSet; import resources.collections.SWGList; import resources.collections.SWGMap; @@ -45,6 +46,7 @@ import utilities.MathUtils; import utilities.Encoder.StringType; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collections; import java.util.List; @@ -56,8 +58,8 @@ public class PlayerObject extends IntangibleObject { private List joinedChannels = new ArrayList<>(); // PLAY 03 - private SWGBitSet flagsList = new SWGBitSet(3, 5); - private SWGBitSet profileFlags = new SWGBitSet(3, 6); + private SWGFlag flagsList = new SWGFlag(3, 5); + private SWGFlag profileFlags = new SWGFlag(3, 6); private String title = ""; private int bornDate = 0; private int playTime = 0; @@ -66,7 +68,7 @@ public class PlayerObject extends IntangibleObject { private int pvpKills = 0; private long lifetimeGcwPoints = 0; private int lifetimePvpKills = 0; - private SWGList collections = new SWGList<>(3, 16); + private SWGBitSet collectionBadges = new SWGBitSet(3, 16); private SWGList guildRanks = new SWGList<>(3, 17); private boolean showHelmet = true; private boolean showBackpack = true; @@ -151,7 +153,7 @@ public class PlayerObject extends IntangibleObject { this.title = title; sendDelta(3, 7, title, StringType.ASCII); } - + public int getPlayTime() { return playTime; } @@ -196,6 +198,16 @@ public class PlayerObject extends IntangibleObject { this.lifetimePvpKills = lifetimePvpKills; sendDelta(3, 15, lifetimePvpKills); } + + public byte[] getCollectionBadges() { + return collectionBadges.toByteArray(); + } + + public void setCollectionBadges(byte[] collection) { + this.collectionBadges.clear(); + this.collectionBadges.or(BitSet.valueOf(collection)); + sendDelta(3, 16, collectionBadges); + } public SWGList getGuildRanks() { return guildRanks; @@ -491,7 +503,7 @@ public class PlayerObject extends IntangibleObject { bb.addInt(pvpKills); // 13 bb.addLong(lifetimeGcwPoints); // 14 bb.addInt(lifetimePvpKills); // 15 - bb.addObject(collections); // 16 + bb.addObject(collectionBadges); // 16 bb.addObject(guildRanks); // 17 bb.addBoolean(showBackpack); // 18 bb.addBoolean(showHelmet); // 19