Created StatListWriter and tests

Additional testing required, but workable code
This commit is contained in:
Collin Smith 2020-09-02 18:20:30 -07:00
parent e6f4a8b222
commit ca829a4025
2 changed files with 125 additions and 0 deletions

View File

@ -0,0 +1,56 @@
package com.riiablo.attributes;
import java.util.Iterator;
import com.riiablo.codec.excel.ItemStatCost;
import com.riiablo.io.BitOutput;
import com.riiablo.logger.LogManager;
import com.riiablo.logger.Logger;
import com.riiablo.logger.MDC;
public class StatListWriter {
private static final Logger log = LogManager.getLogger(StatListWriter.class);
public void write(StatListGetter stats, StatGetter stat, BitOutput bits) {
log.traceEntry("write(stats: {}, stat: {}, bits: {})", stats, stat, bits);
final ItemStatCost.Entry entry = stat.entry();
if (entry.Saved) {
if (log.traceEnabled()) log.trace("Writing character save stat {}", stat.debugString());
assert !entry.CSvSigned : "entry.CSvSigned(" + entry.CSvSigned + ") unsupported";
bits.write63u(stat.param(), entry.CSvParam);
bits.write63u(stat.value(), entry.CSvBits);
} else {
if (log.traceEnabled()) log.trace("Writing stat {}", stat.debugString());
bits.write63u(stat.param(), entry.Save_Param_Bits);
bits.write63u(stat.value() + entry.Save_Add, entry.Save_Bits);
}
}
public void write(StatListGetter stats, BitOutput bits) {
for (Iterator<StatGetter> it = stats.iterator(); it.hasNext();) {
final StatGetter stat = it.next();
final short id = stat.id();
try {
MDC.put("stat", id);
bits.write15u(id, Stat.BITS);
final byte numEncoded = Stat.getNumEncoded(id);
try {
if (numEncoded > 1) MDC.put("numEncoded", numEncoded);
write(stats, stat, bits);
for (short j = 1; j < numEncoded; j++) {
final StatGetter next = it.next();
assert next.id() == id + j : String.format(
"it.next(%s) != %d : getNumEncoded(%s)[%d..%d]", next, id + j, id + j, id, id + numEncoded - 1);
write(stats, stat, bits);
}
} finally {
MDC.remove("numEncoded");
}
} finally {
MDC.remove("stat");
}
}
bits.write15u(Stat.NONE, Stat.BITS);
}
}

View File

@ -0,0 +1,69 @@
package com.riiablo.attributes;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.headless.HeadlessApplication;
import com.riiablo.Files;
import com.riiablo.Riiablo;
import com.riiablo.codec.StringTBLs;
import com.riiablo.io.BitInput;
import com.riiablo.io.BitOutput;
import com.riiablo.io.ByteInput;
import com.riiablo.io.ByteOutput;
import com.riiablo.logger.Level;
import com.riiablo.logger.LogManager;
import com.riiablo.mpq.MPQFileHandleResolver;
public class StatListWriterTest {
@BeforeClass
public static void setup() {
Gdx.app = new HeadlessApplication(new ApplicationAdapter() {});
Riiablo.home = Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II");
Riiablo.mpqs = new MPQFileHandleResolver();
Riiablo.string = new StringTBLs(Riiablo.mpqs);
Riiablo.files = new Files();
}
@AfterClass
public static void teardown() {
Gdx.app.exit();
}
@BeforeClass
public static void before() {
LogManager.setLevel("com.riiablo.attributes", Level.TRACE);
}
private void testItem(byte[] data, long bitsToSkip, int length) {
final int offset = (int) (bitsToSkip >> 3);
final int bitOffset = (int) (bitsToSkip & 0x7);
ByteInput in = ByteInput.wrap(Unpooled.wrappedBuffer(data, offset, length));
BitInput bitInput = in.unalign().skipBits(bitOffset);
StatListReader reader = new StatListReader();
final StatListGetter stats = reader.read(StatList.obtain().buildList(), bitInput);
System.out.println(ByteBufUtil.prettyHexDump(in.buffer(), 0, in.buffer().readerIndex()));
ByteOutput out = ByteOutput.wrap(Unpooled.buffer(length, length));
BitOutput bitOutput = out.unalign().writeRaw(data[offset], bitOffset);
System.out.println(ByteBufUtil.prettyHexDump(out.buffer()));
StatListWriter writer = new StatListWriter();
writer.write(stats, bitOutput);
bitOutput.flush();
System.out.println(ByteBufUtil.prettyHexDump(out.buffer()));
Assert.assertTrue(ByteBufUtil.equals(in.buffer(), 0, out.buffer(), 0, in.buffer().readerIndex()));
}
@Test
public void read_item_grief_stats() {
testItem(Gdx.files.internal("test/Grief.d2i").readBytes(), 197, 0x12);
}
}