diff --git a/src/main/java/com/projectswg/common/data/sui/ISuiCallback.java b/src/main/java/com/projectswg/common/data/sui/ISuiCallback.kt similarity index 90% rename from src/main/java/com/projectswg/common/data/sui/ISuiCallback.java rename to src/main/java/com/projectswg/common/data/sui/ISuiCallback.kt index 5559070..1d82167 100644 --- a/src/main/java/com/projectswg/common/data/sui/ISuiCallback.java +++ b/src/main/java/com/projectswg/common/data/sui/ISuiCallback.kt @@ -1,5 +1,5 @@ /*********************************************************************************** - * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * Copyright (c) 2024 /// 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. * @@ -24,10 +24,8 @@ * You should have received a copy of the GNU Affero General Public License * * along with PSWGCommon. If not, see . * ***********************************************************************************/ -package com.projectswg.common.data.sui; +package com.projectswg.common.data.sui -import java.util.Map; +import java.util.function.BiConsumer -public interface ISuiCallback { - void handleEvent(SuiEvent event, Map parameters); -} +typealias ISuiCallback = BiConsumer> diff --git a/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.java b/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.java deleted file mode 100644 index 0c38f8e..0000000 --- a/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.java +++ /dev/null @@ -1,289 +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 PSWGCommon. * - * * - * --------------------------------------------------------------------------------* - * * - * PSWGCommon 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. * - * * - * PSWGCommon 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 PSWGCommon. If not, see . * - ***********************************************************************************/ -package com.projectswg.common.data.sui; - -import me.joshlarson.jlcommon.log.Log; -import com.projectswg.common.encoding.Encodable; -import com.projectswg.common.network.NetBuffer; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SuiBaseWindow implements Encodable { - - private int id; - private String suiScript; - private long rangeObjId; - private float maxDistance = 0; - private List components = new ArrayList<>(); - private Map callbacks; - private boolean hasSubscriptionComponent = false; - - public SuiBaseWindow() { - } - - public SuiBaseWindow(String suiScript) { - this.suiScript = suiScript; - } - - public final void clearDataSource(String dataSource) { - SuiComponent component = new SuiComponent(SuiComponent.Type.CLEAR_DATA_SOURCE, dataSource); - components.add(component); - } - - public final void addChildWidget(String type, String childWidget, String parentWidget) { - SuiComponent component = new SuiComponent(SuiComponent.Type.ADD_CHILD_WIDGET, parentWidget); - - component.addNarrowParam(type); - component.addNarrowParam(childWidget); - - components.add(component); - } - - public final void setProperty(String widget, String property, String value) { - SuiComponent component = new SuiComponent(SuiComponent.Type.SET_PROPERTY, widget); - - component.addNarrowParam(property); - component.addWideParam(value); - - components.add(component); - } - - public final void addDataItem(String dataSource, String name, String value) { - SuiComponent component = new SuiComponent(SuiComponent.Type.ADD_DATA_ITEM, dataSource); - - component.addNarrowParam(name); - component.addWideParam(value); - - components.add(component); - } - - protected void subscribeToEvent(int event, String widgetSource, String callback) { - SuiComponent component = getSubscriptionForEvent(event, widgetSource); - if (component != null) { - Log.i("Added event callback %d to %s when the event is already subscribed to, replacing callback to %s", event, widgetSource, callback); - component.getNarrowParams().set(2, callback); - } else { - component = new SuiComponent(SuiComponent.Type.SUBSCRIBE_TO_EVENT, widgetSource); - component.addNarrowParam(getWrappedEventString(event)); - component.addNarrowParam(callback); - - components.add(component); - } - if (!hasSubscriptionComponent()) - hasSubscriptionComponent = true; - } - - protected void subscribeToPropertyEvent(int event, String widgetSource, String propertyWidget, String propertyName) { - SuiComponent component = getSubscriptionForEvent(event, widgetSource); - if (component != null) { - // This component already has the trigger and source param, just need to add the widget and property - // for client to return the value to the server - component.addNarrowParam(propertyWidget); - component.addNarrowParam(propertyName); - } else { - component = new SuiComponent(SuiComponent.Type.SUBSCRIBE_TO_EVENT, widgetSource); - component.addNarrowParam(getWrappedEventString(event)); - component.addNarrowParam(""); - component.addNarrowParam(propertyWidget); - component.addNarrowParam(propertyName); - components.add(component); - } - if (!hasSubscriptionComponent()) - hasSubscriptionComponent = true; - } - - public final void addDataSourceContainer(String dataSourceContainer, String name, String value) { - SuiComponent component = new SuiComponent(SuiComponent.Type.ADD_DATA_SOURCE_CONTAINER, dataSourceContainer); - - component.addNarrowParam(name); - component.addWideParam(value); - - components.add(component); - } - - public final void clearDataSourceContainer(String dataSourceContainer) { - SuiComponent component = new SuiComponent(SuiComponent.Type.CLEAR_DATA_SOURCE_CONTAINER, dataSourceContainer); - components.add(component); - } - - public final void addDataSource(String dataSource, String name, String value) { - SuiComponent component = new SuiComponent(SuiComponent.Type.ADD_DATA_SOURCE, dataSource); - - component.addNarrowParam(name); - component.addWideParam(value); - - components.add(component); - } - - public final void addReturnableProperty(SuiEvent event, String source, String widget, String property) { - subscribeToPropertyEvent(event.getValue(), source, widget, property); - } - - public final void addReturnableProperty(SuiEvent event, String widget, String property) { - addReturnableProperty(event, "", widget, property); - } - - public final void addReturnableProperty(String widget, String property) { - subscribeToPropertyEvent(SuiEvent.OK_PRESSED.getValue(), "", widget, property); - subscribeToPropertyEvent(SuiEvent.CANCEL_PRESSED.getValue(), "", widget, property); - } - - public final void addCallback(SuiEvent event, String source, String name, ISuiCallback callback) { - subscribeToEvent(event.getValue(), source, name); - addJavaCallback(name, callback); - } - - public final void addCallback(SuiEvent event, String name, ISuiCallback callback) { - addCallback(event, "", name, callback); - } - - public final void addCallback(String source, String name, ISuiCallback callback) { - subscribeToEvent(SuiEvent.OK_PRESSED.getValue(), source, name); - subscribeToEvent(SuiEvent.CANCEL_PRESSED.getValue(), source, name); - addJavaCallback(name, callback); - } - - public final void addCallback(String name, ISuiCallback callback) { - addCallback("", name, callback); - } - - public final SuiComponent getSubscriptionForEvent(int event, String widget) { - for (SuiComponent component : components) { - if (component.getType() != SuiComponent.Type.SUBSCRIBE_TO_EVENT) - continue; - - int eventType = component.getSubscribedToEventType(); - - if (eventType == event && component.getTarget().equals(widget)) - return component; - } - return null; - } - - public final SuiComponent getSubscriptionByIndex(int index) { - int count = 0; - for (SuiComponent component : components) { - if (component.getType() == SuiComponent.Type.SUBSCRIBE_TO_EVENT) { - if (index == count) return component; - else count++; - } - } - return null; - } - - public final long getRangeObjId() { - return rangeObjId; - } - - public final void setRangeObjId(long rangeObjId) { - this.rangeObjId = rangeObjId; - } - - public final int getId() { - return id; - } - - public final void setId(int id) { - this.id = id; - } - - public final String getSuiScript() { - return suiScript; - } - - public final float getMaxDistance() { - return maxDistance; - } - - public final void setMaxDistance(float maxDistance) { - this.maxDistance = maxDistance; - } - - public final List getComponents() { - return components; - } - - public final ISuiCallback getJavaCallback(String name) { - return callbacks != null ? callbacks.get(name) : null; - } - - public final boolean hasJavaCallback(String name) { - return callbacks != null && callbacks.containsKey(name); - } - - public final boolean hasSubscriptionComponent() { - return hasSubscriptionComponent; - } - - private void addJavaCallback(String name, ISuiCallback callback) { - if (callbacks == null) callbacks = new HashMap<>(); - - callbacks.put(name, callback); - } - - private String getWrappedEventString(int event) { - return new String(new byte[]{(byte) event}, StandardCharsets.UTF_8); - } - - @Override - public byte[] encode() { - NetBuffer data = NetBuffer.allocate(getLength()); - data.addInt(id); - data.addAscii(suiScript); - data.addList(components); - data.addLong(rangeObjId); - data.addFloat(maxDistance); - data.addLong(0); // Window Location? - data.addInt(0); - return data.array(); - } - - @Override - public void decode(NetBuffer data) { - id = data.getInt(); - suiScript = data.getAscii(); - components = data.getList(SuiComponent.class); - rangeObjId = data.getLong(); - maxDistance = data.getFloat(); - // unk long - // unk int - } - - @Override - public int getLength() { - int listSize = 0; - for (SuiComponent component : components) { - listSize += component.getLength(); - } - return 34 + suiScript.length() + listSize; - } - -} diff --git a/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.kt b/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.kt new file mode 100644 index 0000000..feeea3d --- /dev/null +++ b/src/main/java/com/projectswg/common/data/sui/SuiBaseWindow.kt @@ -0,0 +1,242 @@ +/*********************************************************************************** + * Copyright (c) 2024 /// 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 PSWGCommon. * + * * + * --------------------------------------------------------------------------------* + * * + * PSWGCommon 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. * + * * + * PSWGCommon 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 PSWGCommon. If not, see . * + ***********************************************************************************/ +package com.projectswg.common.data.sui + +import com.projectswg.common.encoding.Encodable +import com.projectswg.common.network.NetBuffer +import me.joshlarson.jlcommon.log.Log +import java.nio.charset.StandardCharsets + +open class SuiBaseWindow : Encodable { + var id: Int = 0 + var suiScript: String? = null + var rangeObjId: Long = 0 + var maxDistance: Float = 0f + private var components: MutableList = ArrayList() + private var callbacks: MutableMap? = null + private var hasSubscriptionComponent = false + + fun clearDataSource(dataSource: String) { + val component = SuiComponent(SuiComponent.Type.CLEAR_DATA_SOURCE, dataSource) + components.add(component) + } + + fun addChildWidget(type: String, childWidget: String, parentWidget: String) { + val component = SuiComponent(SuiComponent.Type.ADD_CHILD_WIDGET, parentWidget) + + component.addNarrowParam(type) + component.addNarrowParam(childWidget) + + components.add(component) + } + + fun setProperty(widget: String, property: String, value: String) { + val component = SuiComponent(SuiComponent.Type.SET_PROPERTY, widget) + + component.addNarrowParam(property) + component.addWideParam(value) + + components.add(component) + } + + fun addDataItem(dataSource: String, name: String, value: String) { + val component = SuiComponent(SuiComponent.Type.ADD_DATA_ITEM, dataSource) + + component.addNarrowParam(name) + component.addWideParam(value) + + components.add(component) + } + + protected fun subscribeToEvent(event: Int, widgetSource: String, callback: String) { + var component = getSubscriptionForEvent(event, widgetSource) + if (component != null) { + Log.i("Added event callback %d to %s when the event is already subscribed to, replacing callback to %s", event, widgetSource, callback) + component.setNarrowParam(1, callback) // Replaces the callback for a SUBSCRIBE_TO_EVENT component that's set 4 lines below + } else { + component = SuiComponent(SuiComponent.Type.SUBSCRIBE_TO_EVENT, widgetSource) + component.addNarrowParam(getWrappedEventString(event)) + component.addNarrowParam(callback) + + components.add(component) + } + if (!hasSubscriptionComponent()) hasSubscriptionComponent = true + } + + protected fun subscribeToPropertyEvent(event: Int, widgetSource: String, propertyWidget: String, propertyName: String) { + var component = getSubscriptionForEvent(event, widgetSource) + if (component != null) { + // This component already has the trigger and source param, just need to add the widget and property + // for client to return the value to the server + component.addNarrowParam(propertyWidget) + component.addNarrowParam(propertyName) + } else { + component = SuiComponent(SuiComponent.Type.SUBSCRIBE_TO_EVENT, widgetSource) + component.addNarrowParam(getWrappedEventString(event)) + component.addNarrowParam("") + component.addNarrowParam(propertyWidget) + component.addNarrowParam(propertyName) + components.add(component) + } + if (!hasSubscriptionComponent()) hasSubscriptionComponent = true + } + + fun addDataSourceContainer(dataSourceContainer: String, name: String, value: String) { + val component = SuiComponent(SuiComponent.Type.ADD_DATA_SOURCE_CONTAINER, dataSourceContainer) + + component.addNarrowParam(name) + component.addWideParam(value) + + components.add(component) + } + + fun clearDataSourceContainer(dataSourceContainer: String) { + val component = SuiComponent(SuiComponent.Type.CLEAR_DATA_SOURCE_CONTAINER, dataSourceContainer) + components.add(component) + } + + fun addDataSource(dataSource: String, name: String, value: String) { + val component = SuiComponent(SuiComponent.Type.ADD_DATA_SOURCE, dataSource) + + component.addNarrowParam(name) + component.addWideParam(value) + + components.add(component) + } + + fun addReturnableProperty(event: SuiEvent, source: String, widget: String, property: String) { + subscribeToPropertyEvent(event.value, source, widget, property) + } + + fun addReturnableProperty(event: SuiEvent, widget: String, property: String) { + addReturnableProperty(event, "", widget, property) + } + + fun addReturnableProperty(widget: String, property: String) { + subscribeToPropertyEvent(SuiEvent.OK_PRESSED.value, "", widget, property) + subscribeToPropertyEvent(SuiEvent.CANCEL_PRESSED.value, "", widget, property) + } + + fun addCallback(event: SuiEvent, source: String, name: String, callback: ISuiCallback) { + subscribeToEvent(event.value, source, name) + addJavaCallback(name, callback) + } + + fun addCallback(event: SuiEvent, name: String, callback: ISuiCallback) { + addCallback(event, "", name, callback) + } + + fun addCallback(source: String, name: String, callback: ISuiCallback) { + subscribeToEvent(SuiEvent.OK_PRESSED.value, source, name) + subscribeToEvent(SuiEvent.CANCEL_PRESSED.value, source, name) + addJavaCallback(name, callback) + } + + fun addCallback(name: String, callback: ISuiCallback) { + addCallback("", name, callback) + } + + fun getSubscriptionForEvent(event: Int, widget: String): SuiComponent? { + for (component in components) { + if (component.type != SuiComponent.Type.SUBSCRIBE_TO_EVENT) continue + + val eventType = component.subscribedToEventType + + if (eventType == event && component.target == widget) return component + } + return null + } + + fun getSubscriptionByIndex(index: Int): SuiComponent? { + var count = 0 + for (component in components) { + if (component.type == SuiComponent.Type.SUBSCRIBE_TO_EVENT) { + if (index == count) return component + else count++ + } + } + return null + } + + fun getComponents(): List { + return components + } + + fun getJavaCallback(name: String?): ISuiCallback? { + return callbacks?.get(name) + } + + fun hasJavaCallback(name: String?): Boolean { + return callbacks?.containsKey(name) ?: false + } + + fun hasSubscriptionComponent(): Boolean { + return hasSubscriptionComponent + } + + private fun addJavaCallback(name: String, callback: ISuiCallback) { + if (callbacks == null) + callbacks = HashMap() + + callbacks!![name] = callback + } + + private fun getWrappedEventString(event: Int): String { + return String(byteArrayOf(event.toByte()), StandardCharsets.UTF_8) + } + + override fun encode(): ByteArray { + val data = NetBuffer.allocate(length) + data.addInt(id) + data.addAscii(suiScript) + data.addList(components) + data.addLong(rangeObjId) + data.addFloat(maxDistance) + data.addLong(0) // Window Location? + data.addInt(0) + return data.array() + } + + override fun decode(data: NetBuffer) { + id = data.int + suiScript = data.ascii + components = data.getList(SuiComponent::class.java) + rangeObjId = data.long + maxDistance = data.float + // unk long + // unk int + } + + override val length: Int + get() { + var listSize = 0 + for (component in components) { + listSize += component.length + } + return 34 + suiScript!!.length + listSize + } +} diff --git a/src/main/java/com/projectswg/common/data/sui/SuiComponent.java b/src/main/java/com/projectswg/common/data/sui/SuiComponent.java deleted file mode 100644 index 3feb476..0000000 --- a/src/main/java/com/projectswg/common/data/sui/SuiComponent.java +++ /dev/null @@ -1,199 +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 PSWGCommon. * - * * - * --------------------------------------------------------------------------------* - * * - * PSWGCommon 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. * - * * - * PSWGCommon 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 PSWGCommon. If not, see . * - ***********************************************************************************/ -package com.projectswg.common.data.sui; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -import me.joshlarson.jlcommon.log.Log; -import com.projectswg.common.encoding.Encodable; -import com.projectswg.common.encoding.StringType; -import com.projectswg.common.network.NetBuffer; - -/** - * @author Waverunner - */ -public class SuiComponent implements Encodable { - - private Type type; - private List wideParams; - private List narrowParams; - - public SuiComponent() { - type = Type.NONE; - wideParams = new ArrayList<>(); - narrowParams = new ArrayList<>(); - } - - public SuiComponent(Type type, String widget) { - this.type = type; - this.wideParams = new ArrayList<>(3); - this.narrowParams = new ArrayList<>(3); - - narrowParams.add(widget); - } - - public Type getType() { - return type; - } - public List getNarrowParams() { - return narrowParams; - } - public List getWideParams() { - return wideParams; - } - - /** - * Retrieve the base widget that this component targets - * @return Base widget this component targets - */ - public String getTarget() { - return narrowParams.get(0); - } - - public void addNarrowParam(String param) { - narrowParams.add(param); - } - - public void addWideParam(String param) { - wideParams.add(param); - } - - public List getSubscribedProperties() { - if (type != Type.SUBSCRIBE_TO_EVENT) - return null; - - int size = narrowParams.size(); - if (size < 3) { - Log.w("Tried to get subscribed properties when there are none for target %s", getTarget()); - } else { - List subscribedProperties = new ArrayList<>(); - - for (int i = 3; i < size;) { - String property = narrowParams.get(i++) + "." + narrowParams.get(i++); - subscribedProperties.add(property); - } - - return subscribedProperties; - } - return null; - } - - public String getSubscribeToEventCallback() { - if (type != Type.SUBSCRIBE_TO_EVENT) - return null; - - int size = narrowParams.size(); - if (size < 3) { - Log.w("Tried to get subscribed callback when there is none for target %s", getTarget()); - } else { - - return narrowParams.get(2); - } - return null; - } - - public int getSubscribedToEventType() { - if (type != Type.SUBSCRIBE_TO_EVENT) - return -1; - - int size = narrowParams.size(); - if (size < 3) { - Log.w("Tried to get subscribed event type when there is none for target %s", getTarget()); - } else { - byte[] bytes = narrowParams.get(1).getBytes(StandardCharsets.UTF_8); - if (bytes.length > 1) { - Log.w("Tried to get eventType but narrowparams string byte array length is more than 1"); - return -1; - } - - return bytes[0]; - } - return -1; - } - - @Override - public byte[] encode() { - NetBuffer data = NetBuffer.allocate(getLength()); - data.addByte(type.getValue()); - data.addList(wideParams, StringType.UNICODE); - data.addList(narrowParams, StringType.ASCII); - return data.array(); - } - - @Override - public void decode(NetBuffer data) { - type = Type.valueOf(data.getByte()); - wideParams = data.getList(StringType.UNICODE); - narrowParams = data.getList(StringType.ASCII); - } - - @Override - public int getLength() { - int size = 9; - - for (String param : wideParams) { - size += 4 + (param.length() * 2); - } - for (String param : narrowParams) { - size += 2 + param.length(); - } - - return size; - } - - public enum Type { - NONE(0), - CLEAR_DATA_SOURCE(1), - ADD_CHILD_WIDGET(2), - SET_PROPERTY(3), - ADD_DATA_ITEM(4), - SUBSCRIBE_TO_EVENT(5), - ADD_DATA_SOURCE_CONTAINER(6), - CLEAR_DATA_SOURCE_CONTAINER(7), - ADD_DATA_SOURCE(8); - - private byte value; - - Type(int value) { - this.value = (byte) value; - } - - public byte getValue() { - return value; - } - - public static Type valueOf(byte value) { - for (Type type : Type.values()) { - if (type.getValue() == value) - return type; - } - return NONE; - } - } -} diff --git a/src/main/java/com/projectswg/common/data/sui/SuiComponent.kt b/src/main/java/com/projectswg/common/data/sui/SuiComponent.kt new file mode 100644 index 0000000..49ea126 --- /dev/null +++ b/src/main/java/com/projectswg/common/data/sui/SuiComponent.kt @@ -0,0 +1,171 @@ +/*********************************************************************************** + * Copyright (c) 2024 /// 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 PSWGCommon. * + * * + * --------------------------------------------------------------------------------* + * * + * PSWGCommon 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. * + * * + * PSWGCommon 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 PSWGCommon. If not, see . * + ***********************************************************************************/ +package com.projectswg.common.data.sui + +import com.projectswg.common.encoding.Encodable +import com.projectswg.common.encoding.StringType +import com.projectswg.common.network.NetBuffer +import me.joshlarson.jlcommon.log.Log +import java.nio.charset.StandardCharsets +import kotlin.collections.ArrayList + +class SuiComponent(type: Type, widget: String) : Encodable { + var type: Type = type + private set + + private var _wideParams: MutableList = ArrayList() + private var _narrowParams: MutableList = ArrayList() + + val target: String + /** + * Retrieve the base widget that this component targets + * @return Base widget this component targets + */ + get() = _narrowParams[0] + + fun addNarrowParam(param: String) { + _narrowParams.add(param) + } + + fun setNarrowParam(index: Int, param: String) { + _narrowParams[index] = param + } + + fun addWideParam(param: String) { + _wideParams.add(param) + } + + val subscribedProperties: List? + get() { + if (type != Type.SUBSCRIBE_TO_EVENT) return null + + val size = _narrowParams.size + if (size < 3) { + Log.w("Tried to get subscribed properties when there are none for target %s", target) + } else { + val subscribedProperties: MutableList = ArrayList() + + var i = 3 + while (i < size) { + val property = _narrowParams[i++] + "." + _narrowParams[i++] + subscribedProperties.add(property) + } + + return subscribedProperties + } + return null + } + + val subscribeToEventCallback: String? + get() { + if (type != Type.SUBSCRIBE_TO_EVENT) return null + + val size = _narrowParams.size + if (size < 3) { + Log.w("Tried to get subscribed callback when there is none for target %s", target) + } else { + return _narrowParams[2] + } + return null + } + + val subscribedToEventType: Int + get() { + if (type != Type.SUBSCRIBE_TO_EVENT) return -1 + + val size = _narrowParams.size + if (size < 3) { + Log.w("Tried to get subscribed event type when there is none for target %s", target) + } else { + val bytes = _narrowParams[1].toByteArray(StandardCharsets.UTF_8) + if (bytes.size > 1) { + Log.w("Tried to get eventType but narrowparams string byte array length is more than 1") + return -1 + } + + return bytes[0].toInt() + } + return -1 + } + + override fun encode(): ByteArray { + val data = NetBuffer.allocate(length) + data.addByte(type.value.toInt()) + data.addList(_wideParams, StringType.UNICODE) + data.addList(_narrowParams, StringType.ASCII) + return data.array() + } + + override fun decode(data: NetBuffer) { + type = Type.valueOf(data.byte) + _wideParams = data.getList(StringType.UNICODE) + _narrowParams = data.getList(StringType.ASCII) + } + + override val length: Int + get() { + var size = 9 + + for (param in _wideParams) { + size += 4 + (param.length * 2) + } + for (param in _narrowParams) { + size += 2 + param.length + } + + return size + } + + enum class Type(value: Int) { + NONE(0), + CLEAR_DATA_SOURCE(1), + ADD_CHILD_WIDGET(2), + SET_PROPERTY(3), + ADD_DATA_ITEM(4), + SUBSCRIBE_TO_EVENT(5), + ADD_DATA_SOURCE_CONTAINER(6), + CLEAR_DATA_SOURCE_CONTAINER(7), + ADD_DATA_SOURCE(8); + + val value: Byte = value.toByte() + + companion object { + fun valueOf(value: Byte): Type { + for (type in entries) { + if (type.value == value) return type + } + return NONE + } + } + } + + init { + this._wideParams = ArrayList(3) + this._narrowParams = ArrayList(3) + _narrowParams.add(widget) + } +} diff --git a/src/main/java/com/projectswg/common/data/sui/SuiEvent.java b/src/main/java/com/projectswg/common/data/sui/SuiEvent.kt similarity index 70% rename from src/main/java/com/projectswg/common/data/sui/SuiEvent.java rename to src/main/java/com/projectswg/common/data/sui/SuiEvent.kt index 1599719..9969f5c 100644 --- a/src/main/java/com/projectswg/common/data/sui/SuiEvent.java +++ b/src/main/java/com/projectswg/common/data/sui/SuiEvent.kt @@ -1,5 +1,5 @@ /*********************************************************************************** - * Copyright (c) 2018 /// Project SWG /// www.projectswg.com * + * Copyright (c) 2024 /// 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. * @@ -24,48 +24,37 @@ * You should have received a copy of the GNU Affero General Public License * * along with PSWGCommon. If not, see . * ***********************************************************************************/ -package com.projectswg.common.data.sui; +package com.projectswg.common.data.sui -/** - * Created by Waverunner on 8/14/2015 - */ -public enum SuiEvent { - NONE (0), - BUTTON (1), - CHECKBOX (2), - ENABLE_DISABLE (3), - GENERIC (4), - SLIDER (5), - TAB_PANE (6), - TEXTBOX (7), - VISIBILITY_CHANGED (8), - OK_PRESSED (9), - CANCEL_PRESSED (10); - - private int value; - - SuiEvent(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public static SuiEvent valueOf(int value) { - switch(value) { - case 0: return NONE; - case 1: return BUTTON; - case 2: return CHECKBOX; - case 3: return ENABLE_DISABLE; - case 4: return GENERIC; - case 5: return SLIDER; - case 6: return TAB_PANE; - case 7: return TEXTBOX; - case 8: return VISIBILITY_CHANGED; - case 9: return OK_PRESSED; - case 10: return CANCEL_PRESSED; - default: return NONE; +enum class SuiEvent(val value: Int) { + NONE(0), + BUTTON(1), + CHECKBOX(2), + ENABLE_DISABLE(3), + GENERIC(4), + SLIDER(5), + TAB_PANE(6), + TEXTBOX(7), + VISIBILITY_CHANGED(8), + OK_PRESSED(9), + CANCEL_PRESSED(10); + + companion object { + fun valueOf(value: Int): SuiEvent { + return when (value) { + 0 -> NONE + 1 -> BUTTON + 2 -> CHECKBOX + 3 -> ENABLE_DISABLE + 4 -> GENERIC + 5 -> SLIDER + 6 -> TAB_PANE + 7 -> TEXTBOX + 8 -> VISIBILITY_CHANGED + 9 -> OK_PRESSED + 10 -> CANCEL_PRESSED + else -> NONE + } } } }