Merged Engine into the Core! Woooo open source

This commit is contained in:
Obique
2015-05-02 11:56:03 -05:00
committed by Obique
parent 976fca3321
commit 47231d7f4d
225 changed files with 18389 additions and 6 deletions
+224
View File
@@ -0,0 +1,224 @@
package resources.collections;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import network.packets.swg.zone.baselines.Baseline.BaselineType;
import resources.network.DeltaBuilder;
import resources.network.BaselineBuilder.Encodable;
import resources.objects.SWGObject;
import resources.player.PlayerState;
import utilities.Encoder;
import utilities.Encoder.StringType;
public class SWGMap<K, V> extends AbstractMap<K, V> implements Encodable {
private static final long serialVersionUID = 1L;
private BaselineType baseline;
private int view;
private int updateType;
private transient int updateCount;
private int dataSize;
private StringType strType = StringType.UNSPECIFIED;
/*
* Map which will contain all the byte data. A map is used here because it allows the encode method to not have to guess the ByteBuffer size. Doing it this way will
* also allow all the data to be pre-compiled for the list, so it can have a positive impact on large SWGList's. This means that only 1 ByteBuffer is being created,
* and that is to just take the data from this map and put it all together!
*/
private Map<Object, byte[]> data = new ConcurrentHashMap<>();
private Map<K, V> map = new ConcurrentHashMap<K, V>();
private Map<Object, byte[]> deltas = new HashMap<>();
private int deltaSize;
public SWGMap(BaselineType baseline, int view, int updateType) {
this.baseline = baseline;
this.view = view;
this.updateType = updateType;
}
public SWGMap(BaselineType baseline, int view, int updateType, StringType strType) {
this.baseline = baseline;
this.view = view;
this.updateType = updateType;
this.strType = strType;
}
@Override
public V get(Object key) {
return map.get(key);
}
@Override
public V put(K key, V value) {
updateCount++;
V old = map.put(key, value);
if (old != null) {
removeData(key);
}
addData(key, value, (byte) 0);
return old;
}
@Override
public V remove(Object key) {
updateCount++;
V old = map.remove(key);
removeData(key);
return old;
}
@Override
public Set<K> keySet() {
return map.keySet();
}
@Override
public Set<Entry<K, V>> entrySet() {
return map.entrySet();
}
@Override
public int size() {
return map.size();
}
@Override
public boolean containsValue(Object value) {
return map.containsValue(value);
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
/**
* Sends a delta and updates the data, notifying clients of the changed item in this map. Use this if you are not adding or removing the element
* and just simply changing it. Should be used after changing values for an item in this map.
* @param key Associated key with the value that was modified.
* @param parent The parent of this map, who the map is bound to in order to send the delta
*/
public void update(Object key, SWGObject parent) {
updateCount++;
removeDataSize(key); // remove the size of the prior data because not all encodables are fixed sizes (ie some have strings inside them)
addData(key, map.get(key), (byte) 2);
sendDeltaMessage(parent);
}
@Override
public byte[] encode() {
int size = map.size();
if (size == 0 || dataSize == 0) {
return new byte[8];
}
ByteBuffer buffer = ByteBuffer.allocate(8 + dataSize + data.size()).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(size);
buffer.putInt(updateCount);
for (byte[] bytes : data.values()) {
buffer.put((byte) 0);
buffer.put(bytes);
}
return buffer.array();
}
public void sendDeltaMessage(SWGObject target) {
if (!(deltas.size() > 0))
return;
if (target.getOwner() == null || target.getOwner().getPlayerState() != PlayerState.ZONED_IN) {
clearDeltaQueue();
return;
}
DeltaBuilder builder = new DeltaBuilder(target, baseline, view, updateType, getDeltaData());
builder.send();
clearDeltaQueue();
}
public void clearDeltaQueue() {
deltas.clear();
deltaSize = 0;
}
private byte[] getDeltaData() {
ByteBuffer buffer = ByteBuffer.allocate(8 + deltaSize).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(deltas.size());
buffer.putInt(updateCount);
for (byte[] data : deltas.values()) {
buffer.put(data);
}
return buffer.array();
}
private void createDeltaData(Object key, byte[] delta, byte update) {
synchronized(deltas) {
byte[] combindedUpdate = new byte[delta.length + 1];
combindedUpdate[0] = update;
System.arraycopy(delta, 0, combindedUpdate, 1, delta.length);
if (deltas.containsKey(key)) {
deltaSize -= deltas.remove(key).length;
}
deltaSize += delta.length + 1;
deltas.put(key, combindedUpdate);
}
}
private void addData(Object key, Object value, byte update) {
byte[] encodedKey = Encoder.encode(key, strType);
byte[] encodedValue = Encoder.encode(value, strType);
byte[] encodedData = new byte[encodedKey.length + encodedValue.length];
System.arraycopy(encodedKey, 0, encodedData, 0, encodedKey.length);
System.arraycopy(encodedValue, 0, encodedData, encodedKey.length, encodedValue.length);
data.put(key, encodedData);
dataSize += encodedData.length;
createDeltaData(key, encodedData, update);
}
// Removes Key and its Value size of data and removes it from the data map
private void removeData(Object key) {
byte[] bytes = data.remove(key);
if (bytes == null) {
System.err.println("[SWGMap] Could not remove key as it wasn't in the data map: " + key);
return;
}
dataSize -= bytes.length;
createDeltaData(key, bytes, (byte) 1);
}
// Removes Key and its Value size of data without removing it from the data map
private void removeDataSize(Object key) {
dataSize -= data.get(key).length;
}
}