This commit is contained in:
Felix Cravic 2020-04-05 17:46:29 +02:00
parent 3b06c5b9ef
commit 35b77e4e8c
14 changed files with 145 additions and 43 deletions

View File

@ -36,6 +36,6 @@ dependencies {
// https://mvnrepository.com/artifact/com.google.code.gson/gson // https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
implementation 'com.github.TheMode:CommandBuilder:e70e2bd6b7' implementation 'com.github.TheMode:CommandBuilder:611d16a487'
} }

View File

@ -3,7 +3,6 @@ package fr.themode.demo;
import fr.themode.demo.entity.ChickenCreature; import fr.themode.demo.entity.ChickenCreature;
import fr.themode.demo.generator.ChunkGeneratorDemo; import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.minestom.MinecraftServer; import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.command.CommandManager;
import fr.themode.minestom.entity.Entity; import fr.themode.minestom.entity.Entity;
import fr.themode.minestom.entity.EntityCreature; import fr.themode.minestom.entity.EntityCreature;
import fr.themode.minestom.entity.GameMode; import fr.themode.minestom.entity.GameMode;
@ -70,15 +69,6 @@ public class PlayerInit {
}); });
player.setEventCallback(PlayerChatEvent.class, event -> {
String message = event.getMessage();
System.out.println("Chat: " + message);
CommandManager commandManager = MinecraftServer.getCommandManager();
boolean result = commandManager.execute(event.getSender(), message);
if (!result)
player.sendMessage("No command found");
});
player.setEventCallback(PickupItemEvent.class, event -> { player.setEventCallback(PickupItemEvent.class, event -> {
event.setCancelled(!player.getInventory().addItemStack(event.getItemStack())); // Cancel event if player does not have enough inventory space event.setCancelled(!player.getInventory().addItemStack(event.getItemStack())); // Cancel event if player does not have enough inventory space
}); });

View File

@ -2,6 +2,7 @@ package fr.themode.demo.blocks;
import fr.themode.minestom.data.Data; import fr.themode.minestom.data.Data;
import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.Player;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.instance.block.CustomBlock; import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.utils.BlockPosition; import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.time.UpdateOption; import fr.themode.minestom.utils.time.UpdateOption;
@ -13,8 +14,18 @@ public class StoneBlock extends CustomBlock {
} }
@Override @Override
public void interact(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) { public void onPlace(Instance instance, BlockPosition blockPosition, Data data) {
player.sendMessage("INTERACT STONE");
}
@Override
public void onDestroy(Instance instance, BlockPosition blockPosition, Data data) {
}
@Override
public void onInteract(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) {
} }
@Override @Override

View File

@ -22,8 +22,18 @@ public class UpdatableBlockDemo extends CustomBlock {
} }
@Override @Override
public void interact(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) { public void onPlace(Instance instance, BlockPosition blockPosition, Data data) {
player.sendMessage("INTERACT UPDATABLE");
}
@Override
public void onDestroy(Instance instance, BlockPosition blockPosition, Data data) {
}
@Override
public void onInteract(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) {
} }
@Override @Override

View File

@ -27,10 +27,12 @@ public class CommandManager {
public void register(Command<Player> command) { public void register(Command<Player> command) {
this.dispatcher.register(command); this.dispatcher.register(command);
refreshPacket();
} }
public void register(CommandProcessor commandProcessor) { public void register(CommandProcessor commandProcessor) {
this.commandProcessorMap.put(commandProcessor.getCommandName().toLowerCase(), commandProcessor); this.commandProcessorMap.put(commandProcessor.getCommandName().toLowerCase(), commandProcessor);
refreshPacket();
} }
public boolean execute(Player source, String command) { public boolean execute(Player source, String command) {
@ -69,6 +71,56 @@ public class CommandManager {
} }
private void refreshPacket() { private void refreshPacket() {
List<String> commands = new ArrayList<>();
for (Command<Player> command : dispatcher.getCommands()) {
commands.add(command.getName());
for (String alias : command.getAliases()) {
commands.add(alias);
}
}
for (CommandProcessor commandProcessor : commandProcessorMap.values()) {
commands.add(commandProcessor.getCommandName());
}
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
ArrayList<Integer> rootChildren = new ArrayList<>();
DeclareCommandsPacket.Node argNode = new DeclareCommandsPacket.Node();
argNode.flags = 0b10;
argNode.name = "arg";
argNode.parser = "brigadier:string";
argNode.properties = packetWriter -> {
packetWriter.writeVarInt(0);
};
int argOffset = nodes.size();
rootChildren.add(argOffset);
nodes.add(argNode);
argNode.children = new int[]{argOffset};
for (String commandName : commands) {
DeclareCommandsPacket.Node literalNode = new DeclareCommandsPacket.Node();
literalNode.flags = 0b1;
literalNode.name = commandName;
literalNode.children = new int[]{argOffset};
rootChildren.add(nodes.size());
nodes.add(literalNode);
}
DeclareCommandsPacket.Node rootNode = new DeclareCommandsPacket.Node();
rootNode.flags = 0;
rootNode.children = ArrayUtils.toArray(rootChildren);
nodes.add(rootNode);
declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[nodes.size()]);
declareCommandsPacket.rootIndex = nodes.size() - 1;
}
private void refreshPacket2() {
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>(); List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
ArrayList<Integer> rootChildren = new ArrayList<>(); ArrayList<Integer> rootChildren = new ArrayList<>();

View File

@ -90,9 +90,9 @@ public class Player extends LivingEntity {
setBoundingBox(0.8f, 1.8f, 0.8f); setBoundingBox(0.8f, 1.8f, 0.8f);
playerConnection.sendPacket(getPropertiesPacket()); // Send default properties // Some client update
getPlayerConnection().sendPacket(getPropertiesPacket()); // Send default properties
refreshHealth(); refreshHealth();
refreshAbilities(); refreshAbilities();
this.settings = new PlayerSettings(); this.settings = new PlayerSettings();
@ -445,7 +445,7 @@ public class Player extends LivingEntity {
}); });
} }
private void refreshHealth() { protected void refreshHealth() {
heal(); heal();
this.food = 20; this.food = 20;
this.foodSaturation = 5; this.foodSaturation = 5;
@ -780,7 +780,7 @@ public class Player extends LivingEntity {
return vehicleInformation; return vehicleInformation;
} }
private void refreshAbilities() { protected void refreshAbilities() {
PlayerAbilitiesPacket playerAbilitiesPacket = new PlayerAbilitiesPacket(); PlayerAbilitiesPacket playerAbilitiesPacket = new PlayerAbilitiesPacket();
playerAbilitiesPacket.invulnerable = invulnerable; playerAbilitiesPacket.invulnerable = invulnerable;
playerAbilitiesPacket.flying = flying; playerAbilitiesPacket.flying = flying;

View File

@ -9,6 +9,10 @@ public enum Attribute {
ATTACK_DAMAGE("generic.attackDamage", 2, 2048), ATTACK_DAMAGE("generic.attackDamage", 2, 2048),
ATTACK_SPEED("generic.attackSpeed", 4, 1024), ATTACK_SPEED("generic.attackSpeed", 4, 1024),
FLYING_SPEED("generic.flyingSpeed", 0.4f, 1024), FLYING_SPEED("generic.flyingSpeed", 0.4f, 1024),
ARMOR("generic.armor", 0, 30),
ARMOR_TOUGHNESS("generic.armorToughness", 0, 20),
ATTACK_KNOCKBACK("generic.attackKnockback", 0, 5),
LUCK("generic.luck", 0, 1024),
HORSE_JUMP_STRENGTH("horse.jumpStrength", 0.7f, 2), HORSE_JUMP_STRENGTH("horse.jumpStrength", 0.7f, 2),
ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawnReinforcements", 0, 1); ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawnReinforcements", 0, 1);

View File

@ -64,33 +64,33 @@ public class Chunk implements Viewable {
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
} }
public void UNSAFE_setBlock(byte x, byte y, byte z, short blockId, Data data) { public void UNSAFE_setBlock(int index, short blockId, Data data) {
setBlock(x, y, z, blockId, (short) 0, data, null); setBlock(index, blockId, (short) 0, data, null);
} }
public void UNSAFE_setBlock(byte x, byte y, byte z, short blockId) { public void UNSAFE_setBlock(int index, short blockId) {
UNSAFE_setBlock(x, y, z, blockId, null); UNSAFE_setBlock(index, blockId, null);
} }
public void UNSAFE_setCustomBlock(byte x, byte y, byte z, short customBlockId, Data data) { public void UNSAFE_setCustomBlock(int index, short customBlockId, Data data) {
CustomBlock customBlock = BLOCK_MANAGER.getBlock(customBlockId); CustomBlock customBlock = BLOCK_MANAGER.getBlock(customBlockId);
if (customBlock == null) if (customBlock == null)
throw new IllegalArgumentException("The custom block " + customBlockId + " does not exist or isn't registered"); throw new IllegalArgumentException("The custom block " + customBlockId + " does not exist or isn't registered");
setCustomBlock(x, y, z, customBlock, data); setCustomBlock(index, customBlock, data);
} }
public void UNSAFE_setCustomBlock(byte x, byte y, byte z, short customBlockId) { public void UNSAFE_setCustomBlock(int index, short customBlockId) {
UNSAFE_setCustomBlock(x, y, z, customBlockId, null); UNSAFE_setCustomBlock(index, customBlockId, null);
} }
private void setCustomBlock(byte x, byte y, byte z, CustomBlock customBlock, Data data) { private void setCustomBlock(int index, CustomBlock customBlock, Data data) {
UpdateConsumer updateConsumer = customBlock.hasUpdate() ? customBlock::update : null; UpdateConsumer updateConsumer = customBlock.hasUpdate() ? customBlock::update : null;
setBlock(x, y, z, customBlock.getType(), customBlock.getId(), data, updateConsumer); setBlock(index, customBlock.getType(), customBlock.getId(), data, updateConsumer);
} }
private void setBlock(byte x, byte y, byte z, short blockType, short customId, Data data, UpdateConsumer updateConsumer) { private void setBlock(int index, short blockType, short customId, Data data, UpdateConsumer updateConsumer) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (blockType != 0 if (blockType != 0
|| (blockType == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found || (blockType == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
int value = (blockType << 16 | customId & 0xFFFF); // Merge blockType and customId to one unique Integer (16/16 bits) int value = (blockType << 16 | customId & 0xFFFF); // Merge blockType and customId to one unique Integer (16/16 bits)
@ -156,7 +156,7 @@ public class Chunk implements Viewable {
return getCustomBlock(index); return getCustomBlock(index);
} }
private CustomBlock getCustomBlock(int index) { protected CustomBlock getCustomBlock(int index) {
int value = getBlockValue(index); int value = getBlockValue(index);
short id = (short) (value & 0xffff); short id = (short) (value & 0xffff);
return id != 0 ? BLOCK_MANAGER.getBlock(id) : null; return id != 0 ? BLOCK_MANAGER.getBlock(id) : null;
@ -171,7 +171,7 @@ public class Chunk implements Viewable {
return getData(index); return getData(index);
} }
private Data getData(int index) { protected Data getData(int index) {
return blocksData.get(index); return blocksData.get(index);
} }

View File

@ -6,11 +6,13 @@ import fr.themode.minestom.entity.Player;
import fr.themode.minestom.event.PlayerBlockBreakEvent; import fr.themode.minestom.event.PlayerBlockBreakEvent;
import fr.themode.minestom.instance.batch.BlockBatch; import fr.themode.minestom.instance.batch.BlockBatch;
import fr.themode.minestom.instance.batch.ChunkBatch; import fr.themode.minestom.instance.batch.ChunkBatch;
import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.net.PacketWriterUtils; import fr.themode.minestom.net.PacketWriterUtils;
import fr.themode.minestom.net.packet.server.play.BlockChangePacket; import fr.themode.minestom.net.packet.server.play.BlockChangePacket;
import fr.themode.minestom.net.packet.server.play.ParticlePacket; import fr.themode.minestom.net.packet.server.play.ParticlePacket;
import fr.themode.minestom.utils.BlockPosition; import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.ChunkUtils; import fr.themode.minestom.utils.ChunkUtils;
import fr.themode.minestom.utils.SerializerUtils;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
@ -41,10 +43,16 @@ public class InstanceContainer extends Instance {
public synchronized void setBlock(int x, int y, int z, short blockId, Data data) { public synchronized void setBlock(int x, int y, int z, short blockId, Data data) {
Chunk chunk = getChunkAt(x, z); Chunk chunk = getChunkAt(x, z);
synchronized (chunk) { synchronized (chunk) {
byte chunkX = (byte) (x % 16); byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y; byte chunkY = (byte) y;
byte chunkZ = (byte) (z % 16); byte chunkZ = (byte) (z % 16);
chunk.UNSAFE_setBlock(chunkX, chunkY, chunkZ, blockId, data);
int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
callBlockDestroy(chunk, index, x, y, z);
chunk.UNSAFE_setBlock(index, blockId, data);
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket // TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
sendBlockChange(chunk, x, y, z, blockId); sendBlockChange(chunk, x, y, z, blockId);
@ -58,14 +66,34 @@ public class InstanceContainer extends Instance {
byte chunkX = (byte) (x % 16); byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y; byte chunkY = (byte) y;
byte chunkZ = (byte) (z % 16); byte chunkZ = (byte) (z % 16);
chunk.UNSAFE_setCustomBlock(chunkX, chunkY, chunkZ, blockId, data); int index = SerializerUtils.chunkCoordToIndex(chunkX, chunkY, chunkZ);
callBlockDestroy(chunk, index, x, y, z);
chunk.UNSAFE_setCustomBlock(index, blockId, data);
short id = BLOCK_MANAGER.getBlock(blockId).getType(); short id = BLOCK_MANAGER.getBlock(blockId).getType();
callBlockPlace(chunk, index, x, y, z);
// TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket // TODO instead of sending a block change packet each time, cache changed blocks and flush them every tick with a MultiBlockChangePacket
sendBlockChange(chunk, x, y, z, id); sendBlockChange(chunk, x, y, z, id);
} }
} }
private void callBlockDestroy(Chunk chunk, int index, int x, int y, int z) {
CustomBlock previousBlock = chunk.getCustomBlock(index);
if (previousBlock != null) {
Data previousData = chunk.getData(index);
previousBlock.onDestroy(this, new BlockPosition(x, y, z), previousData);
}
}
private void callBlockPlace(Chunk chunk, int index, int x, int y, int z) {
CustomBlock actualBlock = chunk.getCustomBlock(index);
Data previousData = chunk.getData(index);
actualBlock.onPlace(this, new BlockPosition(x, y, z), previousData);
}
@Override @Override
public void breakBlock(Player player, BlockPosition blockPosition) { public void breakBlock(Player player, BlockPosition blockPosition) {
Chunk chunk = getChunkAt(blockPosition); Chunk chunk = getChunkAt(blockPosition);

View File

@ -3,6 +3,7 @@ package fr.themode.minestom.instance.batch;
import fr.themode.minestom.data.Data; import fr.themode.minestom.data.Data;
import fr.themode.minestom.instance.Chunk; import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.InstanceContainer; import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.utils.SerializerUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -85,10 +86,11 @@ public class BlockBatch implements InstanceBatch {
private Data data; private Data data;
public void apply(Chunk chunk) { public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex((byte) x, (byte) y, (byte) z);
if (!isCustomBlock) { if (!isCustomBlock) {
chunk.UNSAFE_setBlock((byte) x, (byte) y, (byte) z, blockId, data); chunk.UNSAFE_setBlock(index, blockId, data);
} else { } else {
chunk.UNSAFE_setCustomBlock((byte) x, (byte) y, (byte) z, blockId, data); chunk.UNSAFE_setCustomBlock(index, blockId, data);
} }
} }

View File

@ -4,6 +4,7 @@ import fr.themode.minestom.data.Data;
import fr.themode.minestom.instance.Chunk; import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.ChunkGenerator; import fr.themode.minestom.instance.ChunkGenerator;
import fr.themode.minestom.instance.InstanceContainer; import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.utils.SerializerUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -81,10 +82,11 @@ public class ChunkBatch implements InstanceBatch {
private Data data; private Data data;
public void apply(Chunk chunk) { public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (!isCustomBlock) { if (!isCustomBlock) {
chunk.UNSAFE_setBlock(x, y, z, blockId, data); chunk.UNSAFE_setBlock(index, blockId, data);
} else { } else {
chunk.UNSAFE_setCustomBlock(x, y, z, blockId, data); chunk.UNSAFE_setCustomBlock(index, blockId, data);
} }
} }

View File

@ -31,7 +31,11 @@ public abstract class CustomBlock {
throw new UnsupportedOperationException("Update method not overridden"); throw new UnsupportedOperationException("Update method not overridden");
} }
public abstract void interact(Player player, Player.Hand hand, BlockPosition blockPosition, Data data); public abstract void onPlace(Instance instance, BlockPosition blockPosition, Data data);
public abstract void onDestroy(Instance instance, BlockPosition blockPosition, Data data);
public abstract void onInteract(Player player, Player.Hand hand, BlockPosition blockPosition, Data data);
public abstract UpdateOption getUpdateOption(); public abstract UpdateOption getUpdateOption();

View File

@ -36,7 +36,7 @@ public class BlockPlacementListener {
CustomBlock customBlock = instance.getCustomBlock(blockPosition); CustomBlock customBlock = instance.getCustomBlock(blockPosition);
if (customBlock != null) { if (customBlock != null) {
Data data = instance.getBlockData(blockPosition); Data data = instance.getBlockData(blockPosition);
customBlock.interact(player, hand, blockPosition, data); customBlock.onInteract(player, hand, blockPosition, data);
} }
}); });

View File

@ -98,8 +98,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
CommandManager commandManager = MinecraftServer.getCommandManager(); CommandManager commandManager = MinecraftServer.getCommandManager();
DeclareCommandsPacket declareCommandsPacket = commandManager.getDeclareCommandsPacket(); DeclareCommandsPacket declareCommandsPacket = commandManager.getDeclareCommandsPacket();
// FIXME connection.sendPacket(declareCommandsPacket);
//connection.sendPacket(declareCommandsPacket);
} }