Skip to content

Commit cd3df31

Browse files
authored
Merge pull request #294 from Vftdan/fishing-loot-override
Use modules' fishing loot tables to randomly override fished items
2 parents d291a79 + c19286a commit cd3df31

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

vane-core/src/main/java/org/oddlama/vane/core/LootTable.java

+26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.oddlama.vane.core;
22

3+
import java.util.ArrayList;
4+
import java.util.Collections;
35
import java.util.HashMap;
46
import java.util.List;
57
import java.util.Map;
@@ -33,6 +35,12 @@ public Map<NamespacedKey, List<LootTableEntry>> possible_loot() {
3335
return possible_loot;
3436
}
3537

38+
public List<LootTableEntry> flat_copy() {
39+
List<LootTableEntry> list = new ArrayList<>();
40+
possible_loot.values().forEach(list::addAll);
41+
return list;
42+
}
43+
3644
public void generate_loot(final List<ItemStack> output, final Random random) {
3745
for (final var set : possible_loot.values()) {
3846
for (final var loot : set) {
@@ -43,6 +51,24 @@ public void generate_loot(final List<ItemStack> output, final Random random) {
4351
}
4452
}
4553

54+
public ItemStack generate_override(final Random random) {
55+
double total_chance = 0;
56+
final double threshold = random.nextDouble();
57+
final List<ItemStack> result_container = new ArrayList<>(1);
58+
final var loot_list = flat_copy();
59+
Collections.shuffle(loot_list, random);
60+
for (final var loot : loot_list) {
61+
total_chance += loot.chance;
62+
if (total_chance > threshold) {
63+
loot.add_sample(result_container, random);
64+
}
65+
if (!result_container.isEmpty()) {
66+
return result_container.get(0);
67+
}
68+
}
69+
return null;
70+
}
71+
4672
public static class LootTableEntry {
4773

4874
public double chance;

vane-core/src/main/java/org/oddlama/vane/core/module/Module.java

+48
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,19 @@
2727
import org.bstats.bukkit.Metrics;
2828
import org.bukkit.NamespacedKey;
2929
import org.bukkit.OfflinePlayer;
30+
import org.bukkit.attribute.Attribute;
3031
import org.bukkit.configuration.file.YamlConfiguration;
32+
import org.bukkit.enchantments.Enchantment;
33+
import org.bukkit.entity.FishHook;
34+
import org.bukkit.entity.Item;
35+
import org.bukkit.entity.Player;
3136
import org.bukkit.event.EventHandler;
3237
import org.bukkit.event.EventPriority;
3338
import org.bukkit.event.HandlerList;
3439
import org.bukkit.event.Listener;
40+
import org.bukkit.event.player.PlayerFishEvent;
3541
import org.bukkit.event.world.LootGenerateEvent;
42+
import org.bukkit.inventory.ItemStack;
3643
import org.bukkit.loot.LootTables;
3744
import org.bukkit.permissions.Permission;
3845
import org.bukkit.permissions.PermissionAttachment;
@@ -515,4 +522,45 @@ public void on_module_loot_generate(final LootGenerateEvent event) {
515522
(loc.getBlockZ() & (0xffff << 48)));
516523
additional_loot_table.generate_loot(event.getLoot(), local_random);
517524
}
525+
526+
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
527+
public void on_module_player_caught_fish(final PlayerFishEvent event) {
528+
// This is a dirty non-commutative way to apply fishing loot tables
529+
// that skews subtable probabilities,
530+
// consider somehow programmatically generating datapacks or
531+
// modifying loot tables directly instead.
532+
if (event.getState() != PlayerFishEvent.State.CAUGHT_FISH) {
533+
return;
534+
}
535+
if (event.getCaught() instanceof Item item_entity) {
536+
final Player player = event.getPlayer();
537+
final FishHook hook_entity = event.getHook();
538+
final double player_luck = player.getAttribute(Attribute.LUCK).getValue();
539+
final ItemStack rod_stack = player.getInventory().getItem(event.getHand());
540+
final double rod_luck = rod_stack.getEnchantmentLevel(Enchantment.LUCK_OF_THE_SEA); // Can bukkit provide access to fishing_luck_bonus of 1.24 item component system?
541+
final double total_luck = player_luck + rod_luck;
542+
final double weight_fish = Math.max(0, 85 + total_luck * -1);
543+
final double weight_junk = Math.max(0, 10 + total_luck * -2);
544+
final double weight_treasure = hook_entity.isInOpenWater() ? Math.max(0, 5 + total_luck * 2) : 0;
545+
final double roll = random.nextDouble() * (weight_fish + weight_junk + weight_treasure);
546+
NamespacedKey key;
547+
if (roll < weight_fish) {
548+
key = LootTables.FISHING_FISH.getKey();
549+
} else if (roll < weight_fish + weight_junk) {
550+
key = LootTables.FISHING_JUNK.getKey();
551+
} else {
552+
key = LootTables.FISHING_TREASURE.getKey();
553+
}
554+
final var additional_loot_table = additional_loot_tables.get(key);
555+
if (additional_loot_table == null) {
556+
// Do not modify the caught item
557+
return;
558+
}
559+
final var new_item = additional_loot_table.generate_override(new Random(random.nextInt()));
560+
if (new_item == null) {
561+
return;
562+
}
563+
item_entity.setItemStack(new_item);
564+
}
565+
}
518566
}

0 commit comments

Comments
 (0)