From e5d00f0d7e7848e248de0c7b5188f3ba61bd63c3 Mon Sep 17 00:00:00 2001 From: Ziggy Date: Sun, 30 Jul 2023 01:52:35 +0200 Subject: [PATCH] Fixed client crash issue with DraftSlotsQueryResponse when including multiple ingredients --- .../data/schematic/DraftSlotDataOption.java | 28 +++++++----- .../common/data/schematic/IngridientSlot.java | 43 +++++++++--------- .../common/data/schematic/SlotType.kt | 44 +++++++++++++++++++ .../DraftSlotsQueryResponse.java | 18 +++++--- 4 files changed, 94 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/projectswg/common/data/schematic/SlotType.kt diff --git a/src/main/java/com/projectswg/common/data/schematic/DraftSlotDataOption.java b/src/main/java/com/projectswg/common/data/schematic/DraftSlotDataOption.java index ebc05c5..9b1dd1c 100644 --- a/src/main/java/com/projectswg/common/data/schematic/DraftSlotDataOption.java +++ b/src/main/java/com/projectswg/common/data/schematic/DraftSlotDataOption.java @@ -27,7 +27,6 @@ package com.projectswg.common.data.schematic; import com.projectswg.common.data.encodables.oob.StringId; -import com.projectswg.common.data.schematic.IngridientSlot.IngridientType; import com.projectswg.common.encoding.Encodable; import com.projectswg.common.network.NetBuffer; @@ -35,20 +34,20 @@ public class DraftSlotDataOption implements Encodable { private StringId stfName; private String ingredientName; - private IngridientType ingredientType; + private SlotType slotType; private int amount; - public DraftSlotDataOption(StringId stfName, String ingredientName, IngridientType ingredientType, int amount) { + public DraftSlotDataOption(StringId stfName, String ingredientName, SlotType slotType, int amount) { this.stfName = stfName; this.ingredientName = ingredientName; - this.ingredientType = ingredientType; + this.slotType = slotType; this.amount = amount; } public DraftSlotDataOption(){ this.stfName = new StringId("", ""); this.ingredientName = ""; - this.ingredientType = IngridientType.IT_NONE; + this.slotType = SlotType.RESOURCES; this.amount = 0; } @@ -60,8 +59,8 @@ public class DraftSlotDataOption implements Encodable { return ingredientName; } - public IngridientType getIngredientType() { - return ingredientType; + public SlotType getSlotType() { + return slotType; } public int getAmount() { @@ -72,7 +71,7 @@ public class DraftSlotDataOption implements Encodable { public void decode(NetBuffer data) { stfName = data.getEncodable(StringId.class); ingredientName = data.getUnicode(); - ingredientType = IngridientType.getTypeForInt(data.getByte()); + slotType = SlotType.IDENTICAL.getSlotType(data.getByte()); amount = data.getInt(); } @@ -81,13 +80,22 @@ public class DraftSlotDataOption implements Encodable { NetBuffer data = NetBuffer.allocate(getLength()); data.addEncodable(stfName); data.addUnicode(ingredientName); - data.addByte(ingredientType.getId()); + data.addByte(slotType.getId()); data.addInt(amount); + if (slotType == SlotType.IDENTICAL) { + data.addShort(0); // Client crash if we don't do this + } return data.array(); } @Override public int getLength() { - return 9 + stfName.getLength() + ingredientName.length() * 2; + int length = 9 + stfName.getLength() + ingredientName.length() * 2; + + if (slotType == SlotType.IDENTICAL) { + length += 2; + } + + return length; } } diff --git a/src/main/java/com/projectswg/common/data/schematic/IngridientSlot.java b/src/main/java/com/projectswg/common/data/schematic/IngridientSlot.java index acbc012..99f1d88 100644 --- a/src/main/java/com/projectswg/common/data/schematic/IngridientSlot.java +++ b/src/main/java/com/projectswg/common/data/schematic/IngridientSlot.java @@ -41,20 +41,17 @@ public class IngridientSlot implements Encodable{ private StringId name; private boolean optional; - private String hardPoint; - + public IngridientSlot(StringId name, boolean optional) { this.name = name; this.optional = optional; this.slotOptions = new ArrayList<>(); - this.hardPoint = ""; } public IngridientSlot(){ this.name = new StringId("", ""); this.optional = false; this.slotOptions = new ArrayList<>(); - this.hardPoint = ""; } public StringId getName() { @@ -75,17 +72,12 @@ public class IngridientSlot implements Encodable{ return Collections.unmodifiableList(slotOptions); } - public String getHardPoint() { - return hardPoint; - } - @Override public void decode(NetBuffer data) { name = data.getEncodable(StringId.class); optional = data.getBoolean(); slotOptions.clear(); slotOptions.addAll(data.getList(DraftSlotDataOption.class)); - hardPoint = data.getAscii(); } @Override @@ -94,7 +86,6 @@ public class IngridientSlot implements Encodable{ data.addEncodable(name); data.addBoolean(optional); data.addList(slotOptions); - data.addAscii(hardPoint); return data.array(); } @@ -104,32 +95,38 @@ public class IngridientSlot implements Encodable{ for (DraftSlotDataOption draftSlotDataOption : slotOptions) { length += draftSlotDataOption.getLength(); } - return 7 + name.getLength() + hardPoint.length() + length; + return 5 + name.getLength() + length; } public enum IngridientType { - UNDEFINED (Integer.MIN_VALUE), - IT_NONE (0), - IT_ITEM (1), - IT_TEMPLATE (2), - IT_RESOURCE_TYPE (3), - IT_RESOURCE_CLASS (4), - IT_TEMPLATE_GENERIC (5), - IT_SCHEMATIC (6), - IT_SCHEMATIC_GENERIC (7); + UNDEFINED (Integer.MIN_VALUE, SlotType.RESOURCES), + IT_NONE (0, SlotType.RESOURCES), + IT_ITEM (1, SlotType.SIMILAR_COMPONENTS), + IT_TEMPLATE (2, SlotType.IDENTICAL), + IT_RESOURCE_TYPE (3, SlotType.RESOURCES), + IT_RESOURCE_CLASS (4, SlotType.RESOURCES), + IT_TEMPLATE_GENERIC (5, SlotType.IDENTICAL), + IT_SCHEMATIC (6, SlotType.SIMILAR_COMPONENTS), + IT_SCHEMATIC_GENERIC (7, SlotType.SIMILAR_COMPONENTS); private static final EnumLookup LOOKUP = new EnumLookup<>(IngridientType.class, i -> i.getId()); - private int id; + private final int id; + private final SlotType slotType; - IngridientType(int id) { + IngridientType(int id, SlotType slotType) { this.id = id; + this.slotType = slotType; } public int getId() { return id; } - + + public SlotType getSlotType() { + return slotType; + } + public static IngridientType getTypeForInt(int id) { return LOOKUP.getEnum(id, UNDEFINED); } diff --git a/src/main/java/com/projectswg/common/data/schematic/SlotType.kt b/src/main/java/com/projectswg/common/data/schematic/SlotType.kt new file mode 100644 index 0000000..1edb84f --- /dev/null +++ b/src/main/java/com/projectswg/common/data/schematic/SlotType.kt @@ -0,0 +1,44 @@ +/*********************************************************************************** + * Copyright (c) 2023 /// 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.schematic + +enum class SlotType(val id: Int) { + IDENTICAL(2), RESOURCES(4), SIMILAR_COMPONENTS(5); + + private val map = mutableMapOf() + + fun getSlotType(id: Int): SlotType { + if (map.isEmpty()) { + for (type in values()) { + map[type.id] = type + } + } + + return map.getOrElse(id) { RESOURCES } + } + +} \ No newline at end of file diff --git a/src/main/java/com/projectswg/common/network/packets/swg/zone/object_controller/DraftSlotsQueryResponse.java b/src/main/java/com/projectswg/common/network/packets/swg/zone/object_controller/DraftSlotsQueryResponse.java index 8244377..c336ea7 100644 --- a/src/main/java/com/projectswg/common/network/packets/swg/zone/object_controller/DraftSlotsQueryResponse.java +++ b/src/main/java/com/projectswg/common/network/packets/swg/zone/object_controller/DraftSlotsQueryResponse.java @@ -33,12 +33,16 @@ import com.projectswg.common.network.NetBuffer; public class DraftSlotsQueryResponse extends ObjectController { private final static int CRC = 0x01BF; - + private DraftSchematic schematic; - - public DraftSlotsQueryResponse(DraftSchematic schematic, long objectId) { + private int clientCrc; + private int serverCrc; + + public DraftSlotsQueryResponse(DraftSchematic schematic, long objectId, int clientCrc, int serverCrc) { super(objectId, CRC); this.schematic = schematic; + this.clientCrc = clientCrc; + this.serverCrc = serverCrc; } public DraftSlotsQueryResponse(NetBuffer data){ @@ -49,7 +53,8 @@ public class DraftSlotsQueryResponse extends ObjectController { @Override public void decode(NetBuffer data) { decodeHeader(data); - schematic.setCombinedCrc(data.getLong()); + clientCrc = data.getInt(); + serverCrc = data.getInt(); schematic.setComplexity(data.getInt()); schematic.setVolume(data.getInt()); schematic.setCanManufacture(data.getBoolean()); @@ -65,11 +70,12 @@ public class DraftSlotsQueryResponse extends ObjectController { } NetBuffer data = NetBuffer.allocate(HEADER_LENGTH + 21 + length); encodeHeader(data); - data.addLong(schematic.getCombinedCrc()); + data.addInt(clientCrc); + data.addInt(serverCrc); data.addInt(schematic.getComplexity()); data.addInt(schematic.getVolume()); data.addBoolean(schematic.isCanManufacture()); - data.addList(schematic.getIngridientSlot()); + data.addList(schematic.getIngridientSlot()); return data; }