package net.scapeemulator.game.msg.encoder; import java.util.HashSet; import java.util.Set; import io.netty.buffer.ByteBufAllocator; import net.scapeemulator.game.model.Position; import net.scapeemulator.game.msg.MessageEncoder; import net.scapeemulator.game.msg.impl.RegionConstructMessage; import net.scapeemulator.game.net.game.DataOrder; import net.scapeemulator.game.net.game.DataTransformation; import net.scapeemulator.game.net.game.DataType; import net.scapeemulator.game.net.game.GameFrame; import net.scapeemulator.game.net.game.GameFrame.Type; import net.scapeemulator.game.net.game.GameFrameBuilder; import net.scapeemulator.game.util.LandscapeKeyTable; public final class RegionConstructMessageEncoder extends MessageEncoder<RegionConstructMessage> { private final LandscapeKeyTable keyTable; public RegionConstructMessageEncoder(LandscapeKeyTable keyTable) { super(RegionConstructMessage.class); this.keyTable = keyTable; } @Override public GameFrame encode(ByteBufAllocator alloc, RegionConstructMessage message) { GameFrameBuilder builder = new GameFrameBuilder(alloc, 214, Type.VARIABLE_SHORT); Position position = message.getPosition(); builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, position.getLocalX()); builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, position.getRegionX()); builder.put(DataType.BYTE, DataTransformation.SUBTRACT, position.getHeight() % 4); builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, position.getLocalY()); builder.switchToBitAccess(); for (int height = 0; height < 4; height++) { for (int x = 0; x < 13; x++) { for (int y = 0; y < 13; y++) { int hash = message.getPalette().getHash(height, x, y); if (hash != -1) { builder.putBit(1); builder.putBits(26, hash); } else { builder.putBit(0); } } } } builder.switchToByteAccess(); Set<Integer> sentKeys = new HashSet<>(); for (int height = 0; height < 4; height++) { for (int x = 0; x < 13; x++) { for (int y = 0; y < 13; y++) { int hash = message.getPalette().getHash(height, x, y); if (hash == -1) { continue; } int hashX = (hash >> 14 & 1023) / 8; int hashY = (hash >> 3 & 1023) / 8; int region = hashY + (hashX << 8); if (!sentKeys.add(region)) { continue; } int[] keys = keyTable.getKeys(hashX, hashY); for (int i = 0; i < 4; i++) { builder.put(DataType.INT, DataOrder.INVERSED_MIDDLE, keys[i]); } } } } builder.put(DataType.SHORT, position.getRegionY()); return builder.toGameFrame(); } }