Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Item functions #587

Open
wants to merge 20 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/main/java/net/glowstone/block/ItemTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@
import net.glowstone.block.blocktype.BlockWeb;
import net.glowstone.block.blocktype.BlockWoodenTrapDoor;
import net.glowstone.block.blocktype.BlockWorkbench;
import net.glowstone.block.function.GlowBlockFunctionHandler;
import net.glowstone.block.function.GlowItemFunctionHandler;
import net.glowstone.block.function.ItemFunction;
import net.glowstone.block.function.ItemFunctionHandler;
import net.glowstone.block.itemtype.ItemArmorStand;
import net.glowstone.block.itemtype.ItemBanner;
import net.glowstone.block.itemtype.ItemBoat;
Expand Down Expand Up @@ -154,11 +158,14 @@ public final class ItemTable {
private static final ItemTable INSTANCE = new ItemTable();

static {
INSTANCE.registerBuiltins();
INSTANCE.init();
}

private final EnumMap<Material, ItemType> materialToType = new EnumMap<>(Material.class);
private final Map<NamespacedKey, ItemType> extraTypes = new HashMap<>();
private final Map<String, ItemFunctionHandler> itemFunctionHandlers = new HashMap<>();
private final ItemFunctionHandler itemFunctionHandler = new GlowItemFunctionHandler();
private final ItemFunctionHandler blockFunctionHandler = new GlowBlockFunctionHandler();
private int nextBlockId;
private int nextItemId;

Expand All @@ -168,6 +175,15 @@ public final class ItemTable {
private ItemTable() {
}

private void init() {
registerBuiltins();
assignHandler("block.place.allow", blockFunctionHandler);
assignHandler("block.interact", blockFunctionHandler);
assignHandler("block.pulse", blockFunctionHandler);
assignHandler("block.pulse.rate", blockFunctionHandler);
assignHandler("block.pulse.multiple", blockFunctionHandler);
}

public static ItemTable instance() {
return INSTANCE;
}
Expand Down Expand Up @@ -627,4 +643,34 @@ public BlockType getBlock(Material mat) {
return null;
}

////////////////////////////////////////////////////////////////////////////
// Functions

/**
* Assigns a function handler to accept new function registrations of this type.
* @param functionality The type of function this function handler accepts
* @param handler The handler
* @return The resultant handler that will be used to handle functions of this type
*/
public ItemFunctionHandler assignHandler(String functionality, ItemFunctionHandler handler) {
return itemFunctionHandlers.putIfAbsent(functionality, handler);
}

/**
* Get the function handler that accepts functions of this type.
* @param functionality The function type
* @return The function handler
*/
public ItemFunctionHandler getFunctionHandler(String functionality) {
return itemFunctionHandlers.get(functionality);
}

/**
* Add this function to the specified item's behavior
* @param item The item
* @param function The function to add
*/
public void addFunction(ItemType item, ItemFunction function) {
itemFunctionHandlers.get(function.getFunctionality()).accept(item, function);
}
}
16 changes: 4 additions & 12 deletions src/main/java/net/glowstone/block/blocktype/BlockAnvil.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
package net.glowstone.block.blocktype;

import java.util.Arrays;
import java.util.Collection;
import net.glowstone.block.GlowBlock;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.inventory.GlowAnvilInventory;
import net.glowstone.inventory.ToolType;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;

import java.util.Arrays;
import java.util.Collection;

public class BlockAnvil extends BlockFalling {

public BlockAnvil() {
super(Material.ANVIL);
}

@Override
public boolean blockInteract(GlowPlayer player, GlowBlock block, BlockFace face,
Vector clickedLoc) {
return player.openInventory(new GlowAnvilInventory(player)) != null;
addFunction(Functions.Interact.ANVIL);
}

@Override
Expand Down
45 changes: 31 additions & 14 deletions src/main/java/net/glowstone/block/blocktype/BlockCactus.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.glowstone.EventFactory;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.GlowBlockState;
import net.glowstone.block.function.BlockFunctions;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
Expand All @@ -14,10 +15,9 @@

public class BlockCactus extends BlockType {

@Override
public boolean canPlaceAt(GlowBlock block, BlockFace against) {
Material below = block.getRelative(BlockFace.DOWN).getType();
return (below == Material.CACTUS || below == Material.SAND) && !hasNearBlocks(block);
public BlockCactus() {
super();
addFunction(Functions.PlaceAllow.CACTUS);
}

@Override
Expand Down Expand Up @@ -75,16 +75,7 @@ public void updateBlock(GlowBlock block) {
}
}

private boolean hasNearBlocks(GlowBlock block) {
for (BlockFace face : SIDES) {
if (!canPlaceNear(block.getRelative(face).getType())) {
return true;
}
}
return false;
}

private boolean canPlaceNear(Material type) {
private static boolean canPlaceNear(Material type) {
// TODO: return true for non-buildable blocks
switch (type) {
case GRASS:
Expand Down Expand Up @@ -133,4 +124,30 @@ public Collection<ItemStack> getDrops(GlowBlock me, ItemStack tool) {
// Overridden for cactus to remove data from the dropped item
return Collections.unmodifiableList(Arrays.asList(new ItemStack(Material.CACTUS)));
}

/**
* Builtin block functions specific to cactus.
*/
public static class Functions {

public static class PlaceAllow {

/**
* Check for allowing place for cactus.
*/
public static final BlockFunctions.BlockFunctionPlaceAllow CACTUS = (block,
against) -> {
Material below = block.getRelative(BlockFace.DOWN).getType();
boolean hasSurroundingBlocks = false;
for (BlockFace face : SIDES) {
if (!canPlaceNear(block.getRelative(face).getType())) {
hasSurroundingBlocks = true;
break;
}
}
return ((below == Material.CACTUS) || below == Material.SAND)
&& !hasSurroundingBlocks;
};
}
}
}
30 changes: 10 additions & 20 deletions src/main/java/net/glowstone/block/blocktype/BlockChest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package net.glowstone.block.blocktype;

import java.util.ArrayList;
import java.util.Collection;
import net.glowstone.GlowServer;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.GlowBlockState;
Expand All @@ -10,14 +8,16 @@
import net.glowstone.chunk.GlowChunk;
import net.glowstone.entity.GlowPlayer;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Chest;
import org.bukkit.material.MaterialData;
import org.bukkit.util.Vector;

import java.util.ArrayList;
import java.util.Collection;

public class BlockChest extends BlockContainer {

private final boolean isTrapped;
Expand All @@ -26,8 +26,15 @@ public BlockChest() {
this(false);
}

/**
* Creates a block type for chest functionality with optional trapped behavior.
*
* @param isTrapped If the chest uses the trapped behavior
*/
public BlockChest(boolean isTrapped) {
super();
this.isTrapped = isTrapped;
addFunction(Functions.Interact.CHEST);
}

private static BlockFace getFacingDirection(BlockFace myFacing, BlockFace otherFacing,
Expand Down Expand Up @@ -115,23 +122,6 @@ public void placeBlock(GlowPlayer player, GlowBlockState state, BlockFace face,
}
}

@Override
public boolean blockInteract(GlowPlayer player, GlowBlock block, BlockFace face,
Vector clickedLoc) {
BlockState state = block.getState();
if (state instanceof org.bukkit.block.Chest) {
org.bukkit.block.Chest chest = (org.bukkit.block.Chest) state;
player.openInventory(chest.getInventory());
player.incrementStatistic(Statistic.CHEST_OPENED);
return true;
}

GlowServer.logger
.warning("Calling blockInteract on BlockChest, but BlockState is " + state);

return false;
}

@Override
public boolean canPlaceAt(GlowBlock block, BlockFace against) {
Collection<BlockFace> nearChests = searchChests(block);
Expand Down
23 changes: 0 additions & 23 deletions src/main/java/net/glowstone/block/blocktype/BlockDoublePlant.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,6 @@ public Collection<ItemStack> getDrops(GlowBlock block, ItemStack tool) {
return BlockDropless.EMPTY_STACK;
}

@Override
public void blockDestroy(GlowPlayer player, GlowBlock block, BlockFace face) {
MaterialData data = block.getState().getData();
if (data instanceof DoublePlant) {
DoublePlantSpecies species = ((DoublePlant) data).getSpecies();
if (species == DoublePlantSpecies.PLANT_APEX) {
GlowBlock blockUnder = block.getRelative(BlockFace.DOWN);
if (!(blockUnder.getState().getData() instanceof DoublePlant)) {
return;
}
blockUnder.setType(Material.AIR);
} else {
GlowBlock blockTop = block.getRelative(BlockFace.UP);
if (!(blockTop.getState().getData() instanceof DoublePlant)) {
return;
}
blockTop.setType(Material.AIR);
}
} else {
warnMaterialData(DoublePlant.class, data);
}
}

@Override
public boolean isFertilizable(GlowBlock block) {
MaterialData data = block.getState().getData();
Expand Down
49 changes: 12 additions & 37 deletions src/main/java/net/glowstone/block/blocktype/BlockJukebox.java
Original file line number Diff line number Diff line change
@@ -1,54 +1,29 @@
package net.glowstone.block.blocktype;

import java.util.Arrays;
import java.util.Collection;
import net.glowstone.block.GlowBlock;
import net.glowstone.block.entity.BlockEntity;
import net.glowstone.block.entity.JukeboxEntity;
import net.glowstone.block.entity.state.GlowJukebox;
import net.glowstone.chunk.GlowChunk;
import net.glowstone.entity.GlowPlayer;
import org.bukkit.GameMode;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Jukebox;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;

public class BlockJukebox extends BlockType {
import java.util.Arrays;
import java.util.Collection;

@Override
public BlockEntity createBlockEntity(GlowChunk chunk, int cx, int cy, int cz) {
return new JukeboxEntity(chunk.getBlock(cx, cy, cz));
}
public class BlockJukebox extends BlockType {

@Override
public boolean blockInteract(GlowPlayer player, GlowBlock block, BlockFace face,
Vector clickedLoc) {
Jukebox jukebox = (Jukebox) block.getState();
if (jukebox.isPlaying()) {
jukebox.eject();
jukebox.update();
return true;
}
ItemStack handItem = player.getItemInHand();
if (handItem != null && handItem.getType().isRecord()) {
jukebox.setPlaying(handItem.getType());
jukebox.update();
if (player.getGameMode() != GameMode.CREATIVE) {
handItem.setAmount(handItem.getAmount() - 1);
player.setItemInHand(handItem);
}
return true;
}
return false;
/**
* Creates a block type with jukebox functionality.
*/
public BlockJukebox() {
super();
addFunction(Functions.Interact.JUKEBOX);
addFunction(Functions.Destroy.JUKEBOX);
}

@Override
public void blockDestroy(GlowPlayer player, GlowBlock block, BlockFace face) {
Jukebox jukebox = (Jukebox) block.getState();
if (jukebox.eject()) {
jukebox.update();
}
public BlockEntity createBlockEntity(GlowChunk chunk, int cx, int cy, int cz) {
return new JukeboxEntity(chunk.getBlock(cx, cy, cz));
}

@Override
Expand Down