Minor performance improvement for custom mining

This commit is contained in:
Jules 2024-07-26 15:32:48 -07:00
parent b80cda490c
commit 61efa519c2
6 changed files with 146 additions and 118 deletions

View File

@ -43,7 +43,7 @@ public class BlockInfo {
options.put(option, config.getBoolean("options." + key)); options.put(option, config.getBoolean("options." + key));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load option '" + key + "' from block info '" + block.generateKey() + "': " + exception.getMessage()); "Could not load option '" + key + "' from block info '" + block.display() + "': " + exception.getMessage());
} }
if (config.contains("triggers")) { if (config.contains("triggers")) {
@ -55,7 +55,7 @@ public class BlockInfo {
triggers.add(MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(key))); triggers.add(MMOCore.plugin.loadManager.loadTrigger(new MMOLineConfig(key)));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load trigger '" + key + "' from block info '" + block.generateKey() + "': " + exception.getMessage()); "Could not load trigger '" + key + "' from block info '" + block.display() + "': " + exception.getMessage());
} }
} }
@ -71,6 +71,7 @@ public class BlockInfo {
return options.getOrDefault(option, option.getDefault()); return options.getOrDefault(option, option.getDefault());
} }
@NotNull
public BlockType getBlock() { public BlockType getBlock() {
return block; return block;
} }

View File

@ -1,29 +1,31 @@
package net.Indyuce.mmocore.api.block; package net.Indyuce.mmocore.api.block;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface BlockType { public interface BlockType {
/** /**
* Called when placing temporary blocks * Called when placing temporary blocks
*/ */
void place(BlockInfo.RegeneratingBlock placed); void place(@NotNull BlockInfo.RegeneratingBlock placed);
/** /**
* Called when regenerating an older block with block regen * Called when regenerating an older block with block regen
*/ */
void regenerate(BlockInfo.RegeneratingBlock regenerating); void regenerate(@NotNull BlockInfo.RegeneratingBlock regenerating);
/** @NotNull String display();
* Generates a key used to store the BlockInfo instance in the manager map,
* the key depends on the block type to make sure there is no interference
*/
String generateKey();
/** /**
* Applies some extra break restrictions; returns TRUE if the block can be * Applies some extra break restrictions; returns TRUE if the block can be
* broken. This method is used to prevent non mature crops from being broken * broken. This method is used to prevent non mature crops from being broken
* for example * for example
*/ */
boolean breakRestrictions(Block block); boolean breakRestrictions(@NotNull Block block);
int hashCode();
boolean equals(@Nullable Object obj);
} }

View File

@ -8,51 +8,66 @@ import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import java.util.Objects;
public class SkullBlockType implements BlockType { public class SkullBlockType implements BlockType {
private final String value; private final String value;
public SkullBlockType(MMOLineConfig config) { public SkullBlockType(MMOLineConfig config) {
config.validate("value"); config.validate("value");
value = config.getString("value"); value = config.getString("value");
} }
public SkullBlockType(Block block) { public SkullBlockType(Block block) {
value = MythicLib.plugin.getVersion().getWrapper().getSkullValue(block); value = MythicLib.plugin.getVersion().getWrapper().getSkullValue(block);
} }
public String getValue() { public String getValue() {
return value; return value;
} }
@Override @Override
public void place(RegeneratingBlock block) { public void place(RegeneratingBlock block) {
Location loc = block.getLocation(); Location loc = block.getLocation();
loc.getBlock().setType(Material.PLAYER_HEAD); loc.getBlock().setType(Material.PLAYER_HEAD);
// save skull orientation if replaced block is a player head // save skull orientation if replaced block is a player head
if (MMOCoreUtils.isPlayerHead(block.getBlockData().getMaterial())) if (MMOCoreUtils.isPlayerHead(block.getBlockData().getMaterial()))
loc.getBlock().setBlockData(block.getBlockData()); loc.getBlock().setBlockData(block.getBlockData());
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value); MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
} }
@Override @Override
public void regenerate(RegeneratingBlock block) { public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation(); Location loc = block.getLocation();
// This makes sure that if a skull loses its original rotation // This makes sure that if a skull loses its original rotation
// it can revert back to it when the base block is regenerated // it can revert back to it when the base block is regenerated
loc.getBlock().setBlockData(block.getBlockData()); loc.getBlock().setBlockData(block.getBlockData());
MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value); MythicLib.plugin.getVersion().getWrapper().setSkullValue(loc.getBlock(), value);
} }
@Override @Override
public String generateKey() { public String display() {
return "vanilla-skull-" + value; return "Skull{" + value + "}";
} }
@Override @Override
public boolean breakRestrictions(Block block) { public boolean breakRestrictions(Block block) {
return true; return true;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SkullBlockType that = (SkullBlockType) o;
return Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
} }

View File

@ -1,5 +1,7 @@
package net.Indyuce.mmocore.api.block; package net.Indyuce.mmocore.api.block;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -7,63 +9,75 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable; import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import net.Indyuce.mmocore.api.block.BlockInfo.RegeneratingBlock; import java.util.Objects;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class VanillaBlockType implements BlockType { public class VanillaBlockType implements BlockType {
private final Material type; private final Material type;
/* /*
* allows to plant back crops with a custom age so that it does not always * allows to plant back crops with a custom age so that it does not always
* have to full grow again- * have to full grow again-
*/ */
private final int age; private final int age;
public VanillaBlockType(MMOLineConfig config) { public VanillaBlockType(MMOLineConfig config) {
config.validate("type"); config.validate("type");
type = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_")); type = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
age = config.getInt("age", 0); age = config.getInt("age", 0);
Validate.isTrue(age >= 0 && age < 8, "Age must be between 0 and 7"); Validate.isTrue(age >= 0 && age < 8, "Age must be between 0 and 7");
} }
public VanillaBlockType(Block block) { public VanillaBlockType(Block block) {
type = block.getType(); type = block.getType();
age = 0; age = 0;
} }
public Material getType() { public Material getType() {
return type; return type;
} }
@Override @Override
public void place(RegeneratingBlock block) { public void place(RegeneratingBlock block) {
Location loc = block.getLocation(); Location loc = block.getLocation();
block.getLocation().getBlock().setType(type); block.getLocation().getBlock().setType(type);
BlockData state = block.getLocation().getBlock().getBlockData(); BlockData state = block.getLocation().getBlock().getBlockData();
if (age > 0 && state instanceof Ageable) { if (age > 0 && state instanceof Ageable) {
((Ageable) state).setAge(age); ((Ageable) state).setAge(age);
loc.getBlock().setBlockData(state); loc.getBlock().setBlockData(state);
} }
} }
@Override @Override
public void regenerate(RegeneratingBlock block) { public void regenerate(RegeneratingBlock block) {
Location loc = block.getLocation(); Location loc = block.getLocation();
loc.getBlock().setType(type); loc.getBlock().setType(type);
// Sets the original blocks old data (only when regenerating) // Sets the original blocks old data (only when regenerating)
loc.getBlock().setBlockData(block.getBlockData()); loc.getBlock().setBlockData(block.getBlockData());
} }
@Override @Override
public String generateKey() { public String display() {
return "vanilla-block-" + type.name(); return "Vanilla{" + type.name() + "}";
} }
@Override @Override
public boolean breakRestrictions(Block block) { public boolean breakRestrictions(Block block) {
return age == 0 || (block.getBlockData() instanceof Ageable && ((Ageable) block.getBlockData()).getAge() >= age); return age == 0 || (block.getBlockData() instanceof Ageable && ((Ageable) block.getBlockData()).getAge() >= age);
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VanillaBlockType that = (VanillaBlockType) o;
return type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(type);
}
} }

View File

@ -91,13 +91,7 @@ public class RestrictionManager implements MMOCoreManager {
} }
public class ToolPermissions implements PreloadedObject { public class ToolPermissions implements PreloadedObject {
private final Set<BlockType> mineable = new HashSet<>();
/**
* Now saving string keys using {@link BlockType#generateKey()} instead
* of iterating through the set to take advantage of the O(1) time
* complexity of hash sets.
*/
private final Set<String> mineable = new HashSet<>();
private final ItemType tool; private final ItemType tool;
private final boolean defaultSet; private final boolean defaultSet;
@ -112,7 +106,7 @@ public class RestrictionManager implements MMOCoreManager {
} }
if (config.contains("can-mine")) if (config.contains("can-mine"))
for (String key : config.getStringList("can-mine")) for (String key : config.getStringList("can-mine"))
mineable.add(MMOCore.plugin.loadManager.loadBlockType(new MMOLineConfig(key)).generateKey()); mineable.add(MMOCore.plugin.loadManager.loadBlockType(new MMOLineConfig(key)));
}); });
public ToolPermissions(ConfigurationSection config) { public ToolPermissions(ConfigurationSection config) {
@ -138,9 +132,9 @@ public class RestrictionManager implements MMOCoreManager {
* @param type Block being broken * @param type Block being broken
* @return If the given block can be broken * @return If the given block can be broken
*/ */
public boolean canMine(BlockType type) { public boolean canMine(@NotNull BlockType type) {
ToolPermissions parent; ToolPermissions parent;
return mineable.contains(type.generateKey()) || ((parent = getParent()) != null && parent.canMine(type)); return mineable.contains(type) || ((parent = getParent()) != null && parent.canMine(type));
} }
/** /**

View File

@ -15,6 +15,7 @@ import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.*;
@ -26,7 +27,7 @@ public class CustomBlockManager extends SpecificProfessionManager {
/** /**
* Registered block infos * Registered block infos
*/ */
private final Map<String, BlockInfo> map = new HashMap<>(); private final Map<BlockType, BlockInfo> map = new HashMap<>();
/** /**
* Blocks that are regenerating and that must be refreshed whenever the * Blocks that are regenerating and that must be refreshed whenever the
@ -57,8 +58,8 @@ public class CustomBlockManager extends SpecificProfessionManager {
blockTypes.add(function); blockTypes.add(function);
} }
public void register(BlockInfo regen) { public void register(@NotNull BlockInfo regen) {
map.put(regen.getBlock().generateKey(), regen); map.put(regen.getBlock(), regen);
} }
/** /**
@ -68,10 +69,11 @@ public class CustomBlockManager extends SpecificProfessionManager {
* @param block Block to check * @param block Block to check
* @return The new block behaviour or null if no new behaviour * @return The new block behaviour or null if no new behaviour
*/ */
public @Nullable BlockInfo getInfo(Block block) { public @Nullable BlockInfo getInfo(@NotNull Block block) {
return map.get(findBlockType(block).generateKey()); return map.get(findBlockType(block));
} }
@NotNull
public BlockType findBlockType(Block block) { public BlockType findBlockType(Block block) {
for (Function<Block, Optional<BlockType>> blockType : blockTypes) { for (Function<Block, Optional<BlockType>> blockType : blockTypes) {
Optional<BlockType> type = blockType.apply(block); Optional<BlockType> type = blockType.apply(block);