Skip to content

Commit

Permalink
Optimized packet snapshot. Readers closing. Restructured schematic cl…
Browse files Browse the repository at this point in the history
…asses
  • Loading branch information
Nan1t committed Jan 24, 2022
1 parent 864a84b commit 1c3cb9b
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 154 deletions.
12 changes: 5 additions & 7 deletions src/main/java/ru/nanit/limbo/protocol/ByteMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,7 @@ public void writeLongArray(long[] array) {
}

public void writeCompoundTagArray(CompoundBinaryTag[] compoundTags) {
try {
ByteBufOutputStream stream = new ByteBufOutputStream(buf);

try (ByteBufOutputStream stream = new ByteBufOutputStream(buf)) {
writeVarInt(compoundTags.length);

for (CompoundBinaryTag tag : compoundTags) {
Expand All @@ -174,16 +172,16 @@ public void writeCompoundTagArray(CompoundBinaryTag[] compoundTags) {
}

public CompoundBinaryTag readCompoundTag() {
try {
return BinaryTagIO.reader().read((InputStream) new ByteBufInputStream(buf));
try (ByteBufInputStream stream = new ByteBufInputStream(buf)) {
return BinaryTagIO.reader().read((InputStream) stream);
} catch (IOException thrown) {
throw new DecoderException("Cannot read NBT CompoundTag");
}
}

public void writeCompoundTag(CompoundBinaryTag compoundTag) {
try {
BinaryTagIO.writer().write(compoundTag, (OutputStream) new ByteBufOutputStream(buf));
try (ByteBufOutputStream stream = new ByteBufOutputStream(buf)) {
BinaryTagIO.writer().write(compoundTag, (OutputStream) stream);
} catch (IOException e) {
throw new EncoderException("Cannot write NBT CompoundTag");
}
Expand Down
32 changes: 25 additions & 7 deletions src/main/java/ru/nanit/limbo/protocol/PacketSnapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,44 @@
import java.util.HashMap;
import java.util.Map;

/**
* PacketSnapshot encodes packet to byt array for each MC version.
* Some versions have same bytes snapshot, so there are mappings
* to avoid storing same byte array for different versions
*/
public class PacketSnapshot implements PacketOut {

private final PacketOut packet;
private final Map<Version, byte[]> versionMessages;
private final Map<Version, byte[]> versionMessages = new HashMap<>();
private final Map<Version, Version> mappings = new HashMap<>();

public PacketSnapshot(PacketOut packet) {
this.packet = packet;
this.versionMessages = new HashMap<>();
}

public PacketOut getWrappedPacket() {
return packet;
}

public PacketSnapshot encodePacket() {
Map<Integer, Version> hashes = new HashMap<>();

for (Version version : Version.values()) {
if (version.equals(Version.UNDEFINED)) continue;

ByteMessage encodedMessage = ByteMessage.create();
packet.encode(encodedMessage, version);
byte[] message = encodedMessage.toByteArray();
versionMessages.put(version, message);

int hash = encodedMessage.hashCode();
Version hashed = hashes.get(hash);

if (hashed != null) {
mappings.put(version, hashed);
continue;
}

hashes.put(hash, version);
versionMessages.put(version, encodedMessage.toByteArray());
encodedMessage.release();
}

Expand All @@ -50,11 +68,11 @@ public PacketSnapshot encodePacket() {

@Override
public void encode(ByteMessage msg, Version version) {
byte[] message = versionMessages.get(version);
Version mapped = mappings.get(version);
byte[] message = versionMessages.get(mapped);

if (message != null) {
if (message != null)
msg.writeBytes(message);
}
}

@Override
Expand Down
34 changes: 0 additions & 34 deletions src/main/java/ru/nanit/limbo/world/BlockMap.java

This file was deleted.

68 changes: 68 additions & 0 deletions src/main/java/ru/nanit/limbo/world/BlockMappings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (C) 2020 Nan1t
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package ru.nanit.limbo.world;

import ru.nanit.limbo.protocol.registry.Version;

import java.util.HashMap;
import java.util.Map;

public final class BlockMappings {

private final Map<String, String> idToState = new HashMap<>();
private final Map<String, String> stateToId = new HashMap<>();

public BlockData convert(int id, byte data, Version version) {
if (version.less(Version.V1_13))
return new BlockData(id, data);

String state = idToState.get(toId(id, data));

return state != null ? new BlockData(state) : null;
}

public BlockData convert(String state, Version version) {
if (state == null) return null;

if (version.moreOrEqual(Version.V1_13)) {
return new BlockData(state);
}

String id = stateToId.get(state);

if (id != null) {
String[] arr = id.split(":");
int blockId = Integer.parseInt(arr[0]);
byte data = Byte.parseByte(arr[1]);

return new BlockData(blockId, data);
}

return null;
}

public void register(int id, byte data, String state) {
String strId = toId(id, data);
idToState.put(strId, state);
stateToId.put(state, strId);
}

private String toId(int id, byte data) {
return id + ":" + data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,15 @@ private CompoundBinaryTag readCodecFile(String resPath) throws IOException {
return TagStringIO.get().asCompound(streamToString(in));
}

private String streamToString(InputStream in) {
return new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
.lines()
private String streamToString(InputStream in) throws IOException {
InputStreamReader isReader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader bufReader = new BufferedReader(isReader);
String content = bufReader.lines()
.collect(Collectors.joining("\n"));

isReader.close();
bufReader.close();

return content;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2020 Nan1t
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package ru.nanit.limbo.world.schematic;

import ru.nanit.limbo.world.BlockEntity;
import ru.nanit.limbo.world.BlockMappings;

import java.util.List;

public abstract class AbstractSchematic implements Schematic {

protected final BlockMappings mappings;

private int width;
private int height;
private int length;
private List<BlockEntity> blockEntities;

public AbstractSchematic(BlockMappings mappings) {
this.mappings = mappings;
}

@Override
public int getWidth() {
return width;
}

@Override
public int getHeight() {
return height;
}

@Override
public int getLength() {
return length;
}

@Override
public List<BlockEntity> getBlockEntities() {
return blockEntities;
}

public void setWidth(int width) {
this.width = width;
}

public void setHeight(int height) {
this.height = height;
}

public void setLength(int length) {
this.length = length;
}

public void setBlockEntities(List<BlockEntity> blockEntities) {
this.blockEntities = blockEntities;
}
}
3 changes: 1 addition & 2 deletions src/main/java/ru/nanit/limbo/world/schematic/Schematic.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import ru.nanit.limbo.protocol.registry.Version;
import ru.nanit.limbo.world.BlockData;
import ru.nanit.limbo.world.BlockEntity;
import ru.nanit.limbo.world.BlockMap;
import ru.nanit.limbo.world.Location;

import java.util.List;
Expand All @@ -35,6 +34,6 @@ public interface Schematic {

List<BlockEntity> getBlockEntities();

BlockData getBlock(Location loc, Version version, BlockMap mappings);
BlockData getBlock(Location loc, Version version);

}
17 changes: 12 additions & 5 deletions src/main/java/ru/nanit/limbo/world/schematic/SchematicLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import ru.nanit.limbo.world.BlockEntity;
import ru.nanit.limbo.world.BlockMappings;
import ru.nanit.limbo.world.Location;
import ru.nanit.limbo.world.schematic.versions.LegacySchematic;
import ru.nanit.limbo.world.schematic.versions.SpongeSchematic;
Expand All @@ -36,23 +37,29 @@

public class SchematicLoader {

private final BlockMappings mappings;

public SchematicLoader(BlockMappings mappings) {
this.mappings = mappings;
}

public Schematic load(Path file) throws IOException {
return load(Files.newInputStream(file));
}

public Schematic load(InputStream stream) throws IOException {
CompoundBinaryTag nbt = BinaryTagIO.unlimitedReader().read(stream, BinaryTagIO.Compression.GZIP);

if (nbt.getCompound("BlockData") == CompoundBinaryTag.empty()) {
return loadLegacy(nbt);
} else {
if (nbt.keySet().contains("BlockData")) {
return loadSponge(nbt);
} else {
return loadLegacy(nbt);
}
}

// Specification: https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-2.md
private Schematic loadSponge(CompoundBinaryTag nbt) {
SpongeSchematic schematic = new SpongeSchematic();
SpongeSchematic schematic = new SpongeSchematic(mappings);

schematic.setDataVersion(nbt.getInt("DataVersion"));

Expand Down Expand Up @@ -93,7 +100,7 @@ private Schematic loadSponge(CompoundBinaryTag nbt) {
}

private Schematic loadLegacy(CompoundBinaryTag nbt) {
LegacySchematic schematic = new LegacySchematic();
LegacySchematic schematic = new LegacySchematic(mappings);

schematic.setWidth(nbt.getShort("Width"));
schematic.setHeight(nbt.getShort("Height"));
Expand Down
Loading

0 comments on commit 1c3cb9b

Please sign in to comment.