Skip to content

Commit

Permalink
Countdown + Random Spawns
Browse files Browse the repository at this point in the history
  • Loading branch information
ellieisjelly committed Jan 3, 2024
1 parent 5c6590d commit 07cd9d1
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 26 deletions.
16 changes: 15 additions & 1 deletion src/main/java/me/ellieis/Sabotage/game/SabotageConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,32 @@

public class SabotageConfig {
private final Identifier map;
private final int countdownTime;
private final int gracePeriod;
private final PlayerConfig playerConfig;
public static final Codec<SabotageConfig> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(
Identifier.CODEC.fieldOf("map").forGetter(SabotageConfig::getMap),
Codec.INT.fieldOf("countdown_time").forGetter(SabotageConfig::getCountdownTime),
Codec.INT.fieldOf("grace_period").forGetter(SabotageConfig::getGracePeriod),
PlayerConfig.CODEC.fieldOf("players").forGetter(SabotageConfig::getPlayerConfig)
).apply(instance, SabotageConfig::new);
});
public SabotageConfig(Identifier map, PlayerConfig playerConfig) {
public SabotageConfig(Identifier map, int countdownTime, int gracePeriod, PlayerConfig playerConfig) {
this.map = map;
this.countdownTime = countdownTime;
this.gracePeriod = gracePeriod;
this.playerConfig = playerConfig;
}

public int getCountdownTime() {
return countdownTime;
}

public int getGracePeriod() {
return gracePeriod;
}

public PlayerConfig getPlayerConfig() {
return this.playerConfig;
}
Expand Down
47 changes: 33 additions & 14 deletions src/main/java/me/ellieis/Sabotage/game/map/SabotageMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,59 @@
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.gen.chunk.ChunkGenerator;

import xyz.nucleoid.map_templates.MapTemplate;
import xyz.nucleoid.map_templates.TemplateRegion;
import xyz.nucleoid.plasmid.game.GameOpenException;
import xyz.nucleoid.plasmid.game.world.generator.TemplateChunkGenerator;
import xyz.nucleoid.plasmid.util.PlayerRef;

import java.util.*;
import java.util.stream.Stream;

public class SabotageMap {
private final MapTemplate template;
private final TemplateRegion spawn;
private final Stream<TemplateRegion> spawns;
private final Map<PlayerRef, Vec3d> playerSpawnPos = new HashMap<>();

public SabotageMap(MapTemplate template) {
this.template = template;
this.spawn = template.getMetadata().getFirstRegion("spawn");
this.spawns = template.getMetadata().getRegions("spawn");
if (this.spawns == null) {
throw new GameOpenException(Text.literal("Failed to load spawns"));
}
}

public MapTemplate getTemplate() {
return this.template;
}

public TemplateRegion getSpawn() {
return this.spawn;
public Stream<TemplateRegion> getSpawns() {
return this.spawns;
}

public void spawnEntity(ServerWorld world, Entity entity) {
float yaw = this.spawn.getData().getFloat("Rotation");
Vec3d pos = this.spawn.getBounds().center();
if (entity instanceof ServerPlayerEntity) {
ServerPlayerEntity plr = (ServerPlayerEntity) entity;
plr.teleport(world, pos.getX(), pos.getY(), pos.getZ(), yaw, 0);
} else {
entity.teleport(pos.getX(), pos.getY(), pos.getZ());
entity.setYaw(yaw);
}
public Map<PlayerRef, Vec3d> getPlayerSpawns() {
return this.playerSpawnPos;
}

public void spawnEntity(Entity entity) {
List<TemplateRegion> spawnList = spawns.toList();
TemplateRegion spawn = spawnList.get(new Random().nextInt(spawnList.size()));
Vec3d pos = spawn.getBounds().centerBottom();
entity.teleport(pos.getX(), pos.getY(), pos.getZ());
entity.setYaw(spawn.getData().getFloat("Rotation"));
}

public void spawnEntity(ServerWorld world, ServerPlayerEntity plr) {
List<TemplateRegion> spawnList = spawns.toList();
TemplateRegion spawn = spawnList.get(new Random().nextInt(spawnList.size()));
Vec3d pos = spawn.getBounds().centerBottom();
plr.teleport(world, pos.getX(), pos.getY(), pos.getZ(), spawn.getData().getFloat("Rotation"), 0);
this.playerSpawnPos.put(new PlayerRef(plr.getUuid()), pos);
}

public ChunkGenerator asChunkGenerator(MinecraftServer server) {
Expand Down
61 changes: 57 additions & 4 deletions src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
package me.ellieis.Sabotage.game.phase;

import com.google.common.collect.ImmutableSet;
import me.ellieis.Sabotage.game.SabotageConfig;
import me.ellieis.Sabotage.game.map.SabotageMap;
import net.minecraft.network.packet.s2c.play.PositionFlag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d;
import xyz.nucleoid.plasmid.game.GameActivity;
import xyz.nucleoid.plasmid.game.GameSpace;
import xyz.nucleoid.plasmid.game.event.GameActivityEvents;
import xyz.nucleoid.plasmid.game.player.PlayerSet;
import xyz.nucleoid.plasmid.game.rule.GameRuleType;
import xyz.nucleoid.plasmid.util.PlayerRef;

import java.util.Set;

public class SabotageActive {
private final SabotageConfig config;
private final GameSpace gameSpace;
private final SabotageMap map;
private final ServerWorld world;
private boolean gameStarted = false;
private boolean countdown = false;
private long startTime;
public SabotageActive(SabotageConfig config, GameSpace gameSpace, SabotageMap map, ServerWorld world) {
this.config = config;
this.gameSpace = gameSpace;
this.map = map;
this.world = world;
}
private static void rules(GameActivity activity) {
private static void gameStartedRules(GameActivity activity) {
activity.allow(GameRuleType.FALL_DAMAGE);
activity.allow(GameRuleType.PVP);
}
private static void rules(GameActivity activity) {
activity.deny(GameRuleType.FALL_DAMAGE);
activity.allow(GameRuleType.INTERACTION);
activity.allow(GameRuleType.PICKUP_ITEMS);
activity.allow(GameRuleType.MODIFY_ARMOR);
activity.allow(GameRuleType.MODIFY_INVENTORY);
activity.allow(GameRuleType.PVP);
activity.deny(GameRuleType.PVP);
activity.allow(GameRuleType.THROW_ITEMS);
activity.deny(GameRuleType.PORTALS);
activity.deny(GameRuleType.HUNGER);
Expand All @@ -38,13 +57,47 @@ private static void rules(GameActivity activity) {
public static void Open(GameSpace gameSpace, ServerWorld world, SabotageMap map, SabotageConfig config) {
gameSpace.setActivity(activity -> {
SabotageActive game = new SabotageActive(config, gameSpace, map, world);

game.startTime = world.getTime();
game.countdown = true;
rules(activity);
activity.listen(GameActivityEvents.TICK, game::onTick);
PlayerSet plrs = game.gameSpace.getPlayers();
plrs.showTitle(Text.literal(Integer.toString(game.config.getCountdownTime())).formatted(Formatting.GOLD), 20);
plrs.playSound(SoundEvents.BLOCK_NOTE_BLOCK_HARP.value(), SoundCategory.PLAYERS, 1.0F, 2.0F);
for (ServerPlayerEntity plr : plrs) {
game.map.spawnEntity(world, plr);
}
});
}

public void onTick() {

long time = this.world.getTime();
if (!gameStarted) {
// to-do: implement grace period
if (this.countdown) {
if (time % 20 == 0) {
// second has passed
int secondsSinceStart = (int) Math.floor((time / 20) - (this.startTime / 20));
int countdownTime = this.config.getCountdownTime();
if (secondsSinceStart >= countdownTime) {
this.countdown = false;
} else {
PlayerSet plrs = this.gameSpace.getPlayers();
plrs.showTitle(Text.literal(Integer.toString(countdownTime - secondsSinceStart)).formatted(Formatting.GOLD), 20);
plrs.playSound(SoundEvents.BLOCK_NOTE_BLOCK_HARP.value(), SoundCategory.PLAYERS, 1.0F, 2.0F);
}
}
// Make sure players don't move during countdown
for (ServerPlayerEntity plr : gameSpace.getPlayers()) {
Vec3d pos = this.map.getPlayerSpawns().get(new PlayerRef(plr.getUuid()));
// Set X and Y as relative so it will send 0 change when we pass yaw (yaw - yaw = 0) and pitch
Set<PositionFlag> flags = ImmutableSet.of(PositionFlag.X_ROT, PositionFlag.Y_ROT);
// Teleport without changing the pitch and yaw
plr.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), plr.getYaw(), plr.getPitch(), flags);
}
}
} else {
// to-do: implement game loop
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,16 @@ public static GameOpenProcedure Open(GameOpenContext<SabotageConfig> context) {
GameWaitingLobby.addTo(activity, config.getPlayerConfig());

rules(activity);
activity.listen(GameActivityEvents.TICK, game::onTick);
activity.listen(GamePlayerEvents.OFFER, game::onOffer);
activity.listen(GameActivityEvents.REQUEST_START, game::requestStart);
});
}

public GameResult requestStart() {
// to-do: checks if start should happen
SabotageActive.Open(this.gameSpace, this.world, this.map, this.config);
return GameResult.ok();
}

private void onTick() {

}

private PlayerOfferResult onOffer(PlayerOffer offer) {
ServerPlayerEntity plr = offer.player();
return offer.accept(this.world, new Vec3d(0.0, 66.0, 0.0)).and(() -> {
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/data/sabotage/games/sabotage.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"type": "sabotage:sabotage",
"map": "sabotage:lobby",
"countdown_time": 5,
"grace_period": 15,
"players": {
"min": 1,
"max": 64,
"threshold": 2
"threshold": 6
}
}
Binary file modified src/main/resources/data/sabotage/map_templates/lobby.nbt
Binary file not shown.

0 comments on commit 07cd9d1

Please sign in to comment.