Added redstone placement

This commit is contained in:
Felix Cravic 2020-04-12 10:24:25 +02:00
parent a8f48aafe9
commit 126d778221
8 changed files with 143 additions and 8 deletions

View File

@ -7,6 +7,7 @@ import fr.themode.demo.commands.SimpleCommand;
import fr.themode.minestom.MinecraftServer; import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.command.CommandManager; import fr.themode.minestom.command.CommandManager;
import fr.themode.minestom.instance.block.BlockManager; import fr.themode.minestom.instance.block.BlockManager;
import fr.themode.minestom.instance.block.rule.vanilla.RedstonePlacementRule;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.item.Material; import fr.themode.minestom.item.Material;
import fr.themode.minestom.net.packet.server.play.DeclareRecipesPacket; import fr.themode.minestom.net.packet.server.play.DeclareRecipesPacket;
@ -23,6 +24,8 @@ public class Main {
blockManager.registerCustomBlock(new StoneBlock()); blockManager.registerCustomBlock(new StoneBlock());
blockManager.registerCustomBlock(new UpdatableBlockDemo()); blockManager.registerCustomBlock(new UpdatableBlockDemo());
blockManager.registerBlockPlacementRule(new RedstonePlacementRule());
CommandManager commandManager = MinecraftServer.getCommandManager(); CommandManager commandManager = MinecraftServer.getCommandManager();
commandManager.register(new HealthCommand()); commandManager.register(new HealthCommand());
commandManager.register(new SimpleCommand()); commandManager.register(new SimpleCommand());

View File

@ -90,7 +90,6 @@ public class Chunk implements Viewable {
} }
private void setBlock(int index, short blockId, short customId, Data data, UpdateConsumer updateConsumer) { private void setBlock(int index, short blockId, short customId, Data data, UpdateConsumer updateConsumer) {
if (blockId != 0 if (blockId != 0
|| (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found || (blockId == 0 && customId != 0 && updateConsumer != null)) { // Allow custom air block for update purpose, refused if no update consumer has been found
refreshBlockValue(index, blockId, customId); refreshBlockValue(index, blockId, customId);

View File

@ -7,6 +7,7 @@ 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.instance.block.CustomBlock;
import fr.themode.minestom.instance.block.rule.BlockPlacementRule;
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;
@ -52,8 +53,14 @@ public class InstanceContainer extends Instance {
callBlockDestroy(chunk, index, x, y, z); callBlockDestroy(chunk, index, x, y, z);
BlockPosition blockPosition = new BlockPosition(x, y, z);
blockId = executeBlockPlacementRule(blockId, blockPosition);
chunk.UNSAFE_setBlock(index, blockId, data); chunk.UNSAFE_setBlock(index, blockId, data);
executeNeighboursBlockPlacementRule(blockId, blockPosition);
// 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);
} }
@ -70,12 +77,18 @@ public class InstanceContainer extends Instance {
callBlockDestroy(chunk, index, x, y, z); callBlockDestroy(chunk, index, x, y, z);
BlockPosition blockPosition = new BlockPosition(x, y, z);
blockId = executeBlockPlacementRule(blockId, blockPosition);
chunk.UNSAFE_setCustomBlock(index, blockId, data); chunk.UNSAFE_setCustomBlock(index, blockId, data);
short id = BLOCK_MANAGER.getBlock(blockId).getType();
executeNeighboursBlockPlacementRule(blockId, blockPosition);
callBlockPlace(chunk, index, x, y, z); 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
short id = BLOCK_MANAGER.getBlock(blockId).getType();
sendBlockChange(chunk, x, y, z, id); sendBlockChange(chunk, x, y, z, id);
} }
} }
@ -110,6 +123,38 @@ public class InstanceContainer extends Instance {
actualBlock.onPlace(this, new BlockPosition(x, y, z), previousData); actualBlock.onPlace(this, new BlockPosition(x, y, z), previousData);
} }
private short executeBlockPlacementRule(short blockId, BlockPosition blockPosition) {
BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(blockId);
if (blockPlacementRule != null) {
return blockPlacementRule.blockRefresh(this, blockPosition);
}
return blockId;
}
private void executeNeighboursBlockPlacementRule(short blockId, BlockPosition blockPosition) {
for (int offsetX = -1; offsetX < 2; offsetX++) {
for (int offsetY = -1; offsetY < 2; offsetY++) {
for (int offsetZ = -1; offsetZ < 2; offsetZ++) {
if (offsetX == 0 && offsetY == 0 && offsetZ == 0)
continue;
int neighborX = blockPosition.getX() + offsetX;
int neighborY = blockPosition.getY() + offsetY;
int neighborZ = blockPosition.getZ() + offsetZ;
short neighborId = getBlockId(neighborX, neighborY, neighborZ);
BlockPlacementRule neighborBlockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(neighborId);
if (neighborBlockPlacementRule != null) {
short newNeighborId = neighborBlockPlacementRule.blockRefresh(this,
new BlockPosition(neighborX, neighborY, neighborZ));
if (neighborId != newNeighborId) {
refreshBlockId(neighborX, neighborY, neighborZ, newNeighborId);
}
}
}
}
}
}
@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

@ -1,5 +1,7 @@
package fr.themode.minestom.instance.block; package fr.themode.minestom.instance.block;
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -688,6 +690,12 @@ public enum Block {
HONEY_BLOCK, HONEY_BLOCK,
HONEYCOMB_BLOCK; HONEYCOMB_BLOCK;
private static Short2ObjectOpenHashMap<Block> blocksMap = new Short2ObjectOpenHashMap<>();
public static Block getBlockFromId(short blockId) {
return blocksMap.getOrDefault(blockId, AIR);
}
private short blockId; private short blockId;
private List<BlockAlternative> blockAlternatives = new ArrayList<>(); private List<BlockAlternative> blockAlternatives = new ArrayList<>();
@ -697,6 +705,7 @@ public enum Block {
public void addBlockAlternative(short id, String... properties) { public void addBlockAlternative(short id, String... properties) {
this.blockAlternatives.add(new BlockAlternative(id, properties)); this.blockAlternatives.add(new BlockAlternative(id, properties));
blocksMap.put(id, this);
} }
public short withProperties(String... properties) { public short withProperties(String... properties) {
@ -705,8 +714,8 @@ public enum Block {
return blockAlternative.id; return blockAlternative.id;
} }
} }
// No id found // No id found, return default
return 0; return blockId;
} }
public short getBlockId() { public short getBlockId() {
@ -734,5 +743,13 @@ public enum Block {
public String[] getProperties() { public String[] getProperties() {
return properties; return properties;
} }
@Override
public String toString() {
return "BlockAlternative{" +
"id=" + id +
", properties=" + Arrays.toString(properties) +
'}';
}
} }
} }

View File

@ -25,6 +25,11 @@ public class BlockManager {
this.placementRules.put(blockPlacementRule.getBlock(), blockPlacementRule); this.placementRules.put(blockPlacementRule.getBlock(), blockPlacementRule);
} }
public BlockPlacementRule getBlockPlacementRule(short blockId) {
Block block = Block.getBlockFromId(blockId);
return this.placementRules.get(block);
}
public CustomBlock getBlock(String identifier) { public CustomBlock getBlock(String identifier) {
return blocksId.get(identifier); return blocksId.get(identifier);
} }

View File

@ -12,9 +12,7 @@ public abstract class BlockPlacementRule {
this.block = block; this.block = block;
} }
public abstract void onPlace(Instance instance, BlockPosition blockPosition); public abstract short blockRefresh(Instance instance, BlockPosition blockPosition);
public abstract void onNeighborPlace(Instance instance, int offsetX, int offsetY, int offsetZ);
public Block getBlock() { public Block getBlock() {
return block; return block;

View File

@ -0,0 +1,68 @@
package fr.themode.minestom.instance.block.rule.vanilla;
import fr.themode.minestom.instance.Instance;
import fr.themode.minestom.instance.block.Block;
import fr.themode.minestom.instance.block.rule.BlockPlacementRule;
import fr.themode.minestom.utils.BlockPosition;
public class RedstonePlacementRule extends BlockPlacementRule {
public RedstonePlacementRule() {
super(Block.REDSTONE_WIRE);
}
@Override
public short blockRefresh(Instance instance, BlockPosition blockPosition) {
int x = blockPosition.getX();
int y = blockPosition.getY();
int z = blockPosition.getZ();
String east = "none";
String north = "none";
String power = "0";
String south = "none";
String west = "none";
if (isRedstone(instance, x + 1, y + 1, z)) {
east = "up";
} else if (isRedstone(instance, x + 1, y, z)) {
east = "side";
} else if (isRedstone(instance, x + 1, y - 1, z)) {
east = "side";
}
if (isRedstone(instance, x - 1, y + 1, z)) {
west = "up";
} else if (isRedstone(instance, x - 1, y, z)) {
west = "side";
} else if (isRedstone(instance, x - 1, y - 1, z)) {
west = "side";
}
if (isRedstone(instance, x, y + 1, z + 1)) {
south = "up";
} else if (isRedstone(instance, x, y, z + 1)) {
south = "side";
} else if (isRedstone(instance, x, y - 1, z + 1)) {
south = "side";
}
if (isRedstone(instance, x, y + 1, z - 1)) {
north = "up";
} else if (isRedstone(instance, x, y, z - 1)) {
north = "side";
} else if (isRedstone(instance, x, y - 1, z - 1)) {
north = "side";
}
return Block.REDSTONE_WIRE.withProperties(east, north, power, south, west);
}
private boolean isRedstone(Instance instance, int x, int y, int z) {
short blockId = instance.getBlockId(x, y, z);
return Block.getBlockFromId(blockId) == Block.REDSTONE_WIRE;
}
}

View File

@ -45,7 +45,7 @@ public class RegistryMain {
for (RegistryBlock.BlockState blockState : registryBlock.states) { for (RegistryBlock.BlockState blockState : registryBlock.states) {
short id = blockState.id; short id = blockState.id;
String[] properties = blockState.propertiesValues.toArray(new String[registryBlock.states.size()]); String[] properties = blockState.propertiesValues.toArray(new String[blockState.propertiesValues.size()]);
block.addBlockAlternative(id, properties); block.addBlockAlternative(id, properties);
} }
} }