Skip to content

Commit

Permalink
Improvements to the demo command
Browse files Browse the repository at this point in the history
* Added better UI for background tasks which might take a while
* /fml confirm command no longer needed
* Demo world no longer wrecks any other worlds on the server
* There are still issues with re-loading the demo
* Players never get sent back to their original locations (EntitySnapshots not working)
* Player inventory never emptied for beginning of match
* Leave command actually used
* BlockSnapshots are part of a GameConfig, but they're still not saved

Saving BlockSnapshots is really expensive. I need to find a better way to
do this: maybe just write out chunks, or always unzip a new world.
  • Loading branch information
mattysweeps committed Mar 8, 2019
1 parent 9008d44 commit f2a4d28
Show file tree
Hide file tree
Showing 35 changed files with 433 additions and 220 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ NOTE: Players participating in the demo must be opped.
Installing the plugin on your server gives you instant access to survival games. just run ```/ssg demo``` to have the demo worlds and config files automatically downloaded. BE WARNED: running this command replaces your world with another one (still working out bugs), so please run it on a fresh server.
Run these commands to get the server running:
- ```/ssg demo```
- (Watch the terminal for a prompt to enter `/fml confirm`. This is necessary because the demo map is from an older version of Minecraft.)
- ```/ssg load demo demo.yml```
- ```/ssg set blocks demo```
- ```/ssg ready demo```
Expand Down
1 change: 1 addition & 0 deletions scripts/upload-javadoc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ git clone --single-branch --branch ${BRANCH_NAME} https://${GH_TOKEN}@github.com
cd ${BRANCH_NAME}

pwd
ls -R ../build/

# Remove existing docs
echo "Removing existing docs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
import org.spongepowered.api.command.args.CommandContext;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.world.DimensionTypes;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.WorldArchetype;
import org.spongepowered.api.world.storage.WorldProperties;

import javax.annotation.Nonnull;
Expand All @@ -53,19 +55,20 @@
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import static io.github.m0pt0pmatt.survivalgames.Util.sendSuccess;

class DemoCommand extends LeafCommand {

private static final DemoCommand INSTANCE = new DemoCommand();

private static final String DEMO_MAP_OBJECT = "ssg-demo-map_v2.zip";
private static final String DEMO_MAP_OBJECT = "ssg-demo-map_v3.zip";

private static final String DEMO_MAP_WORLD_NAME = "ssg-demo-map";

private static final String DEMO_MAP_ID = "e6514a90-390f-4481-8d4d-56d30660c849";

private static final String S3_BUCKET =
"https://s3.amazonaws.com/com.cloudcraftnetwork.survivalgames.maps/";

Expand All @@ -78,8 +81,6 @@ private DemoCommand() {
public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext args)
throws CommandException {

deleteExistingWorld(src, DEMO_MAP_WORLD_NAME);

URL url;
try {
url = new URL(S3_BUCKET + DEMO_MAP_OBJECT);
Expand All @@ -90,7 +91,7 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
UrlDownloadRunnable urlDownloadRunnable = new UrlDownloadRunnable(url, DEMO_MAP_OBJECT, 24869722);
Runnable unzipRunnable = () -> {

File existing = new File("world", DEMO_MAP_WORLD_NAME);
File existing = new File(Sponge.getServer().getDefaultWorldName(), DEMO_MAP_WORLD_NAME);
if (existing.exists()) {
try {
MoreFiles.deleteRecursively(existing.toPath(), RecursiveDeleteOption.ALLOW_INSECURE);
Expand All @@ -99,18 +100,29 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
}
}

new UnzipRunnable(DEMO_MAP_OBJECT, "world").run();
new UnzipRunnable(DEMO_MAP_OBJECT, Sponge.getServer().getDefaultWorldName()).run();
};

TemporalAmount timeout = Duration.of(60, ChronoUnit.SECONDS);

ProgressBuilder.builder(src, SurvivalGamesPlugin.SYNC_EXECUTOR, SurvivalGamesPlugin.ASYNC_EXECUTOR)
.runSync(new DotProgressable(this::deleteExistingWorld), "Deleting Old World", timeout)
.runAsync(urlDownloadRunnable, "Downloading World", timeout)
.runAsync(new DotProgressable(unzipRunnable), "Unzipping World", timeout)
.runSync(new DotProgressable(() -> {

if (!Sponge.getServer().loadWorld(DEMO_MAP_WORLD_NAME).isPresent()) {
throw new RuntimeException("Could not load world, check logs");
try {
WorldProperties props = Sponge.getServer().createWorldProperties(DEMO_MAP_WORLD_NAME, WorldArchetype.builder()
.dimension(DimensionTypes.OVERWORLD)
.enabled(true)
.pvp(true)
.build(UUID.randomUUID().toString(), DEMO_MAP_WORLD_NAME));

if (!Sponge.getServer().loadWorld(props).isPresent()) {
throw new RuntimeException("Could not load world, check logs");
}
} catch (IOException e) {
throw new RuntimeException(e);
}

}), "Loading World", timeout)
Expand Down Expand Up @@ -141,16 +153,30 @@ private void downloadConfig() {
}
}

private void deleteExistingWorld(CommandSource src, String worldName) {
Optional<World> existingWorld = Sponge.getServer().getWorld(worldName);
existingWorld.ifPresent(
world -> {
WorldProperties properties = world.getProperties();
src.sendMessage(Text.of("Unloading: ", worldName));
Sponge.getServer().unloadWorld(world);
src.sendMessage(Text.of("Deleting: ", worldName));
Sponge.getServer().deleteWorld(properties);
});
private void deleteExistingWorld() {

Optional<World> world = Sponge.getServer().getWorld(DEMO_MAP_WORLD_NAME);
if (world.isPresent()) {
World w = world.get();
if (!Sponge.getServer().unloadWorld(w)) {
throw new RuntimeException("Could not unload demo world");
}
}

Optional<WorldProperties> worldProperties = Sponge.getServer().getWorldProperties(DEMO_MAP_WORLD_NAME);
if (worldProperties.isPresent()) {
WorldProperties wp = worldProperties.get();
CompletableFuture<Boolean> future = Sponge.getServer().deleteWorld(wp);
try {
if (!future.get(60, TimeUnit.SECONDS)) {
throw new RuntimeException("Could not delete demo world");
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("Could not delete demo world");
}
}
}

static DemoCommand getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext

Player player = (Player) src;

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

survivalGame.getPlayerUUIDs().add(player.getUniqueId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext

Player player = (Player) src;

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

survivalGame.getPlayerUUIDs().remove(player.getUniqueId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static io.github.m0pt0pmatt.survivalgames.Util.getOrThrow;
import static io.github.m0pt0pmatt.survivalgames.Util.sendSuccess;

import io.github.m0pt0pmatt.survivalgames.SurvivalGamesPlugin;
import io.github.m0pt0pmatt.survivalgames.command.CommandKeys;
import io.github.m0pt0pmatt.survivalgames.command.element.ConfigFileCommandElement;
import io.github.m0pt0pmatt.survivalgames.data.GameConfig;
Expand All @@ -35,6 +36,9 @@
import java.io.IOException;
import java.nio.file.Path;
import javax.annotation.Nonnull;

import io.github.m0pt0pmatt.survivalgames.thread.DotProgressable;
import io.github.m0pt0pmatt.survivalgames.thread.ProgressBuilder;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
Expand Down Expand Up @@ -66,30 +70,39 @@ private LoadConfigCommand() {
public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext args)
throws CommandException {

Path potentialFile = (Path) getOrThrow(args, CommandKeys.FILE_PATH);
String survivalGameName = (String) getOrThrow(args, CommandKeys.SURVIVAL_GAME_NAME);
ProgressBuilder.builder(src, SurvivalGamesPlugin.SYNC_EXECUTOR, SurvivalGamesPlugin.ASYNC_EXECUTOR)
.runAsync(new DotProgressable(() -> {
try {
Path potentialFile = (Path) getOrThrow(args, CommandKeys.FILE_PATH);
String survivalGameName = (String) getOrThrow(args, CommandKeys.SURVIVAL_GAME_NAME);

if (SurvivalGameRepository.contains(survivalGameName)) {
throw new CommandException(Text.of("Already exists a game of the same name"));
}

if (SurvivalGameRepository.contains(survivalGameName)) {
throw new CommandException(Text.of("Already exists a game of the same name"));
}
ConfigurationLoader<CommentedConfigurationNode> loader =
HoconConfigurationLoader.builder().setPath(potentialFile).build();
try {

ConfigurationLoader<CommentedConfigurationNode> loader =
HoconConfigurationLoader.builder().setPath(potentialFile).build();
try {
CommentedConfigurationNode node = loader.load(ConfigurationOptions.defaults());

CommentedConfigurationNode node = loader.load(ConfigurationOptions.defaults());
ObjectMapper.BoundInstance i = GameConfig.OBJECT_MAPPER.bindToNew();
GameConfig config = (GameConfig) i.populate(node);
SurvivalGame game = new SurvivalGame(survivalGameName, config);
SurvivalGameRepository.put(survivalGameName, game);

ObjectMapper.BoundInstance i = GameConfig.OBJECT_MAPPER.bindToNew();
GameConfig config = (GameConfig) i.populate(node);
SurvivalGame game = new SurvivalGame(survivalGameName, config);
SurvivalGameRepository.put(survivalGameName, game);
} catch (IOException | ObjectMappingException | RuntimeException e) {
e.printStackTrace();
throw new CommandException(Text.of("An error occurred when loading"));
}

} catch (IOException | ObjectMappingException | RuntimeException e) {
e.printStackTrace();
throw new CommandException(Text.of("An error occurred when loading"));
}
sendSuccess(src, "Survival Game Loaded", survivalGameName);
} catch (CommandException e) {
throw new RuntimeException(e);
}
}), "Loading", null)
.start();

sendSuccess(src, "Survival Game Loaded", survivalGameName);
return CommandResult.success();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class RootCommand extends ParentCommand {
.put(toEntry(DemoCommand.getInstance()))
.put(toEntry(TeleportCommand.getInstance()))
.put(toEntry(JoinCommand.getInstance()))
.put(toEntry(LeaveCommand.getInstance()))
.put(toEntry(SpectateCommand.getInstance()))
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
import java.io.IOException;
import java.nio.file.Path;
import javax.annotation.Nonnull;

import io.github.m0pt0pmatt.survivalgames.thread.DotProgressable;
import io.github.m0pt0pmatt.survivalgames.thread.ProgressBuilder;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
Expand Down Expand Up @@ -68,31 +71,40 @@ private SaveConfigCommand() {
public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext args)
throws CommandException {

Path potentialFile;
ProgressBuilder.builder(src, SurvivalGamesPlugin.SYNC_EXECUTOR, SurvivalGamesPlugin.ASYNC_EXECUTOR)
.runAsync(new DotProgressable(() -> {
try {
Path potentialFile;

if (args.hasAny(CommandKeys.FILE_PATH)) {
potentialFile = (Path) getOrThrow(args, CommandKeys.FILE_PATH);
} else if (args.hasAny(CommandKeys.FILE_NAME)) {
String potentialFileName = (String) getOrThrow(args, CommandKeys.FILE_NAME);
potentialFile = SurvivalGamesPlugin.CONFIG_DIRECTORY.resolve(potentialFileName);
} else {
throw new CommandException(Text.of("No file name"));
}

SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
ConfigurationLoader<CommentedConfigurationNode> loader =
HoconConfigurationLoader.builder().setPath(potentialFile).build();
try {
CommentedConfigurationNode node = loader.load(ConfigurationOptions.defaults());
ObjectMapper.BoundInstance i = GameConfig.OBJECT_MAPPER.bind(survivalGame.getConfig());
i.serialize(node);
loader.save(node);
} catch (IOException | ObjectMappingException | RuntimeException e) {
e.printStackTrace();
throw new CommandException(Text.of("Error saving to file"), e);
}

if (args.hasAny(CommandKeys.FILE_PATH)) {
potentialFile = (Path) getOrThrow(args, CommandKeys.FILE_PATH);
} else if (args.hasAny(CommandKeys.FILE_NAME)) {
String potentialFileName = (String) getOrThrow(args, CommandKeys.FILE_NAME);
potentialFile = SurvivalGamesPlugin.CONFIG_DIRECTORY.resolve(potentialFileName);
} else {
throw new CommandException(Text.of("No file name"));
}
sendSuccess(src, "Survival Game Saved", potentialFile.getFileName());
} catch (CommandException e) {
throw new RuntimeException(e);
}

SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
ConfigurationLoader<CommentedConfigurationNode> loader =
HoconConfigurationLoader.builder().setPath(potentialFile).build();
try {
CommentedConfigurationNode node = loader.load(ConfigurationOptions.defaults());
ObjectMapper.BoundInstance i = GameConfig.OBJECT_MAPPER.bind(survivalGame.getConfig());
i.serialize(node);
loader.save(node);
} catch (IOException | ObjectMappingException | RuntimeException e) {
e.printStackTrace();
throw new CommandException(Text.of("Error saving to file"), e);
}
}), "Saving", null).start();

sendSuccess(src, "Survival Game Saved", potentialFile.getFileName());
return CommandResult.success();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext

Player player = (Player) src;

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

survivalGame.getSpectatorUUIDs().add(player.getUniqueId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
Player player = (Player) getOrThrow(args, CommandKeys.PLAYER);

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

survivalGame.getPlayerUUIDs().add(player.getUniqueId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
Player player = (Player) getOrThrow(args, CommandKeys.PLAYER);

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

survivalGame.getSpectatorUUIDs().add(player.getUniqueId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
Player player = (Player) getOrThrow(args, CommandKeys.PLAYER);

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

if (!survivalGame.getPlayerUUIDs().contains(player.getUniqueId())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext
SurvivalGame survivalGame = (SurvivalGame) getOrThrow(args, CommandKeys.SURVIVAL_GAME);
Player player = (Player) getOrThrow(args, CommandKeys.PLAYER);

if (survivalGame.getState() != SurvivalGameState.JOINABLE) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.JOINABLE));
if (survivalGame.getState() != SurvivalGameState.READY) {
throw new CommandException(Text.of("State must be " + SurvivalGameState.READY));
}

if (!survivalGame.getPlayerUUIDs().contains(player.getUniqueId())) {
Expand Down
Loading

0 comments on commit f2a4d28

Please sign in to comment.