Fixed client crash issue with DraftSlotsQueryResponse when including multiple ingredients

This commit is contained in:
Ziggy
2023-07-30 01:52:35 +02:00
parent 945bc5d1b0
commit e5d00f0d7e
4 changed files with 94 additions and 39 deletions

View File

@@ -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;
}
}

View File

@@ -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<Integer, IngridientType> 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);
}

View File

@@ -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 <http://www.gnu.org/licenses/>. *
***********************************************************************************/
package com.projectswg.common.data.schematic
enum class SlotType(val id: Int) {
IDENTICAL(2), RESOURCES(4), SIMILAR_COMPONENTS(5);
private val map = mutableMapOf<Int, SlotType>()
fun getSlotType(id: Int): SlotType {
if (map.isEmpty()) {
for (type in values()) {
map[type.id] = type
}
}
return map.getOrElse(id) { RESOURCES }
}
}

View File

@@ -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;
}