#176 adds support for custom blocks with ItemsAdder
This commit is contained in:
parent
68f696a46c
commit
ff813e3e53
10
pom.xml
10
pom.xml
|
@ -125,6 +125,10 @@
|
|||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack-repo</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
|
@ -160,6 +164,12 @@
|
|||
<version>${bentobox.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.LoneDev6</groupId>
|
||||
<artifactId>api-itemsadder</artifactId>
|
||||
<version>3.4.1-r4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
package world.bentobox.limits.listeners;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
@ -15,13 +23,27 @@ import org.bukkit.event.Event;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockBurnEvent;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.BlockFadeEvent;
|
||||
import org.bukkit.event.block.BlockFormEvent;
|
||||
import org.bukkit.event.block.BlockFromToEvent;
|
||||
import org.bukkit.event.block.BlockGrowEvent;
|
||||
import org.bukkit.event.block.BlockMultiPlaceEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.block.BlockSpreadEvent;
|
||||
import org.bukkit.event.block.EntityBlockFormEvent;
|
||||
import org.bukkit.event.block.LeavesDecayEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import world.bentobox.bentobox.api.events.island.IslandDeleteEvent;
|
||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
|
@ -59,7 +81,10 @@ public class BlockLimitsListener implements Listener {
|
|||
private final Map<String, Integer> saveMap = new HashMap<>();
|
||||
private final Database<IslandBlockCount> handler;
|
||||
private final Map<World, Map<Material, Integer>> worldLimitMap = new HashMap<>();
|
||||
//private final Map<World, Map<String, Integer>> customWorldLimitMap = new HashMap<>();
|
||||
private Map<Material, Integer> defaultLimitMap = new EnumMap<>(Material.class);
|
||||
private Map<String, Integer> defaultCustomLimitMap = new HashMap<>();
|
||||
private Plugin itemsAdder;
|
||||
|
||||
public BlockLimitsListener(Limits addon) {
|
||||
this.addon = addon;
|
||||
|
@ -89,6 +114,11 @@ public class BlockLimitsListener implements Listener {
|
|||
ConfigurationSection limitConfig = addon.getConfig().getConfigurationSection("blocklimits");
|
||||
defaultLimitMap = loadLimits(Objects.requireNonNull(limitConfig));
|
||||
}
|
||||
// Load custom blocks
|
||||
if (addon.getConfig().isConfigurationSection("customblocklimits")) {
|
||||
ConfigurationSection limitConfig = addon.getConfig().getConfigurationSection("customblocklimits");
|
||||
defaultCustomLimitMap = loadCustomLimits(Objects.requireNonNull(limitConfig));
|
||||
}
|
||||
|
||||
// Load specific worlds
|
||||
if (addon.getConfig().isConfigurationSection("worlds")) {
|
||||
|
@ -126,6 +156,21 @@ public class BlockLimitsListener implements Listener {
|
|||
return mats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads custom limit map from configuration section
|
||||
*
|
||||
* @param cs - configuration section
|
||||
* @return limit map
|
||||
*/
|
||||
private Map<String, Integer> loadCustomLimits(ConfigurationSection cs) {
|
||||
Map<String, Integer> mats = new HashMap<>();
|
||||
for (String material : cs.getKeys(false)) {
|
||||
mats.put(material, cs.getInt(material));
|
||||
addon.log("Limit " + material + " to " + cs.getInt(material));
|
||||
}
|
||||
return mats;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the count database completely
|
||||
|
@ -137,7 +182,7 @@ public class BlockLimitsListener implements Listener {
|
|||
// Player-related events
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onBlock(BlockPlaceEvent e) {
|
||||
notify(e, User.getInstance(e.getPlayer()), process(e.getBlock(), true), e.getBlock().getType());
|
||||
notify(e, User.getInstance(e.getPlayer()), process(e.getBlock(), true), e.getBlock());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
|
@ -187,7 +232,7 @@ public class BlockLimitsListener implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onBlock(BlockMultiPlaceEvent e) {
|
||||
notify(e, User.getInstance(e.getPlayer()), process(e.getBlock(), true), e.getBlock().getType());
|
||||
notify(e, User.getInstance(e.getPlayer()), process(e.getBlock(), true), e.getBlock());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,10 +242,15 @@ public class BlockLimitsListener implements Listener {
|
|||
* @param limit maximum limit allowed
|
||||
* @param m material
|
||||
*/
|
||||
private void notify(Cancellable e, User user, int limit, Material m) {
|
||||
private void notify(Cancellable e, User user, int limit, Block block) {
|
||||
if (limit > -1) {
|
||||
String name = Util.prettifyText(block.getType().toString());
|
||||
if (this.itemsAdder != null) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
name = customBlock.getDisplayName();
|
||||
}
|
||||
user.notify("block-limits.hit-limit",
|
||||
"[material]", Util.prettifyText(m.toString()),
|
||||
"[material]", name,
|
||||
TextVariables.NUMBER, String.valueOf(limit));
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
@ -318,6 +368,8 @@ public class BlockLimitsListener implements Listener {
|
|||
* @return limit amount if over limit, or -1 if no limitation
|
||||
*/
|
||||
private int process(Block b, boolean add) {
|
||||
// Check for custom block handlers
|
||||
checkCustom();
|
||||
if (DO_NOT_COUNT.contains(fixMaterial(b.getBlockData())) || !addon.inGameModeWorld(b.getWorld())) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -335,12 +387,27 @@ public class BlockLimitsListener implements Listener {
|
|||
}
|
||||
islandCountMap.putIfAbsent(id, new IslandBlockCount(id, gameMode));
|
||||
if (add) {
|
||||
// Check limit
|
||||
int limit = checkLimit(b.getWorld(), fixMaterial(b.getBlockData()), id);
|
||||
if (limit > -1) {
|
||||
return limit;
|
||||
// Check if custom block
|
||||
if (itemsAdder != null ) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(b);
|
||||
if(customBlock != null) {
|
||||
// Custom block
|
||||
// Check limit
|
||||
int limit = checkCustomLimit(b.getWorld(), b, id);
|
||||
if (limit > -1) {
|
||||
return limit;
|
||||
}
|
||||
islandCountMap.get(id).add(b);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check limit
|
||||
int limit = checkLimit(b.getWorld(), fixMaterial(b.getBlockData()), id);
|
||||
if (limit > -1) {
|
||||
return limit;
|
||||
}
|
||||
islandCountMap.get(id).add(fixMaterial(b.getBlockData()));
|
||||
}
|
||||
islandCountMap.get(id).add(fixMaterial(b.getBlockData()));
|
||||
} else {
|
||||
if (islandCountMap.containsKey(id)) {
|
||||
islandCountMap.get(id).remove(fixMaterial(b.getBlockData()));
|
||||
|
@ -351,6 +418,11 @@ public class BlockLimitsListener implements Listener {
|
|||
}).orElse(-1);
|
||||
}
|
||||
|
||||
private void checkCustom() {
|
||||
itemsAdder = Bukkit.getPluginManager().getPlugin("ItemsAdder");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed a block from any island limit count
|
||||
* @param b - block to remove
|
||||
|
@ -364,10 +436,17 @@ public class BlockLimitsListener implements Listener {
|
|||
// Invalid world
|
||||
return;
|
||||
}
|
||||
islandCountMap.computeIfAbsent(id, k -> new IslandBlockCount(id, gameMode)).remove(fixMaterial(b.getBlockData()));
|
||||
updateSaveMap(id);
|
||||
// Check for custom block
|
||||
if (this.itemsAdder != null && CustomBlock.byAlreadyPlaced(b) != null) {
|
||||
islandCountMap.computeIfAbsent(id, k -> new IslandBlockCount(id, gameMode)).remove(b);
|
||||
updateSaveMap(id);
|
||||
} else {
|
||||
islandCountMap.computeIfAbsent(id, k -> new IslandBlockCount(id, gameMode)).remove(fixMaterial(b.getBlockData()));
|
||||
updateSaveMap(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateSaveMap(String id) {
|
||||
saveMap.putIfAbsent(id, 0);
|
||||
if (saveMap.merge(id, 1, Integer::sum) > CHANGE_LIMIT) {
|
||||
|
@ -404,6 +483,37 @@ public class BlockLimitsListener implements Listener {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this custom block is at its limit for world on this island
|
||||
*
|
||||
* @param w - world
|
||||
* @param block - custom block
|
||||
* @param id - island id
|
||||
* @return limit amount if at limit or -1 if no limit
|
||||
*/
|
||||
private int checkCustomLimit(World w, Block block, String islandId) {
|
||||
// Check island limits
|
||||
IslandBlockCount ibc = islandCountMap.get(islandId);
|
||||
if (ibc.isCustomBlockLimited(block)) {
|
||||
return ibc.isAtLimit(block) ? ibc.getBlockLimit(block) : -1;
|
||||
}
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
/* NOT SUPPORTED YET
|
||||
// Check specific world limits
|
||||
if (customWorldLimitMap.containsKey(w) && customWorldLimitMap.get(w).containsKey(id)) {
|
||||
// Material is overridden in world
|
||||
return ibc.isAtLimit(block, worldLimitMap.get(w).get(id)) ? worldLimitMap.get(w).get(id) : -1; // TODO Add perm offset
|
||||
}
|
||||
*/
|
||||
// Check default limit map
|
||||
if (defaultCustomLimitMap.containsKey(id) && ibc.isAtLimit(block, defaultCustomLimitMap.get(id))) {
|
||||
return defaultCustomLimitMap.get(id);// TODO add perm offset
|
||||
}
|
||||
// No limit
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an aggregate map of the limits for this island
|
||||
*
|
||||
|
@ -427,7 +537,7 @@ public class BlockLimitsListener implements Listener {
|
|||
|
||||
// Add offsets to the every limit.
|
||||
islandBlockCount.getBlockLimitsOffset().forEach((material, offset) ->
|
||||
result.put(material, result.getOrDefault(material, 0) + offset));
|
||||
result.put(material, result.getOrDefault(material, 0) + offset));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,15 @@ package world.bentobox.limits.objects;
|
|||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomBlock;
|
||||
import world.bentobox.bentobox.database.objects.DataObject;
|
||||
import world.bentobox.bentobox.database.objects.Table;
|
||||
|
||||
|
@ -28,6 +31,9 @@ public class IslandBlockCount implements DataObject {
|
|||
@Expose
|
||||
private Map<Material, Integer> blockCounts = new EnumMap<>(Material.class);
|
||||
|
||||
@Expose
|
||||
private Map<String, Integer> customBlockCounts = new HashMap<>();
|
||||
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
|
@ -36,6 +42,8 @@ public class IslandBlockCount implements DataObject {
|
|||
@Expose
|
||||
private Map<Material, Integer> blockLimits = new EnumMap<>(Material.class);
|
||||
@Expose
|
||||
private Map<String, Integer> customBlockLimits = new HashMap<>();
|
||||
@Expose
|
||||
private Map<EntityType, Integer> entityLimits = new EnumMap<>(EntityType.class);
|
||||
@Expose
|
||||
private Map<String, Integer> entityGroupLimits = new HashMap<>();
|
||||
|
@ -120,6 +128,28 @@ public class IslandBlockCount implements DataObject {
|
|||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom block to the count
|
||||
* @param block - custom block
|
||||
*/
|
||||
public void add(Block block) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
customBlockCounts.merge(Objects.requireNonNull(customBlock).getNamespacedID(), 1, Integer::sum);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a custom block from the count
|
||||
* @param block - block
|
||||
*/
|
||||
public void remove(Block block) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
customBlockCounts.put(id, blockCounts.getOrDefault(id, 0) - 1);
|
||||
blockCounts.values().removeIf(v -> v <= 0);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this material is at or over a limit
|
||||
* @param material - block material
|
||||
|
@ -129,6 +159,18 @@ public class IslandBlockCount implements DataObject {
|
|||
public boolean isAtLimit(Material material, int limit) {
|
||||
return blockCounts.getOrDefault(material, 0) >= limit + this.getBlockLimitOffset(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this custom block is at or over a limit
|
||||
* @param block - block
|
||||
* @param limit - limit to check
|
||||
* @return true if count is >= limit
|
||||
*/
|
||||
public boolean isAtLimit(Block block, int limit) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
return customBlockCounts.getOrDefault(id, 0) >= limit; // TODO Add a permission offset
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if no more of this material can be added to this island
|
||||
|
@ -139,10 +181,28 @@ public class IslandBlockCount implements DataObject {
|
|||
// Check island limits first
|
||||
return blockLimits.containsKey(m) && blockCounts.getOrDefault(m, 0) >= getBlockLimit(m) + this.getBlockLimitOffset(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if no more of this custom block can be added to this island
|
||||
* @param block - block
|
||||
* @return true if no more block can be added
|
||||
*/
|
||||
public boolean isAtLimit(Block block) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
// Check island limits first
|
||||
return customBlockLimits.containsKey(id) && customBlockCounts.getOrDefault(id, 0) >= getBlockLimit(block); // TODO add perm offset
|
||||
}
|
||||
|
||||
public boolean isBlockLimited(Material m) {
|
||||
return blockLimits.containsKey(m);
|
||||
}
|
||||
|
||||
public boolean isCustomBlockLimited(Block block) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
return customBlockLimits.containsKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the blockLimits
|
||||
|
@ -167,6 +227,17 @@ public class IslandBlockCount implements DataObject {
|
|||
public int getBlockLimit(Material m) {
|
||||
return blockLimits.getOrDefault(m, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom block limit for this material for this island
|
||||
* @param block - block
|
||||
* @return limit or -1 for unlimited
|
||||
*/
|
||||
public int getBlockLimit(Block block) {
|
||||
CustomBlock customBlock = CustomBlock.byAlreadyPlaced(block);
|
||||
String id = Objects.requireNonNull(customBlock).getNamespacedID();
|
||||
return customBlockLimits.getOrDefault(id, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block offset for this material for this island
|
||||
|
@ -186,6 +257,16 @@ public class IslandBlockCount implements DataObject {
|
|||
blockLimits.put(m, limit);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom block limit for this island
|
||||
* @param id - namespaced id
|
||||
* @param limit - maximum number allowed
|
||||
*/
|
||||
public void setCustomBlockLimit(String id, int limit) {
|
||||
customBlockLimits.put(id, limit);
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the gameMode
|
||||
|
@ -385,4 +466,32 @@ public class IslandBlockCount implements DataObject {
|
|||
public void setEntityGroupLimitsOffset(String name, Integer entityGroupLimitsOffset) {
|
||||
getEntityGroupLimitsOffset().put(name, entityGroupLimitsOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the customBlockCounts
|
||||
*/
|
||||
public Map<String, Integer> getCustomBlockCounts() {
|
||||
return customBlockCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customBlockCounts the customBlockCounts to set
|
||||
*/
|
||||
public void setCustomBlockCounts(Map<String, Integer> customBlockCounts) {
|
||||
this.customBlockCounts = customBlockCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the customBlockLimits
|
||||
*/
|
||||
public Map<String, Integer> getCustomBlockLimits() {
|
||||
return customBlockLimits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customBlockLimits the customBlockLimits to set
|
||||
*/
|
||||
public void setCustomBlockLimits(Map<String, Integer> customBlockLimits) {
|
||||
this.customBlockLimits = customBlockLimits;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,13 @@ async-golums: true
|
|||
# These limits apply to every game mode world
|
||||
blocklimits:
|
||||
HOPPER: 10
|
||||
|
||||
# Custom block limits
|
||||
# Requires use of the ItemsAdder plugin. Custom blocks are currently only supported globally and not on a per-world basis.
|
||||
# Limits require the full namespace name of the custom block material
|
||||
customblocklimits:
|
||||
# "iafestivities:christmas/christmas_tree/green_orb": 5
|
||||
|
||||
# This section is for world-specific limits and overrides the general limit
|
||||
# Specify each world you want to limit individually (including nether and end worlds)
|
||||
# If these worlds are not covered by the game modes above, nothing will happen
|
||||
|
|
|
@ -400,7 +400,7 @@ public class JoinListenerTest {
|
|||
@Test
|
||||
public void testOnPlayerJoinWithPermLimitsMultiPermsSameMaterial() {
|
||||
// IBC - set the block limit for STONE to be 25 already
|
||||
when(ibc.getBlockLimit(any())).thenReturn(25);
|
||||
when(ibc.getBlockLimit(any(Material.class))).thenReturn(25);
|
||||
Set<PermissionAttachmentInfo> perms = new HashSet<>();
|
||||
PermissionAttachmentInfo permAtt = mock(PermissionAttachmentInfo.class);
|
||||
when(permAtt.getPermission()).thenReturn("bskyblock.island.limit.STONE.24");
|
||||
|
|
Loading…
Reference in New Issue