mirror of
https://github.com/Minestom/Minestom.git
synced 2024-09-27 14:13:24 +02:00
Custom block contact behaviour + fix breaking of 0 hardness blocks not removing the block in survival, fixed players in survival not taking damage.
This commit is contained in:
parent
486cf989a1
commit
365c3edbdf
@ -1,6 +1,7 @@
|
||||
package fr.themode.demo;
|
||||
|
||||
import fr.themode.demo.blocks.StoneBlock;
|
||||
import fr.themode.demo.blocks.BurningTorchBlock;
|
||||
import fr.themode.demo.blocks.UpdatableBlockDemo;
|
||||
import fr.themode.demo.commands.GamemodeCommand;
|
||||
import fr.themode.demo.commands.HealthCommand;
|
||||
@ -30,6 +31,7 @@ public class Main {
|
||||
BlockManager blockManager = MinecraftServer.getBlockManager();
|
||||
blockManager.registerCustomBlock(new StoneBlock());
|
||||
blockManager.registerCustomBlock(new UpdatableBlockDemo());
|
||||
blockManager.registerCustomBlock(new BurningTorchBlock());
|
||||
|
||||
blockManager.registerBlockPlacementRule(new RedstonePlacementRule());
|
||||
|
||||
|
@ -114,6 +114,9 @@ public class PlayerInit {
|
||||
if (event.getBlockId() == Block.STONE.getBlockId()) {
|
||||
event.setCustomBlockId((short) 2); // custom stone block
|
||||
}
|
||||
if (event.getBlockId() == Block.TORCH.getBlockId()) {
|
||||
event.setCustomBlockId((short) 3); // custom torch block
|
||||
}
|
||||
|
||||
/*for (Player p : player.getInstance().getPlayers()) {
|
||||
if (p != player)
|
||||
|
53
src/main/java/fr/themode/demo/blocks/BurningTorchBlock.java
Normal file
53
src/main/java/fr/themode/demo/blocks/BurningTorchBlock.java
Normal file
@ -0,0 +1,53 @@
|
||||
package fr.themode.demo.blocks;
|
||||
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
|
||||
/**
|
||||
* Custom block which burns entities that touch it
|
||||
*/
|
||||
public class BurningTorchBlock extends CustomBlock {
|
||||
public BurningTorchBlock() {
|
||||
super(Block.TORCH.getBlockId(), "torch_block");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleContact(Instance instance, BlockPosition position, Entity touching) {
|
||||
System.out.println("touching "+touching);
|
||||
if(touching instanceof LivingEntity) {
|
||||
((LivingEntity) touching).damage(DamageType.GRAVITY, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlace(Instance instance, BlockPosition blockPosition, Data data) {
|
||||
System.out.println(blockPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(Instance instance, BlockPosition blockPosition, Data data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInteract(Player player, Player.Hand hand, BlockPosition blockPosition, Data data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getCustomBlockId() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player, BlockPosition position) {
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import net.minestom.server.event.Event;
|
||||
import net.minestom.server.event.EventCallback;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
@ -278,6 +280,32 @@ public abstract class Entity implements Viewable, DataContainer {
|
||||
}
|
||||
}
|
||||
|
||||
// handle block contacts
|
||||
int minX = (int) Math.floor(boundingBox.getMinX());
|
||||
int maxX = (int) Math.ceil(boundingBox.getMaxX());
|
||||
int minY = (int) Math.floor(boundingBox.getMinY());
|
||||
int maxY = (int) Math.ceil(boundingBox.getMaxY());
|
||||
int minZ = (int) Math.floor(boundingBox.getMinZ());
|
||||
int maxZ = (int) Math.ceil(boundingBox.getMaxZ());
|
||||
BlockPosition tmpPosition = new BlockPosition(0,0,0); // allow reuse
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
CustomBlock customBlock = instance.getCustomBlock(x, y, z);
|
||||
if(customBlock != null) {
|
||||
tmpPosition.setX(x);
|
||||
tmpPosition.setY(y);
|
||||
tmpPosition.setZ(z);
|
||||
// checks that we are actually in the block, and not just here because of a rounding error
|
||||
if(boundingBox.intersect(tmpPosition)) {
|
||||
// TODO: replace with check with custom block bounding box
|
||||
customBlock.handleContact(instance, tmpPosition, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleVoid();
|
||||
|
||||
// Call the abstract update method
|
||||
|
@ -476,7 +476,7 @@ public class Player extends LivingEntity {
|
||||
|
||||
@Override
|
||||
public boolean isImmune(DamageType type) {
|
||||
if (getGameMode().canTakeDamage()) {
|
||||
if (!getGameMode().canTakeDamage()) {
|
||||
return type != DamageType.VOID;
|
||||
}
|
||||
return super.isImmune(type);
|
||||
|
@ -1362,6 +1362,208 @@ public enum Block {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean breaksInstantaneously() {
|
||||
// from https://minecraft.gamepedia.com/Breaking#Instant_breaking
|
||||
switch (this) {
|
||||
// circuits
|
||||
case COMPARATOR:
|
||||
case REPEATER:
|
||||
case REDSTONE_TORCH:
|
||||
case REDSTONE_WIRE:
|
||||
case TRIPWIRE:
|
||||
case TRIPWIRE_HOOK:
|
||||
|
||||
// other
|
||||
case FIRE:
|
||||
case INFESTED_STONE:
|
||||
case TNT:
|
||||
case TORCH:
|
||||
case SCAFFOLDING:
|
||||
case SLIME_BLOCK:
|
||||
case HONEY_BLOCK:
|
||||
|
||||
// plants
|
||||
case BEETROOTS:
|
||||
case CARROTS:
|
||||
case DEAD_BUSH:
|
||||
case FERN:
|
||||
case KELP:
|
||||
case LILY_PAD:
|
||||
case MELON_STEM:
|
||||
case ATTACHED_MELON_STEM:
|
||||
case NETHER_WART:
|
||||
case POTATOES:
|
||||
case PUMPKIN_STEM:
|
||||
case ATTACHED_PUMPKIN_STEM:
|
||||
case SEAGRASS:
|
||||
case TALL_SEAGRASS:
|
||||
case SEA_PICKLE:
|
||||
case SUGAR_CANE:
|
||||
case TALL_GRASS:
|
||||
case WHEAT:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return isFlowerPot() || isSapling() || isCoral() || isFlower() || isMushroom();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCoral() {
|
||||
switch (this) {
|
||||
case DEAD_TUBE_CORAL_BLOCK:
|
||||
case DEAD_BRAIN_CORAL_BLOCK:
|
||||
case DEAD_BUBBLE_CORAL_BLOCK:
|
||||
case DEAD_FIRE_CORAL_BLOCK:
|
||||
case DEAD_HORN_CORAL_BLOCK:
|
||||
case TUBE_CORAL_BLOCK:
|
||||
case BRAIN_CORAL_BLOCK:
|
||||
case BUBBLE_CORAL_BLOCK:
|
||||
case FIRE_CORAL_BLOCK:
|
||||
case HORN_CORAL_BLOCK:
|
||||
case DEAD_TUBE_CORAL:
|
||||
case DEAD_BRAIN_CORAL:
|
||||
case DEAD_BUBBLE_CORAL:
|
||||
case DEAD_FIRE_CORAL:
|
||||
case DEAD_HORN_CORAL:
|
||||
case TUBE_CORAL:
|
||||
case BRAIN_CORAL:
|
||||
case BUBBLE_CORAL:
|
||||
case FIRE_CORAL:
|
||||
case HORN_CORAL:
|
||||
case DEAD_TUBE_CORAL_FAN:
|
||||
case DEAD_BRAIN_CORAL_FAN:
|
||||
case DEAD_BUBBLE_CORAL_FAN:
|
||||
case DEAD_FIRE_CORAL_FAN:
|
||||
case DEAD_HORN_CORAL_FAN:
|
||||
case TUBE_CORAL_FAN:
|
||||
case BRAIN_CORAL_FAN:
|
||||
case BUBBLE_CORAL_FAN:
|
||||
case FIRE_CORAL_FAN:
|
||||
case HORN_CORAL_FAN:
|
||||
case DEAD_TUBE_CORAL_WALL_FAN:
|
||||
case DEAD_BRAIN_CORAL_WALL_FAN:
|
||||
case DEAD_BUBBLE_CORAL_WALL_FAN:
|
||||
case DEAD_FIRE_CORAL_WALL_FAN:
|
||||
case DEAD_HORN_CORAL_WALL_FAN:
|
||||
case TUBE_CORAL_WALL_FAN:
|
||||
case BRAIN_CORAL_WALL_FAN:
|
||||
case BUBBLE_CORAL_WALL_FAN:
|
||||
case FIRE_CORAL_WALL_FAN:
|
||||
case HORN_CORAL_WALL_FAN:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlower() {
|
||||
switch (this) {
|
||||
case ALLIUM:
|
||||
case AZURE_BLUET:
|
||||
case BLUE_ORCHID:
|
||||
case CORNFLOWER:
|
||||
case DANDELION:
|
||||
case LILY_OF_THE_VALLEY:
|
||||
case ORANGE_TULIP:
|
||||
case OXEYE_DAISY:
|
||||
case PINK_TULIP:
|
||||
case POPPY:
|
||||
case RED_TULIP:
|
||||
case WHITE_TULIP:
|
||||
case WITHER_ROSE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMushroom() {
|
||||
switch (this) {
|
||||
case POTTED_SPRUCE_SAPLING:
|
||||
case POTTED_BIRCH_SAPLING:
|
||||
case POTTED_JUNGLE_SAPLING:
|
||||
case POTTED_ACACIA_SAPLING:
|
||||
case POTTED_OAK_SAPLING:
|
||||
case POTTED_DARK_OAK_SAPLING:
|
||||
case POTTED_ALLIUM:
|
||||
case POTTED_AZURE_BLUET:
|
||||
case POTTED_BAMBOO:
|
||||
case POTTED_BLUE_ORCHID:
|
||||
case POTTED_BROWN_MUSHROOM:
|
||||
case POTTED_CACTUS:
|
||||
case POTTED_CORNFLOWER:
|
||||
case POTTED_DANDELION:
|
||||
case POTTED_DEAD_BUSH:
|
||||
case POTTED_FERN:
|
||||
case POTTED_LILY_OF_THE_VALLEY:
|
||||
case POTTED_ORANGE_TULIP:
|
||||
case POTTED_OXEYE_DAISY:
|
||||
case POTTED_PINK_TULIP:
|
||||
case POTTED_POPPY:
|
||||
case POTTED_RED_MUSHROOM:
|
||||
case POTTED_RED_TULIP:
|
||||
case POTTED_WHITE_TULIP:
|
||||
case POTTED_WITHER_ROSE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlowerPot() {
|
||||
switch (this) {
|
||||
case POTTED_SPRUCE_SAPLING:
|
||||
case POTTED_BIRCH_SAPLING:
|
||||
case POTTED_JUNGLE_SAPLING:
|
||||
case POTTED_ACACIA_SAPLING:
|
||||
case POTTED_OAK_SAPLING:
|
||||
case POTTED_DARK_OAK_SAPLING:
|
||||
case POTTED_ALLIUM:
|
||||
case POTTED_AZURE_BLUET:
|
||||
case POTTED_BAMBOO:
|
||||
case POTTED_BLUE_ORCHID:
|
||||
case POTTED_BROWN_MUSHROOM:
|
||||
case POTTED_CACTUS:
|
||||
case POTTED_CORNFLOWER:
|
||||
case POTTED_DANDELION:
|
||||
case POTTED_DEAD_BUSH:
|
||||
case POTTED_FERN:
|
||||
case POTTED_LILY_OF_THE_VALLEY:
|
||||
case POTTED_ORANGE_TULIP:
|
||||
case POTTED_OXEYE_DAISY:
|
||||
case POTTED_PINK_TULIP:
|
||||
case POTTED_POPPY:
|
||||
case POTTED_RED_MUSHROOM:
|
||||
case POTTED_RED_TULIP:
|
||||
case POTTED_WHITE_TULIP:
|
||||
case POTTED_WITHER_ROSE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isSapling() {
|
||||
switch (this) {
|
||||
case SPRUCE_SAPLING:
|
||||
case BIRCH_SAPLING:
|
||||
case JUNGLE_SAPLING:
|
||||
case ACACIA_SAPLING:
|
||||
case BAMBOO_SAPLING:
|
||||
case OAK_SAPLING:
|
||||
case DARK_OAK_SAPLING:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlockAlternative> getBlockAlternatives() {
|
||||
return Collections.unmodifiableList(blockAlternatives);
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package net.minestom.server.instance.block;
|
||||
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.querz.nbt.CompoundTag;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@ -73,6 +75,15 @@ public abstract class CustomBlock {
|
||||
return updateOption.getValue() > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines custom behaviour for entities touching this block.
|
||||
* @param instance
|
||||
* @param position the position at which the block is
|
||||
* @param touching the entity currently touching the block
|
||||
*/
|
||||
public void handleContact(Instance instance, BlockPosition position, Entity touching) {}
|
||||
|
||||
public short getBlockId() {
|
||||
return blockId;
|
||||
}
|
||||
@ -100,7 +111,7 @@ public abstract class CustomBlock {
|
||||
* @param directNeighbor is the neighbor directly connected to this block? (No diagonals)
|
||||
*/
|
||||
public void updateFromNeighbor(Instance instance, BlockPosition thisPosition, BlockPosition neighborPosition, boolean directNeighbor) {
|
||||
if(directNeighbor) {
|
||||
if(directNeighbor && hasUpdate()) {
|
||||
update(instance, thisPosition, instance.getBlockData(thisPosition));
|
||||
}
|
||||
}
|
||||
@ -114,4 +125,12 @@ public abstract class CustomBlock {
|
||||
public void scheduledUpdate(Instance instance, BlockPosition position, Data blockData) {
|
||||
update(instance, position, blockData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows custom block to write block entity data to a given NBT compound
|
||||
* @param instance instance of which the block lives
|
||||
* @param position position of the block
|
||||
* @param blockData equivalent to <pre>instance.getBlockData(position)</pre>
|
||||
*/
|
||||
public void writeBlockEntity(Instance instance, BlockPosition position, Data blockData, CompoundTag nbt) {}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.minestom.server.event.ItemUpdateStateEvent;
|
||||
import net.minestom.server.event.PlayerStartDiggingEvent;
|
||||
import net.minestom.server.event.PlayerSwapItemEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.inventory.PlayerInventory;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
@ -19,6 +20,7 @@ import net.minestom.server.utils.BlockPosition;
|
||||
public class PlayerDiggingListener {
|
||||
|
||||
public static void playerDiggingListener(ClientPlayerDiggingPacket packet, Player player) {
|
||||
System.out.println(">> "+packet.status.name());
|
||||
ClientPlayerDiggingPacket.Status status = packet.status;
|
||||
BlockPosition blockPosition = packet.blockPosition;
|
||||
|
||||
@ -51,8 +53,16 @@ public class PlayerDiggingListener {
|
||||
}
|
||||
addEffect(player);
|
||||
} else {
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
if(Block.fromId(instance.getBlockId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ())).breaksInstantaneously()) {
|
||||
if (player.getCustomBlockTarget() != null) {
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
}
|
||||
instance.breakBlock(player, blockPosition);
|
||||
} else {
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.resetTargetBlock();
|
||||
|
Loading…
Reference in New Issue
Block a user