Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions src/main/java/net/tfminecraft/dowsing/managers/NodeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,24 @@ public void run()
{
validate();
for(Node n : nodes) {
try {
if(!n.getIsActive()) continue;
if(!n.hasGuild()) continue;
if(n.getLoc().getChunk().isForceLoaded() == false) {
n.getLoc().getChunk().setForceLoaded(true);
}
if(n.getTimeLeft() <= 0) {
if(!new ItemDropper().dropItems(n)) continue;
n.setTimeLeft(n.getModifiedTime());
n.setInputCounter(0);
}
n.tickCycle();
if(n.getCycleTime().equals(Cache.cycleLength)) {
n.setCycleTime(0);
n.input();
}
if(n.getTimeLeft() > 0) {
n.tick();
} else {
ItemDropper dropper = new ItemDropper();
dropper.dropItems(n);
n.setTimeLeft(n.getModifiedTime());
n.setInputCounter(0);
}
if(!n.getIsActive()) continue;
n.tick();
for(Player p : Bukkit.getOnlinePlayers()) {
if(currentNode.containsKey(p)) {
if(currentNode.get(p).getId().equals(n.getId())) {
Expand All @@ -190,6 +190,10 @@ public void run()
}
}
}
} catch(RuntimeException ex) {
DowsingMain.plugin.getLogger().log(java.util.logging.Level.SEVERE,
"Failed to process node " + n.getId() + " at " + n.getLoc(), ex);
}
}
}
}.runTaskTimer(DowsingMain.plugin, 0L, 1200L);
Expand Down
59 changes: 48 additions & 11 deletions src/main/java/net/tfminecraft/dowsing/utils/ItemDropper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package net.tfminecraft.dowsing.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.function.Function;
import java.util.function.Consumer;

import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.Item;
Expand All @@ -9,8 +16,36 @@
import net.tfminecraft.dowsing.objects.Node;

public class ItemDropper {
public void dropItems(Node n) {
n.getLastResult().clear();
private static final Set<String> unavailableRewardsLogged = new HashSet<>();
private final Function<String, ItemStack> itemFactory;
private final Consumer<String> warning;

public ItemDropper() {
this(new ItemCreator()::getItemFromPath, message -> org.bukkit.Bukkit.getLogger().warning(message));
}

ItemDropper(Function<String, ItemStack> itemFactory, Consumer<String> warning) {
this.itemFactory = itemFactory;
this.warning = warning;
}

/** Returns false when a configured reward cannot be created, so the cycle can retry. */
public boolean dropItems(Node n) {
Map<String, ItemStack> items = new HashMap<>();
for(String key : n.getCompleteDrop().keySet()) {
if(key.equalsIgnoreCase("nothing")) continue;
ItemStack item = itemFactory.apply(key);
if(item == null) {
if(unavailableRewardsLogged.add(key)) {
warning.accept("[Dowsing] Cannot complete node " + n.getId()
+ ": reward item is unavailable: " + key);
}
return false;
}
unavailableRewardsLogged.remove(key);
items.put(key, item);
}
Map<String, Integer> result = new HashMap<>();
Double maxWeight = 0.0;
for(String key : n.getCompleteDrop().keySet()) {
maxWeight = maxWeight+n.getCompleteDrop().get(key);
Expand All @@ -30,22 +65,24 @@ public void dropItems(Node n) {
if(random <= max && random > previous) {
dropped++;
if(!key.equalsIgnoreCase("nothing")) {
Integer a = 1;
if(n.getLastResult().containsKey(key)) {
a = 1+n.getLastResult().get(key);
}
n.getLastResult().put(key, a);
Location loc = new Location(n.getLoc().getWorld(), n.getLoc().getX(), n.getLoc().getY(), n.getLoc().getZ());
loc.add(0.5,2,0.5);
dropItem(loc, key, true);
loc.getWorld().playSound(loc, Sound.ENTITY_ITEM_PICKUP, 0.5f, 1f);
result.merge(key, 1, Integer::sum);
}
break;
}
previous = max;
}
}
n.update();
Location loc = n.getLoc().clone().add(0.5, 2, 0.5);
for(Map.Entry<String, Integer> entry : result.entrySet()) {
for(int count = 0; count < entry.getValue(); count++) {
Item e = loc.getWorld().dropItem(loc, items.get(entry.getKey()).clone());
e.setVelocity(new Vector());
loc.getWorld().playSound(loc, Sound.ENTITY_ITEM_PICKUP, 0.5f, 1f);
}
}
n.setLastResult(result);
return true;
}
public void dropItem(Location loc, String path, Boolean noV) {
ItemCreator ic = new ItemCreator();
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/net/tfminecraft/dowsing/utils/ItemDropperTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.tfminecraft.dowsing.utils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.bukkit.inventory.ItemStack;

import net.tfminecraft.dowsing.objects.Node;

class ItemDropperTest {
@Test
void unavailableRewardKeepsCyclePendingAndLastResultIntact() {
Node node = mock(Node.class);
when(node.getId()).thenReturn(UUID.randomUUID());
Map<String, Double> rewards = new LinkedHashMap<>();
rewards.put("first.item", 100.0);
rewards.put("missing.item", 100.0);
when(node.getCompleteDrop()).thenReturn(rewards);
Map<String, Integer> previous = new HashMap<>(Map.of("old.item", 2));
when(node.getLastResult()).thenReturn(previous);

ItemStack first = mock(ItemStack.class);
assertFalse(new ItemDropper(path -> path.equals("first.item") ? first : null,
message -> {}).dropItems(node));
assertEquals(Map.of("old.item", 2), previous);
verify(node, never()).getLoc();
verify(node, never()).update();
verify(node, never()).setLastResult(any());
}
}