Skip to content

Commit 56546db

Browse files
authored
1.0.12 Bugfixes (#33)
* Fix randomjoin not being random * Fix lobby world not loading non-default worlds This commit will address the issue sending a player to a world that was not loaded/created before. * Append -bugfixes suffix to version * Fix empty messages being shown * Replace outdated links with new ones * Add commit patch to version * Fix improper island positioning Due to island position being inaccurate, it caused some islands to clash together. This commit solves #31 issue. * Add debug commands for islands
1 parent 03bab9d commit 56546db

18 files changed

Lines changed: 386 additions & 27 deletions

File tree

build.gradle.kts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ allprojects {
1212
}
1313

1414
group = "io.tofpu.speedbridge2"
15-
version = "1.1.0"
15+
version = "1.1.0-" + "git rev-parse --short=8 HEAD".runCommand(rootDir)
1616

1717
repositories {
1818
mavenLocal()
@@ -72,3 +72,21 @@ allprojects {
7272
}
7373
}
7474
}
75+
76+
fun String.runCommand(
77+
workingDir: File = File("."),
78+
timeoutAmount: Long = 60,
79+
timeoutUnit: TimeUnit = TimeUnit.SECONDS
80+
): String = ProcessBuilder(split("\\s(?=(?:[^'\"`]*(['\"`])[^'\"`]*\\1)*[^'\"`]*$)".toRegex()))
81+
.directory(workingDir)
82+
.redirectOutput(ProcessBuilder.Redirect.PIPE)
83+
.redirectError(ProcessBuilder.Redirect.PIPE)
84+
.start()
85+
.apply { waitFor(timeoutAmount, timeoutUnit) }
86+
.run {
87+
val error = errorStream.bufferedReader().readText().trim()
88+
if (error.isNotEmpty()) {
89+
throw Exception(error)
90+
}
91+
inputStream.bufferedReader().readText().trim()
92+
}

speedbridge2-spigot-plugin/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
id("xyz.jpenilla.run-paper") version "1.0.6"
2+
id("xyz.jpenilla.run-paper") version "2.0.1"
33
}
44

55
dependencies {

speedbridge2-spigot-plugin/src/main/java/io/tofpu/speedbridge2/SpeedBridge.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.bukkit.plugin.java.JavaPlugin;
3131

3232
import java.io.IOException;
33+
import java.lang.reflect.Field;
34+
import java.util.Map;
3335

3436
public final class SpeedBridge {
3537
private static BukkitAudiences adventure;
@@ -71,13 +73,18 @@ public void enable() {
7173
arenaManager, leaderboard);
7274
DynamicClass.alternativeScan(getClass().getClassLoader(), "io.tofpu" +
7375
".speedbridge2");
74-
} catch (final IOException | NoClassDefFoundError e) {
76+
77+
Field objectMap = DynamicClass.class.getDeclaredField("OBJECT_MAP");
78+
objectMap.setAccessible(true);
79+
Map<Class<?>, Object> o = (Map<Class<?>, Object>) objectMap.get(null);
80+
BridgeUtil.debug("key set of dynamic class: " + o.keySet());
81+
} catch (final IOException | NoClassDefFoundError | NoSuchFieldException | IllegalAccessException e) {
7582
throw new IllegalStateException(e);
7683
}
7784

7885
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
7986
ExpansionHandler.INSTANCE.load();
80-
87+
8188
log("Hooking into PlaceholderAPI...");
8289
new PluginExpansion(javaPlugin, playerService);
8390
}
@@ -88,7 +95,7 @@ public void enable() {
8895
IslandSetupHandler.INSTANCE.load();
8996

9097
log("Registering the commands...");
91-
CommandManager.load(javaPlugin, playerService, islandService);
98+
CommandManager.load(javaPlugin, playerService, islandService, arenaManager);
9299

93100
log("Loading the Block Menu GUI.");
94101
BlockMenuManager.INSTANCE.load();

speedbridge2-spigot-plugin/src/main/java/io/tofpu/speedbridge2/command/CommandManager.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import io.tofpu.speedbridge2.command.parser.LampParseRegistry;
1010
import io.tofpu.speedbridge2.command.subcommand.CommandCompletion;
1111
import io.tofpu.speedbridge2.command.subcommand.SpeedBridgeCommand;
12+
import io.tofpu.speedbridge2.command.subcommand.debug.SpeedBridgeDebugCommand;
1213
import io.tofpu.speedbridge2.model.common.util.BridgeUtil;
1314
import io.tofpu.speedbridge2.model.island.IslandService;
15+
import io.tofpu.speedbridge2.model.island.arena.ArenaManager;
1416
import io.tofpu.speedbridge2.model.island.object.Island;
1517
import io.tofpu.speedbridge2.model.player.PlayerFactory;
1618
import io.tofpu.speedbridge2.model.player.PlayerService;
@@ -31,8 +33,8 @@ public final class CommandManager {
3133
private static BukkitCommandHandler commandHandler;
3234

3335
public static void load(final @NotNull Plugin plugin,
34-
final @NotNull PlayerService playerService,
35-
final @NotNull IslandService islandService) {
36+
final @NotNull PlayerService playerService,
37+
final @NotNull IslandService islandService, ArenaManager arenaManager) {
3638
commandHandler = BukkitCommandHandler.create(plugin);
3739

3840
commandHandler.registerResponseHandler(String.class, (response, actor, command) -> {
@@ -83,6 +85,7 @@ public boolean isCustomType(final Class<?> type) {
8385
constructCommandConditions();
8486

8587
commandHandler.register(new SpeedBridgeCommand(playerService, islandService));
88+
commandHandler.register(new SpeedBridgeDebugCommand(arenaManager));
8689
}
8790

8891
private static void constructTabCompleter(final @NotNull IslandService islandService) {
@@ -96,8 +99,10 @@ private static void constructTabCompleter(final @NotNull IslandService islandSer
9699
private static void constructContext() {
97100
final AbstractLampRegistry<?, AbstractLampContext<?>> registry =
98101
DynamicClass.getInstance(LampContextRegistry.class);
102+
99103
if (registry == null) {
100-
return;
104+
BridgeUtil.debug("Unable to find LampContextRegistry instance... shutting down!");
105+
throw new RuntimeException("Unable to find LampContextRegistry instance... shutting down now!");
101106
}
102107

103108
BridgeUtil.debug("Constructing contexts...");
@@ -113,7 +118,8 @@ private static void constructContext() {
113118
private static void constructParsers() {
114119
final AbstractLampRegistry<?, AbstractLampParser<?>> lampParseRegistry = DynamicClass.getInstance(LampParseRegistry.class);
115120
if (lampParseRegistry == null) {
116-
return;
121+
BridgeUtil.debug("Unable to find LampParseRegistry instance... shutting down!");
122+
throw new RuntimeException("Unable to find LampParseRegistry instance... shutting down now!");
117123
}
118124

119125
BridgeUtil.debug("Constructing parsers...");

speedbridge2-spigot-plugin/src/main/java/io/tofpu/speedbridge2/command/subcommand/HelpCommandGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public final class HelpCommandGenerator {
2424
private static final String KEY_STYLE = "<yellow>%s";
2525
private static final String VALUE_STYLE = "<white>%s";
2626
private static final String COMMAND_STYLE = "<yellow>/sb %s %s<dark_gray>- <white>%s";
27+
private static final String DISCORD_LINK = "https://discord.gg/cDQjsHugPw";
2728

2829
private static Component helpMessageComponent = null;
2930

@@ -65,8 +66,7 @@ public static void generateHelpCommand(final @NotNull Plugin plugin) {
6566

6667
builder.title(String.format(TITLE, "Support"))
6768
.pair(String.format(KEY_STYLE, "Discord"), String.format(VALUE_STYLE,
68-
"<click:OPEN_URL:https://tofpu" + ".me/discord>tofpu" +
69-
".me/discord"));
69+
"<click:OPEN_URL:" + DISCORD_LINK + ">" + DISCORD_LINK));
7070

7171
return builder.build();
7272
});

speedbridge2-spigot-plugin/src/main/java/io/tofpu/speedbridge2/command/subcommand/SpeedBridgeCommand.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.bukkit.Location;
2626
import org.bukkit.command.CommandSender;
2727
import org.bukkit.entity.Player;
28+
import org.jetbrains.annotations.NotNull;
2829
import revxrsal.commands.annotation.AutoComplete;
2930
import revxrsal.commands.annotation.Command;
3031
import revxrsal.commands.annotation.Default;
@@ -39,7 +40,9 @@
3940
import java.util.Optional;
4041
import java.util.UUID;
4142
import java.util.concurrent.CompletableFuture;
43+
import java.util.concurrent.ThreadLocalRandom;
4244
import java.util.function.Consumer;
45+
import java.util.stream.Collectors;
4346

4447
import static io.tofpu.speedbridge2.model.common.Message.INSTANCE;
4548
import static io.tofpu.speedbridge2.model.common.util.MessageUtil.Symbols.ARROW_RIGHT;
@@ -77,9 +80,7 @@ public void onLobbySet(final BridgePlayer bridgePlayer) {
7780
ConfigurationManager.INSTANCE.getLobbyCategory()
7881
.setLobbyLocation(bridgePlayer.getPlayer()
7982
.getLocation())
80-
.whenComplete((unused, throwable) -> {
81-
BridgeUtil.sendMessage(bridgePlayer, INSTANCE.lobbySetLocation);
82-
});
83+
.thenRun(() -> BridgeUtil.sendMessage(bridgePlayer, INSTANCE.lobbySetLocation));
8384
}
8485

8586
@Subcommand("create")
@@ -346,11 +347,7 @@ public String onRandomJoin(final BridgePlayer bridgePlayer) {
346347
return INSTANCE.alreadyInAIsland;
347348
}
348349

349-
final Optional<Island> optionalIsland = islandService.getAllIslands()
350-
.stream()
351-
.parallel()
352-
.filter(Island::isReady)
353-
.findAny();
350+
final Optional<Island> optionalIsland = getRandomIsland();
354351

355352
if (!optionalIsland.isPresent()) {
356353
return INSTANCE.noAvailableIsland;
@@ -362,6 +359,17 @@ public String onRandomJoin(final BridgePlayer bridgePlayer) {
362359
return String.format(INSTANCE.joinedAnIsland, island.getSlot() + "");
363360
}
364361

362+
@NotNull
363+
private Optional<Island> getRandomIsland() {
364+
final List<Island> filteredIslands = islandService.getAllIslands()
365+
.stream()
366+
.parallel()
367+
.filter(Island::isReady)
368+
.collect(Collectors.toList());
369+
370+
return Optional.ofNullable(filteredIslands.get(ThreadLocalRandom.current().nextInt(filteredIslands.size())));
371+
}
372+
365373
@Subcommand("setup")
366374
@Description("Create an island setup")
367375
@CommandPermission("speedbridge.setup.admin")
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.tofpu.speedbridge2.command.subcommand.debug;
2+
3+
import com.sk89q.worldedit.EditSession;
4+
import com.sk89q.worldedit.MaxChangedBlocksException;
5+
import com.sk89q.worldedit.WorldEditException;
6+
import com.sk89q.worldedit.bukkit.BukkitWorld;
7+
import com.sk89q.worldedit.extent.clipboard.Clipboard;
8+
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
9+
import com.sk89q.worldedit.function.operation.Operation;
10+
import com.sk89q.worldedit.function.operation.Operations;
11+
import io.tofpu.multiworldedit.EditSessionWrapper;
12+
import io.tofpu.multiworldedit.MultiWorldEditAPI;
13+
import io.tofpu.speedbridge2.model.common.util.BridgeUtil;
14+
import io.tofpu.speedbridge2.model.island.object.land.IslandLand;
15+
16+
import java.io.IOException;
17+
18+
public class DestroyableLand extends IslandLand {
19+
private EditSession editSession;
20+
21+
public DestroyableLand(IslandLand islandLand) {
22+
super(islandLand.getIsland(), islandLand.getWorld(), islandLand.getPositions());
23+
}
24+
25+
@Override
26+
public void generatePlot() throws WorldEditException {
27+
// TODO: Make this generation operation async
28+
BridgeUtil.debug("Generating plot at " + getPlotLocation().toString() + " for " +
29+
"island " + getIsland().getSlot());
30+
31+
final BukkitWorld bukkitWorld = new BukkitWorld(getWorld());
32+
33+
try (final EditSessionWrapper editSessionWrapper = MultiWorldEditAPI.getMultiWorldEdit()
34+
.create(bukkitWorld, -1)) {
35+
final Clipboard schematicClipboard = getIsland().getSchematicClipboard();
36+
this.editSession = editSessionWrapper.to();
37+
38+
final Operation operation = MultiWorldEditAPI.getMultiWorldEdit()
39+
.create(schematicClipboard, editSession, bukkitWorld)
40+
.to((int) getX(), (int) getY(), (int) getZ())
41+
.ignoreAirBlocks(true)
42+
.build();
43+
44+
Operations.completeLegacy(operation);
45+
} catch (IOException e) {
46+
throw new IllegalStateException(e);
47+
}
48+
}
49+
50+
public void destroy() {
51+
// TODO: Make this generation operation async
52+
BridgeUtil.debug("Generating plot at " + getPlotLocation().toString() + " for " +
53+
"island " + getIsland().getSlot());
54+
55+
final BukkitWorld bukkitWorld = new BukkitWorld(getWorld());
56+
57+
try (final EditSessionWrapper editSessionWrapper = MultiWorldEditAPI.getMultiWorldEdit()
58+
.create(bukkitWorld, -1)) {
59+
EditSession session = editSessionWrapper.to();
60+
this.editSession.undo(session);
61+
// session.undo(this.editSession);
62+
} catch (IOException e) {
63+
throw new IllegalStateException(e);
64+
}
65+
this.free();
66+
}
67+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.tofpu.speedbridge2.command.subcommand.debug;
2+
3+
import io.tofpu.speedbridge2.model.player.object.BridgePlayer;
4+
5+
import java.util.UUID;
6+
7+
public class EmptyBridgePlayer extends BridgePlayer {
8+
protected EmptyBridgePlayer(UUID id) {
9+
super(null, null, id);
10+
}
11+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.tofpu.speedbridge2.command.subcommand.debug;
2+
3+
import io.tofpu.speedbridge2.model.island.arena.ArenaManager;
4+
import io.tofpu.speedbridge2.model.island.object.GameIsland;
5+
import io.tofpu.speedbridge2.model.island.object.land.IslandLand;
6+
7+
public class GameIsland2 extends GameIsland {
8+
private IslandLand islandLand;
9+
10+
public GameIsland2(final ArenaManager arenaManager, GameIsland gameIsland) {
11+
super(arenaManager, gameIsland.getIsland(), gameIsland.getGamePlayer());
12+
}
13+
14+
public void setIslandPlot(final IslandLand islandLand) {
15+
this.islandLand = islandLand;
16+
}
17+
18+
@Override
19+
public IslandLand getIslandPlot() {
20+
return this.islandLand;
21+
}
22+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package io.tofpu.speedbridge2.command.subcommand.debug;
2+
3+
import com.sk89q.worldedit.WorldEditException;
4+
import io.tofpu.speedbridge2.model.island.IslandFactory;
5+
import io.tofpu.speedbridge2.model.island.arena.ArenaManager;
6+
import io.tofpu.speedbridge2.model.island.object.GameIsland;
7+
import io.tofpu.speedbridge2.model.island.object.Island;
8+
import io.tofpu.speedbridge2.model.island.object.land.IslandLand;
9+
import io.tofpu.speedbridge2.model.player.object.GamePlayer;
10+
import org.bukkit.Location;
11+
import org.bukkit.entity.Player;
12+
import revxrsal.commands.annotation.Command;
13+
import revxrsal.commands.annotation.Default;
14+
import revxrsal.commands.annotation.Subcommand;
15+
import revxrsal.commands.annotation.Usage;
16+
import revxrsal.commands.bukkit.annotation.CommandPermission;
17+
18+
import java.util.*;
19+
20+
@Command("speedbridge debug")
21+
@CommandPermission("speedbridge.debug")
22+
public class SpeedBridgeDebugCommand {
23+
private final Map<Island, List<GameIsland>> generatedGames = new HashMap<>();
24+
private final ArenaManager arenaManager;
25+
26+
public SpeedBridgeDebugCommand(ArenaManager arenaManager) {
27+
this.arenaManager = arenaManager;
28+
}
29+
30+
@Subcommand("arena teleport")
31+
public String islandTeleport(final Player player) {
32+
double[] positions = arenaManager.getPositions();
33+
player.teleport(new Location(this.arenaManager.getWorld(), positions[0], positions[1], positions[2]));
34+
return String.format("Teleported you to world %s with %s coordinates", arenaManager.getWorld().getName(), positions);
35+
}
36+
37+
@Subcommand("island generate")
38+
@Usage("island generate <island> [amount]")
39+
public String generateGame(final Island island, final @Default("1") int amount) {
40+
for (int i = 0; i < amount; i++) {
41+
generateGame(island);
42+
}
43+
return String.format("Generated %s games of island type %s", amount, island.getSlot());
44+
}
45+
46+
@Subcommand("island destroy")
47+
@Usage("island destroy")
48+
public String islandClear(final Island island) {
49+
int gameAmountDestroyed = destroyGames(island);
50+
int islandType = island.getSlot();
51+
return String.format("Destroyed %s games of island type %s!", gameAmountDestroyed, islandType);
52+
}
53+
54+
private int destroyGames(final Island island) {
55+
List<GameIsland> games = this.generatedGames.get(island);
56+
games.forEach(game -> {
57+
DestroyableLand islandPlot = (DestroyableLand) game.getIslandPlot();
58+
islandPlot.destroy();
59+
});
60+
return games.size();
61+
}
62+
63+
public void generateGame(final Island island) {
64+
final GamePlayer gamePlayer = GamePlayer.of(new EmptyBridgePlayer(UUID.randomUUID()));
65+
final GameIsland2 gameIsland = new GameIsland2(arenaManager, IslandFactory.createGame(island, gamePlayer));
66+
67+
DestroyableLand islandLand = new DestroyableLand(arenaManager.justReservePlot(gameIsland));
68+
try {
69+
islandLand.generatePlot();
70+
} catch (WorldEditException e) {
71+
throw new RuntimeException(e);
72+
}
73+
74+
gameIsland.setIslandPlot(islandLand);
75+
76+
this.generatedGames.compute(island, (island1, gameIslands) -> {
77+
if (gameIslands == null) {
78+
gameIslands = new ArrayList<>();
79+
}
80+
gameIslands.add(gameIsland);
81+
return gameIslands;
82+
});
83+
}
84+
}

0 commit comments

Comments
 (0)