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
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ public void inventoryClick(InventoryClickEvent e) {
return;
}
p.closeInventory();
if (!isRegistered(h.getStation())) {
p.sendMessage("§cThe station was removed, so nothing can be built there.");
return;
}

ActivePlacement placement = new ActivePlacement(p, h.getStation(), b);
activePlacements.put(p.getUniqueId(), placement);
Expand All @@ -263,6 +267,12 @@ public void onPlayerLeftClick(PlayerInteractEvent e) {
Location stationLoc = placement.getStation().getLocation();
Location clickLoc = p.getLocation();

if (!isRegistered(placement.getStation())) {
activePlacements.remove(uuid);
p.sendMessage("§cBuilding site choice cancelled: the station was removed.");
return;
}

if (!java.util.Objects.equals(clickLoc.getWorld(), stationLoc.getWorld())
|| clickLoc.distanceSquared(stationLoc) > Math.pow(Cache.constructionDistance, 2)) {
p.sendMessage("§cToo far from the station! (max "+Cache.constructionDistance+" blocks)");
Expand Down Expand Up @@ -430,7 +440,17 @@ private boolean remove(Location loc) {
stations.put(loc, station);
return false;
}
// A site choice for the removed station must not start a build on it later.
activePlacements.values().removeIf(placement -> {
if (placement.getStation() != station) return false;
placement.getPlayer().sendMessage("§cBuilding site choice cancelled: the station was removed.");
return true;
});
return true;
}

private boolean isRegistered(ActiveStation station) {
return stations.get(station.getLocation()) == station;
}

}
98 changes: 98 additions & 0 deletions src/test/java/net/tfminecraft/vfbuilders/ManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@
void quitAndBreakRemoveOnlyTheirOwnState() throws Exception {
var s = manager.getStation(block);
placements().put(player.getUniqueId(), new ActivePlacement(player, s, mock(Blueprint.class)));
manager.onPlayerQuit(new PlayerQuitEvent(player, "quit"));

Check warning on line 425 in src/test/java/net/tfminecraft/vfbuilders/ManagerTest.java

View workflow job for this annotation

GitHub Actions / build

PlayerQuitEvent(org.bukkit.entity.Player,java.lang.String) in org.bukkit.event.player.PlayerQuitEvent has been deprecated and marked for removal
assertTrue(placements().isEmpty());
manager.onPlayerQuit(new PlayerQuitEvent(player, "quit"));

Check warning on line 427 in src/test/java/net/tfminecraft/vfbuilders/ManagerTest.java

View workflow job for this annotation

GitHub Actions / build

PlayerQuitEvent(org.bukkit.entity.Player,java.lang.String) in org.bukkit.event.player.PlayerQuitEvent has been deprecated and marked for removal
manager.onBlockBreak(new BlockBreakEvent(player.getWorld().getBlockAt(50, 64, 50), player));
manager.onBlockBreak(new BlockBreakEvent(block, player));
assertNotSame(s, manager.getStation(block));
Expand Down Expand Up @@ -504,4 +504,102 @@
manager.onBlockBreak(new BlockBreakEvent(block, player));
verify(b).drop(any());
}

String drainMessagesUntil(String fragment) {
var mock = (org.mockbukkit.mockbukkit.entity.PlayerMock) player;
for (String m = mock.nextMessage(); m != null; m = mock.nextMessage()) {
if (m.contains(fragment)) return m;
}
return null;
}

@Test
void breakingAnIdleStationDuringSiteChoiceCannotStartABuildOnIt() throws Exception {
var s = manager.getStation(block);
var b = mock(Blueprint.class);
when(b.hasInputs(player)).thenReturn(true);
BlueprintLoader.get().put("windrider", b);
player.teleport(block.getLocation());
manager.inventoryClick(
click(s, tagged("vfb_blueprint_id", "windrider"), net.tfminecraft.vfbuilders.enums.VFBGUI.BLUEPRINT));
assertNotNull(drainMessagesUntil("and left-click"));

manager.onBlockBreak(new BlockBreakEvent(block, player));

assertTrue(placements().isEmpty());
assertNotNull(drainMessagesUntil("the station was removed"));
manager.onPlayerLeftClick(left());
verify(b, never()).takeInputs(player);
assertFalse(s.hasBlueprint());
assertNull(s.getSpawnLocation());
}

@Test
void stalePlacementOnARemovedStationIsDroppedEvenIfAStationReturnsThere() throws Exception {
var old = manager.getStation(block);
var b = mock(Blueprint.class);
when(b.hasInputs(player)).thenReturn(true);
manager.onBlockBreak(new BlockBreakEvent(block, player));
var replacement = manager.getStation(block);
assertNotSame(old, replacement);
player.teleport(block.getLocation());
placements().put(player.getUniqueId(), new ActivePlacement(player, old, b));

manager.onPlayerLeftClick(left());

assertTrue(placements().isEmpty());
verify(b, never()).takeInputs(player);
assertFalse(old.hasBlueprint());
assertFalse(replacement.hasBlueprint());
assertNotNull(drainMessagesUntil("the station was removed"));
}

@Test
void blueprintMenuLeftOpenOnARemovedStationStartsNoSiteChoice() throws Exception {
var s = manager.getStation(block);
var b = mock(Blueprint.class);
when(b.hasInputs(player)).thenReturn(true);
BlueprintLoader.get().put("boat", b);
manager.onBlockBreak(new BlockBreakEvent(block, player));
assertNotSame(s, manager.getStation(block)); // a new station now stands on the same spot

manager.inventoryClick(
click(s, tagged("vfb_blueprint_id", "boat"), net.tfminecraft.vfbuilders.enums.VFBGUI.BLUEPRINT));

assertTrue(placements().isEmpty());
assertNotNull(drainMessagesUntil("nothing can be built there"));
}

@Test
void removingAStationKeepsSiteChoicesForOtherStations() throws Exception {
var other = player.getWorld().getBlockAt(2, 64, 1);
when(api.getChecker().checkBlock(other, "v.stone")).thenReturn(true);
var s = manager.getStation(block);
var otherStation = manager.getStation(other);
var second = server.addPlayer();
var mine = new ActivePlacement(player, s, mock(Blueprint.class));
var theirs = new ActivePlacement(second, otherStation, mock(Blueprint.class));
placements().put(player.getUniqueId(), mine);
placements().put(second.getUniqueId(), theirs);

manager.onBlockBreak(new BlockBreakEvent(block, player));

assertNull(placements().get(player.getUniqueId()));
assertSame(theirs, placements().get(second.getUniqueId()));
}

@Test
void failedRemovalSaveKeepsTheSiteChoiceForTheRestoredStation() throws Exception {
var s = manager.getStation(block);
var mine = new ActivePlacement(player, s, mock(Blueprint.class));
placements().put(player.getUniqueId(), mine);
database.when(() -> Database.saveStationsNow(anyMap())).thenReturn(false);
var event = new BlockBreakEvent(block, player);

manager.onBlockBreak(event);

assertTrue(event.isCancelled());
assertSame(s, manager.getStation(block));
assertSame(mine, placements().get(player.getUniqueId()));
}
}
Loading