### Getting Plugin Instance Source: https://context7_llms How to obtain the singleton instance of the BukkitCustomFishingPlugin. ```java BukkitCustomFishingPlugin api = BukkitCustomFishingPlugin.getInstance() ``` -------------------------------- ### Project Setup and Dependency Source: https://context7_llms Instructions on how to add the CustomFishing API as a dependency to your PaperMC project, including repository and dependency configurations. ```gradle repositories { maven("https://repo.momirealms.net/releases/") } dependencies { compileOnly("net.momirealms:custom-fishing:{version}") } ``` -------------------------------- ### Building Item Stacks Source: https://context7_llms Example of how to build an ItemStack using the API's item manager, referencing an internal item ID. ```java ItemStack itemStack = api.getItemManager().buildInternal(context, "rubbish"); ``` -------------------------------- ### Lava Fishing Mechanic: preStart() Method Source: https://context7_llms Executes logic before the Lava Fishing Mechanic starts. It sets the 'SURROUNDING' context key to the 'LAVA_FISHING' effect property. ```java @Override public void preStart() { this.context.arg(ContextKeys.SURROUNDING, EffectProperties.LAVA_FISHING.key()); ``` -------------------------------- ### Getting Loot and Converting to ItemStack Source: https://context7_llms Illustrates how to set context arguments for location and surrounding environment, retrieve the next loot, and convert loot items into ItemStacks. ```java context.arg(ContextKeys.LOCATION, player.getLocation()); // sets the player location context.arg(ContextKeys.OTHER_LOCATION, custom_location); // sets the custom location, in most cases, it's the hook's context.arg(ContextKeys.SURROUNDING, "water"); Loot loot = api.getLootManager().getNextLoot(effect, context); if (loot.type() == LootType.ITEM) { ItemStack itemStack = api.getItemManager().buildInternal(context, loot.id()); } ``` -------------------------------- ### Implementing Custom Hook Logics Source: https://context7_llms Guides on how to implement custom fishing mechanics by creating a class that implements the HookMechanic interface and adding it to the available mechanisms. ```java CustomFishingHook.mechanicProviders((h, c, e) -> { ArrayList mechanics = new ArrayList<>(); mechanics.add(new VanillaMechanic(h, c)); mechanics.add(new LavaFishingMechanic(h, e, c)); return mechanics; }); ``` -------------------------------- ### Accessing ItemStack from Event Source: https://context7_llms An example of an event handler for FishingLootSpawnEvent to retrieve the ItemStack from the spawned entity. ```java @EventHandler public void onLootSpawn(FishingLootSpawnEvent event) { if (event.getEntity() instanceof Item item) { ItemStack itemStack = item.getItemStack(); } } ``` -------------------------------- ### Lava Fishing Mechanic: start() Method - Core Loop Source: https://context7_llms Initiates the Lava Fishing Mechanic's main loop. This method handles the fishing logic, including fish nibbling, movement within lava, entity spawning, and state transitions. It uses a repeating scheduler task to manage these actions. ```java @Override public void start(Effect finalEffect) { EventUtils.fireAndForget(new FishingHookStateEvent(context.holder(), hook, FishingHookStateEvent.State.LAND)); this.setWaitTime(finalEffect); this.task = BukkitCustomFishingPlugin.getInstance().getScheduler().sync().runRepeating(() -> { Location location = this.hook.getLocation(); float lavaHeight = 0F; FluidData fluidData = SparrowHeart.getInstance().getFluidData(location); if (fluidData.getFluidType() == Fluid.LAVA || fluidData.getFluidType() == Fluid.FLOWING_LAVA) { lavaHeight = (float) (fluidData.getLevel() * 0.125); } if (this.nibble > 0) { --this.nibble; if (location.getY() % 1 <= lavaHeight) { this.jumpTimer++; if (this.jumpTimer >= 4) { this.jumpTimer = 0; this.hook.setVelocity(new Vector(0,0.24,0)); } } if (this.nibble <= 0) { this.timeUntilLured = 0; this.timeUntilHooked = 0; this.hooked = false; this.jumpTimer = 0; this.currentState = 0; } } else { double hookY = location.getY(); if (hookY < 0) { hookY += Math.abs(Math.floor(hookY)); } if (hookY % 1 <= lavaHeight || this.hook.isInLava()) { Vector previousVector = this.hook.getVelocity(); this.hook.setVelocity(new Vector(previousVector.getX() * 0.6, Math.min(0.1, Math.max(-0.1, previousVector.getY() + 0.07)), previousVector.getZ() * 0.6)); this.currentState = 1; } else { if (currentState == 1) { this.currentState = 0; // set temp entity this.tempEntity = this.hook.getWorld().spawn(location.clone().subtract(0,1,0), ArmorStand.class); this.setTempEntityProperties(this.tempEntity); this.hook.setHookedEntity(this.tempEntity); if (!firstTime) { EventUtils.fireAndForget(new FishingHookStateEvent(context.holder(), hook, FishingHookStateEvent.State.ESCAPE)); } firstTime = false; } } float f; float f1; float f2; double d0; double d1; double d2; if (this.timeUntilHooked > 0) { this.timeUntilHooked -= 1; if (this.timeUntilHooked > 0) { this.fishAngle += (float) RandomUtils.triangle(0.0D, 9.188D); f = this.fishAngle * 0.017453292F; f1 = (float) Math.sin(f); f2 = (float) Math.cos(f); d0 = location.getX() + (double) (f1 * (float) this.timeUntilHooked * 0.1F); ``` -------------------------------- ### Getting Effect Modifiers Source: https://context7_llms Demonstrates how to retrieve an EffectModifier by its name and MechanicType, and how to handle the Optional result. ```java Optional optional = api.getEffectManager().getEffectModifier("beginner_rod", MechanicType.ROD); if (optional.isPresent()) { EffectModifier modifier = optional.get(); } ``` -------------------------------- ### Creating and Applying Effects Source: https://context7_llms Shows how to create a new Effect instance and apply an EffectModifier to it at different stages (CAST, LOOT, FISHING). ```java Effect effect = Effect.newInstance(); // There are three stages in total // CAST: Determines what fishing mechanics are available (such as lava fishing) // LOOT: Affects the weight of the next loot // FISHING: Determines loot-related properties, such as size, and score, and game difficulty modifier.apply(effect, FishingEffectApplyEvent.Stage.CAST, context); ``` -------------------------------- ### Creating Player Context Source: https://context7_llms Demonstrates how to create a context for a player, either with a valid player object or with null, with a warning about using null contexts. ```java Player player = Bukkit.getPlayer("player"); Context context = Context.player(player); // You can create it with null, but please be careful not to use it in any place // where a player is needed, such as checking permissions, sending messages Context context = Context.player(null); ``` -------------------------------- ### GameBasics Configuration Source: https://context7_llms Provides a method to build GameBasics objects from a section, extracting difficulty and time settings. It uses MathValue.auto for flexible value parsing. ```java private GameBasics getGameBasics(Section section) { return GameBasics.builder() .difficulty(MathValue.auto(section.get("difficulty", "20~80"), false)) .time(MathValue.auto(section.get("time", 15), false)) .build(); } ``` -------------------------------- ### LavaFishingMechanic Implementation Source: https://context7_llms The beginning of the LavaFishingMechanic class, implementing the HookMechanic interface, and importing necessary classes from the CustomFishing API and Sparrow library. ```java package net.momirealms.customfishing.api.mechanic.fishing.hook; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.event.FishingHookStateEvent; import net.momirealms.customfishing.api.mechanic.config.ConfigManager; import net.momirealms.customfishing.api.mechanic.context.Context; import net.momirealms.customfishing.api.mechanic.context.ContextKeys; import net.momirealms.customfishing.api.mechanic.effect.Effect; import net.momirealms.customfishing.api.mechanic.effect.EffectProperties; import net.momirealms.customfishing.api.util.EventUtils; import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask; import net.momirealms.customfishing.common.util.RandomUtils; import net.momirealms.sparrow.heart.SparrowHeart; import net.momirealms.sparrow.heart.feature.fluid.FluidData; import org.bukkit.*; import org.bukkit.block.BlockFace; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; public class LavaFishingMechanic implements HookMechanic { ``` -------------------------------- ### Plugin Configuration Source: https://context7_llms How to declare CustomFishing as a dependency in your plugin.yml file. ```yaml depend: - CustomFishing ``` -------------------------------- ### Registering Integration Providers Source: https://context7_llms Shows how to register various providers (items, creatures, enchantments, etc.) with the IntegrationManager to extend plugin functionality and reload the plugin to apply changes. ```java BukkitCustomFishingPlugin api = BukkitCustomFishingPlugin.getInstance(); api.getIntegrationManager().registerBlockProvider(...); api.getIntegrationManager().registerEnchantmentProvider(...); api.getIntegrationManager().registerEntityProvider(...); api.getIntegrationManager().registerSeasonProvider(...); api.getIntegrationManager().registerLevelerProvider(...); api.getIntegrationManager().registerItemProvider(...); api.reload(); ``` -------------------------------- ### Lava Fishing Mechanic Initialization and Properties Source: https://context7_llms Details the constructor and member variables of the LavaFishingMechanic class, which manages the fishing process in lava. It initializes the hook, effects, context, and various timers and state variables. ```java private final FishHook hook; private final Effect gearsEffect; private final Context context; private ArmorStand tempEntity; private SchedulerTask task; private int timeUntilLured; private int timeUntilHooked; private int nibble; private boolean hooked; private float fishAngle; private int currentState; private int jumpTimer; private boolean firstTime = true; private boolean freeze = false; public LavaFishingMechanic(FishHook hook, Effect gearsEffect, Context context) { this.hook = hook; this.gearsEffect = gearsEffect; this.context = context; } ``` -------------------------------- ### Fishing Game Logic Implementation Source: https://context7_llms Implements the core game loop, pointer movement, and UI rendering for a fishing mini-game. It uses random number generation for game parameters and SparrowHeart for displaying titles and subtitles to the player. The success condition is checked based on the pointer's position relative to the target zone. ```java private final int totalWidth = RandomUtils.generateRandomInt(minWidth, maxWidth); private final int successWidth = RandomUtils.generateRandomInt(minSuccess, maxSuccess); private final int successPosition = ThreadLocalRandom.current().nextInt((totalWidth - successWidth + 1)) + 1; private int currentIndex = 0; private int timer = 0; private boolean face = true; @Override protected void tick() { timer++; if (timer % ((106 - (int) settings.difficulty()) / 5) == 0) { movePointer(); } showUI(); } private void movePointer() { if (face) { currentIndex++; if (currentIndex >= totalWidth - 1) { face = false; } } else { currentIndex--; if (currentIndex <= 0) { face = true; } } } private void showUI() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 1; i <= totalWidth; i++) { if (i == currentIndex + 1) { stringBuilder.append(barPointer); continue; } if (i >= successPosition && i <= successPosition + successWidth - 1) { stringBuilder.append(barTarget); continue; } stringBuilder.append(barBody); } SparrowHeart.getInstance().sendTitle(getPlayer(), AdventureHelper.miniMessageToJson(left + stringBuilder + right), AdventureHelper.miniMessageToJson(subtitle), 0, 20, 0); } @Override public boolean isSuccessful() { if (isTimeOut) return false; return currentIndex + 1 <= successPosition + successWidth - 1 && currentIndex + 1 >= successPosition; } ``` -------------------------------- ### Setting Temporary Entity Properties Source: https://context7_llms Configures properties for a temporary ArmorStand entity, making it invisible, non-collidable, invulnerable, and setting its persistent data container. ```java private void setTempEntityProperties(ArmorStand entity) { entity.setInvisible(true); entity.setCollidable(false); entity.setInvulnerable(true); entity.setVisible(false); entity.setCustomNameVisible(false); entity.setSmall(true); entity.setGravity(false); entity.getPersistentDataContainer().set( Objects.requireNonNull(NamespacedKey.fromString("temp-entity", BukkitCustomFishingPlugin.getInstance().getBootstrap())), PersistentDataType.STRING, "lava" ); } ``` -------------------------------- ### Fishing Hook Particle Effects and State Management Source: https://context7_llms Handles the spawning of particle effects (FLAME) for fishing hooks, manages the state transitions (BITE, LURE), and plays sound effects. It also includes logic for removing temporary entities and cancelling tasks. ```java d1 = location.getY(); d2 = location.getZ() + (double) (f2 * (float) this.timeUntilHooked * 0.1F); if (RandomUtils.generateRandomFloat(0,1) < 0.15F) { hook.getWorld().spawnParticle(Particle.FLAME, d0, d1 - 0.10000000149011612D, d2, 1, f1, 0.1D, f2, 0.0D); } float f3 = f1 * 0.04F; float f4 = f2 * 0.04F; hook.getWorld().spawnParticle(Particle.FLAME, d0, d1, d2, 0, f4, 0.01D, -f3, 1.0D); } else { double d3 = location.getY() + 0.5D; hook.getWorld().spawnParticle(Particle.FLAME, location.getX(), d3, location.getZ(), (int) (1.0F + 0.3 * 20.0F), 0.3, 0.0D, 0.3, 0.20000000298023224D); this.nibble = RandomUtils.generateRandomInt(20, 40); this.hooked = true; hook.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXTINGUISH_FIRE, 0.25F, 1.0F + (RandomUtils.generateRandomFloat(0,1)-RandomUtils.generateRandomFloat(0,1)) * 0.4F); EventUtils.fireAndForget(new FishingHookStateEvent(context.holder(), hook, FishingHookStateEvent.State.BITE)); if (this.tempEntity != null && this.tempEntity.isValid()) { this.tempEntity.remove(); } } } else if (timeUntilLured > 0) { if (!freeze) { timeUntilLured--; } if (this.timeUntilLured <= 0) { this.fishAngle = RandomUtils.generateRandomFloat(0F, 360F); this.timeUntilHooked = RandomUtils.generateRandomInt(20, 80); EventUtils.fireAndForget(new FishingHookStateEvent(context.holder(), hook, FishingHookStateEvent.State.LURE)); } } else { setWaitTime(finalEffect); } } }, 1, 1, hook.getLocation()); ``` -------------------------------- ### Lava Fishing Mechanic: canStart() Method Source: https://context7_llms Determines if the Lava Fishing Mechanic can be initiated. It checks if the 'LAVA_FISHING' effect property is enabled and if the fishing hook is currently in lava or positioned correctly relative to lava. ```java @Override public boolean canStart() { if (!(boolean) gearsEffect.properties().getOrDefault(EffectProperties.LAVA_FISHING, false)) { return false; } if (hook.isInLava()) { return true; } float lavaHeight = 0F; Location location = this.hook.getLocation(); FluidData fluidData = SparrowHeart.getInstance().getFluidData(location); if (fluidData.getFluidType() == Fluid.LAVA || fluidData.getFluidType() == Fluid.FLOWING_LAVA) { lavaHeight = (float) (fluidData.getLevel() * 0.125); } return lavaHeight > 0 && location.getY() % 1 <= lavaHeight; ``` -------------------------------- ### CustomGameFactory API Source: https://context7_llms Provides an interface for creating custom fishing game types. It allows developers to define game versions, authors, types, and factory implementations for new game mechanics. ```APIDOC CustomGameFactory extends GameExpansion getVersion(): string - Returns the version of the game expansion. getAuthor(): string - Returns the author of the game expansion. getGameType(): string - Returns the unique identifier for the game type. getGameFactory(): GameFactory - Returns a GameFactory instance for creating game instances. GameFactory invoke(id: string, section: Section): AbstractGame - Creates and returns an AbstractGame instance. - Parameters: - id: The unique identifier for the game. - section: A Section object containing game configuration settings. AbstractGame constructor(id: string, basics: GameBasics) - Initializes an AbstractGame. - Parameters: - id: The unique identifier for the game. - basics: Basic game information. gamingPlayerProvider(): BiFunction - Provides a function to create AbstractGamingPlayer instances. AbstractGamingPlayer constructor(customFishingHook: CustomFishingHook, gameSetting: GameSetting) - Initializes an AbstractGamingPlayer. - Parameters: - customFishingHook: The custom fishing hook instance. - gameSetting: The game settings. tick(): void - Called every game tick to update game state. isSuccessful(): boolean - Checks if the player's action was successful. ``` -------------------------------- ### Registering Accurate Click v2 Game Type Source: https://context7_llms Registers a new game type named 'accurate_click_v2' with the game manager. This function initializes the game basics and returns an AbstractGame instance. ```java BukkitCustomFishingPlugin.getInstance().getGameManager().registerGameType("accurate_click_v2", ((id, section) -> { GameBasics basics = getGameBasics(section); return new AbstractGame(id, basics) { private final String barWidth = section.getString("title.total-width", "15~20"); private final String barSuccess = section.getString("title.success-width","3~4"); private final String barBody = section.getString("title.body",""); private final String left = section.getString("title.left",""); private final String right = section.getString("title.right",""); private final String barPointer = section.getString("title.pointer", ""); private final String barTarget = section.getString("title.target",""); private final String subtitle = section.getString("subtitle", "Reel in at the most critical moment"); @Override public BiFunction gamingPlayerProvider() { int minWidth = Integer.parseInt(barWidth.split("~")[0]); int maxWidth = Integer.parseInt(barWidth.split("~")[1]); int minSuccess = Integer.parseInt(barSuccess.split("~")[0]); ``` -------------------------------- ### Custom Fishing Game Logic Source: https://context7_llms Implements the core logic for a custom fishing game, including pointer movement, UI display, and success condition checking. It uses game settings to determine difficulty and visual elements. ```java int maxSuccess = Integer.parseInt(barSuccess.split("~")[1]); return (customFishingHook, gameSetting) -> new AbstractGamingPlayer(customFishingHook, gameSetting) { private final int totalWidth = RandomUtils.generateRandomInt(minWidth, maxWidth); private final int successWidth = RandomUtils.generateRandomInt(minSuccess, maxSuccess); private final int successPosition = ThreadLocalRandom.current().nextInt((totalWidth - successWidth + 1)) + 1; private int currentIndex = 0; private int timer = 0; private boolean face = true; @Override protected void tick() { timer++; if (timer % ((106 - (int) settings.difficulty()) / 5) == 0) { movePointer(); } showUI(); } private void movePointer() { if (face) { currentIndex++; if (currentIndex >= totalWidth - 1) { face = false; } } else { currentIndex--; if (currentIndex <= 0) { face = true; } } } private void showUI() { StringBuilder stringBuilder = new StringBuilder(); for (int i = 1; i <= totalWidth; i++) { if (i == currentIndex + 1) { stringBuilder.append(barPointer); continue; } if (i >= successPosition && i <= successPosition + successWidth - 1) { stringBuilder.append(barTarget); continue; } stringBuilder.append(barBody); } SparrowHeart.getInstance().sendTitle(getPlayer(), AdventureHelper.miniMessageToJson(left + stringBuilder + right), AdventureHelper.miniMessageToJson(subtitle), 0, 20, 0); } @Override public boolean isSuccessful() { if (isTimeOut) return false; return currentIndex + 1 <= successPosition + successWidth - 1 && currentIndex + 1 >= successPosition; } }; } }; })) ``` -------------------------------- ### Wait Time Calculation for Fishing Effects Source: https://context7_llms Calculates and sets the wait time for fishing, adjusting it based on effect multipliers and adders. It also logs the wait time for debugging purposes. ```java private void setWaitTime(Effect effect) { int before = ThreadLocalRandom.current().nextInt(ConfigManager.lavaMaxTime() - ConfigManager.lavaMinTime() + 1) + ConfigManager.lavaMinTime(); int after = Math.max(ConfigManager.lavaMinTime(), (int) (before * effect.waitTimeMultiplier() + effect.waitTimeAdder())); BukkitCustomFishingPlugin.getInstance().debug("Wait time: " + before + " -> " + after + " ticks"); this.timeUntilLured = after; } ``` -------------------------------- ### Fishing Hook State and Lifecycle Management Source: https://context7_llms Provides methods to check if a fishing hook is hooked, destroy the hook and its associated tasks, freeze the hook's state, and unfreeze it. ```java @Override public boolean isHooked() { return hooked; } @Override public void destroy() { if (this.tempEntity != null && this.tempEntity.isValid()) { this.tempEntity.remove(); } if (this.task != null) { this.task.cancel(); } freeze = false; } @Override public void freeze() { freeze = true; } @Override public void unfreeze(Effect effect) { freeze = false; } ``` -------------------------------- ### Lava Fishing Mechanic: shouldStop() Method Source: https://context7_llms Determines if the Lava Fishing Mechanic should terminate. The mechanic stops if the hook is no longer in lava and is either on the ground or not adjacent to lava blocks. ```java @Override public boolean shouldStop() { if (hook.isInLava()) { return false; } return hook.isOnGround() || (hook.getLocation().getBlock().getType() != Material.LAVA && hook.getLocation().getBlock().getRelative(BlockFace.DOWN).getType() != Material.LAVA); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.