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:
jglrxavpok 2020-05-05 15:55:21 +02:00
parent 486cf989a1
commit 365c3edbdf
8 changed files with 321 additions and 4 deletions

View File

@ -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());

View File

@ -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)

View 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;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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) {}
}

View File

@ -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();