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
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.generator.ChunkGeneratorDemo;
import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.command.CommandManager;
import fr.themode.minestom.entity.Entity;
import fr.themode.minestom.entity.EntityCreature;
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 -> {
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.entity.Player;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.time.UpdateOption;
@ -13,8 +14,18 @@ public class StoneBlock extends CustomBlock {
}
@Override
public void interact(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) {
player.sendMessage("INTERACT STONE");
public void onPlace(Instance instance, BlockPosition blockPosition, Data data) {
}
@Override
public void onDestroy(Instance instance, BlockPosition blockPosition, Data data) {
}
@Override
public void onInteract(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) {
}
@Override

View File

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

View File

@ -27,10 +27,12 @@ public class CommandManager {
public void register(Command<Player> command) {
this.dispatcher.register(command);
refreshPacket();
}
public void register(CommandProcessor commandProcessor) {
this.commandProcessorMap.put(commandProcessor.getCommandName().toLowerCase(), commandProcessor);
refreshPacket();
}
public boolean execute(Player source, String command) {
@ -69,6 +71,56 @@ public class CommandManager {
}
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<>();
ArrayList<Integer> rootChildren = new ArrayList<>();

View File

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

View File

@ -9,6 +9,10 @@ public enum Attribute {
ATTACK_DAMAGE("generic.attackDamage", 2, 2048),
ATTACK_SPEED("generic.attackSpeed", 4, 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),
ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawnReinforcements", 0, 1);

View File

@ -64,33 +64,33 @@ public class Chunk implements Viewable {
this.chunkZ = chunkZ;
}
public void UNSAFE_setBlock(byte x, byte y, byte z, short blockId, Data data) {
setBlock(x, y, z, blockId, (short) 0, data, null);
public void UNSAFE_setBlock(int index, short blockId, Data data) {
setBlock(index, blockId, (short) 0, data, null);
}
public void UNSAFE_setBlock(byte x, byte y, byte z, short blockId) {
UNSAFE_setBlock(x, y, z, blockId, null);
public void UNSAFE_setBlock(int index, short blockId) {
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);
if (customBlock == null)
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) {
UNSAFE_setCustomBlock(x, y, z, customBlockId, null);
public void UNSAFE_setCustomBlock(int index, short customBlockId) {
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;
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) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
private void setBlock(int index, short blockType, short customId, Data data, UpdateConsumer updateConsumer) {
if (blockType != 0
|| (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)
@ -156,7 +156,7 @@ public class Chunk implements Viewable {
return getCustomBlock(index);
}
private CustomBlock getCustomBlock(int index) {
protected CustomBlock getCustomBlock(int index) {
int value = getBlockValue(index);
short id = (short) (value & 0xffff);
return id != 0 ? BLOCK_MANAGER.getBlock(id) : null;
@ -171,7 +171,7 @@ public class Chunk implements Viewable {
return getData(index);
}
private Data getData(int index) {
protected Data getData(int 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.instance.batch.BlockBatch;
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.packet.server.play.BlockChangePacket;
import fr.themode.minestom.net.packet.server.play.ParticlePacket;
import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.ChunkUtils;
import fr.themode.minestom.utils.SerializerUtils;
import java.io.File;
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) {
Chunk chunk = getChunkAt(x, z);
synchronized (chunk) {
byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y;
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
sendBlockChange(chunk, x, y, z, blockId);
@ -58,14 +66,34 @@ public class InstanceContainer extends Instance {
byte chunkX = (byte) (x % 16);
byte chunkY = (byte) y;
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();
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
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
public void breakBlock(Player player, BlockPosition 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.instance.Chunk;
import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.utils.SerializerUtils;
import java.util.ArrayList;
import java.util.HashMap;
@ -85,10 +86,11 @@ public class BlockBatch implements InstanceBatch {
private Data data;
public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex((byte) x, (byte) y, (byte) z);
if (!isCustomBlock) {
chunk.UNSAFE_setBlock((byte) x, (byte) y, (byte) z, blockId, data);
chunk.UNSAFE_setBlock(index, blockId, data);
} 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.ChunkGenerator;
import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.utils.SerializerUtils;
import java.util.ArrayList;
import java.util.Collections;
@ -81,10 +82,11 @@ public class ChunkBatch implements InstanceBatch {
private Data data;
public void apply(Chunk chunk) {
int index = SerializerUtils.chunkCoordToIndex(x, y, z);
if (!isCustomBlock) {
chunk.UNSAFE_setBlock(x, y, z, blockId, data);
chunk.UNSAFE_setBlock(index, blockId, data);
} 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");
}
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();

View File

@ -36,7 +36,7 @@ public class BlockPlacementListener {
CustomBlock customBlock = instance.getCustomBlock(blockPosition);
if (customBlock != null) {
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();
DeclareCommandsPacket declareCommandsPacket = commandManager.getDeclareCommandsPacket();
// FIXME
//connection.sendPacket(declareCommandsPacket);
connection.sendPacket(declareCommandsPacket);
}