Skip to content

Commit

Permalink
Add behavior to handle Crab Hockey goal scoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Gegy committed Nov 12, 2024
1 parent c613236 commit 2bdc092
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/generated/resources/assets/ltminigames/lang/en_ud.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"effect.ltminigames.speed_power_up": "dn-ɹǝʍoԀ pǝǝdS",
"entity.ltminigames.driftwood": "pooʍʇɟıɹᗡ",
"entity.ltminigames.lightning_arrow": "ʍoɹɹⱯ buıuʇɥbıꞀ",
"entity.ltminigames.platform": "ɯɹoɟʇɐןԀ",
"entity.ltminigames.quiet_lightning_bolt": "ʇןoᗺ buıuʇɥbıꞀ ʇǝınὉ",
"item.ltminigames.acid_repellent_umbrella": "ɐןןǝɹqɯ∩ ʇuǝןןǝdǝᴚ pıɔⱯ",
"item.ltminigames.carrot_seeds": "spǝǝS ʇoɹɹɐƆ",
Expand Down Expand Up @@ -178,6 +179,7 @@
"ltminigames.minigame.connect_four.teams_goes_next": "ʇxǝu sǝob %s ɯɐǝ⟘",
"ltminigames.minigame.connect_four.your_turn": "ʞɔoןq ɐ ǝɔɐןd oʇ uɹnʇ ɹnoʎ sı ʇI",
"ltminigames.minigame.conservation_exploration": "uoıʇɐɹoןdxƎ uoıʇɐʌɹǝsuoƆ",
"ltminigames.minigame.crab_hockey": "ʎǝʞɔoH qɐɹƆ",
"ltminigames.minigame.crafting_bee": "ǝǝᗺ buıʇɟɐɹƆ",
"ltminigames.minigame.crafting_bee.dont_cheat": "¡ʇɐǝɥɔ ʇ,uoᗡ",
"ltminigames.minigame.crafting_bee.hint": "sʇuǝıpǝɹbuı ɟo ɹǝqɯnu ɯopuɐɹ ɐ ɟo uoıʇısod ǝɥʇ buıʎɐןdsıp 'ʇuıɥ ɐ ʍoɥs oʇ ʞɔıןƆ",
Expand Down Expand Up @@ -347,6 +349,7 @@
"ltminigames.minigame.event.zombie_invasion_event.toast": "¡NOISⱯΛNI ƎIᗺWOZ ɐ pǝʇɹɐʇs ʇɐɥƆ",
"ltminigames.minigame.flying_turtle_race": "ǝɔɐᴚ ǝןʇɹn⟘ buıʎןℲ",
"ltminigames.minigame.game_over.title": "¡ɹǝʌO ǝɯɐ⅁",
"ltminigames.minigame.goal_scored": "¡%s ɹoɟ pǝɹoɔs %s",
"ltminigames.minigame.hide_and_seek": "ʞǝǝS & ǝpıH",
"ltminigames.minigame.levitation": "uoıʇɐʇıʌǝꞀ",
"ltminigames.minigame.levitation.intro1": "¡ǝqnʇ ǝɥʇ ɟo doʇ ǝɥʇ ɥɔɐǝɹ oʇ ʇsɹıɟ ǝɥʇ ǝq oʇ ǝɔɐᴚ",
Expand Down Expand Up @@ -526,6 +529,7 @@
"ltminigames.minigame.turtle_race.warning": "¡buıuɹɐM",
"ltminigames.minigame.turtle_race.wrong_way": "¡ʎɐʍ buoɹʍ ǝɥʇ buıob ǝɹɐ noʎ",
"ltminigames.minigame.turtle_sprint": "ʇuıɹdS ǝןʇɹn⟘",
"ltminigames.minigame.unknown": "uʍouʞu∩",
"ltminigames.minigame.volcano_spleef": "ɟǝǝןdS ouɐɔןoΛ",
"ltminigames.minigame.weather.acid_rain": "uıɐᴚ pıɔⱯ",
"ltminigames.minigame.weather.clear": "ɹɐǝןƆ",
Expand Down
3 changes: 3 additions & 0 deletions src/generated/resources/assets/ltminigames/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"effect.ltminigames.speed_power_up": "Speed Power-up",
"entity.ltminigames.driftwood": "Driftwood",
"entity.ltminigames.lightning_arrow": "Lightning Arrow",
"entity.ltminigames.platform": "Platform",
"entity.ltminigames.quiet_lightning_bolt": "Quiet Lightning Bolt",
"item.ltminigames.acid_repellent_umbrella": "Acid Repellent Umbrella",
"item.ltminigames.carrot_seeds": "Carrot Seeds",
Expand Down Expand Up @@ -178,6 +179,7 @@
"ltminigames.minigame.connect_four.teams_goes_next": "Team %s goes next",
"ltminigames.minigame.connect_four.your_turn": "It is your turn to place a block",
"ltminigames.minigame.conservation_exploration": "Conservation Exploration",
"ltminigames.minigame.crab_hockey": "Crab Hockey",
"ltminigames.minigame.crafting_bee": "Crafting Bee",
"ltminigames.minigame.crafting_bee.dont_cheat": "Don't cheat!",
"ltminigames.minigame.crafting_bee.hint": "Click to show a hint, displaying the position of a random number of ingredients",
Expand Down Expand Up @@ -347,6 +349,7 @@
"ltminigames.minigame.event.zombie_invasion_event.toast": "Chat started a ZOMBIE INVASION!",
"ltminigames.minigame.flying_turtle_race": "Flying Turtle Race",
"ltminigames.minigame.game_over.title": "Game Over!",
"ltminigames.minigame.goal_scored": "%s scored for %s!",
"ltminigames.minigame.hide_and_seek": "Hide & Seek",
"ltminigames.minigame.levitation": "Levitation",
"ltminigames.minigame.levitation.intro1": "Race to be the first to reach the top of the tube!",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public final class MinigameTexts {
public static final Component QOTTOTT = KEYS.add("qottott", "Qottott");
public static final Component CONNECT_FOUR = KEYS.add("connect_four", "Connect Four");
public static final Component CRAFTING_BEE = KEYS.add("crafting_bee", "Crafting Bee");
public static final Component CRAB_HOCKEY = KEYS.add("crab_hockey", "Crab Hockey");

// TODO: These should move into SurviveTheTideTexts
public static final Component[] SURVIVE_THE_TIDE_INTRO = {
Expand Down Expand Up @@ -117,6 +118,7 @@ public static Component progressBarTime(Component text, int secondsLeft) {
public static final TranslationCollector.Fun1 ELIMINATED = KEYS.add1("eliminated", "☠ %s was eliminated!").withStyle(ChatFormatting.GRAY);

public static final Component UNKNOWN = KEYS.add("unknown", "Unknown");
public static final TranslationCollector.Fun2 POINT_SCORED = KEYS.add2("goal_scored", "%s scored for %s!").withStyle(ChatFormatting.GRAY);

static {
KEYS.add("starting_in", "Starting in %time%!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.lovetropics.minigames.common.core.game.behavior.instances.ImmediateRespawnBehavior;
import com.lovetropics.minigames.common.core.game.behavior.instances.IndividualWinTrigger;
import com.lovetropics.minigames.common.core.game.behavior.instances.JoinLateWithRoleBehavior;
import com.lovetropics.minigames.common.core.game.behavior.instances.ScoreMobInGoalBehavior;
import com.lovetropics.minigames.common.core.game.behavior.instances.OnlyTickInPeriodBehavior;
import com.lovetropics.minigames.common.core.game.behavior.instances.PermanentItemBehavior;
import com.lovetropics.minigames.common.core.game.behavior.instances.PlayerHeadRewardBehavior;
Expand Down Expand Up @@ -273,6 +274,7 @@ public class GameBehaviorTypes {
public static final GameBehaviorEntry<CountdownEffectsBehavior> COUNTDOWN_EFFECTS = register("countdown_effects", CountdownEffectsBehavior.CODEC);
public static final GameBehaviorEntry<TriggerEveryPackageBehavior> TRIGGER_EVERY_PACKAGE = register("trigger_every_package", TriggerEveryPackageBehavior.CODEC);
public static final GameBehaviorEntry<WhileInInventoryTrigger> WHILE_IN_INVENTORY = register("while_in_inventory", WhileInInventoryTrigger.CODEC);
public static final GameBehaviorEntry<ScoreMobInGoalBehavior> SCORE_MOB_IN_GOAL = register("score_mob_in_goal", ScoreMobInGoalBehavior.CODEC);

public static final GameBehaviorEntry<SetupIntegrationsBehavior> SETUP_INTEGRATIONS = register("setup_integrations", SetupIntegrationsBehavior.CODEC);
public static final GameBehaviorEntry<AssignPlayerRolesBehavior> ASSIGN_PLAYER_ROLES = register("assign_player_roles", AssignPlayerRolesBehavior.CODEC);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

public class GameActionList<T> {
public static final GameActionList<ServerPlayer> EMPTY = new GameActionList<>(IGameBehavior.EMPTY, PlayerActionTarget.SOURCE);
public static final GameActionList<Void> EMPTY_VOID = new GameActionList<>(IGameBehavior.EMPTY, NoneActionTarget.INSTANCE);

public static final MapCodec<GameActionList<?>> MAP_CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
IGameBehavior.CODEC.fieldOf("actions").forGetter(list -> list.behavior),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.lovetropics.minigames.common.core.game.behavior.action;

import com.lovetropics.minigames.common.core.game.state.team.GameTeam;
import com.lovetropics.minigames.common.core.integration.game_actions.GamePackage;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
Expand All @@ -11,8 +12,10 @@ public class GameActionParameter<T> {
public static final GameActionParameter<ServerPlayer> KILLER = GameActionParameter.create();
public static final GameActionParameter<ServerPlayer> KILLED = GameActionParameter.create();
public static final GameActionParameter<ServerPlayer> TARGET = GameActionParameter.create();
public static final GameActionParameter<ServerPlayer> SCORER = GameActionParameter.create();
public static final GameActionParameter<Integer> COUNT = GameActionParameter.create();
public static final GameActionParameter<ItemStack> ITEM = GameActionParameter.create();
public static final GameActionParameter<GameTeam> TEAM = GameActionParameter.create();

private GameActionParameter() {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.lovetropics.minigames.common.core.game.behavior.instances;

import com.lovetropics.lib.BlockBox;
import com.lovetropics.minigames.common.content.MinigameTexts;
import com.lovetropics.minigames.common.core.game.GameException;
import com.lovetropics.minigames.common.core.game.IGamePhase;
import com.lovetropics.minigames.common.core.game.behavior.GameBehaviorType;
import com.lovetropics.minigames.common.core.game.behavior.GameBehaviorTypes;
import com.lovetropics.minigames.common.core.game.behavior.IGameBehavior;
import com.lovetropics.minigames.common.core.game.behavior.action.GameActionContext;
import com.lovetropics.minigames.common.core.game.behavior.action.GameActionList;
import com.lovetropics.minigames.common.core.game.behavior.action.GameActionParameter;
import com.lovetropics.minigames.common.core.game.behavior.event.EventRegistrar;
import com.lovetropics.minigames.common.core.game.behavior.event.GameLivingEntityEvents;
import com.lovetropics.minigames.common.core.game.state.statistics.StatisticKey;
import com.lovetropics.minigames.common.core.game.state.team.GameTeam;
import com.lovetropics.minigames.common.core.game.state.team.GameTeamKey;
import com.lovetropics.minigames.common.core.game.state.team.TeamState;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

public record ScoreMobInGoalBehavior(
EntityType<?> scoringEntityType,
GameActionList<Void> scoreAction,
Map<GameTeamKey, String> teamGoalRegions,
StatisticKey<Integer> statistic
) implements IGameBehavior {
public static final MapCodec<ScoreMobInGoalBehavior> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
BuiltInRegistries.ENTITY_TYPE.byNameCodec().fieldOf("scoring_entity").forGetter(ScoreMobInGoalBehavior::scoringEntityType),
GameActionList.VOID_CODEC.optionalFieldOf("score_action", GameActionList.EMPTY_VOID).forGetter(ScoreMobInGoalBehavior::scoreAction),
Codec.unboundedMap(GameTeamKey.CODEC, Codec.STRING).fieldOf("team_goal_regions").forGetter(ScoreMobInGoalBehavior::teamGoalRegions),
StatisticKey.codecFor(Integer.class).fieldOf("statistic").forGetter(ScoreMobInGoalBehavior::statistic)
).apply(i, ScoreMobInGoalBehavior::new));

private static final Component POSITIVE_EMOTE = Component.literal("⭐").withStyle(ChatFormatting.GOLD);
private static final Component NEGATIVE_EMOTE = Component.literal("☠").withStyle(ChatFormatting.RED);

@Override
public Supplier<? extends GameBehaviorType<?>> behaviorType() {
return GameBehaviorTypes.SCORE_MOB_IN_GOAL;
}

@Override
public void register(IGamePhase game, EventRegistrar events) {
scoreAction.register(game, events);

TeamState teams = game.instanceState().getOrThrow(TeamState.KEY);
if (teams.getTeamKeys().size() != 2) {
throw new GameException(Component.literal("Only 2 teams are supported"));
}

List<Goal> goals = new ArrayList<>();
for (Map.Entry<GameTeamKey, String> entry : teamGoalRegions.entrySet()) {
BlockBox box = game.mapRegions().getOrThrow(entry.getValue());
GameTeamKey defensiveTeam = entry.getKey();
GameTeamKey offensiveTeam = teams.getTeamKeys().stream().filter(k -> !k.equals(defensiveTeam)).findFirst().orElseThrow();
goals.add(new Goal(box, defensiveTeam, offensiveTeam));
}

events.listen(GameLivingEntityEvents.TICK, entity -> {
if (entity.getType() != scoringEntityType) {
return;
}
Goal goal = getGoalAt(goals, entity.position());
if (goal != null) {
scoreGoal(game, teams, goal, entity);
entity.discard();
}
});
}

private void scoreGoal(IGamePhase game, TeamState teams, Goal goal, LivingEntity entity) {
game.statistics().forTeam(goal.offensiveTeam).incrementInt(statistic, 1);

ServerPlayer scoringPlayer = entity.getLastAttacker() instanceof ServerPlayer p ? p : null;
// Not necessarily the player who scored
GameTeam scoringTeam = Objects.requireNonNull(teams.getTeamByKey(goal.offensiveTeam));

GameActionContext.Builder context = GameActionContext.builder().set(GameActionParameter.TEAM, scoringTeam);
if (scoringPlayer != null) {
context = context.set(GameActionParameter.SCORER, scoringPlayer);
}

scoreAction.apply(game, context.build());

addScoreEffects(game, teams, goal, scoringPlayer, scoringTeam);
}

private static void addScoreEffects(IGamePhase game, TeamState teams, Goal goal, @Nullable ServerPlayer scoringPlayer, GameTeam scoringTeam) {
Component scoringName = scoringPlayer != null ? scoringPlayer.getDisplayName() : MinigameTexts.UNKNOWN;
boolean opposingGoal = scoringPlayer == null || teams.isOnTeam(scoringPlayer, goal.defensiveTeam);

Component title = opposingGoal ? POSITIVE_EMOTE : NEGATIVE_EMOTE;
Component subtitle = MinigameTexts.POINT_SCORED.apply(scoringName, scoringTeam.config().styledName());

int fade = SharedConstants.TICKS_PER_SECOND / 4;
int length = SharedConstants.TICKS_PER_SECOND * 2;
game.allPlayers().showTitle(title, subtitle, fade, length, fade);
game.allPlayers().playSound(SoundEvents.PLAYER_LEVELUP, SoundSource.PLAYERS, 1.0f, 1.0f);
}

@Nullable
private Goal getGoalAt(List<Goal> goals, Vec3 position) {
for (Goal goal : goals) {
if (goal.box.contains(position)) {
return goal;
}
}
return null;
}

private record Goal(BlockBox box, GameTeamKey defensiveTeam, GameTeamKey offensiveTeam) {
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.lovetropics.minigames.common.core.game.behavior.instances.action;

import com.google.common.collect.Lists;
import com.lovetropics.lib.BlockBox;
import com.lovetropics.minigames.common.core.game.GameException;
import com.lovetropics.minigames.common.core.game.IGamePhase;
Expand All @@ -16,32 +15,34 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.levelgen.Heightmap;

import java.util.ArrayList;
import java.util.List;

public class SpawnEntityAtRegionsAction implements IGameBehavior {
public static final MapCodec<SpawnEntityAtRegionsAction> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
Codec.STRING.listOf().fieldOf("regions_to_spawn_at").forGetter(c -> c.regionsToSpawnAtKeys),
EntityTemplate.CODEC.fieldOf("entity").forGetter(c -> c.entity),
Codec.INT.optionalFieldOf("entity_count_per_region", 1).forGetter(c -> c.entityCountPerRegion)
Codec.INT.optionalFieldOf("entity_count_per_region", 1).forGetter(c -> c.entityCountPerRegion),
Codec.BOOL.optionalFieldOf("at_heightmap", true).forGetter(c -> c.atHeightmap)
).apply(i, SpawnEntityAtRegionsAction::new));

private final List<String> regionsToSpawnAtKeys;
private final EntityTemplate entity;
private final int entityCountPerRegion;
private final boolean atHeightmap;

private final List<BlockBox> regionsToSpawnAt = Lists.newArrayList();

public SpawnEntityAtRegionsAction(final List<String> regionsToSpawnAtKeys, final EntityTemplate entity, final int entityCountPerRegion) {
public SpawnEntityAtRegionsAction(final List<String> regionsToSpawnAtKeys, final EntityTemplate entity, final int entityCountPerRegion, boolean atHeightmap) {
this.regionsToSpawnAtKeys = regionsToSpawnAtKeys;
this.entity = entity;
this.entityCountPerRegion = entityCountPerRegion;
this.atHeightmap = atHeightmap;
}

@Override
public void register(IGamePhase game, EventRegistrar events) throws GameException {
MapRegions regions = game.mapRegions();

regionsToSpawnAt.clear();
List<BlockBox> regionsToSpawnAt = new ArrayList<>();
for (String key : regionsToSpawnAtKeys) {
regionsToSpawnAt.addAll(regions.get(key));
}
Expand All @@ -54,7 +55,10 @@ public void register(IGamePhase game, EventRegistrar events) throws GameExceptio
ServerLevel world = game.level();
for (final BlockBox region : regionsToSpawnAt) {
for (int i = 0; i < entityCountPerRegion; i++) {
final BlockPos pos = world.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, region.sample(world.getRandom()));
BlockPos pos = region.sample(world.getRandom());
if (atHeightmap) {
pos = world.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, pos);
}
entity.spawn(world, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
}
}
Expand Down

0 comments on commit 2bdc092

Please sign in to comment.