diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java index e864d534..6ce25f32 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/BlockManager.java @@ -1,7 +1,7 @@ package net.momirealms.customfishing.api.manager; -import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; import net.momirealms.customfishing.api.mechanic.block.BlockDataModifierBuilder; +import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; import net.momirealms.customfishing.api.mechanic.block.BlockStateModifierBuilder; import net.momirealms.customfishing.api.mechanic.loot.Loot; import org.bukkit.Location; diff --git a/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java b/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java index babcd421..bbab3de1 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java +++ b/api/src/main/java/net/momirealms/customfishing/api/manager/VersionManager.java @@ -8,6 +8,8 @@ public interface VersionManager { CompletableFuture checkUpdate(); + boolean isVersionNewerThan1_20(); + boolean isSpigot(); public boolean isFolia(); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java index efcfe961..78918ee2 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockDataModifierBuilder.java @@ -1,7 +1,5 @@ package net.momirealms.customfishing.api.mechanic.block; -import java.util.InvalidPropertiesFormatException; - public interface BlockDataModifierBuilder { BlockDataModifier build(Object args); diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java index c0f0e10e..97fd8800 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockLibrary.java @@ -3,7 +3,6 @@ package net.momirealms.customfishing.api.mechanic.block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; -import java.util.HashMap; import java.util.List; public interface BlockLibrary { diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java index 0aa6c511..314a123d 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/block/BlockStateModifier.java @@ -1,7 +1,6 @@ package net.momirealms.customfishing.api.mechanic.block; import org.bukkit.block.BlockState; -import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; public interface BlockStateModifier { diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java index cf7dc4e6..ea191a54 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/game/AbstractGamingPlayer.java @@ -83,9 +83,7 @@ public abstract class AbstractGamingPlayer implements GamingPlayer, Runnable { protected void timeOutCheck() { if (System.currentTimeMillis() > deadline) { cancel(); - if (manager.removeHook(player.getUniqueId())) { - manager.processGameResult(this); - } + manager.processGameResult(this); } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java index 5f8855b0..5ac10ae5 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java @@ -65,7 +65,6 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin { this.effectManager = new EffectManagerImpl(this); this.fishingManager = new FishingManagerImpl(this); this.gameManager = new GameManagerImpl(this); - this.integrationManager = new IntegrationManagerImpl(this); this.itemManager = new ItemManagerImpl(this); this.lootManager = new LootManagerImpl(this); this.marketManager = new MarketManagerImpl(this); @@ -75,6 +74,7 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin { this.scheduler = new SchedulerImpl(this); this.storageManager = new StorageManagerImpl(this); this.competitionManager = new CompetitionManagerImpl(this); + this.integrationManager = new IntegrationManagerImpl(this); this.reload(); if (Config.updateChecker) this.versionManager.checkUpdate().thenAccept(result -> { diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java index 04e42fa1..8b37a688 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/ItemsAdderBlockImpl.java @@ -6,7 +6,6 @@ import net.momirealms.customfishing.api.mechanic.block.BlockLibrary; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; -import java.util.HashMap; import java.util.List; public class ItemsAdderBlockImpl implements BlockLibrary { diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java index a0088469..79c205c4 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/block/VanillaBlockImpl.java @@ -6,10 +6,8 @@ import org.bukkit.Material; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; public class VanillaBlockImpl implements BlockLibrary { diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java index 0d4ec516..eebc24b1 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/block/BlockManagerImpl.java @@ -10,24 +10,24 @@ import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.util.LogUtils; import net.momirealms.customfishing.compatibility.block.VanillaBlockImpl; import net.momirealms.customfishing.util.ConfigUtils; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.block.Barrel; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.Chest; +import org.bukkit.*; +import org.bukkit.block.*; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.type.Campfire; +import org.bukkit.block.data.type.Farmland; +import org.bukkit.block.data.type.NoteBlock; +import org.bukkit.block.data.type.TurtleEgg; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.ItemSpawnEvent; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; @@ -53,7 +53,32 @@ public class BlockManagerImpl implements BlockManager, Listener { this.stateBuilderMap = new HashMap<>(); this.registerBlockLibrary(new VanillaBlockImpl()); this.registerInbuiltProperties(); - this.registerStorage(); + } + + @EventHandler + public void onBlockLands(EntityChangeBlockEvent event) { + if (event.isCancelled()) return; + String temp = event.getEntity().getPersistentDataContainer().get( + Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), + PersistentDataType.STRING + ); + if (temp == null) return; + String[] split = temp.split(";"); + BlockConfig blockConfig = blockConfigMap.get(split[0]); + if (blockConfig == null) return; + Player player = Bukkit.getPlayer(split[1]); + if (player == null) { + event.getEntity().remove(); + event.getBlock().setType(Material.AIR); + return; + } + Location location = event.getBlock().getLocation(); + plugin.getScheduler().runTaskSyncLater(() -> { + BlockState state = location.getBlock().getState(); + for (BlockStateModifier modifier : blockConfig.getStateModifierList()) { + modifier.apply(player, state); + } + }, location, 50, TimeUnit.MILLISECONDS); } @Override @@ -95,6 +120,12 @@ public class BlockManagerImpl implements BlockManager, Listener { private void registerInbuiltProperties() { this.registerDirectional(); this.registerStorage(); + this.registerRotatable(); + this.registerTurtleEggs(); + this.registerMoisture(); + this.registerNoteBlock(); + this.registerCampfire(); + this.registerAge(); } public void unload() { @@ -192,24 +223,102 @@ public class BlockManagerImpl implements BlockManager, Listener { } else { blockData = blockLibraryMap.get("vanilla").getBlockData(player, blockID, config.getDataModifier()); } - FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData); - fallingBlock.getPersistentDataContainer().set( - Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), - PersistentDataType.STRING, - loot.getID() + ";" + player.getName() - ); - fallingBlock.setDropItem(false); - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); - vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); - fallingBlock.setVelocity(vector); + plugin.getScheduler().runTaskSync(() -> { + FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData); + fallingBlock.getPersistentDataContainer().set( + Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), + PersistentDataType.STRING, + loot.getID() + ";" + player.getName() + ); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); + vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); + fallingBlock.setVelocity(vector); + }, hookLocation); } private void registerDirectional() { - this.registerBlockDataModifierBuilder("directional", (args) -> { + this.registerBlockDataModifierBuilder("directional-4", (args) -> (player, blockData) -> { + boolean arg = (boolean) args; + if (arg && blockData instanceof Directional directional) { + directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0, 4)]); + } + }); + this.registerBlockDataModifierBuilder("directional-6", (args) -> (player, blockData) -> { + boolean arg = (boolean) args; + if (arg && blockData instanceof Directional directional) { + directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0, 6)]); + } + }); + } + + private void registerMoisture() { + this.registerBlockDataModifierBuilder("moisture", (args) -> { + int arg = (int) args; + return (player, blockData) -> { + if (blockData instanceof Farmland farmland) { + farmland.setMoisture(arg); + } + }; + }); + } + + private void registerCampfire() { + this.registerBlockDataModifierBuilder("campfire", (args) -> { boolean arg = (boolean) args; return (player, blockData) -> { - if (arg && blockData instanceof Directional directional) { - directional.setFacing(BlockFace.values()[ThreadLocalRandom.current().nextInt(0,6)]); + if (blockData instanceof Campfire campfire) { + campfire.setSignalFire(arg); + } + }; + }); + } + + private void registerRotatable() { + this.registerBlockDataModifierBuilder("rotatable", (args) -> { + boolean arg = (boolean) args; + return (player, blockData) -> { + if (arg && blockData instanceof Rotatable rotatable) { + rotatable.setRotation(BlockFace.values()[ThreadLocalRandom.current().nextInt(BlockFace.values().length)]); + } + }; + }); + } + + private void registerNoteBlock() { + this.registerBlockDataModifierBuilder("noteblock", (args) -> { + if (args instanceof ConfigurationSection section) { + var instrument = Instrument.valueOf(section.getString("instrument")); + var note = new Note(section.getInt("note")); + return (player, blockData) -> { + if (blockData instanceof NoteBlock noteBlock) { + noteBlock.setNote(note); + noteBlock.setInstrument(instrument); + } + }; + } else { + LogUtils.warn("Invalid property format found at block noteblock."); + return null; + } + }); + } + + private void registerAge() { + this.registerBlockDataModifierBuilder("age", (args) -> { + int arg = (int) args; + return (player, blockData) -> { + if (blockData instanceof Ageable ageable) { + ageable.setAge(arg); + } + }; + }); + } + + private void registerTurtleEggs() { + this.registerBlockDataModifierBuilder("turtle-eggs", (args) -> { + int arg = (int) args; + return (player, blockData) -> { + if (blockData instanceof TurtleEgg egg) { + egg.setEggs(arg); } }; }); @@ -228,29 +337,17 @@ public class BlockManagerImpl implements BlockManager, Listener { } } return (player, blockState) -> { - LinkedList unused = new LinkedList<>(); - for (int i = 0; i < 27; i++) { - unused.add(i); - } - Collections.shuffle(unused); if (blockState instanceof Chest chest) { - for (Tuple> tuple : tempChanceList) { - ItemStack itemStack = plugin.getItemManager().buildAnyItemByID(player, tuple.getMid()); - itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); - if (tuple.getLeft() > Math.random()) { - chest.getBlockInventory().setItem(unused.pop(), itemStack); - } - } + setInventoryItems(tempChanceList, player, chest.getInventory()); return; } if (blockState instanceof Barrel barrel) { - for (Tuple> tuple : tempChanceList) { - ItemStack itemStack = plugin.getItemManager().buildAnyItemByID(player, tuple.getMid()); - itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); - if (tuple.getLeft() > Math.random()) { - barrel.getInventory().setItem(unused.pop(), itemStack); - } - } + setInventoryItems(tempChanceList, player, barrel.getInventory()); + return; + } + if (blockState instanceof ShulkerBox shulkerBox) { + setInventoryItems(tempChanceList, player, shulkerBox.getInventory()); + return; } }; } else { @@ -260,29 +357,22 @@ public class BlockManagerImpl implements BlockManager, Listener { }); } - @EventHandler - public void onBlockLands(EntityChangeBlockEvent event) { - if (event.isCancelled()) return; - String temp = event.getEntity().getPersistentDataContainer().get( - Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())), - PersistentDataType.STRING - ); - if (temp == null) return; - String[] split = temp.split(";"); - BlockConfig blockConfig = blockConfigMap.get(split[0]); - if (blockConfig == null) return; - Player player = Bukkit.getPlayer(split[1]); - if (player == null) { - event.getEntity().remove(); - event.getBlock().setType(Material.AIR); - return; + private void setInventoryItems( + ArrayList>> tempChanceList, + Player player, + Inventory inventory + ) { + LinkedList unused = new LinkedList<>(); + for (int i = 0; i < 27; i++) { + unused.add(i); } - Location location = event.getBlock().getLocation(); - plugin.getScheduler().runTaskSyncLater(() -> { - BlockState state = location.getBlock().getState(); - for (BlockStateModifier modifier : blockConfig.getStateModifierList()) { - modifier.apply(player, state); + Collections.shuffle(unused); + for (Tuple> tuple : tempChanceList) { + ItemStack itemStack = plugin.getItemManager().buildAnyItemByID(player, tuple.getMid()); + itemStack.setAmount(ThreadLocalRandom.current().nextInt(tuple.getRight().left(), tuple.getRight().right() + 1)); + if (tuple.getLeft() > Math.random()) { + inventory.setItem(unused.pop(), itemStack); } - }, location, 50, TimeUnit.MILLISECONDS); + } } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java index 8a1c48d2..db2abfda 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/fishing/FishingManagerImpl.java @@ -406,19 +406,16 @@ public class FishingManagerImpl implements Listener, FishingManager { public void processGameResult(GamingPlayer gamingPlayer) { final Player player = gamingPlayer.getPlayer(); final UUID uuid = player.getUniqueId(); - FishHook fishHook = hookCacheMap.remove(uuid); if (fishHook == null) { LogUtils.warn("Unexpected situation: Can't get player's fish hook when processing game results."); return; } - TempFishingState tempFishingState = tempFishingStateMap.remove(uuid); if (tempFishingState == null) { LogUtils.warn("Unexpected situation: Can't get player's fishing state when processing game results."); return; } - Effect bonus = gamingPlayer.getEffectReward(); if (bonus != null) tempFishingState.getEffect().merge(bonus); @@ -428,10 +425,9 @@ public class FishingManagerImpl implements Listener, FishingManager { else fail(tempFishingState); - // remove hook because some games don't depend on right clicks - fishHook.remove(); gamingPlayer.cancel(); gamingPlayerMap.remove(uuid); + plugin.getScheduler().runTaskSync(fishHook::remove, fishHook.getLocation()); } public void fail(TempFishingState state) { diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java index b80bc134..f8404a7e 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/game/GameManagerImpl.java @@ -33,6 +33,8 @@ public class GameManagerImpl implements GameManager { private void registerInbuiltGames() { this.registerAccurateClickGame(); + this.registerHoldGame(); + this.registerTensionGame(); } public void load() { @@ -210,4 +212,241 @@ public class GameManagerImpl implements GameManager { }; })); } + + private void registerHoldGame() { + this.registerGameType("hold", (section -> { + + var timeRequirements = section.getIntegerList("hold-time-requirements").stream().mapToInt(Integer::intValue).toArray(); + var judgementAreaImage = section.getString("subtitle.judgment-area"); + var fishImage = section.getString("subtitle.fish"); + var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); + var judgementAreaOffset = section.getInt("arguments.judgment-area-offset"); + var judgementAreaWidth = section.getInt("arguments.judgment-area-width"); + var fishIconWidth = section.getInt("arguments.fish-icon-width"); + var punishment = section.getDouble("arguments.punishment"); + var progress = section.getStringList("progress").toArray(new String[0]); + var waterResistance = section.getDouble("arguments.water-resistance", 0.15); + var pullingStrength = section.getDouble("arguments.pulling-strength", 0.45); + var looseningLoss = section.getDouble("arguments.loosening-strength-loss", 0.3); + + var title = section.getString("title","{progress}"); + var font = section.getString("subtitle.font"); + var barImage = section.getString("subtitle.bar"); + var tip = section.getString("tip"); + + return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) { + private double hold_time; + private double judgement_position; + private double fish_position; + private double judgement_velocity; + private double fish_velocity; + private int timer; + private final int time_requirement = timeRequirements[ThreadLocalRandom.current().nextInt(timeRequirements.length)] * 1000; + private boolean played; + + @Override + public void arrangeTask() { + this.judgement_position = (double) (barEffectiveWidth - judgementAreaWidth) / 2; + this.task = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer( + this, + 50, + 33, + TimeUnit.MILLISECONDS + ); + } + + @Override + public void run() { + super.run(); + if (player.isSneaking()) addV(); + else reduceV(); + if (timer < 40 - (settings.getDifficulty() / 10)) { + timer++; + } else { + timer = 0; + if (Math.random() > ((double) 25 / (settings.getDifficulty() + 100))) { + burst(); + } + } + judgement_position += judgement_velocity; + fish_position += fish_velocity; + fraction(); + calibrate(); + if (fish_position >= judgement_position - 2 && fish_position + fishIconWidth <= judgement_position + judgementAreaWidth + 2) { + hold_time += 33; + } else { + hold_time -= punishment * 33; + } + if (hold_time >= time_requirement) { + succeeded = true; + manager.processGameResult(this); + return; + } + hold_time = Math.max(0, Math.min(hold_time, time_requirement)); + showUI(); + } + + private void burst() { + if (Math.random() < (judgement_position / barEffectiveWidth)) { + judgement_velocity = -1 - 0.8 * Math.random() * ((double) settings.getDifficulty() / 15); + } else { + judgement_velocity = 1 + 0.8 * Math.random() * ((double) settings.getDifficulty() / 15); + } + } + + private void fraction() { + if (judgement_velocity > 0) { + judgement_velocity -= waterResistance; + if (judgement_velocity < 0) judgement_velocity = 0; + } else { + judgement_velocity += waterResistance; + if (judgement_velocity > 0) judgement_velocity = 0; + } + } + + private void reduceV() { + fish_velocity -= looseningLoss; + } + + private void addV() { + played = true; + fish_velocity += pullingStrength; + } + + private void calibrate() { + if (fish_position < 0) { + fish_position = 0; + fish_velocity = 0; + } + if (fish_position + fishIconWidth > barEffectiveWidth) { + fish_position = barEffectiveWidth - fishIconWidth; + fish_velocity = 0; + } + if (judgement_position < 0) { + judgement_position = 0; + judgement_velocity = 0; + } + if (judgement_position + judgementAreaWidth > barEffectiveWidth) { + judgement_position = barEffectiveWidth - judgementAreaWidth; + judgement_velocity = 0; + } + } + + public void showUI() { + String bar = FontUtils.surroundWithFont(barImage, font) + + OffsetUtils.getOffsetChars((int) (judgementAreaOffset + judgement_position)) + + FontUtils.surroundWithFont(judgementAreaImage, font) + + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - judgement_position - judgementAreaWidth)) + + OffsetUtils.getOffsetChars((int) (-barEffectiveWidth - 1 + fish_position)) + + FontUtils.surroundWithFont(fishImage, font) + + OffsetUtils.getOffsetChars((int) (barEffectiveWidth - fish_position - fishIconWidth + 1)) + ; + + AdventureManagerImpl.getInstance().sendTitle( + player, + tip != null && !played ? tip : + title.replace("{progress}", progress[(int) ((hold_time / time_requirement) * progress.length)]) + , + bar, + 0, + 500, + 0 + ); + } + }; + })); + } + + private void registerTensionGame() { + this.registerGameType("tension", (section -> { + + var fishIconWidth = section.getInt("arguments.fish-icon-width"); + var fishImage = section.getString("subtitle.fish"); + var tension = section.getStringList("tension").toArray(new String[0]); + var strugglingFishImage = section.getStringList("subtitle.struggling-fish").toArray(new String[0]); + var barEffectiveWidth = section.getInt("arguments.bar-effective-area-width"); + var fishOffset = section.getInt("arguments.fish-offset"); + var fishStartPosition = section.getInt("arguments.fish-start-position"); + var successPosition = section.getInt("arguments.success-position"); + var ultimateTension = section.getDouble("arguments.ultimate-tension", 50); + var normalIncrease = section.getDouble("arguments.normal-pull-tension-increase", 1); + var strugglingIncrease = section.getDouble("arguments.struggling-tension-increase", 2); + var tensionLoss = section.getDouble("arguments.loosening-tension-loss", 2); + + var title = section.getString("title","{progress}"); + var font = section.getString("subtitle.font"); + var barImage = section.getString("subtitle.bar"); + var tip = section.getString("tip"); + + return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) { + + private int fish_position = fishStartPosition; + private double strain; + private int struggling_time; + private boolean played; + + @Override + public void arrangeTask() { + this.task = CustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(this, 50, 40, TimeUnit.MILLISECONDS); + } + + @Override + public void run() { + super.run(); + if (struggling_time <= 0) { + if (Math.random() < ((double) settings.getDifficulty() / 4000)) { + struggling_time = (int) (10 + Math.random() * (settings.getDifficulty() / 4)); + } + } else { + struggling_time--; + } + if (player.isSneaking()) pull(); + else loosen(); + if (fish_position < successPosition - fishIconWidth - 1) { + super.succeeded = true; + manager.processGameResult(this); + return; + } + if (fish_position + fishIconWidth > barEffectiveWidth || strain >= ultimateTension) { + super.succeeded = false; + manager.processGameResult(this); + return; + } + showUI(); + } + + public void pull() { + played = true; + if (struggling_time > 0) { + strain += (strugglingIncrease + ((double) settings.getDifficulty() / 50)); + fish_position -= 1; + } else { + strain += normalIncrease; + fish_position -= 2; + } + } + + public void loosen() { + fish_position++; + strain -= tensionLoss; + } + + public void showUI() { + String bar = FontUtils.surroundWithFont(barImage, font) + + OffsetUtils.getOffsetChars(fishOffset + fish_position) + + FontUtils.surroundWithFont((struggling_time > 0 ? strugglingFishImage[struggling_time % strugglingFishImage.length] : fishImage), font) + + OffsetUtils.getOffsetChars(barEffectiveWidth - fish_position - fishIconWidth); + strain = Math.max(0, Math.min(strain, ultimateTension)); + AdventureManagerImpl.getInstance().sendTitle( + player, + tip != null && !played ? tip : title.replace("{tension}", tension[(int) ((strain / ultimateTension) * tension.length)]), + bar, + 0, + 500, + 0 + ); + } + }; + })); + } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java index baf0f00f..fd0eba96 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/item/ItemManagerImpl.java @@ -266,10 +266,12 @@ public class ItemManagerImpl implements ItemManager { @Override public void dropItem(Location hookLocation, Location playerLocation, ItemStack itemStack) { - Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack); - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105); - vector = vector.setY((vector.getY() + 0.2) * 1.18); - itemEntity.setVelocity(vector); + plugin.getScheduler().runTaskSync(() -> { + Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack); + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105); + vector = vector.setY((vector.getY() + 0.2) * 1.18); + itemEntity.setVelocity(vector); + }, hookLocation); } @NotNull diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java index c6e2000e..3506150d 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/mob/MobManagerImpl.java @@ -125,18 +125,20 @@ public class MobManagerImpl implements MobManager { return; } String mobID = config.getMobID(); - Entity entity; - if (mobID.contains(":")) { - String[] split = mobID.split(":", 2); - String identification = split[0]; - String id = split[1]; - MobLibrary library = mobLibraryMap.get(identification); - entity = library.spawn(hookLocation, id, config.getPropertyMap()); - } else { - entity = mobLibraryMap.get("vanilla").spawn(hookLocation, mobID, config.getPropertyMap()); - } - Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); - vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); - entity.setVelocity(vector); + plugin.getScheduler().runTaskSync(() -> { + Entity entity; + if (mobID.contains(":")) { + String[] split = mobID.split(":", 2); + String identification = split[0]; + String id = split[1]; + MobLibrary library = mobLibraryMap.get(identification); + entity = library.spawn(hookLocation, id, config.getPropertyMap()); + } else { + entity = mobLibraryMap.get("vanilla").spawn(hookLocation, mobID, config.getPropertyMap()); + } + Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1); + vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector()); + entity.setVelocity(vector); + }, hookLocation); } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java index b005525a..70e98427 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/version/VersionManagerImpl.java @@ -17,7 +17,6 @@ package net.momirealms.customfishing.version; -import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; import net.momirealms.customfishing.CustomFishingPluginImpl; import net.momirealms.customfishing.api.manager.VersionManager; import net.momirealms.customfishing.api.util.LogUtils; @@ -32,6 +31,7 @@ import java.util.concurrent.CompletableFuture; public class VersionManagerImpl implements VersionManager { private final boolean isNewerThan1_19_R2; + private final boolean isNewerThan1_20; private final String serverVersion; private final CustomFishingPluginImpl plugin; private final boolean isSpigot; @@ -44,13 +44,20 @@ public class VersionManagerImpl implements VersionManager { serverVersion = plugin.getServer().getClass().getPackage().getName().split("\\.")[3]; String[] split = serverVersion.split("_"); int main_ver = Integer.parseInt(split[1]); - if (main_ver >= 20) isNewerThan1_19_R2 = true; - else if (main_ver == 19) isNewerThan1_19_R2 = Integer.parseInt(split[2].substring(1)) >= 2; - else isNewerThan1_19_R2 = false; + if (main_ver >= 20) { + isNewerThan1_19_R2 = true; + isNewerThan1_20 = true; + } else if (main_ver == 19) { + isNewerThan1_19_R2 = Integer.parseInt(split[2].substring(1)) >= 2; + isNewerThan1_20 = false; + } else { + isNewerThan1_19_R2 = false; + isNewerThan1_20 = false; + } String server_name = plugin.getServer().getName(); this.isSpigot = server_name.equals("CraftBukkit"); try { - Class.forName(String.valueOf(AsyncScheduler.class)); + Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler"); this.isFolia = true; } catch (ClassNotFoundException ignored) {} this.pluginVersion = plugin.getDescription().getVersion(); @@ -61,6 +68,11 @@ public class VersionManagerImpl implements VersionManager { return isNewerThan1_19_R2; } + @Override + public boolean isVersionNewerThan1_20() { + return isNewerThan1_20; + } + @Override public boolean isSpigot() { return isSpigot; diff --git a/plugin/src/main/resources/contents/minigames/default.yml b/plugin/src/main/resources/contents/minigames/default.yml index a49a9b29..0a17a354 100644 --- a/plugin/src/main/resources/contents/minigames/default.yml +++ b/plugin/src/main/resources/contents/minigames/default.yml @@ -552,7 +552,7 @@ hold_game: ########################################################## tension_game: game-type: tension - title: '{strain}' + title: '{tension}' # Tip would show on the title to guide the player how to play tip: 'Press to start' subtitle: @@ -570,11 +570,11 @@ tension_game: fish-start-position: 165 fish-icon-width: 8 success-position: 21 - ultimate-strain: 50 - normal-pull-strain-increase: 1 - struggling-strain-increase: 2 - loosening-strain-loss: 2 - strain: + ultimate-tension: 50 + normal-pull-tension-increase: 1 + struggling-tension-increase: 2 + loosening-tension-loss: 2 + tension: - '뀑' - '뀒' - '뀓'