Skip to content

Commit

Permalink
Try to be a bit more resilient to mischievous players by preventing c…
Browse files Browse the repository at this point in the history
…ollectables in the monument slot from being broken/replaced
  • Loading branch information
Gegy committed Nov 13, 2024
1 parent a9b90db commit 0eb703a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/generated/resources/assets/ltminigames/lang/en_ud.json
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@
"ltminigames.minigame.reward_item": "%s x%s - ",
"ltminigames.minigame.rewards_granted": "¡sǝɯɐbıuıɯ buıʎɐןd ɹoɟ spɹɐʍǝɹ ʇob noʎ",
"ltminigames.minigame.river_race": "ǝɔɐᴚ ɹǝʌıᴚ",
"ltminigames.minigame.river_race.cant_place_collectable": "ssǝɹboɹd oʇ ǝuoz sıɥʇ ɟo puǝ ǝɥʇ ʇɐ ʇuǝɯnuoW ǝɥʇ uı ǝɔɐןԀ",
"ltminigames.minigame.river_race.cant_place_collectable": "ssǝɹboɹd oʇ ǝuoz ʇɔǝɹɹoɔ ǝɥʇ ɟo puǝ ǝɥʇ ʇɐ ʇuǝɯnuoW ǝɥʇ uı ǝɔɐןԀ",
"ltminigames.minigame.river_race.shop": "doɥS",
"ltminigames.minigame.river_race.trivia.collectable_given": "¡ʇuǝɯnuoɯ ǝɥʇ oʇuı ǝɔɐןd oʇ ǝןqɐʇɔǝןןoɔ ɐ uǝʌıb uǝǝq ǝʌ,noʎ",
"ltminigames.minigame.river_race.trivia.collectable_placed": "˙spuoɔǝs %s uı ʇɹɐʇs ןןıʍ sǝɯɐb-oɹɔıɯ ǝɥ⟘ ¡ǝןqɐʇɔǝןןoɔ %s ǝɥʇ ǝɔɐןd oʇ ʇsɹıɟ ǝɹɐ ɯɐǝʇ %s",
Expand Down
2 changes: 1 addition & 1 deletion src/generated/resources/assets/ltminigames/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@
"ltminigames.minigame.reward_item": " - %sx %s",
"ltminigames.minigame.rewards_granted": "You got rewards for playing minigames!",
"ltminigames.minigame.river_race": "River Race",
"ltminigames.minigame.river_race.cant_place_collectable": "Place in the Monument at the end of this zone to progress",
"ltminigames.minigame.river_race.cant_place_collectable": "Place in the Monument at the end of the correct zone to progress",
"ltminigames.minigame.river_race.shop": "Shop",
"ltminigames.minigame.river_race.trivia.collectable_given": "You've been given a collectable to place into the monument!",
"ltminigames.minigame.river_race.trivia.collectable_placed": "%s team are first to place the %s collectable! The micro-games will start in %s seconds.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public final class RiverRaceTexts {
public static final TranslationCollector.Fun1 GAMES_START_IN = KEYS.add1("trivia.games_start_in", "Microgames start in %s second(s)")
.withStyle(ChatFormatting.GREEN);

public static final Component CANT_PLACE_COLLECTABLE = KEYS.add("cant_place_collectable", "Place in the Monument at the end of this zone to progress")
public static final Component CANT_PLACE_COLLECTABLE = KEYS.add("cant_place_collectable", "Place in the Monument at the end of the correct zone to progress")
.withStyle(ChatFormatting.RED);
public static final Component TRIVIA_BLOCK_ALREADY_USED = KEYS.add("trivia_block_already_used", "This Trivia Block has already been used!")
.withStyle(ChatFormatting.RED);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.lovetropics.minigames.common.content.river_race.behaviour;

import com.lovetropics.lib.BlockBox;
import com.lovetropics.lib.codec.MoreCodecs;
import com.lovetropics.lib.entity.FireworkPalette;
import com.lovetropics.minigames.common.content.river_race.RiverRaceTexts;
Expand All @@ -23,6 +22,8 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
Expand All @@ -43,6 +44,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

public final class CollectablesBehaviour implements IGameBehavior, IGameState {
Expand All @@ -58,6 +60,9 @@ public CollectablesBehaviour(List<Collectable> collectables) {
this.collectables = collectables;
}

private final Map<BlockPos, Collectable> monumentSlots = new HashMap<>();
private final LongSet placedCollectables = new LongOpenHashSet();

private final Map<String, GameTeamKey> firstTeamToCollect = new HashMap<>();
@Nullable
private Countdown countdown;
Expand Down Expand Up @@ -87,27 +92,34 @@ public void register(IGamePhase game, EventRegistrar events) throws GameExceptio

for (Collectable collectable : collectables) {
collectable.onCompleteAction.register(game, events);
for (String region : collectable.monumentSlotRegions) {
for (BlockPos pos : game.mapRegions().getOrThrow(region)) {
monumentSlots.put(pos.immutable(), collectable);
}
}
}

events.listen(GamePhaseEvents.TICK, () -> {
if (countdown != null){
countdown.tick(game);
}
});
events.listen(GamePhaseEvents.CREATE, () -> {
for (Collectable collectable : collectables) {
for (String monumentSlotRegion : collectable.monumentSlotRegions()) {
BlockBox region = game.mapRegions().getOrThrow(monumentSlotRegion);
spawnCollectableDisplay(game, collectable, region.center());
}
}
});
events.listen(GamePhaseEvents.CREATE, () ->
monumentSlots.forEach((pos, collectable) -> spawnCollectableDisplay(game, collectable, pos.getCenter()))
);
events.listen(GamePlayerEvents.PLACE_BLOCK, (player, pos, placed, placedOn, placedItemStack) -> {
Collectable expectedCollectable = monumentSlots.get(pos);
Collectable placedCollectable = getMatchingCollectable(placedItemStack);
if (placedCollectable == null) {
return InteractionResult.PASS;
}
return tryPlaceCollectable(game, player, pos, placedCollectable, teams);
if (expectedCollectable != null || placedCollectable != null) {
return tryPlaceCollectable(game, teams, player, pos, expectedCollectable, placedCollectable);
}
return InteractionResult.PASS;
});
events.listen(GamePlayerEvents.BREAK_BLOCK, (player, pos, state, hand) -> {
if (placedCollectables.contains(pos.asLong())) {
return InteractionResult.FAIL;
}
return InteractionResult.PASS;
});
}

Expand All @@ -119,32 +131,38 @@ private void spawnCollectableDisplay(IGamePhase game, Collectable collectable, V
game.level().addFreshEntity(itemDisplay);
}

private InteractionResult tryPlaceCollectable(IGamePhase game, ServerPlayer player, BlockPos pos, Collectable placedCollectable, TeamState teams) {
BlockPos slot = getMonumentSlotAt(placedCollectable, game, pos);
if (slot == null) {
private InteractionResult tryPlaceCollectable(IGamePhase game, TeamState teams, ServerPlayer player, BlockPos pos, @Nullable Collectable expectedCollectable, @Nullable Collectable placedCollectable) {
if (placedCollectable == null || !Objects.equals(expectedCollectable, placedCollectable)) {
player.playNotifySound(SoundEvents.VILLAGER_NO, SoundSource.PLAYERS, 1.0f, 1.0f);
player.sendSystemMessage(RiverRaceTexts.CANT_PLACE_COLLECTABLE, true);
return InteractionResult.FAIL;
}
return tryPlaceIntoMonumentSlot(game, teams, player, placedCollectable, slot);
}

private InteractionResult tryPlaceIntoMonumentSlot(IGamePhase game, TeamState teams, ServerPlayer player, Collectable collectable, BlockPos slotCenterPos) {
GameTeamKey teamKey = teams.getTeamForPlayer(player);
if (teamKey == null) {
GameTeam team = teamKey != null ? teams.getTeamByKey(teamKey) : null;
if (team == null) {
return InteractionResult.FAIL;
}

// If the players somehow broke the old one - don't let them continue to trigger it and gain points
if (!placedCollectables.add(pos.asLong())) {
return InteractionResult.FAIL;
}
GameTeam team = teams.getTeamByKey(teamKey);
if (firstTeamToCollect.putIfAbsent(collectable.zone, teamKey) == null) {

return onCollectablePlaced(game, team, placedCollectable, pos);
}

private InteractionResult onCollectablePlaced(IGamePhase game, GameTeam team, Collectable collectable, BlockPos slotPos) {
if (firstTeamToCollect.putIfAbsent(collectable.zone, team.key()) == null) {
addEffectsForPlacedCollectable(game, collectable, team);
// Start microgames countdown
countdown = new Countdown(game.ticks() + (SharedConstants.TICKS_PER_SECOND * COUNTDOWN_SECONDS), (unused) -> {
collectable.onCompleteAction.apply(game, GameActionContext.EMPTY);
countdown = null;
});
}
game.statistics().forTeam(teamKey).incrementInt(StatisticKey.VICTORY_POINTS, collectable.victoryPoints);
FireworkPalette.DYE_COLORS.spawn(slotCenterPos.above(), game.level());
game.statistics().forTeam(team.key()).incrementInt(StatisticKey.VICTORY_POINTS, collectable.victoryPoints);
FireworkPalette.DYE_COLORS.spawn(slotPos.above(), game.level());
return InteractionResult.PASS;
}

Expand All @@ -166,16 +184,6 @@ private Collectable getMatchingCollectable(ItemStack itemStack) {
return null;
}

@Nullable
private BlockPos getMonumentSlotAt(Collectable collectable, IGamePhase game, BlockPos pos) {
for (BlockBox region : game.mapRegions().getAll(collectable.monumentSlotRegions)) {
if (region.contains(pos)) {
return region.centerBlock();
}
}
return null;
}

public List<Collectable> collectables() {
return collectables;
}
Expand Down

0 comments on commit 0eb703a

Please sign in to comment.