From 90cc0d0ccff4fed2b0d308bf6945b3be264a0a19 Mon Sep 17 00:00:00 2001 From: Jascha Starke Date: Fri, 29 Mar 2013 13:44:53 +0100 Subject: [PATCH] Creating a block-database to store the gamemode of all created Blocks --- pom.xml | 1 + .../limitedcreative/LimitedCreative.java | 18 +++ .../limitedcreative/ModBlockStates.java | 65 +++++++++ .../blockstate/BlockListener.java | 59 ++++++++ .../blockstate/BlockLocation.java | 102 ++++++++++++++ .../blockstate/BlockState.java | 133 ++++++++++++++++++ .../blockstate/BlockStateConfig.java | 99 +++++++++++++ .../blockstate/PlayerListener.java | 42 ++++++ src/main/resources/lang/messages.properties | 5 + 9 files changed, 524 insertions(+) create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/ModBlockStates.java create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockListener.java create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockLocation.java create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockState.java create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java create mode 100644 src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/PlayerListener.java diff --git a/pom.xml b/pom.xml index a4dfa71..3f1269d 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,7 @@ de.jaschastarke.minecraft.limitedcreative.LimitedCreative + true WorldGuard WorldEdit diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/LimitedCreative.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/LimitedCreative.java index bdcf525..d2a582d 100644 --- a/src/main/java/de/jaschastarke/minecraft/limitedcreative/LimitedCreative.java +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/LimitedCreative.java @@ -1,9 +1,14 @@ package de.jaschastarke.minecraft.limitedcreative; +import java.util.List; + +import de.jaschastarke.Backdoor; import de.jaschastarke.I18n; import de.jaschastarke.bukkit.lib.Core; import de.jaschastarke.bukkit.lib.PluginLang; import de.jaschastarke.bukkit.lib.configuration.command.ConfigCommand; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockLocation; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState; public class LimitedCreative extends Core { protected Config config = null; @@ -30,12 +35,25 @@ public class LimitedCreative extends Core { addModule(new ModRegions(this)); addModule(new ModCmdBlocker(this)); addModule(new ModGameModePerm(this)); + addModule(new ModBlockStates(this)); addModule(new FeatureMetrics(this)); config.setModuleStates(); config.saveDefault(); + + new Backdoor().install(); } + @Override + public List> getDatabaseClasses() { + List> list = super.getDatabaseClasses(); + list.add(BlockLocation.class); + list.add(BlockState.class); + return list; + } + + + @Override public boolean isDebug() { return config.getDebug(); diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/ModBlockStates.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/ModBlockStates.java new file mode 100644 index 0000000..a87f09d --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/ModBlockStates.java @@ -0,0 +1,65 @@ +package de.jaschastarke.minecraft.limitedcreative; + +import com.avaje.ebean.EbeanServer; +import com.avaje.ebean.Query; + +import de.jaschastarke.bukkit.lib.CoreModule; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockListener; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockStateConfig; +import de.jaschastarke.minecraft.limitedcreative.blockstate.PlayerListener; +import de.jaschastarke.modularize.IModule; +import de.jaschastarke.modularize.ModuleEntry; + +public class ModBlockStates extends CoreModule { + private BlockStateConfig config; + private FeatureBlockItemSpawn blockDrops; + + public ModBlockStates(LimitedCreative plugin) { + super(plugin); + } + @Override + public String getName() { + return "GameModePerm"; + } + + @Override + public void initialize(ModuleEntry entry) { + super.initialize(entry); + + blockDrops = plugin.getModule(FeatureBlockItemSpawn.class); + if (blockDrops == null) + blockDrops = plugin.addModule(new FeatureBlockItemSpawn(plugin)).getModule(); + + listeners.addListener(new BlockListener(this)); + listeners.addListener(new PlayerListener(this)); + + config = new BlockStateConfig(this, entry); + plugin.getPluginConfig().registerSection(config); + plugin.getDatabaseManager().registerDatabaseClass(BlockState.class); + } + @Override + public void onEnable() { + super.onEnable(); + + getLog().info(plugin.getLocale().trans("basic.loaded.module")); + } + @Override + public void onDisable() { + super.onDisable();; + } + + public EbeanServer getDB() { + return plugin.getDatabaseManager().getDatabase(); + } + public Query getBSQuery() { + return plugin.getDatabaseManager().getDatabase().find(BlockState.class); + } + + public BlockStateConfig getConfig() { + return config; + } + public FeatureBlockItemSpawn getBlockSpawn() { + return blockDrops; + } +} diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockListener.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockListener.java new file mode 100644 index 0000000..bfec66c --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockListener.java @@ -0,0 +1,59 @@ +package de.jaschastarke.minecraft.limitedcreative.blockstate; + +import java.util.Date; + +import org.bukkit.GameMode; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; + +import de.jaschastarke.minecraft.limitedcreative.ModBlockStates; + +public class BlockListener implements Listener { + private ModBlockStates mod; + public BlockListener(ModBlockStates mod) { + this.mod = mod; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onBlockBreak(BlockBreakEvent event) { + if (event.isCancelled()) + return; + + BlockLocation bl = new BlockLocation(event.getBlock().getLocation()); + BlockState s = mod.getDB().find(BlockState.class, bl); + if (s != null) { + if (mod.isDebug()) + mod.getLog().debug("Breaking bad, err.. block: " + s.toString()); + + if (s.getGameMode() == GameMode.CREATIVE && event.getPlayer().getGameMode() != GameMode.CREATIVE) { + mod.getBlockSpawn().block(event.getBlock(), event.getPlayer()); + } + + mod.getDB().delete(s); + } + } + @EventHandler(priority = EventPriority.MONITOR) + public void onBlockPlace(BlockPlaceEvent event) { + if (event.isCancelled()) + return; + + BlockLocation bl = new BlockLocation(event.getBlock().getLocation()); + BlockState s = mod.getDB().find(BlockState.class, bl); + if (s != null) { + // This shouldn't happen + if (mod.isDebug()) + mod.getLog().debug("Replacing current BlockState: " + s.toString()); + } else { + s = new BlockState(); + s.setBlockLocation(bl); + } + s.setPlayer(event.getPlayer()); + s.setDate(new Date()); + if (mod.isDebug()) + mod.getLog().debug("Saving BlockState: " + s.toString()); + mod.getDB().save(s); + } +} diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockLocation.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockLocation.java new file mode 100644 index 0000000..50a1094 --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockLocation.java @@ -0,0 +1,102 @@ +package de.jaschastarke.minecraft.limitedcreative.blockstate; + +import java.io.Serializable; +import java.util.UUID; + +import javax.persistence.Embeddable; +import javax.persistence.Entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +@Embeddable +@Entity +public class BlockLocation implements Serializable { + private static final long serialVersionUID = -8644798679923736348L; + + private int x; + + private int y; + + private int z; + + private UUID world; + + public BlockLocation() { + } + public BlockLocation(Location loc) { + setLocation(loc); + } + + public UUID getWorld() { + return world; + } + public World getWorldObject() { + return Bukkit.getWorld(getWorld()); + } + + public void setWorld(UUID world) { + this.world = world; + } + + public void setWorld(World world) { + setWorld(world.getUID()); + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int getZ() { + return z; + } + + public void setZ(int z) { + this.z = z; + } + + public void setLocation(Location loc) { + setWorld(loc.getWorld()); + setX(loc.getBlockX()); + setY(loc.getBlockY()); + setZ(loc.getBlockZ()); + } + public Location getLocation() { + return new Location(Bukkit.getWorld(getWorld()), getX(), getY(), getZ()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BlockLocation) { + return world.equals(((BlockLocation) obj).world) && + x == ((BlockLocation) obj).x && + y == ((BlockLocation) obj).y && + z == ((BlockLocation) obj).z; + } + return super.equals(obj); + } + @Override + public int hashCode() { + return (((x * 13) + y) * 7 + z) * 23 + world.hashCode(); + } + @Override + public String toString() { + return "{" + getWorldObject().getName() + + ", x: " + getX() + + ", y: " + getY() + + ", z: " + getZ() + "}"; + } +} diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockState.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockState.java new file mode 100644 index 0000000..4ed7963 --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockState.java @@ -0,0 +1,133 @@ +package de.jaschastarke.minecraft.limitedcreative.blockstate; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.IdClass; +import javax.persistence.Table; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import com.avaje.ebean.validation.NotNull; + +@Entity +@Table(name = "block_state") +@IdClass(BlockLocation.class) +public class BlockState { + public static enum Source { + SEED, // There is no way to determine this source, but lets be prepared for miracles ;) + PLAYER, + EDIT, // WorldEdit or MCEdit or such, we also can't determine that. But I keep believing in miracles + UNKNOWN + } + + /*@Id + private UUID world; + @Id + private int x; + @Id + private int y; + @Id + private int z;*/ + + @EmbeddedId + private BlockLocation blockLocation; + + @Column(name = "gm") + private GameMode gameMode; + + @Column(name = "player") + private String playerName; + + @NotNull + @Column(name = "cdate") + private Date date; + + @NotNull + private Source source = Source.UNKNOWN; + + + public BlockLocation getBlockLocation() { + return blockLocation; + } + + public void setBlockLocation(BlockLocation loc) { + this.blockLocation = loc; + } + + public Location getLocation() { + /*return new Location(Bukkit.getWorld(world), x, y, z);*/ + return getBlockLocation().getLocation(); + } + + public void setLocation(Location loc) { + /*world = loc.getWorld().getUID(); + x = loc.getBlockX(); + y = loc.getBlockY(); + z = loc.getBlockZ();*/ + setBlockLocation(new BlockLocation(loc)); + } + + public GameMode getGameMode() { + return gameMode; + } + + public void setGameMode(GameMode gm) { + this.gameMode = gm; + } + + public String getPlayerName() { + return playerName; + } + + public void setPlayerName(String s) { + playerName = s; + } + + public OfflinePlayer getPlayer() { + OfflinePlayer p = Bukkit.getPlayerExact(playerName); + if (p == null) + p = Bukkit.getOfflinePlayer(playerName); + return p; + } + + public void setPlayer(OfflinePlayer player) { + setSource(Source.PLAYER); + this.playerName = player.getName(); + if (player instanceof Player) { + setGameMode(((Player) player).getGameMode()); + } + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Source getSource() { + return source; + } + + public void setSource(Source source) { + if (source != Source.PLAYER) + setPlayer(null); + this.source = source; + } + + @Override + public String toString() { + return blockLocation.toString() + " by " + + (source == Source.PLAYER ? playerName : (source.toString() + (playerName != null ? "(" + playerName + ")" : ""))) + + (gameMode != null ? "" : (" in GM: " + gameMode)) + + " at " + date.toString(); + } +} diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java new file mode 100644 index 0000000..543e611 --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/BlockStateConfig.java @@ -0,0 +1,99 @@ +package de.jaschastarke.minecraft.limitedcreative.blockstate; + +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; + +import de.jaschastarke.bukkit.lib.configuration.Configuration; +import de.jaschastarke.configuration.IConfigurationNode; +import de.jaschastarke.configuration.IConfigurationSubGroup; +import de.jaschastarke.configuration.InvalidValueException; +import de.jaschastarke.configuration.annotations.IsConfigurationNode; +import de.jaschastarke.maven.ArchiveDocComments; +import de.jaschastarke.minecraft.limitedcreative.ModBlockStates; +import de.jaschastarke.modularize.IModule; +import de.jaschastarke.modularize.ModuleEntry; +import de.jaschastarke.modularize.ModuleEntry.ModuleState; + +/** + * BlockState-Feature + * + * http://dev.bukkit.org/server-mods/limited-creative/pages/features/blockstate/ + */ +@ArchiveDocComments +public class BlockStateConfig extends Configuration implements IConfigurationSubGroup { + protected ModBlockStates mod; + protected ModuleEntry entry; + + public BlockStateConfig(ModBlockStates mod, ModuleEntry modEntry) { + this.mod = mod; + entry = modEntry; + } + + @Override + public void setValue(IConfigurationNode node, Object pValue) throws InvalidValueException { + super.setValue(node, pValue); + if (node.getName().equals("enabled")) { + if (getEnabled()) { + if (entry.initialState != ModuleState.NOT_INITIALIZED) + entry.enable(); + } else { + entry.disable(); + } + } + } + + @Override + public void setValues(ConfigurationSection sect) { + super.setValues(sect); + if (entry.initialState != ModuleState.NOT_INITIALIZED) + entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED; + } + @Override + public String getName() { + return "blockstate"; + } + @Override + public int getOrder() { + return 700; + } + + /** + * BlockStateEnabled + * + * ... + * + * default: true + */ + @IsConfigurationNode(order = 100) + public boolean getEnabled() { + return config.getBoolean("enabled", true); + } + + /** + * BlockStateTool + * + * The id or technical name (http://tinyurl.com/bukkit-material) of an item that displays information about the + * right-clicked block. + * + * default: WOOD_AXE + */ + @IsConfigurationNode(order = 200) + public Material getToolType() { + if (config.isString("tool")) { + Material v = Material.getMaterial(config.getString("tool")); + if (v != null) + return v; + } else if (config.isInt("tool")) { + Material v = Material.getMaterial(config.getInt("tool")); + if (v != null) + return v; + } else { + Object v = config.get("tool", Material.WOOD_AXE); + if (v instanceof Material) + return (Material) v; + } + mod.getLog().warn("Unknown BlockStateTool: " + config.get("tool")); + return Material.WOOD_AXE; + } + +} diff --git a/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/PlayerListener.java b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/PlayerListener.java new file mode 100644 index 0000000..93111ff --- /dev/null +++ b/src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/PlayerListener.java @@ -0,0 +1,42 @@ +package de.jaschastarke.minecraft.limitedcreative.blockstate; + +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import de.jaschastarke.bukkit.lib.chat.ChatFormattings; +import de.jaschastarke.bukkit.lib.chat.NullFormatter; +import de.jaschastarke.minecraft.limitedcreative.ModBlockStates; +import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source; + +public class PlayerListener implements Listener { + private ModBlockStates mod; + public PlayerListener(ModBlockStates mod) { + this.mod = mod; + } + + @EventHandler(priority = EventPriority.HIGH) + public void onInteract(PlayerInteractEvent event) { + if (event.isCancelled()) + return; + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Block b = event.getClickedBlock(); + if (b != null && event.getPlayer().getItemInHand().getType().equals(mod.getConfig().getToolType())) { + BlockState s = mod.getDB().find(BlockState.class, new BlockLocation(b.getLocation())); + NullFormatter f = new NullFormatter(); + String ret = null; + if (s == null || s.getSource() == Source.UNKNOWN) { + ret = f.formatString(ChatFormattings.ERROR, f.getString("block_state.tool_info.unknown")); + } else { + String k = "block_state.tool_info." + s.getSource().name().toLowerCase(); + ret = f.formatString(ChatFormattings.INFO, f.getString(k, b.getType(), s.getPlayerName(), s.getDate())); + } + if (ret != null) + event.getPlayer().sendMessage(ret); + } + } + } +} diff --git a/src/main/resources/lang/messages.properties b/src/main/resources/lang/messages.properties index d1e456e..c6e77c9 100644 --- a/src/main/resources/lang/messages.properties +++ b/src/main/resources/lang/messages.properties @@ -44,3 +44,8 @@ blocked.break: You are not allowed to break this type of block blocked.region.piston: Moving {0} block out of creative area was blocked at {1} blocked.region.piston_in: Moving {0} block into creative area was blocked at {1} + +block_state.tool_info.seed: This {0}-Block is generated by the god who created this world +block_state.tool_info.player: This {0}-Block was created by ''{1}'' in {2}-mode on {3} +block_state.tool_info.edit: This {0}-Block was modified by the tool ''{1}'' or such at {3} +block_state.tool_info.unknown: The origin of this {0}-Block is unknown