Skip to content

Commit

Permalink
fix: ench item convert
Browse files Browse the repository at this point in the history
  • Loading branch information
CoolLoong committed Mar 14, 2024
1 parent faf7313 commit 80ce89c
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/main/java/cn/nukkit/blockentity/BlockEntityChest.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public ChestInventory getRealInventory() {
return (ChestInventory) inventory;
}

protected void checkPairing() {
public void checkPairing() {
BlockEntityChest pair = this.getPair();

if (pair != null) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/cn/nukkit/convert/BlockEntityConvert.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
import cn.nukkit.nbt.tag.ListTag;

public class BlockEntityConvert {
public static void convertInventory(CompoundTag root) {
public static void convertBlockEntity(CompoundTag root) {
ListTag<CompoundTag> items = root.getList("Items", CompoundTag.class);
ListTag<CompoundTag> result = new ListTag<>();
for (var nbt : items.getAll()) {
int id = nbt.getShort("id");
int slot = nbt.getByte("Slot");
int count = nbt.getByte("Count");
int damage = nbt.getShort("Damage");
CompoundTag tag = nbt.contains("tag") ? nbt.getCompound("tag") : null;

var newTag = new CompoundTag();
Item item = Item.get(id);
Expand All @@ -22,8 +23,8 @@ public static void convertInventory(CompoundTag root) {
.putShort("Damage", damage);
newTag.putString("Name", namespaceId);
newTag.putByte("Slot", slot);
if (item.hasCompoundTag()) {
newTag.putCompound("tag", item.getNamedTag());
if (tag != null) {
newTag.putCompound("tag", tag);
}
if (item.getBlockUnsafe() != null) {
newTag.putCompound("Block", NBTIO.putBlockHelper(item.getBlockUnsafe()));
Expand Down
127 changes: 86 additions & 41 deletions src/main/java/cn/nukkit/convert/PlayerDataConvert.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import cn.nukkit.nbt.NBTIO;
import cn.nukkit.nbt.tag.CompoundTag;
import cn.nukkit.nbt.tag.ListTag;
import com.google.common.collect.HashBiMap;
import me.tongfei.progressbar.ProgressBar;
import org.iq80.leveldb.CompressionType;
import org.iq80.leveldb.DB;
import org.iq80.leveldb.Options;
Expand All @@ -16,9 +16,9 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinTask;

public class PlayerDataConvert {
static DB db;
Expand All @@ -38,39 +38,81 @@ public static void start() {
throw new RuntimeException(e);
}
DB oldDB = Server.getInstance().nameLookup;
HashBiMap<String, UUID> name2uuid = HashBiMap.create();
ConcurrentHashMap<UUID, String> name2uuid = new ConcurrentHashMap<>();
File file = new File(server.getDataPath() + "players");
for (var f : Objects.requireNonNull(file.listFiles(fi -> fi.getName().endsWith(".dat")))) {
String sUuid = f.getName().replace(".dat", "");
UUID uuid = UUID.fromString(sUuid);
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
byte[] v = buffer.array();
for (java.util.Map.Entry<byte[], byte[]> entry : oldDB) {
if (Arrays.equals(entry.getValue(), v)) {
String s = new String(entry.getKey(), StandardCharsets.UTF_8);
name2uuid.put(s, uuid);
break;
}
File[] files = Objects.requireNonNull(file.listFiles(fi -> fi.getName().endsWith(".dat")));
List<File> task = new ArrayList<>();
List<ForkJoinTask<?>> taskList = new ArrayList<>();
for (File value : files) {
task.add(value);
if (task.size() > 100) {
final var t = new ArrayList<>(task);
task.clear();
taskList.add(Server.getInstance().computeThreadPool.submit(() -> {
for (var f : t) {
String sUuid = f.getName().replace(".dat", "");
UUID uuid = UUID.fromString(sUuid);
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
byte[] v = buffer.array();
for (Map.Entry<byte[], byte[]> entry : oldDB) {
if (Arrays.equals(entry.getValue(), v)) {
String s = new String(entry.getKey(), StandardCharsets.UTF_8);
name2uuid.put(uuid, s);
break;
}
}
}
}));
}
}
for (var f : Objects.requireNonNull(file.listFiles(fi -> fi.getName().endsWith(".dat")))) {
UUID uuid = UUID.fromString(f.getName().replace(".dat", ""));
CompoundTag offlinePlayerData = server.getOfflinePlayerData(uuid, false);
convertInventory(offlinePlayerData);
String s = name2uuid.inverse().get(uuid);

ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
byte[] v = buffer.array();
if (!task.isEmpty()) {
taskList.add(Server.getInstance().computeThreadPool.submit(() -> {
for (var f : task) {
String sUuid = f.getName().replace(".dat", "");
UUID uuid = UUID.fromString(sUuid);
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
byte[] v = buffer.array();
for (java.util.Map.Entry<byte[], byte[]> entry : oldDB) {
if (Arrays.equals(entry.getValue(), v)) {
String s = new String(entry.getKey(), StandardCharsets.UTF_8);
name2uuid.put(uuid, s);
break;
}
}
}
}));
}
for (var t : taskList) {
t.join();
}
System.out.println(name2uuid.size());
System.out.println(files.length);
try (ProgressBar pb = new ProgressBar("Convert Player", files.length)) {
for (var f : files) {
pb.step();
UUID uuid = UUID.fromString(f.getName().replace(".dat", ""));
CompoundTag offlinePlayerData = server.getOfflinePlayerData(uuid, false);
convertInventory(offlinePlayerData);
String s = name2uuid.get(uuid);
if (s == null || s.isBlank()) {
System.out.println(uuid + "is null");
continue;
}
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
byte[] v = buffer.array();

db.put(s.getBytes(StandardCharsets.UTF_8), v);
try {
db.put(v, NBTIO.writeGZIPCompressed(offlinePlayerData, ByteOrder.BIG_ENDIAN));
} catch (IOException e) {
throw new RuntimeException(e);
db.put(s.getBytes(StandardCharsets.UTF_8), v);
try {
db.put(v, NBTIO.writeGZIPCompressed(offlinePlayerData, ByteOrder.BIG_ENDIAN));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
try {
Expand All @@ -89,6 +131,7 @@ public static void convertInventory(CompoundTag root) {
int slot = nbt.getByte("Slot");
int count = nbt.getByte("Count");
int damage = nbt.getShort("Damage");
CompoundTag tag = nbt.contains("tag") ? nbt.getCompound("tag") : null;

if (slot >= 9 && slot < 45) {
Item item = Item.get(id);
Expand All @@ -98,8 +141,8 @@ public static void convertInventory(CompoundTag root) {
.putShort("Damage", damage);
newTag.putString("Name", namespaceId);
newTag.putByte("Slot", slot - 9);
if (item.hasCompoundTag()) {
newTag.putCompound("tag", item.getNamedTag());
if (tag != null) {
newTag.putCompound("tag", tag);
}
if (item.getBlockUnsafe() != null) {
newTag.putCompound("Block", NBTIO.putBlockHelper(item.getBlockUnsafe()));
Expand All @@ -113,8 +156,8 @@ public static void convertInventory(CompoundTag root) {
.putShort("Damage", damage);
newTag.putString("Name", namespaceId);
newTag.putByte("Slot", slot - 64);
if (item.hasCompoundTag()) {
newTag.putCompound("tag", item.getNamedTag());
if (tag != null) {
newTag.putCompound("tag", tag);
}
if (item.getBlockUnsafe() != null) {
newTag.putCompound("Block", NBTIO.putBlockHelper(item.getBlockUnsafe()));
Expand All @@ -128,8 +171,8 @@ public static void convertInventory(CompoundTag root) {
.putShort("Damage", damage);
offHand.putString("Name", namespaceId);
offHand.putByte("Slot", 0);
if (item.hasCompoundTag()) {
offHand.putCompound("tag", item.getNamedTag());
if (tag != null) {
offHand.putCompound("tag", tag);
}
if (item.getBlockUnsafe() != null) {
offHand.putCompound("Block", NBTIO.putBlockHelper(item.getBlockUnsafe()));
Expand All @@ -150,17 +193,19 @@ public static void convertInventory(CompoundTag root) {
int slot = nbt.getByte("Slot");
int count = nbt.getByte("Count");
int damage = nbt.getShort("Damage");
CompoundTag tag = nbt.contains("tag") ? nbt.getCompound("tag") : null;

if (slot >= 0 && slot < 27) {
Item item = Item.get(id);
String namespaceId = item.getNamespaceId();
if (namespaceId == null || namespaceId.isBlank()) continue;
CompoundTag newTag = new CompoundTag()
.putByte("Count", count)
.putShort("Damage", damage);
newTag.putString("Name", namespaceId);
newTag.putByte("Slot", slot);
if (item.hasCompoundTag()) {
newTag.putCompound("tag", item.getNamedTag());
if (tag != null) {
newTag.putCompound("tag", tag);
}
if (item.getBlockUnsafe() != null) {
newTag.putCompound("Block", NBTIO.putBlockHelper(item.getBlockUnsafe()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import cn.nukkit.Player;
import cn.nukkit.blockentity.BlockEntity;
import cn.nukkit.blockentity.BlockEntityChest;
import cn.nukkit.blockstate.BlockState;
import cn.nukkit.blockstate.BlockStateRegistry;
import cn.nukkit.convert.BlockEntityConvert;
Expand Down Expand Up @@ -140,8 +141,9 @@ private void serializeTileAndEntity(WriteBatch writeBatch, Chunk chunk, Dimensio
if (blockEntities.isEmpty()) writeBatch.delete(key);
else {
for (BlockEntity blockEntity : blockEntities) {
if (blockEntity instanceof BlockEntityChest chest) chest.checkPairing();
blockEntity.saveNBT();
BlockEntityConvert.convertInventory(blockEntity.namedTag);
BlockEntityConvert.convertBlockEntity(blockEntity.namedTag);
NBTIO.write(blockEntity.namedTag, bufStream, ByteOrder.LITTLE_ENDIAN);
}
writeBatch.put(key, Utils.convertByteBuf2Array(tileBuffer));
Expand Down

0 comments on commit 80ce89c

Please sign in to comment.