Skip to content

Commit

Permalink
Fix event command and add more events.
Browse files Browse the repository at this point in the history
- Add specific events for game/deathmatch pre/post countdowns
- Fix "/ssg event" logic. More improvements needed
- Command blocks with "/ssg event InternalEvent" actually restored.
- Bug fix: no longer attempt to clean players from a ssg world.
  • Loading branch information
mattysweeps committed Mar 18, 2019
1 parent a173577 commit 1f3c2e2
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 72 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pluginGroup=io.github.m0pt0pmatt.survivalgames
pluginId=survivalgames
pluginVersion=1.1.8
pluginVersion=1.2.0
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
@Plugin(
id = "survival-games",
name = "Survival Games",
version = "1.1.8",
version = "1.2.0",
description = "Survival Games for Sponge.",
url = "https://github.com/mattysweeps/SurvivalGames"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.m0pt0pmatt.survivalgames.event;

import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;

public class DeathmatchPostCountdownEvent extends PostCountdownEvent {
public DeathmatchPostCountdownEvent(SurvivalGame survivalGame) {
super(survivalGame);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.m0pt0pmatt.survivalgames.event;

import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;

public class DeathmatchPreCountdownEvent extends PreCountdownEvent {
public DeathmatchPreCountdownEvent(SurvivalGame survivalGame) {
super(survivalGame);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.m0pt0pmatt.survivalgames.event;

import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;

public class GameStartedPostCountdownEvent extends PostCountdownEvent {
public GameStartedPostCountdownEvent(SurvivalGame survivalGame) {
super(survivalGame);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.m0pt0pmatt.survivalgames.event;

import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;

public class GameStartedPreCountdownEvent extends PreCountdownEvent {
public GameStartedPreCountdownEvent(SurvivalGame survivalGame) {
super(survivalGame);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class SurvivalGameStateManager {
HealPlayersTask.getInstance(),
SpawnSpectatorsTask.getInstance(),
AdjustScoreboardForStartTask.getInstance(),
CreateCountdownTask.withText("Game"),
CreateCountdownTask.getInstance(),
CreateWorldBorderTask.getInstance(),
StartEventIntervalsTask.getInstance(),
StartMobSpawnersTask.getInstance());
Expand All @@ -67,7 +67,7 @@ public class SurvivalGameStateManager {
Arrays.asList(
CreateCageSnapshotsTask.getInstance(),
SpawnPlayersTask.getInstance(),
CreateCountdownTask.withText("Deathmatch"),
CreateCountdownTask.getInstance(),
CreateDeathmatchBorderTask.getInstance());

private static final List<Task> STOP_TASKS =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockSnapshot;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;

public final class ActiveIntervalRepository {

private static final Map<UUID, SpongeExecutorService.SpongeFuture> FUTURE_MAP =
new ConcurrentHashMap<>();

private static final Map<Location<World>, BlockSnapshot> BLOCK_MAP =
new ConcurrentHashMap<>();

private ActiveIntervalRepository() {}

public static UUID start(SurvivalGame survivalGame, String intervalName, int intervalSeconds) {
Expand All @@ -60,4 +66,14 @@ public static void stop(UUID uuid) {
future.cancel(true);
}
}

public static BlockSnapshot getSnapshot(Location<World> location) {
BlockSnapshot blockSnapshot = BLOCK_MAP.get(location);
if (blockSnapshot == null) {
blockSnapshot = location.createSnapshot();
BLOCK_MAP.put(location, blockSnapshot);
}

return blockSnapshot;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,74 +24,94 @@
*/
package io.github.m0pt0pmatt.survivalgames.listener;

import com.google.common.collect.ImmutableList;
import io.github.m0pt0pmatt.survivalgames.SurvivalGamesPlugin;
import io.github.m0pt0pmatt.survivalgames.event.IntervalEvent;
import io.github.m0pt0pmatt.survivalgames.event.PlayerEvent;
import io.github.m0pt0pmatt.survivalgames.event.SurvivalGameEvent;
import java.util.concurrent.TimeUnit;
import io.github.m0pt0pmatt.survivalgames.interval.ActiveIntervalRepository;
import org.apache.commons.lang3.ClassUtils;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockSnapshot;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.block.tileentity.CommandBlock;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.data.value.mutable.Value;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.world.BlockChangeFlags;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class SurvivalGameEventListener {

private static SurvivalGameEventListener INSTANCE = new SurvivalGameEventListener();
private static final SurvivalGameEventListener INSTANCE = new SurvivalGameEventListener();
private static final String COMMAND_BLOCK_STRING = "/ssg event ";
private static final List<Class<?>> survivalGameClasses = ClassUtils.getAllSuperclasses(SurvivalGameEvent.class);

private SurvivalGameEventListener() {}
private SurvivalGameEventListener() {

}

@Listener
public void fireCommandBlocks(SurvivalGameEvent event) {
String eventName = event.getClass().getSimpleName();

for (CommandBlock commandBlock : event.getSurvivalGame().getCommandBlocks()) {

Value<String> storedCommand = commandBlock.storedCommand();
if (storedCommand.exists()) {
if (storedCommand.get().startsWith(COMMAND_BLOCK_STRING)) {

String commandBlockCommandName =
storedCommand.get().substring(COMMAND_BLOCK_STRING.length());

if (eventName.equalsIgnoreCase(commandBlockCommandName)) {

if (event instanceof PlayerEvent) {
String originalCommand = storedCommand.get();

// Strip off "/ssg event [event]" to get the real command
String actual = storedCommand.get()
.substring(COMMAND_BLOCK_STRING.length() + commandBlockCommandName.length() + 1);
storedCommand.set(actual);
commandBlock.execute();
storedCommand.set(originalCommand);


} else {
commandBlock.execute();
}

BlockSnapshot snapshot =
commandBlock.getBlock().snapshotFor(commandBlock.getLocation());
commandBlock
.getLocation()
.setBlock(
BlockState.builder()
.blockType(BlockTypes.REDSTONE_TORCH)
.build(),
BlockChangeFlags.ALL);

SurvivalGamesPlugin.SYNC_EXECUTOR.schedule(
() -> snapshot.restore(true, BlockChangeFlags.ALL),
5,
TimeUnit.SECONDS);
}
}
event.getSurvivalGame().getCommandBlocks().forEach(c -> handleCommandBlock(c, event));
}

private void handleCommandBlock(CommandBlock commandBlock, SurvivalGameEvent event) {
Value<String> storedCommand = commandBlock.storedCommand();
if (!storedCommand.exists()) {
return;
}

String[] parts = storedCommand.get().trim().split("\\s+");
if (parts.length < 3) {
return;
}

if (!parts[0].equalsIgnoreCase("/ssg") || !parts[1].equalsIgnoreCase("event")) {
return;
}

String eventName = parts[2];

List<String> classes = ImmutableList.<Class<?>>builder()
.add(event.getClass())
.addAll(ClassUtils.getAllSuperclasses(event.getClass()))
.build()
.stream()
.filter(c -> !survivalGameClasses.contains(c))
.map(Class::getSimpleName)
.collect(Collectors.toList());

if (!classes.contains(eventName)) {
return;
}

// execute other command
if (parts.length > 3) {

String internalCommand =
storedCommand.get().substring(COMMAND_BLOCK_STRING.length());

CommandSource source = null;
if (event instanceof PlayerEvent) {
source = ((PlayerEvent) event).getPlayer();
} else if (event instanceof IntervalEvent){
source = commandBlock;
}

if (source != null) {
Sponge.getCommandManager().process(source, internalCommand);
}
}

// Redstone trick
BlockSnapshot snapshot = ActiveIntervalRepository.getSnapshot(commandBlock.getLocation());
commandBlock.getLocation().setBlock(BlockState.builder().blockType(BlockTypes.REDSTONE_TORCH).build(), BlockChangeFlags.ALL);
SurvivalGamesPlugin.SYNC_EXECUTOR.schedule(() -> snapshot.restore(true, BlockChangeFlags.ALL), 1, TimeUnit.SECONDS);
}

public static SurvivalGameEventListener getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.util.TextMessageException;
import org.spongepowered.api.world.World;

Expand All @@ -23,7 +24,9 @@ public void execute(SurvivalGame survivalGame) throws TextMessageException {
getOrThrow(survivalGame.getConfig().getWorldName(), CommandKeys.WORLD_NAME);
World world = getOrThrow(Sponge.getServer().getWorld(worldName), CommandKeys.WORLD_NAME);

world.getEntities().forEach(Entity::remove);
world.getEntities().stream()
.filter(e -> !(e instanceof Player))
.forEach(Entity::remove);
}

public static ClearEntitiesTask getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,50 @@
*/
package io.github.m0pt0pmatt.survivalgames.task.player;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.github.m0pt0pmatt.survivalgames.Util.getOrThrow;

import com.google.common.collect.ImmutableMap;
import io.github.m0pt0pmatt.survivalgames.SurvivalGamesPlugin;
import io.github.m0pt0pmatt.survivalgames.command.CommandKeys;
import io.github.m0pt0pmatt.survivalgames.event.PostCountdownEvent;
import io.github.m0pt0pmatt.survivalgames.event.PreCountdownEvent;
import io.github.m0pt0pmatt.survivalgames.event.*;
import io.github.m0pt0pmatt.survivalgames.game.SurvivalGame;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.github.m0pt0pmatt.survivalgames.game.SurvivalGameRunningState;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.text.format.TextColors;
import org.spongepowered.api.text.title.Title;
import org.spongepowered.api.util.TextMessageException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

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

/** Create countdown titles for the start of the game . */
public class CreateCountdownTask extends PlayerAndSpectatorTask {

private final String text;
private static final Map<SurvivalGameRunningState, Function<SurvivalGame, PostCountdownEvent>> postEvents
= ImmutableMap.<SurvivalGameRunningState, Function<SurvivalGame, PostCountdownEvent>>builder()
.put(SurvivalGameRunningState.STOPPED, GameStartedPostCountdownEvent::new)
.put(SurvivalGameRunningState.IN_PROGRESS, DeathmatchPostCountdownEvent::new)
.build();

private static final Map<SurvivalGameRunningState, Function<SurvivalGame, PreCountdownEvent>> preEvents
= ImmutableMap.<SurvivalGameRunningState, Function<SurvivalGame, PreCountdownEvent>>builder()
.put(SurvivalGameRunningState.STOPPED, GameStartedPreCountdownEvent::new)
.put(SurvivalGameRunningState.IN_PROGRESS, DeathmatchPreCountdownEvent::new)
.build();

private CreateCountdownTask(String text) {
this.text = checkNotNull(text, "text");
private static final Map<SurvivalGameRunningState, Text> text = ImmutableMap.<SurvivalGameRunningState, Text>builder()
.put(SurvivalGameRunningState.STOPPED, Text.of("Game"))
.put(SurvivalGameRunningState.IN_PROGRESS, Text.of("Deathmatch"))
.build();


private CreateCountdownTask() {
}

@Override
Expand All @@ -60,13 +79,15 @@ public void execute(SurvivalGame survivalGame, Player player) throws TextMessage

List<Title> titles = new ArrayList<>();

Text title = Optional.ofNullable(text.get(survivalGame.getRunningState())).orElse(Text.of("Game"));

for (int i = 0; i < countDown + 1; i++) {
titles.add(
Title.builder()
.fadeIn(5)
.stay(20)
.fadeOut(5)
.title(Text.of(TextColors.RED, this.text + " begins in..."))
.title(Text.of(TextColors.RED, title, " begins in..."))
.subtitle(Text.of(TextColors.RED, countDown - i))
.build());
}
Expand All @@ -77,15 +98,20 @@ public void execute(SurvivalGame survivalGame, Player player) throws TextMessage
() -> player.sendTitle(titles.get(j)), i, TimeUnit.SECONDS);
}

Sponge.getEventManager().post(new PreCountdownEvent(survivalGame));
Optional.ofNullable(preEvents.get(survivalGame.getRunningState()))
.map(f -> f.apply(survivalGame))
.ifPresent(e -> Sponge.getEventManager().post(e));

SurvivalGamesPlugin.SYNC_EXECUTOR.schedule(
() -> Sponge.getEventManager().post(new PostCountdownEvent(survivalGame)),
countDown,
TimeUnit.SECONDS);
Optional.ofNullable(postEvents.get(survivalGame.getRunningState()))
.map(f -> f.apply(survivalGame))
.ifPresent(e ->
SurvivalGamesPlugin.SYNC_EXECUTOR.schedule(
() -> Sponge.getEventManager().post(e),
countDown,
TimeUnit.SECONDS));
}

public static CreateCountdownTask withText(String text) {
return new CreateCountdownTask(text);
public static CreateCountdownTask getInstance() {
return new CreateCountdownTask();
}
}

0 comments on commit 1f3c2e2

Please sign in to comment.