Custom Games

There are two methods to register a custom game type: using an expansion jar or a plugin. Using the expansion jar method requires placing the built jar file into the "expansion" folder, similar to how it works with PlaceholderAPI. If you're using the plugin method to register a custom game type, after adding the custom game factory, you will need to call the CustomFishing's reload function to apply the changes.

Using a plugin

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", "<gray>Reel in at the most critical moment</gray>");

        @Override
        public BiFunction<CustomFishingHook, GameSetting, AbstractGamingPlayer> gamingPlayerProvider() {

            int minWidth = Integer.parseInt(barWidth.split("~")[0]);
            int maxWidth = Integer.parseInt(barWidth.split("~")[1]);
            int minSuccess = Integer.parseInt(barSuccess.split("~")[0]);
            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;
                }
            };
        }
    };
}));

Using an expansion jar