Skip to content

Commit

Permalink
Add BlockLoom & Some skin check changes
Browse files Browse the repository at this point in the history
  • Loading branch information
lt-name committed Oct 19, 2024
1 parent 153af6b commit d5abb15
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 35 deletions.
11 changes: 9 additions & 2 deletions src/main/java/cn/nukkit/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ public class Player extends EntityHuman implements CommandSender, InventoryHolde
public static final int CRAFTING_ANVIL = 2;
public static final int CRAFTING_ENCHANT = 3;
public static final int CRAFTING_BEACON = 4;

public static final int CRAFTING_SMITHING = 1003;
public static final int CRAFTING_LOOM = 1004;

public static final int TRADE_WINDOW_ID = 500;

Expand All @@ -159,6 +159,7 @@ public class Player extends EntityHuman implements CommandSender, InventoryHolde
public static final int ANVIL_WINDOW_ID = 2;
public static final int ENCHANT_WINDOW_ID = 3;
public static final int BEACON_WINDOW_ID = 4;
public static final int LOOM_WINDOW_ID = 2;
public static final int GRINDSTONE_WINDOW_ID = 5;
public static final int SMITHING_WINDOW_ID = 6;
/**
Expand Down Expand Up @@ -2976,7 +2977,13 @@ public void handleDataPacket(DataPacket packet) {
return;
}

this.loginChainData = ClientChainData.read(loginPacket);
try {
// TODO: Why do we read this separately?
this.loginChainData = ClientChainData.read(loginPacket);
} catch (ClientChainData.TooBigSkinException ex) {
this.close("", "disconnectionScreen.invalidSkin");
return;
}

if (!loginChainData.isXboxAuthed() && server.xboxAuth) {
this.close("", "disconnectionScreen.notAuthenticated");
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/cn/nukkit/block/BlockLoom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package cn.nukkit.block;

import cn.nukkit.Player;
import cn.nukkit.inventory.LoomInventory;
import cn.nukkit.item.Item;
import cn.nukkit.item.ItemBlock;
import cn.nukkit.item.ItemTool;
import cn.nukkit.math.BlockFace;
import cn.nukkit.utils.BlockColor;

public class BlockLoom extends BlockSolidMeta {

private static final short[] FACES = {2, 3, 0, 1};

public BlockLoom() {
this(0);
}

public BlockLoom(int meta) {
super(meta);
}

@Override
public String getName() {
return "Loom";
}

@Override
public int getId() {
return LOOM;
}

@Override
public int getToolType() {
return ItemTool.TYPE_AXE;
}

@Override
public double getResistance() {
return 12.5;
}

@Override
public double getHardness() {
return 2.5;
}

@Override
public BlockColor getColor() {
return BlockColor.WOOD_BLOCK_COLOR;
}

@Override
public boolean canBeActivated() {
return true;
}

@Override
public boolean onActivate(Item item, Player player) {
if (player != null) {
player.addWindow(new LoomInventory(player.getUIInventory(), this), Player.LOOM_WINDOW_ID);
}
return true;
}

@Override
public Item toItem() {
return new ItemBlock(Block.get(this.getId(), 0), 0);
}

@Override
public boolean place(Item item, Block block, Block target, BlockFace face, double fx, double fy, double fz, Player player) {
this.setDamage(FACES[player != null ? player.getDirection().getHorizontalIndex() : 0]);
return this.getLevel().setBlock(this, this, true, true);
}
}
1 change: 1 addition & 0 deletions src/main/java/cn/nukkit/block/Blocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ public class Blocks {
list[FLETCHING_TABLE] = BlockFletchingTable.class; //456
list[SMITHING_TABLE] = BlockSmithingTable.class; //457
list[BARREL] = BlockBarrel.class; //458
list[LOOM] = BlockLoom.class; //459

list[BELL] = BlockBell.class; //461
list[SWEET_BERRY_BUSH] = BlockSweetBerryBush.class; //462
Expand Down
1 change: 1 addition & 0 deletions src/main/java/cn/nukkit/inventory/InventoryType.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public enum InventoryType {
UI(1, "UI", -1), //1 CONTAINER
SHULKER_BOX(27, "Shulker Box", 0), //27 CONTAINER
BEACON(1, "Beacon", 13), //1 INPUT
LOOM(4, "Loom", 24), //4 CONTAINER
CHEST_BOAT(27, "Chest Boat", 0),// 34 CONTAINER
ENTITY_ARMOR(4, "Entity Armor", -1), //4 ARMOR
ENTITY_EQUIPMENT(36, "Entity Equipment", -1), //36 CONTAINER
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/cn/nukkit/inventory/LoomInventory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cn.nukkit.inventory;

import cn.nukkit.Player;
import cn.nukkit.item.Item;
import cn.nukkit.level.Position;

public class LoomInventory extends FakeBlockUIComponent {

public static final int OFFSET = 9;

public LoomInventory(PlayerUIInventory playerUI, Position position) {
super(playerUI, InventoryType.LOOM, OFFSET, position);
}

@Override
public void onOpen(Player who) {
super.onOpen(who);
who.craftingType = Player.CRAFTING_LOOM;
}

public Item getFirstItem() {
return getItem(0);
}

public Item getSecondItem() {
return getItem(1);
}

public void setFirstItem(Item item) {
this.setItem(0, item);
}

public void setSecondItem(Item item) {
this.setItem(1, item);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import cn.nukkit.block.BlockID;
import cn.nukkit.level.GlobalBlockPalette;
import cn.nukkit.level.Level;
import cn.nukkit.level.format.anvil.util.BlockStorage;
import cn.nukkit.level.format.anvil.util.NibbleArray;
import cn.nukkit.level.format.leveldb.BlockStateMapping;
import cn.nukkit.level.util.BitArray;
Expand All @@ -26,13 +27,12 @@
import java.util.Arrays;
import java.util.List;

import static cn.nukkit.level.format.anvil.util.BlockStorage.SECTION_SIZE;
import static cn.nukkit.level.format.leveldb.LevelDBConstants.SUB_CHUNK_SIZE;

@Log4j2
public class StateBlockStorage {

private static final int SIZE = 16 * 16 * 16;
private static final int SECTION_SIZE = 16 * 16 * 16;

private List<BlockStateSnapshot> palette;
private BitArray bitArray;
Expand All @@ -50,8 +50,8 @@ public StateBlockStorage(BitArrayVersion version) {
this.palette = new ObjectArrayList<>(16);
this.palette.add(BlockStateMapping.get().getState(0, 0));

this.blockIds = new byte[SIZE];
this.blockData = new NibbleArray(SECTION_SIZE);
this.blockIds = new byte[SECTION_SIZE];
this.blockData = new NibbleArray(BlockStorage.SECTION_SIZE);
}

protected StateBlockStorage(BitArray bitArray, List<BlockStateSnapshot> palette, byte[] blockIds, NibbleArray blockData) {
Expand Down Expand Up @@ -158,7 +158,7 @@ public void readFromStorage(ByteBuf buffer, ChunkBuilder chunkBuilder) {
}
this.palette.add(blockState);
} catch (Exception e) {
log.error("[" + chunkBuilder.debugString() + "] Unable to deserialize chunk block state", e);
log.error("[{}] Unable to deserialize chunk block state", chunkBuilder.debugString(), e);
}
}

Expand Down Expand Up @@ -223,21 +223,10 @@ public void set(BlockVector3 pos, int value) {
this.set(elementIndex(pos.x, pos.y, pos.z), BlockStateMapping.get().getBlockStateFromFullId(value));
}

/**
* Fast check.
*/
public boolean has(int id) {
return this.palette.contains(id);
}

public int indexOf(int id) {
return this.palette.indexOf(id);
}

public void writeTo(int protocol, BinaryStream stream, boolean antiXray) {
PalettedBlockStorage palettedBlockStorage = PalettedBlockStorage.createFromBlockPalette(protocol);

for (int i = 0; i < SECTION_SIZE; i++) {
for (int i = 0; i < BlockStorage.SECTION_SIZE; i++) {
int fullId = get(i);
int id = fullId >> Block.DATA_BITS;
int meta = fullId & Block.DATA_MASK;
Expand All @@ -252,8 +241,8 @@ public void writeTo(int protocol, BinaryStream stream, boolean antiXray) {
}

private void grow(BitArrayVersion version) {
BitArray newBitArray = version.createPalette(SIZE);
for (int i = 0; i < SIZE; i++) {
BitArray newBitArray = version.createPalette(SECTION_SIZE);
for (int i = 0; i < SECTION_SIZE; i++) {
newBitArray.set(i, this.bitArray.get(i));
}
this.bitArray = newBitArray;
Expand Down Expand Up @@ -288,10 +277,9 @@ public boolean isEmpty() {
}

for (int word : this.bitArray.getWords()) {
if (Integer.toUnsignedLong(word) == 0L) {
continue;
if (Integer.toUnsignedLong(word) != 0L) {
return false;
}
return false;
}
return true;
}
Expand All @@ -300,7 +288,7 @@ public byte[] getBlockIds() {
if (!this.isEmpty()) {
return Arrays.copyOf(blockIds, blockIds.length);
} else {
return new byte[SECTION_SIZE];
return new byte[BlockStorage.SECTION_SIZE];
}
}

Expand Down Expand Up @@ -340,15 +328,15 @@ public boolean compress() {
this.palette.add(firstId);

// Arrays.fill(this.bitArray.getWords(), 0);
this.bitArray = BitArrayVersion.V1.createPalette(SIZE);
this.bitArray = BitArrayVersion.V1.createPalette(SECTION_SIZE);
return true;
}

BitArrayVersion version = BitArrayVersion.V2;
BitArray newArray = version.createPalette(SIZE);
BitArray newArray = version.createPalette(SECTION_SIZE);
List<BlockStateSnapshot> newPalette = new ObjectArrayList<>(count);
newPalette.add(this.palette.get(0));
for (int i = 0; i < SIZE; i++) {
for (int i = 0; i < SECTION_SIZE; i++) {
int paletteIndex = this.bitArray.get(i);
BlockStateSnapshot snapshot = this.palette.get(paletteIndex);
int newIndex = newPalette.indexOf(snapshot);
Expand All @@ -359,7 +347,7 @@ public boolean compress() {

if (newIndex > version.getMaxEntryValue()) {
version = version.next();
BitArray growArray = version.createPalette(SIZE);
BitArray growArray = version.createPalette(SECTION_SIZE);
for (int j = 0; j < i; j++) {
growArray.set(j, newArray.get(j));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public void handle(@NotNull PlayerHandle playerHandle, @NotNull PlayerSkinPacket

if (!skin.isValid()) {
player.getServer().getLogger().warning(playerHandle.getUsername() + ": PlayerSkinPacket with invalid skin");
player.close("", "disconnectionScreen.invalidSkin");
return;
}

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/cn/nukkit/network/protocol/LoginPacket.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cn.nukkit.network.protocol;

import cn.nukkit.Server;
import cn.nukkit.entity.data.Skin;
import cn.nukkit.utils.PersonaPiece;
import cn.nukkit.utils.PersonaPieceTint;
Expand Down Expand Up @@ -93,13 +94,12 @@ private void decodeChainData() {
private void decodeSkinData() {
int size = this.getLInt();
if (size > 52428800) {
throw new IllegalArgumentException("The skin data is too big: " + size);
Server.getInstance().getLogger().warning(username + ": The skin data is too big: " + size);
return; // Get disconnected due to "invalid skin"
}

String data = new String(this.get(size), StandardCharsets.UTF_8);
JsonObject skinToken = decodeToken(data);

if (skinToken == null) return;
JsonObject skinToken = decodeToken(new String(this.get(size), StandardCharsets.UTF_8));
if (skinToken == null) throw new RuntimeException("Invalid null skin token");

// 将1.19.62按1.19.63版本处理 修复1.19.62皮肤修改问题
if (this.protocol_ == ProtocolInfo.v1_19_60 &&
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/cn/nukkit/utils/ClientChainData.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public boolean isXboxAuthed() {
private void decodeSkinData() {
int size = bs.getLInt();
if (size > 52428800) {
throw new IllegalArgumentException("The skin data is too big: " + size);
throw new TooBigSkinException("The skin data is too big: " + size);
}
JsonObject skinToken = decodeToken(new String(bs.get(size), StandardCharsets.UTF_8));
if (skinToken == null) return;
Expand Down Expand Up @@ -294,4 +294,11 @@ private static boolean verifyChain(List<String> chains) throws Exception {

private static class MapTypeToken extends TypeToken<Map<String, List<String>>> {
}

public static class TooBigSkinException extends RuntimeException {

public TooBigSkinException(String s) {
super(s);
}
}
}

0 comments on commit d5abb15

Please sign in to comment.