Changed Attributes(Im/Mutable) from Java to Kotlin

This commit is contained in:
Obique
2019-05-18 10:59:48 -05:00
parent 570e36d4cd
commit 76812efecd
15 changed files with 811 additions and 747 deletions

View File

@@ -6,8 +6,8 @@ plugins {
id 'idea'
id "com.github.johnrengelman.shadow" version "5.0.0"
id "org.javamodularity.moduleplugin" version "1.5.0"
id 'org.jetbrains.kotlin.jvm' version '1.3.30'
id "org.beryx.jlink" version "2.10.1"
id 'org.jetbrains.kotlin.jvm' version '1.3.31'
id "org.beryx.jlink" version "2.10.2"
}
mainClassName = 'holocore/com.projectswg.holocore.ProjectSWG'
@@ -58,7 +58,7 @@ repositories {
dependencies {
compile project(':pswgcommon')
compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: '1.3.30'
compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: '1.3.31'
compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
compile group: 'org.mongodb', name: 'mongodb-driver-sync', version: '3.9.1'
compile group: 'me.joshlarson', name: "fast-json", version: '3.0.0'

View File

@@ -1,340 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.data.collections;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.encoding.Encoder;
import com.projectswg.common.encoding.StringType;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import me.joshlarson.jlcommon.log.Log;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Supports a list of elements which automatically sends data as a delta when changed for baselines.
*
* @param <E> Element that implements {@link Encodable} in order for data to be sent, or a basic
* type.
*/
public class SWGList<E> extends CopyOnWriteArrayList<E> implements Encodable {
private static final long serialVersionUID = 1L;
private final StringType strType;
private final int view;
private final int updateType;
private final AtomicInteger updateCount;
private final List<byte[]> deltas;
private final List<byte[]> data;
private int deltaSize;
private int dataSize;
/**
* Creates a new {@link SWGList} for the defined baseline with the given view and update. Note
* that this is an extension of {@link AbstractList} and makes use of
* {@link java.util.ArrayList}
*
* @param view The baseline number this list resides in
* @param updateType The update variable used for sending a delta, it's the operand count that
* this list resides at within the baseline
*/
public SWGList(int view, int updateType) {
this(view, updateType, StringType.UNSPECIFIED);
}
/**
* Creates a new {@link SWGList} with the given StringType to encode in. Note that this
* constructor must be used if the elements within the list is a String.
*
* @param view The baseline number this list resides in
* @param updateType The update number for this variable
* @param strType The {@link StringType} of the string, required only if the element in the list
* is a String as it's used for encoding either Unicode or ASCII characters
*/
public SWGList(int view, int updateType, StringType strType) {
this.view = view;
this.updateType = updateType;
this.strType = strType;
this.dataSize = 0;
this.updateCount = new AtomicInteger(0);
this.deltas = Collections.synchronizedList(new LinkedList<>());
this.data = new ArrayList<>();
this.deltaSize = 0;
}
public void resetUpdateCount() {
updateCount.set(0);
}
@Override
public boolean add(E e) {
add(size(), e);
return true;
}
@Override
public void add(int index, E e) {
super.add(index, e);
updateCount.incrementAndGet();
addObjectData(index, e, (byte) 1);
}
@Override
public E set(int index, E element) {
// Sends a "change" delta
E previous = super.set(index, element);
if (previous != null) {
removeData(index);
}
updateCount.incrementAndGet();
addObjectData(index, element, (byte) 2);
return previous;
}
@Override
public boolean remove(Object o) {
int index = indexOf(o);
if (index != -1) {
remove(index);
return true;
}
return false;
}
@Override
public E remove(int index) {
E element = super.remove(index);
if (element != null) {
updateCount.incrementAndGet();
removeObjectData(index);
}
return element;
}
@Override
public E get(int index) {
return super.get(index);
}
/**
* Creates an array of bytes based off of the elements within this Elements that are not of a
* standard type handled by {@link Encoder} should implement the {@link Encodable} interface.
*
* @return Array of bytes with the size, update count, and encoded elements
*/
@Override
public byte[] encode() {
ByteBuffer buffer;
synchronized (data) {
if (dataSize == 0)
return new byte[8];
buffer = ByteBuffer.allocate(getLength()).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(data.size());
buffer.putInt(updateCount.get());
data.forEach(buffer::put);
}
return buffer.array();
}
@Override
public void decode(NetBuffer data) {
// We need specific type information
throw new UnsupportedOperationException("Use decode(ByteBuffer data, Class<E> elementType) instead");
}
@Override
public int getLength() {
return 8 + dataSize;
}
public void decode(ByteBuffer data, StringType type) {
int size = data.getInt();
updateCount.set(data.getInt());
NetBuffer buffer = NetBuffer.wrap(data);
for (int i = 0; i < size; i++) {
@SuppressWarnings("unchecked")
E obj = (E) buffer.getString(type);
add(obj);
}
clearDeltaQueue();
}
public void decode(ByteBuffer data, Class<E> elementType) {
int size = data.getInt();
updateCount.set(data.getInt());
boolean encodable = Encodable.class.isAssignableFrom(elementType);
NetBuffer wrap = NetBuffer.wrap(data);
for (int i = 0; i < size; i++) {
if (!decodeElement(wrap, elementType, encodable))
break;
}
clearDeltaQueue();
}
private boolean decodeElement(NetBuffer wrap, Class<E> elementType, boolean encodable) {
if (encodable) {
try {
E instance = elementType.getConstructor().newInstance();
if (instance instanceof Encodable) {
((Encodable) instance).decode(wrap);
add(instance);
}
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
Log.e(e);
return false;
}
} else {
Object o = wrap.getGeneric(elementType);
if (o != null && elementType.isAssignableFrom(o.getClass())) {
// Shouldn't be possible to get an exception with the isAssignableFrom check
@SuppressWarnings("unchecked")
E obj = (E) o;
add(obj);
} else
return false;
}
return true;
}
public void sendRefreshedListData(SWGObject target) {
clearDeltaQueue();
ByteBuffer buffer;
synchronized (data) {
updateCount.addAndGet(data.size());
buffer = ByteBuffer.allocate(11 + dataSize).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(data.size() + 1);
buffer.putInt(updateCount.get());
buffer.put((byte) 3);
buffer.putShort((short) data.size());
for (byte[] bytes : data) {
buffer.put(bytes);
}
}
target.sendDelta(view, updateType, buffer.array());
}
public void sendDeltaMessage(SWGObject target) {
if (deltas.isEmpty())
return;
target.sendDelta(view, updateType, getDeltaData());
// Clear the queue since the delta has been sent to observers through the builder
clearDeltaQueue();
}
public void clearDeltaQueue() {
synchronized (deltas) {
deltas.clear();
deltaSize = 0;
}
}
private byte[] getDeltaData() {
ByteBuffer buffer;
synchronized (deltas) {
buffer = ByteBuffer.allocate(8 + deltaSize).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(deltas.size());
buffer.putInt(updateCount.get());
for (byte[] data : deltas) {
buffer.put(data);
}
}
return buffer.array();
}
private void createDeltaData(byte[] delta) {
synchronized (deltas) {
deltaSize += delta.length;
deltas.add(delta);
}
}
private void addObjectData(int index, E obj, byte update) {
byte[] encodedData = Encoder.encode(obj, strType);
Objects.requireNonNull(encodedData, "Unable to encode obj");
synchronized (data) {
dataSize += encodedData.length;
data.add(index, encodedData);
}
ByteBuffer buffer = ByteBuffer.allocate(encodedData.length + 3).order(ByteOrder.LITTLE_ENDIAN);
buffer.put(update);
buffer.putShort((short) index);
buffer.put(encodedData);
createDeltaData(buffer.array());
}
private void removeObjectData(int index) {
removeData(index);
// Only the index is sent for removing data
ByteBuffer buffer = ByteBuffer.allocate(3).order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte) 0);
buffer.putShort((short) index);
createDeltaData(buffer.array());
}
private void removeData(int index) {
synchronized (data) {
dataSize -= data.remove(index).length;
}
}
@Override
public String toString() {
return "SWGList[0" + view + ':' + updateType + ']';
}
public static SWGList<String> getSwgList(NetBuffer buffer, int num, int var, StringType type) {
SWGList<String> list = new SWGList<>(num, var, type);
list.decode(buffer.getBuffer(), type);
return list;
}
public static <T> SWGList<T> getSwgList(NetBuffer buffer, int num, int var, Class<T> c) {
SWGList<T> list = new SWGList<>(num, var);
list.decode(buffer.getBuffer(), c);
return list;
}
}

View File

@@ -0,0 +1,410 @@
/***********************************************************************************
* Copyright (c) 2019 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.data.collections
import com.projectswg.common.encoding.Encodable
import com.projectswg.common.encoding.StringType
import com.projectswg.common.network.NetBuffer
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class SWGList<T: Any>: AbstractMutableList<T>, Encodable {
val page: Int
val update: Int
var updateCount: Int = 0
private set
private val list: MutableList<T> = ArrayList()
private val deltaQueue: MutableList<Byte> = ArrayList()
private var deltaQueueCount: Int = 0
private val lock = ReentrantLock()
private val encoder: (NetBuffer, T) -> Unit
private val decoder: (NetBuffer) -> T
private val encodedLength: (T) -> Int
constructor(page: Int, update: Int, decoder: (NetBuffer) -> T, encoder: (NetBuffer, T) -> Unit, encodedLength: (T) -> Int = ::getMaxEncodedSize) {
this.page = page
this.update = update
this.encoder = encoder
this.decoder = decoder
this.encodedLength = encodedLength
}
constructor(page: Int, update: Int, supplier: () -> T, encoder: (NetBuffer, T) -> Unit, encodedLength: (T) -> Int = ::getMaxEncodedSize) {
this.page = page
this.update = update
this.encoder = encoder
this.decoder = createDecoder(supplier)
this.encodedLength = encodedLength
}
@JvmOverloads
@Deprecated(message="use a lambda-based constructor")
constructor(page: Int, update: Int, stringType: StringType = StringType.UNSPECIFIED):
this(page, update, decoder={throw UnsupportedOperationException("don't know how to decode object")}, encoder=createDefaultEncoder<T>(stringType), encodedLength=createDefaultEncodedLength(stringType))
override val size: Int = list.size
override fun isEmpty(): Boolean = list.isEmpty()
override fun contains(element: T): Boolean = list.contains(element)
override fun containsAll(elements: Collection<T>): Boolean = list.containsAll(elements)
override fun get(index: Int): T = list[index]
override fun indexOf(element: T): Int = list.indexOf(element)
override fun lastIndexOf(element: T): Int = list.lastIndexOf(element)
override fun iterator(): MutableIterator<T> = SWGListIterator(this, list)
override fun listIterator(): MutableListIterator<T> = SWGListIterator(this, list)
override fun listIterator(index: Int): MutableListIterator<T> = SWGListIterator(this, list)
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> = throw UnsupportedOperationException("can't return mutable sublist")
// Add
override fun addAll(index: Int, elements: Collection<T>): Boolean {
lock.withLock {
var indexMut = index
for (e in elements) {
addInsertDelta(indexMut++, e)
}
return list.addAll(index, elements)
}
}
override fun addAll(elements: Collection<T>): Boolean {
lock.withLock {
var index = list.size
for (e in elements) {
addInsertDelta(index++, e)
}
return list.addAll(elements)
}
}
override fun add(index: Int, element: T) {
lock.withLock {
addInsertDelta(index, element)
list.add(index, element)
}
}
override fun add(element: T): Boolean {
lock.withLock {
addInsertDelta(list.size, element)
return list.add(element)
}
}
// Remove
override fun clear() {
lock.withLock {
for (index in (list.size-1)..0)
addRemoveDelta(index)
list.clear()
}
}
override fun retainAll(elements: Collection<T>): Boolean {
lock.withLock {
var changed = false
for (index in (list.size-1)..0) {
if (list[index] in elements) {
addRemoveDelta(index)
list.removeAt(index)
changed = true
}
}
return changed
}
}
override fun remove(element: T): Boolean {
lock.withLock {
val index = list.indexOf(element)
if (index != -1) {
addRemoveDelta(index)
list.removeAt(index)
return true
}
return false
}
}
override fun removeAll(elements: Collection<T>): Boolean {
lock.withLock {
var changed = false
for (e in elements) {
if (remove(e))
changed = true
}
return changed
}
}
override fun removeAt(index: Int): T {
lock.withLock {
addRemoveDelta(index)
return list.removeAt(index)
}
}
// Set
override fun set(index: Int, element: T): T {
lock.withLock {
addSetDelta(index, element)
return list.set(index, element)
}
}
override fun encode(): ByteArray {
lock.withLock {
with(NetBuffer.allocate(8 + list.sumBy(encodedLength))) {
addInt(list.size)
addInt(updateCount)
list.forEach { encoder(this, it) }
return array()
}
}
}
override fun decode(buffer: NetBuffer) {
lock.withLock {
val size = buffer.int
updateCount = buffer.int
for (index in 0 until size) {
list.add(decoder(buffer))
}
}
}
override fun getLength(): Int {
lock.withLock {
return 8 + list.sumBy(encodedLength)
}
}
private fun addRemoveDelta(index: Int) {
deltaQueue.add(0)
deltaQueue.add(index.toByte())
deltaQueue.add(index.ushr(8).toByte())
deltaQueueCount++
updateCount++
}
private fun addInsertDelta(index: Int, value: T) {
val encoded = NetBuffer.allocate(encodedLength(value))
encoder(encoded, value)
deltaQueue.add(1)
deltaQueue.add(index.toByte())
deltaQueue.add(index.ushr(8).toByte())
deltaQueue.addAll(encoded.array().asList())
deltaQueueCount++
updateCount++
}
private fun addSetDelta(index: Int, value: T) {
val encoded = NetBuffer.allocate(encodedLength(value))
encoder(encoded, value)
deltaQueue.add(2)
deltaQueue.add(index.toByte())
deltaQueue.add(index.ushr(8).toByte())
deltaQueue.addAll(encoded.array().asList())
deltaQueueCount++
updateCount++
}
fun clearDeltaQueue() {
lock.withLock {
deltaQueue.clear()
deltaQueueCount = 0
}
}
fun sendRefreshedListData(obj: SWGObject) {
lock.withLock {
deltaQueue.clear()
deltaQueueCount = 0
updateCount += list.size
with(NetBuffer.allocate(11 + list.sumBy(encodedLength))) {
addInt(list.size+1)
addInt(updateCount)
addByte(3)
addShort(list.size)
list.forEach { encoder(this, it) }
obj.sendDelta(page, update, array())
}
}
}
fun sendDeltaMessage(obj: SWGObject) {
lock.withLock {
with(NetBuffer.allocate(8 + deltaQueue.size)) {
addInt(deltaQueueCount)
addInt(updateCount)
addRawArray(deltaQueue.toByteArray())
obj.sendDelta(page, update, array())
}
deltaQueue.clear()
deltaQueueCount = 0
}
}
override fun equals(other: Any?): Boolean = other is SWGList<*> && page == other.page && update == other.update && list == other.list
override fun hashCode(): Int = page * 10 + update
override fun toString(): String = list.toString()
class SWGListIterator<T: Any>(private val swgList: SWGList<T>, private val list: List<T>) : AbstractIterator<T>(), MutableIterator<T>, MutableListIterator<T> {
override fun hasPrevious(): Boolean {
return position > 0 && list.isNotEmpty()
}
override fun nextIndex(): Int {
return position
}
override fun previous(): T {
position--
return list[--position]
}
override fun previousIndex(): Int {
return position-1
}
override fun add(element: T) {
swgList.add(position, element)
}
override fun set(element: T) {
assert(position > 0)
swgList[position-1] = element
}
override fun remove() {
assert(position > 0)
swgList.removeAt(--position)
}
private var position = 0
override fun computeNext() {
val value = list.getOrNull(position++) ?: return done()
setNext(value)
}
}
companion object {
@JvmStatic
fun getSwgList(buffer: NetBuffer, num: Int, `var`: Int, type: StringType): SWGList<String> {
val list = SWGList<String>(num, `var`, type)
// list.decode(buffer.buffer, type)
return list
}
@JvmStatic
fun <T: Any> getSwgList(buffer: NetBuffer, num: Int, `var`: Int, c: Class<T>): SWGList<T> {
val list = SWGList<T>(num, `var`)
// list.decode(buffer.buffer, c)
return list
}
fun createByteList(page: Int, update: Int): SWGList<Byte> = SWGList(page, update, NetBuffer::getByte, { buf, b -> buf.addByte(b.toInt())}, {1})
fun createShortList(page: Int, update: Int): SWGList<Short> = SWGList(page, update, NetBuffer::getShort, { buf, s -> buf.addShort(s.toInt())}, {2})
fun createIntList(page: Int, update: Int): SWGList<Int> = SWGList(page, update, NetBuffer::getInt, NetBuffer::addInt) {4}
fun createLongList(page: Int, update: Int): SWGList<Long> = SWGList(page, update, NetBuffer::getLong, NetBuffer::addLong) {8}
fun createFloatList(page: Int, update: Int): SWGList<Float> = SWGList(page, update, NetBuffer::getFloat, NetBuffer::addFloat) {4}
fun createDoubleList(page: Int, update: Int): SWGList<Double> = SWGList(page, update, {buf -> buf.float.toDouble()}, {buf, d -> buf.addFloat(d.toFloat())}, {8})
fun <T: Encodable> createEncodableList(page: Int, update: Int, supplier: () -> T): SWGList<T> = SWGList(page, update, supplier, NetBuffer::addEncodable, Encodable::getLength)
fun createAsciiList(page: Int, update: Int): SWGList<String> = SWGList(page, update, NetBuffer::getAscii, NetBuffer::addAscii) {2+it.length}
fun createUnicodeList(page: Int, update: Int): SWGList<String> = SWGList(page, update, NetBuffer::getUnicode, NetBuffer::addUnicode) {4+it.length*2}
private fun <T: Any> createDefaultEncoder(stringType: StringType): (NetBuffer, T) -> Unit =
{ buffer: NetBuffer, obj: T ->
when (obj) {
is Boolean -> buffer.addBoolean(obj)
is Byte -> buffer.addByte(obj.toInt())
is Short -> buffer.addShort(obj.toInt())
is Int -> buffer.addInt(obj)
is Long -> buffer.addLong(obj)
is Float -> buffer.addFloat(obj)
is Double -> buffer.addFloat(obj.toFloat())
is Encodable -> buffer.addEncodable(obj)
is String -> {
when (stringType) {
StringType.ASCII -> buffer.addAscii(obj)
StringType.UNICODE -> buffer.addUnicode(obj)
else -> throw UnsupportedOperationException("must specify string type to encode a string")
}
}
else -> throw UnsupportedOperationException("don't know how to encode $obj")
}
}
private fun <T: Any> createDecoder(supplier: () -> T): (NetBuffer) -> T = { buffer: NetBuffer ->
val ret = supplier()
if (ret is Encodable)
ret.decode(buffer)
else
throw IllegalArgumentException("invalid type - not encodable: $ret")
ret
}
private fun <T: Any> createDefaultEncodedLength(stringType: StringType): (T) -> Int =
{ obj: T ->
when (obj) {
is Boolean -> 1
is Byte -> 1
is Short -> 2
is Int -> 4
is Long -> 8
is Float -> 4
is Double -> 8
is Encodable -> obj.length
is String -> {
when (stringType) {
StringType.ASCII -> 2 + obj.length
StringType.UNICODE -> 4 + obj.length * 2
else -> throw UnsupportedOperationException("must specify string type to encode a string")
}
}
else -> throw UnsupportedOperationException("don't know how to encode $obj")
}
}
private fun <T> getMaxEncodedSize(item: T): Int {
return when (item) {
is Boolean -> 1
is Byte -> 1
is Short -> 2
is Int -> 4
is Long -> 8
is Float -> 4
is Double -> 8
is Encodable -> item.length
is String -> 4 + item.length*2
else -> throw UnsupportedOperationException("don't know how to encode $item")
}
}
}
}

View File

@@ -34,13 +34,17 @@ import com.mongodb.client.model.Indexes
import org.bson.Document
import java.util.*
class PswgConfigDatabase(private val collection: MongoCollection<Document>){
/**
* Empty config database that only returns the defaults
*/
class PswgConfigDatabase(private val collection: MongoCollection<Document>?) {
init {
collection.createIndex(Indexes.ascending("package"), IndexOptions().unique(true))
collection?.createIndex(Indexes.ascending("package"), IndexOptions().unique(true))
}
fun getString(o: Any, key: String, def: String): String {
collection ?: return def
for (config in getConfigurations(o)) {
if (config.containsKey(key))
return config.getString(key)
@@ -49,6 +53,7 @@ class PswgConfigDatabase(private val collection: MongoCollection<Document>){
}
fun getBoolean(o: Any, key: String, def: Boolean): Boolean {
collection ?: return def
for (config in getConfigurations(o)) {
if (config.containsKey(key))
return config.getBoolean(key)!!
@@ -57,6 +62,7 @@ class PswgConfigDatabase(private val collection: MongoCollection<Document>){
}
fun getInt(o: Any, key: String, def: Int): Int {
collection ?: return def
for (config in getConfigurations(o)) {
if (config.containsKey(key))
return config.getInteger(key)!!
@@ -65,6 +71,7 @@ class PswgConfigDatabase(private val collection: MongoCollection<Document>){
}
fun getDouble(o: Any, key: String, def: Double): Double {
collection ?: return def
for (config in getConfigurations(o)) {
if (config.containsKey(key))
return config.getDouble(key)!!
@@ -72,15 +79,17 @@ class PswgConfigDatabase(private val collection: MongoCollection<Document>){
return def
}
fun getLong(o: Any, key: String, def: Long): Double {
fun getLong(o: Any, key: String, def: Long): Long {
collection ?: return def
for (config in getConfigurations(o)) {
if (config.containsKey(key))
return config.getLong(key)!!.toDouble()
return config.getLong(key)!!
}
return def.toDouble()
return def
}
private fun getConfigurations(o: Any): List<Document> {
collection!! // Should be verified in calling functions
var packageKey = if (o is Class<*>) o.packageName else o.javaClass.packageName
require(packageKey.startsWith("com.projectswg.holocore")) { "packageKey must be a part of holocore, was: $packageKey" }

View File

@@ -12,7 +12,7 @@ import java.util.logging.Logger
object PswgDatabase {
var config: PswgConfigDatabase? = null
@NotNull get() = field!!
@NotNull get() = field ?: PswgConfigDatabase(null)
private set
var users: PswgUserDatabase? = null
@NotNull get() = field!!

View File

@@ -25,59 +25,19 @@
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.objects.swg.creature.attributes;
package com.projectswg.holocore.resources.support.objects.swg
public class AttributesImmutable implements Attributes {
import kotlin.reflect.KProperty
class BaselineDelegate<T>(private var value: T, private val page: Int, private val update: Int) {
private final int health;
private final int healthRegen;
private final int action;
private final int actionRegen;
private final int mind;
private final int mindRegen;
AttributesImmutable(Attributes a) {
this.health = a.getHealth();
this.healthRegen = a.getHealthRegen();
this.action = a.getAction();
this.actionRegen = a.getActionRegen();
this.mind = a.getMind();
this.mindRegen = a.getMindRegen();
operator fun getValue(thisRef: SWGObject, property: KProperty<*>): T {
return value
}
@Override
public int getHealth() {
return health;
}
@Override
public int getHealthRegen() {
return healthRegen;
}
@Override
public int getAction() {
return action;
}
@Override
public int getActionRegen() {
return actionRegen;
}
@Override
public int getMind() {
return mind;
}
@Override
public int getMindRegen() {
return mindRegen;
}
@Override
public Attributes getImmutable() {
return this;
operator fun setValue(thisRef: SWGObject, property: KProperty<*>, value: T) {
this.value = value
thisRef.sendDelta(page, update, value)
}
}

View File

@@ -79,8 +79,8 @@ class CreatureObjectSharedNP implements Persistable, MongoPersistable {
private AttributesMutable attributes;
private AttributesMutable maxAttributes;
private SWGList<Equipment> equipmentList = new SWGList<>(6, 23);
private SWGList<Equipment> appearanceList = new SWGList<>(6, 33);
private SWGList<Equipment> equipmentList = SWGList.Companion.createEncodableList(6, 23, Equipment::new);
private SWGList<Equipment> appearanceList = SWGList.Companion.createEncodableList(6, 33, Equipment::new);
private SWGMap<CRC, Buff> buffs = new SWGMap<>(6, 26);

View File

@@ -0,0 +1,40 @@
/***********************************************************************************
* Copyright (c) 2019 /// 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 <http:></http:>//www.gnu.org/licenses/>. *
*/
package com.projectswg.holocore.resources.support.objects.swg.creature.attributes
interface Attributes {
val health: Int
val healthRegen: Int
val action: Int
val actionRegen: Int
val mind: Int
val mindRegen: Int
val immutable: Attributes
}

View File

@@ -0,0 +1,40 @@
/***********************************************************************************
* Copyright (c) 2019 /// 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 <http:></http:>//www.gnu.org/licenses/>. *
*/
package com.projectswg.holocore.resources.support.objects.swg.creature.attributes
class AttributesImmutable internal constructor(a: Attributes) : Attributes {
override val health: Int = a.health
override val healthRegen: Int = a.healthRegen
override val action: Int = a.action
override val actionRegen: Int = a.actionRegen
override val mind: Int = a.mind
override val mindRegen: Int = a.mindRegen
override val immutable = this
}

View File

@@ -1,225 +0,0 @@
/***********************************************************************************
* Copyright (c) 2019 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.objects.swg.creature.attributes;
import com.projectswg.common.data.encodables.mongo.MongoData;
import com.projectswg.common.data.encodables.mongo.MongoPersistable;
import com.projectswg.common.encoding.Encodable;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.persistable.Persistable;
import com.projectswg.holocore.resources.support.data.collections.SWGList;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
public class AttributesMutable implements Attributes, Encodable, Persistable, MongoPersistable {
/*
0 - health
1 - health regen
2 - action
3 - action regen
4 - mind
5 - mind regen
*/
private final SWGObject obj;
private SWGList<Integer> ham;
public AttributesMutable(SWGObject obj, int type, int update) {
this.obj = obj;
this.ham = new SWGList<>(type, update);
for (int i = 0; i < 6; i++)
ham.add(0);
ham.clearDeltaQueue();
}
@Override
public final synchronized int getHealth() {
return ham.get(0);
}
public final synchronized void setHealth(int health) {
if (getHealth() == health)
return;
ham.set(0, health);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyHealth(int health, int max) {
setHealth(Math.max(0, Math.min(max, getHealth()+health)));
}
@Override
public final synchronized int getHealthRegen() {
return ham.get(1);
}
public final synchronized void setHealthRegen(int healthRegen) {
if (getHealthRegen() == healthRegen)
return;
ham.set(1, healthRegen);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyHealthRegen(int healthRegen, int max) {
setHealthRegen(Math.max(0, Math.min(max, getHealthRegen()+healthRegen)));
}
@Override
public final synchronized int getAction() {
return ham.get(2);
}
public final synchronized void setAction(int action) {
if (getAction() == action)
return;
ham.set(2, action);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyAction(int action, int max) {
setAction(Math.max(0, Math.min(max, getAction()+action)));
}
@Override
public final synchronized int getActionRegen() {
return ham.get(3);
}
public final synchronized void setActionRegen(int actionRegen) {
if (getActionRegen() == actionRegen)
return;
ham.set(3, actionRegen);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyActionRegen(int actionRegen, int max) {
setActionRegen(Math.max(0, Math.min(max, getActionRegen()+actionRegen)));
}
@Override
public final synchronized int getMind() {
return ham.get(4);
}
public final synchronized void setMind(int mind) {
if (getMind() == mind)
return;
ham.set(4, mind);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyMind(int mind, int max) {
setMind(Math.max(0, Math.min(max, getMind()+mind)));
}
@Override
public final synchronized int getMindRegen() {
return ham.get(5);
}
public final synchronized void setMindRegen(int mindRegen) {
if (getMindRegen() == mindRegen)
return;
ham.set(5, mindRegen);
ham.sendDeltaMessage(obj);
}
public final synchronized void modifyMindRegen(int mindRegen, int max) {
setMindRegen(Math.max(0, Math.min(max, getMindRegen()+mindRegen)));
}
@Override
public Attributes getImmutable() {
return new AttributesImmutable(this);
}
@Override
public void readMongo(MongoData data) {
setHealth(data.getInteger("health", 0));
setHealthRegen(data.getInteger("healthRegen", 0));
setAction(data.getInteger("action", 0));
setActionRegen(data.getInteger("actionRegen", 0));
setMind(data.getInteger("mind", 0));
setMindRegen(data.getInteger("mindRegen", 0));
}
@Override
public void saveMongo(MongoData data) {
data.putInteger("health", getHealth());
data.putInteger("healthRegen", getHealthRegen());
data.putInteger("action", getAction());
data.putInteger("actionRegen", getActionRegen());
data.putInteger("mind", getMind());
data.putInteger("mindRegen", getMindRegen());
}
@Override
public void read(NetBufferStream stream) {
stream.getByte();
setHealth(stream.getInt());
setHealthRegen(stream.getInt());
setAction(stream.getInt());
setActionRegen(stream.getInt());
setMind(stream.getInt());
setMindRegen(stream.getInt());
}
@Override
public void save(NetBufferStream stream) {
stream.addByte(0);
stream.addInt(getHealth());
stream.addInt(getHealthRegen());
stream.addInt(getAction());
stream.addInt(getActionRegen());
stream.addInt(getMind());
stream.addInt(getMindRegen());
}
@Override
public void decode(NetBuffer data) {
SWGList<Integer> hamDecoded = SWGList.getSwgList(data, 0, 0, Integer.class);
setHealth(hamDecoded.get(0));
setHealthRegen(hamDecoded.get(1));
setAction(hamDecoded.get(2));
setActionRegen(hamDecoded.get(3));
setMind(hamDecoded.get(4));
setMindRegen(hamDecoded.get(5));
}
@Override
public byte[] encode() {
return ham.encode();
}
@Override
public int getLength() {
return ham.getLength();
}
}

View File

@@ -0,0 +1,171 @@
/***********************************************************************************
* Copyright (c) 2019 /// 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 <http:></http:>//www.gnu.org/licenses/>. *
*/
package com.projectswg.holocore.resources.support.objects.swg.creature.attributes
import com.projectswg.common.data.encodables.mongo.MongoData
import com.projectswg.common.data.encodables.mongo.MongoPersistable
import com.projectswg.common.encoding.Encodable
import com.projectswg.common.network.NetBuffer
import com.projectswg.common.network.NetBufferStream
import com.projectswg.common.persistable.Persistable
import com.projectswg.holocore.resources.support.data.collections.SWGList
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
import kotlin.reflect.KProperty
class AttributesMutable(obj: SWGObject, type: Int, update: Int) : Attributes, Encodable, Persistable, MongoPersistable {
private val ham: SWGList<Int> = SWGList.createIntList(type, update)
private val lock = ReentrantLock()
override var health by SWGListDelegate(obj, lock, ham, 0)
override var healthRegen by SWGListDelegate(obj, lock, ham, 1)
override var action by SWGListDelegate(obj, lock, ham, 2)
override var actionRegen by SWGListDelegate(obj, lock, ham, 3)
override var mind by SWGListDelegate(obj, lock, ham, 4)
override var mindRegen by SWGListDelegate(obj, lock, ham, 5)
override val immutable
get() = AttributesImmutable(this)
init {
for (i in 0..5)
ham.add(0)
ham.clearDeltaQueue()
}
operator fun component1(): Int {
return ham[0]
}
operator fun component2(): Int {
return ham[2]
}
operator fun component3(): Int {
return ham[4]
}
fun modifyHealth(health: Int, max: Int) {
lock.withLock { this.health = this.health.addUntilMax(health, max) }
}
fun modifyHealthRegen(healthRegen: Int, max: Int) {
lock.withLock { this.healthRegen = this.healthRegen.addUntilMax(healthRegen, max) }
}
fun modifyAction(action: Int, max: Int) {
lock.withLock { this.action = this.action.addUntilMax(action, max) }
}
fun modifyActionRegen(actionRegen: Int, max: Int) {
lock.withLock { this.actionRegen = this.actionRegen.addUntilMax(actionRegen, max) }
}
fun modifyMind(mind: Int, max: Int) {
lock.withLock { this.mind = this.mind.addUntilMax(mind, max) }
}
fun modifyMindRegen(mindRegen: Int, max: Int) {
lock.withLock { this.mindRegen = this.mindRegen.addUntilMax(mindRegen, max) }
}
override fun readMongo(data: MongoData) {
health = data.getInteger("health", 0)
healthRegen = data.getInteger("healthRegen", 0)
action = data.getInteger("action", 0)
actionRegen = data.getInteger("actionRegen", 0)
mind = data.getInteger("mind", 0)
mindRegen = data.getInteger("mindRegen", 0)
}
override fun saveMongo(data: MongoData) {
data.putInteger("health", health)
data.putInteger("healthRegen", healthRegen)
data.putInteger("action", action)
data.putInteger("actionRegen", actionRegen)
data.putInteger("mind", mind)
data.putInteger("mindRegen", mindRegen)
}
override fun read(stream: NetBufferStream) {
stream.byte
health = stream.int
healthRegen = stream.int
action = stream.int
actionRegen = stream.int
mind = stream.int
mindRegen = stream.int
}
override fun save(stream: NetBufferStream) {
stream.addByte(0)
stream.addInt(health)
stream.addInt(healthRegen)
stream.addInt(action)
stream.addInt(actionRegen)
stream.addInt(mind)
stream.addInt(mindRegen)
}
override fun encode(): ByteArray {
return ham.encode()
}
override fun decode(data: NetBuffer) {
ham.decode(data)
}
override fun getLength(): Int {
return ham.length
}
private fun Int.addUntilMax(num: Int, max: Int): Int = Math.max(0, Math.min(max, this + num))
private class SWGListDelegate(private val obj: SWGObject,
private val lock: Lock,
private val list: SWGList<Int>,
private val index: Int) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
return list[index]
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
if (list[index] != value) {
lock.withLock {
list[index] = value
list.sendDeltaMessage(obj)
}
}
}
}
}

View File

@@ -1,106 +0,0 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.holocore.resources.support.objects.swg.intangible;
import com.projectswg.common.data.encodables.mongo.MongoData;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline.BaselineType;
import com.projectswg.holocore.resources.support.global.network.BaselineBuilder;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
public class IntangibleObject extends SWGObject {
public static final int COUNT_PCD_STORED = 0;
public static final int COUNT_PCD_CALLED = 1;
private int count = 0;
public IntangibleObject(long objectId) {
super(objectId, BaselineType.ITNO);
}
public IntangibleObject(long objectId, BaselineType objectType) {
super(objectId, objectType);
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
sendDelta(3, 4, count);
}
@Override
protected void createBaseline3(Player target, BaselineBuilder bb) {
super.createBaseline3(target, bb); // 4 variables
bb.addInt(count); // 4
bb.incrementOperandCount(1);
}
@Override
protected void parseBaseline3(NetBuffer buffer) {
super.parseBaseline3(buffer);
count = buffer.getInt();
}
@Override
public void saveMongo(MongoData data) {
super.saveMongo(data);
{
MongoData base3 = data.getDocument("base3");
base3.putInteger("count", count);
}
}
@Override
public void readMongo(MongoData data) {
super.readMongo(data);
{
MongoData base3 = data.getDocument("base3");
count = base3.getInteger("count", 0);
}
}
@Override
public void save(NetBufferStream stream) {
super.save(stream);
stream.addByte(0);
stream.addInt(count);
}
@Override
public void read(NetBufferStream stream) {
super.read(stream);
stream.getByte();
count = stream.getInt();
}
}

View File

@@ -0,0 +1,78 @@
/***********************************************************************************
* Copyright (c) 2018 /// 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 <http:></http:>//www.gnu.org/licenses/>. *
*/
package com.projectswg.holocore.resources.support.objects.swg.intangible
import com.projectswg.common.data.encodables.mongo.MongoData
import com.projectswg.common.network.NetBuffer
import com.projectswg.common.network.NetBufferStream
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline.BaselineType
import com.projectswg.holocore.resources.support.global.network.BaselineBuilder
import com.projectswg.holocore.resources.support.global.player.Player
import com.projectswg.holocore.resources.support.objects.swg.BaselineDelegate
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
open class IntangibleObject : SWGObject {
var count: Int by BaselineDelegate(value = 0, page = 3, update = 4)
constructor(objectId: Long) : super(objectId, BaselineType.ITNO)
constructor(objectId: Long, objectType: BaselineType) : super(objectId, objectType)
override fun createBaseline3(target: Player, bb: BaselineBuilder) {
super.createBaseline3(target, bb) // 4 variables
bb.addInt(count) // 4
bb.incrementOperandCount(1)
}
override fun parseBaseline3(buffer: NetBuffer) {
super.parseBaseline3(buffer)
count = buffer.int
}
override fun saveMongo(data: MongoData) {
super.saveMongo(data)
run {
val base3 = data.getDocument("base3")
base3.putInteger("count", count)
}
}
override fun readMongo(data: MongoData) {
super.readMongo(data)
run {
val base3 = data.getDocument("base3")
count = base3.getInteger("count", 0)
}
}
companion object {
const val COUNT_PCD_STORED = 0
const val COUNT_PCD_CALLED = 1
}
}

View File

@@ -27,27 +27,26 @@
package com.projectswg.holocore.resources.support.data.collections;
import com.projectswg.common.encoding.StringType;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.holocore.test.runners.TestRunnerNoIntents;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class TestSWGList extends TestRunnerNoIntents {
@Test
public void testAdd() {
int size = 24;
String[] strings = new String[24];
String[] strings = new String[size];
for (int i = 0; i < size; i++) {
strings[i] = "test" + String.valueOf(i);
strings[i] = "test" + i;
}
SWGList<String> swgList = new SWGList<>(3, 6, StringType.ASCII);
Collections.addAll(swgList, strings);
SWGList<String> swgList = SWGList.Companion.createAsciiList(3, 6);
swgList.addAll(List.of(strings));
Assert.assertArrayEquals(strings, swgList.toArray());
@@ -58,16 +57,46 @@ public class TestSWGList extends TestRunnerNoIntents {
}
@Test
public void testEncode() {
public void testIteratorUpdate() {
int size = 24;
String[] strings = new String[24];
List<String> strings = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
strings[i] = "test" + String.valueOf(i);
strings.add("test" + i);
}
SWGList<String> swgList = new SWGList<>(3, 6, StringType.ASCII);
Collections.addAll(swgList, strings);
swgList.encode();
SWGList<String> swgList = SWGList.Companion.createAsciiList(3, 6);
swgList.addAll(strings);
Assert.assertEquals(size, swgList.getUpdateCount());
Assert.assertEquals(strings, swgList);
for (ListIterator<String> it = swgList.listIterator(); it.hasNext(); ) {
String str = it.next();
it.set(str.replace('t', 'j'));
}
Assert.assertEquals(strings.stream().map(str -> str.replace('t', 'j')).collect(Collectors.toList()), swgList);
Assert.assertEquals(size*2, swgList.getUpdateCount());
}
@Test
public void testEncode() {
int size = 24;
NetBuffer expected = NetBuffer.allocate(8 + 2*size + 5*10 + 6*(size-10));
expected.addInt(size);
expected.addInt(size);
String[] strings = new String[size];
for (int i = 0; i < size; i++) {
strings[i] = "test" + i;
expected.addAscii(strings[i]);
}
SWGList<String> swgList = SWGList.Companion.createAsciiList(3, 6);
Collections.addAll(swgList, strings);
byte [] encoded = swgList.encode();
Assert.assertArrayEquals(expected.array(), encoded);
Assert.assertEquals(encoded.length, swgList.getLength());
SWGList<String> decodedList = SWGList.Companion.createAsciiList(3, 6);
decodedList.decode(NetBuffer.wrap(encoded));
Assert.assertEquals(swgList, decodedList);
}
}

View File

@@ -27,7 +27,6 @@
package com.projectswg.holocore.test.runners;
import com.projectswg.holocore.resources.support.data.server_info.DataManager;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import me.joshlarson.jlcommon.log.Log;
import me.joshlarson.jlcommon.log.log_wrapper.ConsoleLogWrapper;
@@ -39,7 +38,6 @@ public abstract class TestRunner {
public static void initializeStatic() {
Log.clearWrappers();
Log.addWrapper(new ConsoleLogWrapper());
DataManager.initialize();
}
protected static long getUniqueId() {