From df434e7fe21bd893143ec7ac983a7b9dd53854ad Mon Sep 17 00:00:00 2001 From: Fredthedoggy <45927799+fredthedoggy@users.noreply.github.com> Date: Mon, 5 Jul 2021 14:38:22 -0400 Subject: [PATCH 1/2] Add "Icon" Section to Phase Config. --- pom.xml | 11 ++ .../commands/IslandPhasesCommand.java | 5 +- .../aoneblock/oneblocks/OneBlockObject.java | 15 +- .../aoneblock/oneblocks/OneBlockPhase.java | 71 ++++++--- .../aoneblock/oneblocks/OneBlocksManager.java | 140 +++++++++++------- src/main/resources/phases/0_plains.yml | 2 + 6 files changed, 163 insertions(+), 81 deletions(-) diff --git a/pom.xml b/pom.xml index d275004..9af82b6 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,10 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots + + minecraft-repo + https://libraries.minecraft.net/ + codemc https://repo.codemc.org/repository/maven-snapshots/ @@ -163,6 +167,13 @@ ${spigot.version} provided + + + com.mojang + authlib + 1.5.21 + provided + org.mockito diff --git a/src/main/java/world/bentobox/aoneblock/commands/IslandPhasesCommand.java b/src/main/java/world/bentobox/aoneblock/commands/IslandPhasesCommand.java index e4bad02..51f8f23 100644 --- a/src/main/java/world/bentobox/aoneblock/commands/IslandPhasesCommand.java +++ b/src/main/java/world/bentobox/aoneblock/commands/IslandPhasesCommand.java @@ -7,6 +7,7 @@ import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; import world.bentobox.aoneblock.AOneBlock; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; @@ -45,8 +46,8 @@ public boolean execute(User user, String label, List args) { item.name(user.getTranslation("aoneblock.commands.phases.name-syntax", TextVariables.NAME, en.getValue().getPhaseName(), TextVariables.NUMBER, String.valueOf(en.getKey()))); - Material material = en.getValue().getFirstBlock() == null ? Material.STONE : en.getValue().getFirstBlock().getMaterial(); - item.icon(material); + ItemStack icon = en.getValue().getIconBlock() == null ? en.getValue().getFirstBlock() == null ? new ItemStack(Material.STONE, 1) : new ItemStack(en.getValue().getFirstBlock().getMaterial(), 1) : en.getValue().getIconBlock(); + item.icon(icon); item.description(user.getTranslation("aoneblock.commands.phases.description-syntax", TextVariables.NAME, en.getValue().getPhaseName(), TextVariables.NUMBER, String.valueOf(en.getKey()))); diff --git a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockObject.java b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockObject.java index 7b3f761..50c21c3 100644 --- a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockObject.java +++ b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockObject.java @@ -9,8 +9,8 @@ /** * Represents something that can be generated when a block is broken * Can be a block or entity - * @author tastybento * + * @author tastybento */ public class OneBlockObject { @@ -39,14 +39,15 @@ public enum Rarity { private EntityType entityType; private Material material; - private Map chest; + private Map chest; private Rarity rarity; private int prob; /** * An entity + * * @param entityType - type - * @param prob - relative probability + * @param prob - relative probability */ public OneBlockObject(EntityType entityType, int prob) { this.entityType = entityType; @@ -55,8 +56,9 @@ public OneBlockObject(EntityType entityType, int prob) { /** * A block + * * @param material - block type - * @param prob - relative probability + * @param prob - relative probability */ public OneBlockObject(Material material, int prob) { this.material = material; @@ -64,11 +66,13 @@ public OneBlockObject(Material material, int prob) { } + /** * A chest + * * @param chest - list of itemstacks in the chest */ - public OneBlockObject(Map chest, Rarity rarity) { + public OneBlockObject(Map chest, Rarity rarity) { this.material = Material.CHEST; this.chest = chest; this.setRarity(rarity); @@ -77,6 +81,7 @@ public OneBlockObject(Map chest, Rarity rarity) { /** * Copy constructor + * * @param ob - OneBlockObject */ public OneBlockObject(OneBlockObject ob) { diff --git a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java index 1c65f70..d3c0cdc 100644 --- a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java +++ b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java @@ -21,17 +21,19 @@ import world.bentobox.aoneblock.AOneBlock; import world.bentobox.aoneblock.oneblocks.OneBlockObject.Rarity; - public class OneBlockPhase { protected static final SortedMap CHEST_CHANCES = new TreeMap<>(); + static { CHEST_CHANCES.put(0.62D, Rarity.COMMON); CHEST_CHANCES.put(0.87D, Rarity.UNCOMMON); CHEST_CHANCES.put(0.96D, Rarity.RARE); CHEST_CHANCES.put(1D, Rarity.EPIC); } + /** - * Tree map of all materials and their probabilities as a ratio to the sum of all probabilities + * Tree map of all materials and their probabilities as a ratio to the sum of + * all probabilities */ private final TreeMap probMap = new TreeMap<>(); /** @@ -42,6 +44,7 @@ public class OneBlockPhase { private Biome phaseBiome; private Environment environment; private OneBlockObject firstBlock; + private ItemStack iconBlock; private final Map> chests = new EnumMap<>(Rarity.class); private final Random random = new Random(); private final String blockNumber; @@ -53,10 +56,10 @@ public class OneBlockPhase { private List requirements; private Map fixedBlocks; - /** * Construct a phase that starts at blockNumber. Phase continues forever until * another phase starts. + * * @param blockNumber - starting block number */ public OneBlockPhase(String blockNumber) { @@ -76,6 +79,7 @@ public String getBlockNumber() { /** * Get the block number as an integer + * * @return the integer value of the blockNumber */ public int getBlockNumberValue() { @@ -114,8 +118,9 @@ public void setPhaseBiome(Biome phaseBiome) { /** * Adds a material and associated probability + * * @param material - Material - * @param prob - probability + * @param prob - probability */ public void addBlock(Material material, int prob) { total += prob; @@ -125,8 +130,9 @@ public void addBlock(Material material, int prob) { /** * Adds an entity type and associated probability + * * @param entityType - entityType - * @param prob - probability + * @param prob - probability */ public void addMob(EntityType entityType, int prob) { total += prob; @@ -140,15 +146,17 @@ public void addChest(Map items, Rarity rarity) { /** * This picks a random object - * @param addon AOneBlock + * + * @param addon AOneBlock * @param blockNumber the block number in the phase requested * @return OneBlockObject selected */ public OneBlockObject getNextBlock(AOneBlock addon, int blockNumber) { - if (total <1) { - addon.logError("Phase " + this.getPhaseName() + " has zero probability of generating blocks. Check config file. Is the block section missing?"); - return this.getFirstBlock() != null ? getFirstBlock() : new OneBlockObject(Material.GRASS_BLOCK,1); + if (total < 1) { + addon.logError("Phase " + this.getPhaseName() + + " has zero probability of generating blocks. Check config file. Is the block section missing?"); + return this.getFirstBlock() != null ? getFirstBlock() : new OneBlockObject(Material.GRASS_BLOCK, 1); } if (blockNumber == 0 && this.getFirstBlock() != null) { return getResult(this.getFirstBlock()); @@ -158,7 +166,8 @@ public OneBlockObject getNextBlock(AOneBlock addon, int blockNumber) { return getResult(this.getFixedBlocks().get(blockNumber)); } OneBlockObject block = getRandomBlock(probMap, total); - if (block.isEntity()) return block; + if (block.isEntity()) + return block; return getResult(block); } @@ -168,20 +177,23 @@ private OneBlockObject getResult(OneBlockObject block) { private OneBlockObject getRandomChest() { // Get the right type of chest - Rarity r = CHEST_CHANCES.getOrDefault(((TreeMap) CHEST_CHANCES).ceilingKey(random.nextDouble()), Rarity.COMMON); + Rarity r = CHEST_CHANCES.getOrDefault(((TreeMap) CHEST_CHANCES).ceilingKey(random.nextDouble()), + Rarity.COMMON); // If the chest lists have no common fallback, then return empty chest - if (!chests.containsKey(r) && !chests.containsKey(Rarity.COMMON)) return new OneBlockObject(Material.CHEST, 0); + if (!chests.containsKey(r) && !chests.containsKey(Rarity.COMMON)) + return new OneBlockObject(Material.CHEST, 0); // Get the rare chest or worse case the common one List list = chests.containsKey(r) ? chests.get(r) : chests.get(Rarity.COMMON); - // Pick one from the list or return an empty chest. Note list.get() can return nothing + // Pick one from the list or return an empty chest. Note list.get() can return + // nothing return list.isEmpty() ? new OneBlockObject(Material.CHEST, 0) : list.get(random.nextInt(list.size())); } private OneBlockObject getRandomBlock(TreeMap probMap2, int total2) { // Use +1 on the bound because the random choice is exclusive - OneBlockObject temp = probMap2.get(random.nextInt(total2+1)); + OneBlockObject temp = probMap2.get(random.nextInt(total2 + 1)); if (temp == null) { - temp = probMap2.ceilingEntry(random.nextInt(total2+1)).getValue(); + temp = probMap2.ceilingEntry(random.nextInt(total2 + 1)).getValue(); } if (temp == null) { temp = probMap2.firstEntry().getValue(); @@ -211,6 +223,14 @@ public OneBlockObject getFirstBlock() { return firstBlock; } + /** + * @return the iconBlock + */ + @Nullable + public ItemStack getIconBlock() { + return iconBlock; + } + /** * @param firstBlock the firstBlock to set */ @@ -218,14 +238,20 @@ public void setFirstBlock(OneBlockObject firstBlock) { this.firstBlock = firstBlock; } + /** + * @param iconBlock the iconBlock to set + */ + public void setIconBlock(ItemStack iconBlock) { + this.iconBlock = iconBlock; + } + /** * Get all the chests in this phase + * * @return collection of all the chests */ public Collection getChests() { - return chests.values().stream() - .flatMap(List::stream) - .collect(Collectors.toList()); + return chests.values().stream().flatMap(List::stream).collect(Collectors.toList()); } /** @@ -237,18 +263,22 @@ public Map> getChestsMap() { /** * Get the mobs that are in this phase + * * @return map of mob type and its relative probability */ public Map getMobs() { - return probMap.values().stream().filter(OneBlockObject::isEntity).collect(Collectors.toMap(OneBlockObject::getEntityType, OneBlockObject::getProb)); + return probMap.values().stream().filter(OneBlockObject::isEntity) + .collect(Collectors.toMap(OneBlockObject::getEntityType, OneBlockObject::getProb)); } /** * Get the block materials in this phase + * * @return map of materials and relative probabilities */ public Map getBlocks() { - return probMap.values().stream().filter(OneBlockObject::isMaterial).collect(Collectors.toMap(OneBlockObject::getMaterial, OneBlockObject::getProb)); + return probMap.values().stream().filter(OneBlockObject::isMaterial) + .collect(Collectors.toMap(OneBlockObject::getMaterial, OneBlockObject::getProb)); } /** @@ -349,5 +379,4 @@ public void setFixedBlocks(Map fixedBlocks) { this.fixedBlocks = fixedBlocks; } - } \ No newline at end of file diff --git a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java index bb457e4..2a8952e 100644 --- a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java +++ b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java @@ -3,21 +3,14 @@ import java.io.File; import java.io.FilenameFilter; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.lang.reflect.Field; +import java.util.*; import java.util.Map.Entry; -import java.util.NavigableMap; -import java.util.Objects; -import java.util.Optional; -import java.util.TreeMap; import java.util.jar.JarFile; import java.util.stream.Collectors; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; import org.apache.commons.lang.math.NumberUtils; import org.bukkit.Material; import org.bukkit.block.Biome; @@ -25,6 +18,7 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -43,6 +37,7 @@ public class OneBlocksManager { private static final String NAME = "name"; private static final String BIOME = "biome"; private static final String FIRST_BLOCK = "firstBlock"; + private static final String ICON = "icon"; private static final String FIXED_BLOCKS = "fixedBlocks"; private static final String CHESTS = "chests"; private static final String RARITY = "rarity"; @@ -68,6 +63,7 @@ public OneBlocksManager(AOneBlock addon) { /** * Loads the game phases + * * @throws IOException - if config file has bad syntax or migration fails */ public void loadPhases() throws IOException { @@ -103,6 +99,7 @@ public void loadPhases() throws IOException { /** * Copies phase files from the addon jar to the file system + * * @param file - the file to copy */ void copyPhasesFromAddonJar(File file) { @@ -150,8 +147,6 @@ private void loadPhase(File phaseFile) throws IOException { } } - - void initBlock(String blockNumber, OneBlockPhase obPhase, ConfigurationSection phase) throws IOException { if (phase.contains(NAME, true)) { if (obPhase.getPhaseName() != null) { @@ -174,6 +169,31 @@ void initBlock(String blockNumber, OneBlockPhase obPhase, ConfigurationSection p } addFirstBlock(obPhase, phase.getString(FIRST_BLOCK)); } + // Icon block + if (phase.contains(ICON)) { + if (obPhase.getIconBlock() != null) { + throw new IOException("Block " + blockNumber + ": Icon block trying to be set to " + phase.getString(FIRST_BLOCK) + " but already set to " + obPhase.getFirstBlock() + " Duplicate phase file?"); + } + ItemStack item; + try { + item = new ItemStack(Material.valueOf(phase.getString(ICON)), 1); + } catch (IllegalArgumentException err) { + item = new ItemStack(Material.PLAYER_HEAD, 1); + SkullMeta meta = (SkullMeta) item.getItemMeta(); + GameProfile profile = new GameProfile(UUID.randomUUID(), ""); + profile.getProperties().put("textures", new Property("textures", phase.getString(ICON))); + Field profileField = null; + try { + profileField = meta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profileField.set(meta, profile); + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + item.setItemMeta(meta); + } + obPhase.setIconBlock(item); + } // First blocks if (phase.contains(FIXED_BLOCKS)) { if (!obPhase.getFixedBlocks().isEmpty()) { @@ -184,7 +204,8 @@ void initBlock(String blockNumber, OneBlockPhase obPhase, ConfigurationSection p } private void addFixedBlocks(OneBlockPhase obPhase, ConfigurationSection fb) { - if (fb == null) return; + if (fb == null) + return; Map result = new HashMap<>(); for (String key : fb.getKeys(false)) { if (!NumberUtils.isNumber(key)) { @@ -196,7 +217,7 @@ private void addFixedBlocks(OneBlockPhase obPhase, ConfigurationSection fb) { if (mat != null) { Material m = Material.matchMaterial(mat); if (m != null && m.isBlock()) { - result.put(k, new OneBlockObject(m,0)); + result.put(k, new OneBlockObject(m, 0)); } else { addon.logError("Fixed block key " + key + " material is invalid or not a block. Ignoring."); } @@ -212,13 +233,15 @@ private void addFixedBlocks(OneBlockPhase obPhase, ConfigurationSection fb) { } private Biome getBiome(String string) { - if (string == null) return Biome.PLAINS; + if (string == null) + return Biome.PLAINS; if (Enums.getIfPresent(Biome.class, string).isPresent()) { return Biome.valueOf(string); } // Special case for nether if (string.equals("NETHER") || string.equals("NETHER_WASTES")) { - return Enums.getIfPresent(Biome.class, "NETHER").or(Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.PLAINS)); + return Enums.getIfPresent(Biome.class, "NETHER") + .or(Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.PLAINS)); } addon.logError("Biome " + string.toUpperCase() + " is invalid! Use one of these..."); addon.logError(Arrays.stream(Biome.values()).map(Biome::name).collect(Collectors.joining(","))); @@ -226,7 +249,8 @@ private Biome getBiome(String string) { } void addFirstBlock(OneBlockPhase obPhase, @Nullable String material) { - if (material == null) return; + if (material == null) + return; Material m = Material.matchMaterial(material); if (m == null || !m.isBlock()) { addon.logError("Bad firstBlock material: " + material); @@ -266,13 +290,14 @@ void addChests(OneBlockPhase obPhase, ConfigurationSection phase) throws IOExcep throw new IOException(obPhase.getPhaseName() + ": Chests cannot be set more than once. Duplicate file?"); } ConfigurationSection chests = phase.getConfigurationSection(CHESTS); - for (String chestId: chests.getKeys(false)) { + for (String chestId : chests.getKeys(false)) { ConfigurationSection chest = chests.getConfigurationSection(chestId); Rarity rarity = Rarity.COMMON; try { rarity = OneBlockObject.Rarity.valueOf(chest.getString(RARITY, "COMMON").toUpperCase()); } catch (Exception e) { - addon.logError("Rarity value of " + chest.getString(RARITY, "UNKNOWN") + " is invalid! Use one of these..."); + addon.logError( + "Rarity value of " + chest.getString(RARITY, "UNKNOWN") + " is invalid! Use one of these..."); addon.logError(Arrays.stream(Rarity.values()).map(Rarity::name).collect(Collectors.joining(","))); rarity = Rarity.COMMON; } @@ -282,7 +307,8 @@ void addChests(OneBlockPhase obPhase, ConfigurationSection phase) throws IOExcep for (String index : contents.getKeys(false)) { int slot = Integer.parseInt(index); ItemStack item = contents.getItemStack(index); - if (item != null) items.put(slot, item); + if (item != null) + items.put(slot, item); } } obPhase.addChest(items, rarity); @@ -311,10 +337,8 @@ void addMobs(OneBlockPhase obPhase, ConfigurationSection phase) throws IOExcepti // Does not exist addon.logError("Bad entity type in " + obPhase.getPhaseName() + ": " + entity); addon.logError("Try one of these..."); - addon.logError(Arrays.stream(EntityType.values()) - .filter(EntityType::isSpawnable) - .filter(EntityType::isAlive) - .map(EntityType::name).collect(Collectors.joining(","))); + addon.logError(Arrays.stream(EntityType.values()).filter(EntityType::isSpawnable) + .filter(EntityType::isAlive).map(EntityType::name).collect(Collectors.joining(","))); return; } if (et.isSpawnable() && et.isAlive()) { @@ -345,6 +369,7 @@ void addBlocks(OneBlockPhase obPhase, ConfigurationSection phase) { /** * Return the current phase for the block count + * * @param blockCount - number of blocks mined * @return the one block phase based on blockCount or null if there is none */ @@ -355,16 +380,12 @@ public OneBlockPhase getPhase(int blockCount) { } /** - * @return list of phase names with spaces replaced by underscore so they are one word + * @return list of phase names with spaces replaced by underscore so they are + * one word */ public List getPhaseList() { - return blockProbs.values() - .stream() - .map(OneBlockPhase::getPhaseName) - .filter(Objects::nonNull) - .map(n -> - n.replace(" ", "_")) - .collect(Collectors.toList()); + return blockProbs.values().stream().map(OneBlockPhase::getPhaseName).filter(Objects::nonNull) + .map(n -> n.replace(" ", "_")).collect(Collectors.toList()); } /** @@ -375,16 +396,21 @@ public NavigableMap getBlockProbs() { } /** - * Get phase by name. Name should have any spaces converted to underscores. Case insensitive. + * Get phase by name. Name should have any spaces converted to underscores. Case + * insensitive. + * * @param name - name to search * @return optional OneBlockPhase */ public Optional getPhase(String name) { - return blockProbs.values().stream().filter(p -> p.getPhaseName() != null && p.getPhaseName().replace(" ", "_").equalsIgnoreCase(name)).findFirst(); + return blockProbs.values().stream() + .filter(p -> p.getPhaseName() != null && p.getPhaseName().replace(" ", "_").equalsIgnoreCase(name)) + .findFirst(); } /** * Save the oneblock.yml file in memory to disk. Makes a backup. + * * @return true if saved */ public boolean saveOneBlockConfig() { @@ -408,20 +434,23 @@ public boolean saveOneBlockConfig() { } try { // Save - File phaseFile = new File(addon.getDataFolder() + File.separator + PHASES, getPhaseFileName(p) + ".yml"); + File phaseFile = new File(addon.getDataFolder() + File.separator + PHASES, + getPhaseFileName(p) + ".yml"); oneBlocks.save(phaseFile); } catch (IOException e) { addon.logError("Could not save phase " + p.getPhaseName() + " " + e.getMessage()); } // No chests in goto phases - if (p.isGotoPhase()) return; + if (p.isGotoPhase()) + return; // Save chests separately oneBlocks = new YamlConfiguration(); phSec = oneBlocks.createSection(p.getBlockNumber()); saveChests(phSec, p); try { // Save - File phaseFile = new File(addon.getDataFolder() + File.separator + PHASES, getPhaseFileName(p) + "_chests.yml"); + File phaseFile = new File(addon.getDataFolder() + File.separator + PHASES, + getPhaseFileName(p) + "_chests.yml"); oneBlocks.save(phaseFile); } catch (IOException e) { addon.logError("Could not save phase " + p.getPhaseName() + " " + e.getMessage()); @@ -442,7 +471,7 @@ private String getPhaseFileName(OneBlockPhase p) { private void saveChests(ConfigurationSection phSec, OneBlockPhase phase) { ConfigurationSection chests = phSec.createSection(CHESTS); int index = 1; - for (OneBlockObject chest:phase.getChests()) { + for (OneBlockObject chest : phase.getChests()) { ConfigurationSection c = chests.createSection(String.valueOf(index++)); c.set(CONTENTS, chest.getChest()); c.set(RARITY, chest.getRarity().name()); @@ -452,17 +481,18 @@ private void saveChests(ConfigurationSection phSec, OneBlockPhase phase) { private void saveEntities(ConfigurationSection phSec, OneBlockPhase phase) { ConfigurationSection mobs = phSec.createSection(MOBS); - phase.getMobs().forEach((k,v) -> mobs.set(k.name(), v)); + phase.getMobs().forEach((k, v) -> mobs.set(k.name(), v)); } private void saveBlocks(ConfigurationSection phSec, OneBlockPhase phase) { ConfigurationSection blocks = phSec.createSection(BLOCKS); - phase.getBlocks().forEach((k,v) -> blocks.set(k.name(), v)); + phase.getBlocks().forEach((k, v) -> blocks.set(k.name(), v)); } /** * Get the phase after this one + * * @param phase - one block phase * @return next phase or null if there isn't one */ @@ -475,8 +505,10 @@ public OneBlockPhase getNextPhase(@NonNull OneBlockPhase phase) { /** * Get the number of blocks until the next phase after this one + * * @param obi - one block island - * @return number of blocks to the next phase. If there is no phase after -1 is returned. + * @return number of blocks to the next phase. If there is no phase after -1 is + * returned. */ public int getNextPhaseBlocks(@NonNull OneBlockIslands obi) { Integer blockNum = obi.getBlockNumber(); @@ -487,6 +519,7 @@ public int getNextPhaseBlocks(@NonNull OneBlockIslands obi) { /** * Get the percentage done of this phase + * * @param obi - one block island * @return percentage done. If there is no next phase then return 0 */ @@ -502,10 +535,9 @@ public double getPercentageDone(@NonNull OneBlockIslands obi) { return 0; } int phaseSize = nextPhase.getBlockNumberValue() - thisPhase.getBlockNumberValue(); - return 100 - (100 * (double)(nextPhase.getBlockNumberValue() - obi.getBlockNumber()) / phaseSize); + return 100 - (100 * (double) (nextPhase.getBlockNumberValue() - obi.getBlockNumber()) / phaseSize); } - public void getProbs(OneBlockPhase phase) { // Find the phase after this one Integer blockNum = Integer.valueOf(phase.getBlockNumber()); @@ -518,10 +550,11 @@ public void getProbs(OneBlockPhase phase) { double totalBlocks = 0; // Now calculate the relative block probability for (Entry en : phase.getBlocks().entrySet()) { - double chance = (double)en.getValue()/blockTotal; + double chance = (double) en.getValue() / blockTotal; double likelyNumberGenerated = chance * phaseSize; totalBlocks += likelyNumberGenerated; - String report = en.getKey() + " likely generated = " + Math.round(likelyNumberGenerated) + " = " + Math.round(likelyNumberGenerated*100/phaseSize) + "%"; + String report = en.getKey() + " likely generated = " + Math.round(likelyNumberGenerated) + " = " + + Math.round(likelyNumberGenerated * 100 / phaseSize) + "%"; if (likelyNumberGenerated < 1) { addon.logWarning(report); } else { @@ -545,7 +578,8 @@ public void getProbs(OneBlockPhase phase) { int num = phase.getChestsMap().getOrDefault(en.getValue(), Collections.emptyList()).size(); double likelyNumberGenerated = (en.getKey() - lastChance) * likelyChestTotal; lastChance = en.getKey(); - String report = num + " " + en.getValue() + " chests in phase. Likely number generated = " + Math.round(likelyNumberGenerated); + String report = num + " " + en.getValue() + " chests in phase. Likely number generated = " + + Math.round(likelyNumberGenerated); if (num > 0 && likelyNumberGenerated < 1) { addon.logWarning(report); } else { @@ -558,10 +592,11 @@ public void getProbs(OneBlockPhase phase) { double totalMobs = 0; // Now calculate the relative block probability for (Entry en : phase.getMobs().entrySet()) { - double chance = (double)en.getValue()/phase.getTotal(); + double chance = (double) en.getValue() / phase.getTotal(); double likelyNumberGenerated = chance * phaseSize; totalMobs += likelyNumberGenerated; - String report = en.getKey() + " likely generated = " + Math.round(likelyNumberGenerated) + " = " + Math.round(likelyNumberGenerated*100/phaseSize) + "%"; + String report = en.getKey() + " likely generated = " + Math.round(likelyNumberGenerated) + " = " + + Math.round(likelyNumberGenerated * 100 / phaseSize) + "%"; if (likelyNumberGenerated < 1) { addon.logWarning(report); } else { @@ -578,13 +613,12 @@ public void getAllProbs() { /** * Get the next phase name + * * @param obi - one block island * @return next phase name or an empty string */ public String getNextPhase(@NonNull OneBlockIslands obi) { - return getPhase(obi.getPhaseName()) - .map(this::getNextPhase) // Next phase or null - .filter(Objects::nonNull) - .map(OneBlockPhase::getPhaseName).orElse(""); + return getPhase(obi.getPhaseName()).map(this::getNextPhase) // Next phase or null + .filter(Objects::nonNull).map(OneBlockPhase::getPhaseName).orElse(""); } } diff --git a/src/main/resources/phases/0_plains.yml b/src/main/resources/phases/0_plains.yml index b2614b8..99d0c1d 100644 --- a/src/main/resources/phases/0_plains.yml +++ b/src/main/resources/phases/0_plains.yml @@ -1,5 +1,7 @@ '0': name: Plains + # Material (Eg. GRASS_BLOCK) or Base64 Head Texture for Icon in "phases" command. Optional, Falls back to First Block + icon: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWY1ZjE1OTg4NmNjNTMxZmZlYTBkOGFhNWY5MmVkNGU1ZGE2NWY3MjRjMDU3MGFmODZhOTBiZjAwYzY3YzQyZSJ9fX0= # List of blocks that will generate at these specific block counts. # The numbers are relative to the phase and not the overall player's count. # If you define 0 here, then firstBlock is not required and firstBlock will be replaced with this block. From 335cfbdc714178f9b7a72b3d448a9776a7d29d29 Mon Sep 17 00:00:00 2001 From: Fredthedoggy <45927799+fredthedoggy@users.noreply.github.com> Date: Mon, 5 Jul 2021 22:04:48 -0400 Subject: [PATCH 2/2] Fix Code Smells/Inconsistencies --- .../aoneblock/oneblocks/OneBlockPhase.java | 6 ++- .../aoneblock/oneblocks/OneBlocksManager.java | 53 +++++++++++-------- src/main/resources/phases/0_plains.yml | 4 +- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java index d3c0cdc..10cf6c8 100644 --- a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java +++ b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlockPhase.java @@ -166,8 +166,9 @@ public OneBlockObject getNextBlock(AOneBlock addon, int blockNumber) { return getResult(this.getFixedBlocks().get(blockNumber)); } OneBlockObject block = getRandomBlock(probMap, total); - if (block.isEntity()) + if (block.isEntity()) { return block; + } return getResult(block); } @@ -180,8 +181,9 @@ private OneBlockObject getRandomChest() { Rarity r = CHEST_CHANCES.getOrDefault(((TreeMap) CHEST_CHANCES).ceilingKey(random.nextDouble()), Rarity.COMMON); // If the chest lists have no common fallback, then return empty chest - if (!chests.containsKey(r) && !chests.containsKey(Rarity.COMMON)) + if (!chests.containsKey(r) && !chests.containsKey(Rarity.COMMON)) { return new OneBlockObject(Material.CHEST, 0); + } // Get the rare chest or worse case the common one List list = chests.containsKey(r) ? chests.get(r) : chests.get(Rarity.COMMON); // Pick one from the list or return an empty chest. Note list.get() can return diff --git a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java index 2a8952e..e22c6e4 100644 --- a/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java +++ b/src/main/java/world/bentobox/aoneblock/oneblocks/OneBlocksManager.java @@ -175,22 +175,11 @@ void initBlock(String blockNumber, OneBlockPhase obPhase, ConfigurationSection p throw new IOException("Block " + blockNumber + ": Icon block trying to be set to " + phase.getString(FIRST_BLOCK) + " but already set to " + obPhase.getFirstBlock() + " Duplicate phase file?"); } ItemStack item; - try { - item = new ItemStack(Material.valueOf(phase.getString(ICON)), 1); - } catch (IllegalArgumentException err) { - item = new ItemStack(Material.PLAYER_HEAD, 1); - SkullMeta meta = (SkullMeta) item.getItemMeta(); - GameProfile profile = new GameProfile(UUID.randomUUID(), ""); - profile.getProperties().put("textures", new Property("textures", phase.getString(ICON))); - Field profileField = null; - try { - profileField = meta.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(meta, profile); - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { - e.printStackTrace(); - } - item.setItemMeta(meta); + Material m = Enums.getIfPresent(Material.class, phase.getString(ICON).toUpperCase(Locale.ENGLISH)).orNull(); + if (m == null) { + item = generateHead(phase.getString(ICON)); + } else { + item = new ItemStack(m); // note that the default quantity is 1, so you don't need to say 1 } obPhase.setIconBlock(item); } @@ -204,8 +193,9 @@ void initBlock(String blockNumber, OneBlockPhase obPhase, ConfigurationSection p } private void addFixedBlocks(OneBlockPhase obPhase, ConfigurationSection fb) { - if (fb == null) + if (fb == null) { return; + } Map result = new HashMap<>(); for (String key : fb.getKeys(false)) { if (!NumberUtils.isNumber(key)) { @@ -233,8 +223,9 @@ private void addFixedBlocks(OneBlockPhase obPhase, ConfigurationSection fb) { } private Biome getBiome(String string) { - if (string == null) + if (string == null) { return Biome.PLAINS; + } if (Enums.getIfPresent(Biome.class, string).isPresent()) { return Biome.valueOf(string); } @@ -249,8 +240,9 @@ private Biome getBiome(String string) { } void addFirstBlock(OneBlockPhase obPhase, @Nullable String material) { - if (material == null) + if (material == null) { return; + } Material m = Material.matchMaterial(material); if (m == null || !m.isBlock()) { addon.logError("Bad firstBlock material: " + material); @@ -307,8 +299,9 @@ void addChests(OneBlockPhase obPhase, ConfigurationSection phase) throws IOExcep for (String index : contents.getKeys(false)) { int slot = Integer.parseInt(index); ItemStack item = contents.getItemStack(index); - if (item != null) + if (item != null) { items.put(slot, item); + } } } obPhase.addChest(items, rarity); @@ -441,8 +434,9 @@ public boolean saveOneBlockConfig() { addon.logError("Could not save phase " + p.getPhaseName() + " " + e.getMessage()); } // No chests in goto phases - if (p.isGotoPhase()) + if (p.isGotoPhase()) { return; + } // Save chests separately oneBlocks = new YamlConfiguration(); phSec = oneBlocks.createSection(p.getBlockNumber()); @@ -621,4 +615,21 @@ public String getNextPhase(@NonNull OneBlockIslands obi) { return getPhase(obi.getPhaseName()).map(this::getNextPhase) // Next phase or null .filter(Objects::nonNull).map(OneBlockPhase::getPhaseName).orElse(""); } + + private ItemStack generateHead(String texture) { + ItemStack item = new ItemStack(Material.PLAYER_HEAD, 1); + SkullMeta meta = (SkullMeta) item.getItemMeta(); + GameProfile profile = new GameProfile(UUID.randomUUID(), ""); + profile.getProperties().put("textures", new Property("textures", texture)); + Field profileField = null; + try { + profileField = meta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profileField.set(meta, profile); + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + item.setItemMeta(meta); + return item; + } } diff --git a/src/main/resources/phases/0_plains.yml b/src/main/resources/phases/0_plains.yml index 99d0c1d..84cebc3 100644 --- a/src/main/resources/phases/0_plains.yml +++ b/src/main/resources/phases/0_plains.yml @@ -1,6 +1,8 @@ '0': name: Plains - # Material (Eg. GRASS_BLOCK) or Base64 Head Texture for Icon in "phases" command. Optional, Falls back to First Block + # Material (Eg. GRASS_BLOCK) or Base64 Head Texture for Icon in "phases" command. (Optional) + # If icon is not defined, then the first block of the phase will be used. + # See https://minecraft-heads.com/ for info on Base64 Head Textures icon: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWY1ZjE1OTg4NmNjNTMxZmZlYTBkOGFhNWY5MmVkNGU1ZGE2NWY3MjRjMDU3MGFmODZhOTBiZjAwYzY3YzQyZSJ9fX0= # List of blocks that will generate at these specific block counts. # The numbers are relative to the phase and not the overall player's count.