package com.bergerkiller.bukkit.common.wrappers;
import java.util.ArrayList;
import java.util.Collection;
import com.bergerkiller.bukkit.common.reflection.classes.LongHashMapEntryRef;
import com.bergerkiller.bukkit.common.reflection.classes.LongHashMapRef;
import com.bergerkiller.bukkit.common.utils.MathUtil;
/**
* A wrapper around the internal LongHashMap implementation.
* This type of HashMap allows storing values at long keys.
* Ideally, two int values are merged into one long to map against 2D-coordinates.
* This type of class is used by, for example, the internal chunk storage.
*
* @param <V> - Value type
*/
public class LongHashMap<V> extends BasicWrapper {
public LongHashMap() {
this(LongHashMapRef.constructor1.newInstance());
}
/**
* Constructs a new LongHashMap with an initial capacity as specified<br>
* <b>Warning: this method was added in v1.54 and is not compatible with MC 1.5.2.</b>
*
* @param initialCapacity for the new LongHashMap
*/
public LongHashMap(int initialCapacity) {
this();
// Initial capacity is 16 by default...if less it is pointless to decrease
if (initialCapacity > 16) {
LongHashMapRef.setCapacity.invoke(handle, initialCapacity);
}
}
public LongHashMap(Object handle) {
this.setHandle(handle);
}
/**
* Gets the amount of Long:Value pairs stored in this LongHashMap
*
* @return size
*/
public int size() {
return Math.max(((net.minecraft.server.LongHashMap) handle).count(), 0);
}
/**
* Checks whether this Long HashMap contains the coordinates specified.<br>
* <b>Warning: this method was added in v1.54 and is not compatible with MC 1.5.2.</b>
*
* @param msw - most significant part of the key
* @param lsw - least signfificant part of the key
* @return True if contained, False if not
*/
public boolean contains(int msw, int lsw) {
return contains(MathUtil.longHashToLong(msw, lsw));
}
public boolean contains(long key) {
return ((net.minecraft.server.LongHashMap) handle).contains(key);
}
/**
* Gets the value stored at the coordinates specified.<br>
* <b>Warning: this method was added in v1.54 and is not compatible with MC 1.5.2.</b>
*
* @param msw - most significant part of the key
* @param lsw - least signfificant part of the key
* @return The value stored at the key, or null if none stored
*/
public V get(int msw, int lsw) {
return get(MathUtil.longHashToLong(msw, lsw));
}
@SuppressWarnings("unchecked")
public V get(long key) {
return (V) ((net.minecraft.server.LongHashMap) handle).getEntry(key);
}
/**
* Removes and obtains the value stored at the coordinates specified.<br>
* <b>Warning: this method was added in v1.54 and is not compatible with MC 1.5.2.</b>
*
* @param msw - most significant part of the key
* @param lsw - least signfificant part of the key
* @return The removed value previously stored at the key, or null if none was stored
*/
public V remove(int msw, int lsw) {
return remove(MathUtil.longHashToLong(msw, lsw));
}
@SuppressWarnings("unchecked")
public V remove(long key) {
return (V) ((net.minecraft.server.LongHashMap) handle).remove(key);
}
/**
* Puts a value at the coordinates specified.<br>
* <b>Warning: this method was added in v1.54 and is not compatible with MC 1.5.2.</b>
*
* @param msw - most significant part of the key
* @param lsw - least signfificant part of the key
* @param value to put at the coordinates
*/
public void put(int msw, int lsw, V value) {
put(MathUtil.longHashToLong(msw, lsw), value);
}
public void put(long key, V value) {
((net.minecraft.server.LongHashMap) handle).put(key, value);
}
@SuppressWarnings("unchecked")
public Collection<V> getValues() {
Object[] entries = LongHashMapRef.entriesField.get(handle);
ArrayList<V> values = new ArrayList<V>(size());
for (int i = 0; i < entries.length; i++) {
if (entries[i] != null) {
values.add((V) LongHashMapEntryRef.entryValue.get(entries[i]));
}
}
return values;
}
public long[] getKeys() {
Object[] entries = LongHashMapRef.entriesField.get(handle);
long[] keys = new long[size()];
int keyIndex = 0;
for (int i = 0; i < entries.length; i++) {
if (entries[i] != null) {
if (keyIndex >= keys.length) {
// This should never happen, but hey, servers make (size) mistakes!
long[] newKeys = new long[keys.length + 1];
System.arraycopy(keys, 0, newKeys, 0, keys.length);
keys = newKeys;
}
keys[keyIndex++] = LongHashMapEntryRef.entryKey.get(entries[i]);
}
}
return keys;
}
}