mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-03-06 07:30:41 +07:00
Disabled skipping of item byte stream signature
ItemSerializer will process and validate item signature Implemented far more robust logging to ItemSerializer
This commit is contained in:
parent
e8f359ffa2
commit
a8e2402a19
@ -72,7 +72,6 @@ import com.riiablo.net.packet.d2gs.SwapStoreItem;
|
||||
import com.riiablo.net.packet.d2gs.VelocityP;
|
||||
import com.riiablo.net.packet.d2gs.WarpP;
|
||||
import com.riiablo.save.CharData;
|
||||
import com.riiablo.save.D2S;
|
||||
import com.riiablo.util.ArrayUtils;
|
||||
import com.riiablo.util.BufferUtils;
|
||||
import com.riiablo.util.DebugUtils;
|
||||
@ -314,7 +313,7 @@ public class ClientNetworkReceiver extends IntervalSystem {
|
||||
PositionP position = findTable(sync, ComponentP.PositionP, new PositionP());
|
||||
byte[] bytes = BufferUtils.readRemaining(item.dataAsByteBuffer());
|
||||
BitStream bitStream = new BitStream(bytes);
|
||||
bitStream.skip(D2S.ItemData.SECTION_HEADER_BITS);
|
||||
// bitStream.skip(D2S.ItemData.SECTION_HEADER_BITS);
|
||||
Item itemObj = com.riiablo.item.Item.loadFromStream(bitStream);
|
||||
return factory.createItem(itemObj, position.x(), position.y());
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import com.riiablo.engine.server.component.Item;
|
||||
import com.riiablo.net.packet.d2gs.ComponentP;
|
||||
import com.riiablo.net.packet.d2gs.EntitySync;
|
||||
import com.riiablo.net.packet.d2gs.ItemP;
|
||||
import com.riiablo.save.D2S;
|
||||
import com.riiablo.util.BufferUtils;
|
||||
|
||||
public class ItemSerializer implements FlatBuffersSerializer<Item, ItemP> {
|
||||
@ -35,7 +34,7 @@ public class ItemSerializer implements FlatBuffersSerializer<Item, ItemP> {
|
||||
getTable(sync, j);
|
||||
byte[] bytes = BufferUtils.readRemaining(table.dataAsByteBuffer());
|
||||
BitStream bitStream = new BitStream(bytes);
|
||||
bitStream.skip(D2S.ItemData.SECTION_HEADER_BITS);
|
||||
// bitStream.skip(D2S.ItemData.SECTION_HEADER_BITS);
|
||||
c.item = com.riiablo.item.Item.loadFromStream(bitStream);
|
||||
return c;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class Item {
|
||||
private static final ItemLabeler DEFAULT_LABELER = new ItemLabeler();
|
||||
|
||||
public static Item loadFromStream(BitStream bitStream) {
|
||||
return DEFAULT_SERIALIZER.read(bitStream);
|
||||
return DEFAULT_SERIALIZER.readSingleItem(bitStream);
|
||||
}
|
||||
|
||||
public static final float ETHEREAL_ALPHA = 2 / 3f;
|
||||
@ -277,6 +277,10 @@ public class Item {
|
||||
return (flags & flag) == flag;
|
||||
}
|
||||
|
||||
public boolean isCompact() {
|
||||
return hasFlag(ITEMFLAG_COMPACT);
|
||||
}
|
||||
|
||||
public boolean isIdentified() {
|
||||
return hasFlag(ITEMFLAG_IDENTIFIED);
|
||||
}
|
||||
@ -476,7 +480,7 @@ public class Item {
|
||||
return base.usesound;
|
||||
}
|
||||
|
||||
private String getFlagsString() {
|
||||
String getFlagsString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (ONLY_KNOWN_FLAGS && (flags & ITEMFLAG__RELOAD ) == ITEMFLAG__RELOAD ) builder.append("ITEMFLAG__RELOAD" ).append('|');
|
||||
if (ONLY_KNOWN_FLAGS && (flags & ITEMFLAG__BOUGHT ) == ITEMFLAG__BOUGHT ) builder.append("ITEMFLAG__BOUGHT" ).append('|');
|
||||
|
@ -1,43 +1,82 @@
|
||||
package com.riiablo.item;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import java.util.Arrays;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import com.riiablo.Riiablo;
|
||||
import com.riiablo.codec.excel.Gems;
|
||||
import com.riiablo.codec.util.BitStream;
|
||||
import com.riiablo.log.Log;
|
||||
import com.riiablo.log.LogManager;
|
||||
import com.riiablo.save.InvalidFormat;
|
||||
import com.riiablo.util.DebugUtils;
|
||||
|
||||
public class ItemSerializer {
|
||||
private static final String TAG = "ItemSerializer";
|
||||
private static final Logger log = LogManager.getLogger(ItemSerializer.class);
|
||||
|
||||
private static final boolean DEBUG = true;
|
||||
private static final byte[] SIGNATURE = {0x4A, 0x4D};
|
||||
|
||||
public Item read(BitStream bitStream) {
|
||||
private static boolean readSignature(BitStream bitStream) {
|
||||
log.trace("Validating item signature");
|
||||
byte[] signature = bitStream.readFully(SIGNATURE.length);
|
||||
boolean matched = Arrays.equals(signature, SIGNATURE);
|
||||
if (!matched) {
|
||||
throw new InvalidFormat(
|
||||
String.format("Item signature doesn't match expected signature: %s, expected %s",
|
||||
DebugUtils.toByteArray(signature),
|
||||
DebugUtils.toByteArray(SIGNATURE)));
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
public Item readItem(BitStream bitStream) {
|
||||
Item item = readSingleItem(bitStream);
|
||||
if (item.socketsFilled > 0) log.trace("Reading {} sockets...", item.socketsFilled);
|
||||
for (int i = 0; i < item.socketsFilled; i++) {
|
||||
try {
|
||||
Log.put("socket", String.valueOf(i));
|
||||
bitStream.alignToByte();
|
||||
item.sockets.add(readSingleItem(bitStream));
|
||||
} finally {
|
||||
Log.remove("socket");
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public Item readSingleItem(BitStream bitStream) {
|
||||
log.trace("Reading item...");
|
||||
readSignature(bitStream);
|
||||
Item item = new Item();
|
||||
item.reset();
|
||||
item.flags = (int) bitStream.readUnsigned(Integer.SIZE);
|
||||
item.version = bitStream.readUnsigned8OrLess(Byte.SIZE);
|
||||
item.flags = (int) bitStream.readUnsigned(Integer.SIZE);
|
||||
Log.tracef(log, "flags: 0x%08X [%s]", item.flags, item.getFlagsString());
|
||||
item.version = bitStream.readUnsigned8OrLess(Byte.SIZE);
|
||||
log.trace("version: {}", item.version);
|
||||
bitStream.skip(2); // Unknown use -- safe to skip
|
||||
item.location = Location.valueOf(bitStream.readUnsigned7OrLess(3));
|
||||
item.bodyLoc = BodyLoc.valueOf(bitStream.readUnsigned7OrLess(4));
|
||||
item.gridX = bitStream.readUnsigned7OrLess(4);
|
||||
item.gridY = bitStream.readUnsigned7OrLess(4);
|
||||
item.bodyLoc = BodyLoc.valueOf(bitStream.readUnsigned7OrLess(4));
|
||||
item.gridX = bitStream.readUnsigned7OrLess(4);
|
||||
item.gridY = bitStream.readUnsigned7OrLess(4);
|
||||
item.storeLoc = StoreLoc.valueOf(bitStream.readUnsigned7OrLess(3));
|
||||
|
||||
if ((item.flags & Item.ITEMFLAG_BODYPART) == Item.ITEMFLAG_BODYPART) {
|
||||
int charClass = bitStream.readUnsigned7OrLess(3);
|
||||
int charLevel = bitStream.readUnsigned7OrLess(7);
|
||||
String charName = bitStream.readString2(Riiablo.MAX_NAME_LENGTH + 1, 7);
|
||||
int charClass = bitStream.readUnsigned7OrLess(3);
|
||||
int charLevel = bitStream.readUnsigned7OrLess(7);
|
||||
String charName = bitStream.readString2(Riiablo.MAX_NAME_LENGTH + 1, 7);
|
||||
item.setEar(charClass, charLevel, charName);
|
||||
} else {
|
||||
item.setBase(bitStream.readString(4).trim());
|
||||
item.socketsFilled = bitStream.readUnsigned7OrLess(3);
|
||||
}
|
||||
|
||||
log.trace("code: {}", item.code);
|
||||
if ((item.flags & Item.ITEMFLAG_COMPACT) == Item.ITEMFLAG_COMPACT) {
|
||||
readCompact(item);
|
||||
} else {
|
||||
read(bitStream, item);
|
||||
readStandard(bitStream, item);
|
||||
}
|
||||
|
||||
return item;
|
||||
@ -52,12 +91,13 @@ public class ItemSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
private static void read(BitStream bitStream, Item item) {
|
||||
item.data = bitStream.getBufferView(); // TODO: remove when serialization implemented
|
||||
item.id = (int) bitStream.readUnsigned(Integer.SIZE);
|
||||
item.ilvl = bitStream.readUnsigned7OrLess(7);
|
||||
item.quality = Quality.valueOf(bitStream.readUnsigned7OrLess(4));
|
||||
item.pictureId = bitStream.readBoolean() ? bitStream.readUnsigned7OrLess(3) : Item.NO_PICTURE_ID;
|
||||
private static void readStandard(BitStream bitStream, Item item) {
|
||||
item.data = bitStream.getBufferView(); // TODO: remove when serialization implemented
|
||||
item.id = (int) bitStream.readUnsigned(Integer.SIZE);
|
||||
Log.tracef(log, "id: 0x%08X", item.id);
|
||||
item.ilvl = bitStream.readUnsigned7OrLess(7);
|
||||
item.quality = Quality.valueOf(bitStream.readUnsigned7OrLess(4));
|
||||
item.pictureId = bitStream.readBoolean() ? bitStream.readUnsigned7OrLess(3) : Item.NO_PICTURE_ID;
|
||||
item.classOnly = bitStream.readBoolean() ? bitStream.readUnsigned15OrLess(11) : Item.NO_CLASS_ONLY;
|
||||
readQualityData(bitStream, item);
|
||||
|
||||
@ -86,10 +126,12 @@ public class ItemSerializer {
|
||||
}
|
||||
|
||||
private static boolean readQualityData(BitStream bitStream, Item item) {
|
||||
log.trace("quality: {}", item.quality);
|
||||
switch (item.quality) {
|
||||
case LOW:
|
||||
case HIGH:
|
||||
item.qualityId = bitStream.readUnsigned31OrLess(3);
|
||||
log.trace("qualityId: {}", item.qualityId);
|
||||
return true;
|
||||
|
||||
case NORMAL:
|
||||
@ -98,28 +140,39 @@ public class ItemSerializer {
|
||||
|
||||
case SET:
|
||||
item.qualityId = bitStream.readUnsigned31OrLess(Item.SET_ID_SIZE);
|
||||
log.trace("qualityId: {}", item.qualityId);
|
||||
item.qualityData = Riiablo.files.SetItems.get(item.qualityId);
|
||||
log.trace("qualityData: {}", item.qualityData);
|
||||
if (item.qualityId == (1 << Item.SET_ID_SIZE) - 1) {
|
||||
Gdx.app.error(TAG, String.format("Unknown set id: 0x%03x", item.qualityId));
|
||||
log.error("Unknown set item id: {}", item.qualityId);
|
||||
// This is unexpected -- all set items should reference a set id
|
||||
// TODO: throw item format exception
|
||||
}
|
||||
return true;
|
||||
|
||||
case UNIQUE:
|
||||
item.qualityId = bitStream.readUnsigned31OrLess(Item.UNIQUE_ID_SIZE);
|
||||
log.trace("qualityId: {}", item.qualityId);
|
||||
item.qualityData = Riiablo.files.UniqueItems.get(item.qualityId);
|
||||
log.trace("qualityData: {}", item.qualityData);
|
||||
if (item.qualityId == (1 << Item.UNIQUE_ID_SIZE) - 1) {
|
||||
Gdx.app.error(TAG, String.format("Unknown unique id: 0x%03x", item.qualityId));
|
||||
log.warn("Unknown unique item id: {}", item.qualityId);
|
||||
// This is expected for hdm and possibly others
|
||||
// TODO: ensure item can be gracefully handled, else throw item format exception
|
||||
}
|
||||
return true;
|
||||
|
||||
case MAGIC:
|
||||
item.qualityId = bitStream.readUnsigned31OrLess(2 * Item.MAGIC_AFFIX_SIZE); // 11 for prefix, 11 for suffix
|
||||
log.trace("qualityId: {}", item.qualityId);
|
||||
return true;
|
||||
|
||||
case RARE:
|
||||
case CRAFTED:
|
||||
item.qualityId = bitStream.readUnsigned31OrLess(2 * Item.RARE_AFFIX_SIZE); // 8 for prefix, 8 for suffix
|
||||
log.trace("qualityId: {}", item.qualityId);
|
||||
item.qualityData = new RareQualityData(bitStream);
|
||||
log.trace("qualityData: {}", item.qualityData);
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -763,7 +763,7 @@ public class D2S {
|
||||
public static class ItemData {
|
||||
static final byte[] SECTION_HEADER = {0x4A, 0x4D};
|
||||
static final byte[] SECTION_FOOTER = ArrayUtils.addAll(SECTION_HEADER, new byte[] {0x00, 0x00});
|
||||
public static final int SECTION_HEADER_BITS = SECTION_HEADER.length * Byte.SIZE;
|
||||
// public static final int SECTION_HEADER_BITS = SECTION_HEADER.length * Byte.SIZE;
|
||||
|
||||
public byte header[];
|
||||
public short size;
|
||||
@ -784,7 +784,7 @@ public class D2S {
|
||||
//else System.out.println(i + " = " + slice.remaining());
|
||||
byte[] bytes = BufferUtils.readRemaining(slice);
|
||||
BitStream bitStream = new BitStream(bytes);
|
||||
bitStream.skip(SECTION_HEADER_BITS);
|
||||
// bitStream.skip(SECTION_HEADER_BITS);
|
||||
Item item = Item.loadFromStream(bitStream);
|
||||
items.add(item);
|
||||
|
||||
@ -794,7 +794,7 @@ public class D2S {
|
||||
//else System.out.println(i + " = " + slice.remaining());
|
||||
bytes = BufferUtils.readRemaining(slice);
|
||||
bitStream = new BitStream(bytes);
|
||||
bitStream.skip(SECTION_HEADER_BITS);
|
||||
// bitStream.skip(SECTION_HEADER_BITS);
|
||||
Item socket = Item.loadFromStream(bitStream);
|
||||
item.sockets.add(socket);
|
||||
assert socket.location == Location.SOCKET;
|
||||
@ -838,7 +838,7 @@ public class D2S {
|
||||
if (slice.remaining() <= 0) return this;
|
||||
byte[] bytes = BufferUtils.readRemaining(buffer);
|
||||
BitStream bitStream = new BitStream(bytes);
|
||||
bitStream.skip(ItemData.SECTION_HEADER_BITS);
|
||||
// bitStream.skip(ItemData.SECTION_HEADER_BITS);
|
||||
item = Item.loadFromStream(bitStream);
|
||||
for (int j = 0; j < item.socketsFilled; j++) {
|
||||
slice = BufferUtils.slice(buffer, ItemData.SECTION_HEADER, true);
|
||||
@ -846,7 +846,7 @@ public class D2S {
|
||||
//else System.out.println(i + " = " + slice.remaining());
|
||||
bytes = BufferUtils.readRemaining(slice);
|
||||
bitStream = new BitStream(bytes);
|
||||
bitStream.skip(ItemData.SECTION_HEADER_BITS);
|
||||
// bitStream.skip(ItemData.SECTION_HEADER_BITS);
|
||||
Item socket = Item.loadFromStream(bitStream);
|
||||
item.sockets.add(socket);
|
||||
assert socket.location == Location.SOCKET;
|
||||
|
Loading…
Reference in New Issue
Block a user