Skip to content

Commit

Permalink
Add a bunch of text/sounds/flavour to Crafting Bee
Browse files Browse the repository at this point in the history
  • Loading branch information
Gegy committed Nov 15, 2024
1 parent 5053391 commit 9463a4c
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 44 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ minecraft_version=1.21
neo_version=21.0.167
parchment_version=2024.06.23
registrate_version=1.3.0+50
ltlib_version=[1.4.7,1.5)
ltlib_version=[1.4.8,1.5)
ltextras_version=1.3.0-release+32

org.gradle.jvmargs=-Xmx1G
Expand Down
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 @@ -180,10 +180,14 @@
"ltminigames.minigame.conservation_exploration": "uoıʇɐɹoןdxƎ uoıʇɐʌɹǝsuoƆ",
"ltminigames.minigame.crab_hockey": "ʎǝʞɔoH qɐɹƆ",
"ltminigames.minigame.crafting_bee": "ǝǝᗺ buıʇɟɐɹƆ",
"ltminigames.minigame.crafting_bee.cannot_recycle": "¡pǝʇɟɐɹɔ ǝʌɐɥ noʎ ʇɐɥʇ sɯǝʇı ǝןɔʎɔǝɹ ʎןuo uɐɔ noʎ",
"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ʇ ʞɔıןƆ",
"ltminigames.minigame.crafting_bee.hints_left": "ʇɟǝן sʇuıɥ %s ǝʌɐɥ noʎ",
"ltminigames.minigame.crafting_bee.not_enough_to_recycle": "sıɥʇ ǝןɔʎɔǝɹ oʇ %s %s ʇsɐǝן ʇɐ pǝǝu noʎ",
"ltminigames.minigame.crafting_bee.team_has_completed_recipes": "sǝdıɔǝɹ %s ɟo ʇno %s pǝʇǝןdɯoɔ sɐɥ %s ɯɐǝ⟘",
"ltminigames.minigame.crafting_bee.time_penalty": "spuoɔǝs %s-",
"ltminigames.minigame.crafting_bee.time_up": "¡dn s,ǝɯı⟘",
"ltminigames.minigame.donation.acid_rain": "uıɐᴚ pıɔⱯ",
"ltminigames.minigame.donation.acid_rain.description": "¡ǝʇnuıɯ Ɩ ɹoɟ spɐǝɥ ,sɹǝʎɐןd ǝɥʇ uo uʍop pıɔɐ uıɐᴚ",
"ltminigames.minigame.donation.acid_rain.toast": "¡ǝʇnuıɯ Ɩ ɹoɟ pıɔɐ buıuıɐɹ sı ʇI",
Expand Down
4 changes: 4 additions & 0 deletions src/generated/resources/assets/ltminigames/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,14 @@
"ltminigames.minigame.conservation_exploration": "Conservation Exploration",
"ltminigames.minigame.crab_hockey": "Crab Hockey",
"ltminigames.minigame.crafting_bee": "Crafting Bee",
"ltminigames.minigame.crafting_bee.cannot_recycle": "You can only recycle items that you have crafted!",
"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",
"ltminigames.minigame.crafting_bee.hints_left": "You have %s hints left",
"ltminigames.minigame.crafting_bee.not_enough_to_recycle": "You need at least %s %s to recycle this",
"ltminigames.minigame.crafting_bee.team_has_completed_recipes": "Team %s has completed %s out of %s recipes",
"ltminigames.minigame.crafting_bee.time_penalty": "-%s seconds",
"ltminigames.minigame.crafting_bee.time_up": "Time's up!",
"ltminigames.minigame.donation.acid_rain": "Acid Rain",
"ltminigames.minigame.donation.acid_rain.description": "Rain acid down on the players' heads for 1 minute!",
"ltminigames.minigame.donation.acid_rain.toast": "It is raining acid for 1 minute!",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.lovetropics.lib.BlockBox;
import com.lovetropics.lib.entity.FireworkPalette;
import com.lovetropics.minigames.common.content.MinigameTexts;
import com.lovetropics.minigames.common.content.crafting_bee.ingredient.IngredientDecomposer;
import com.lovetropics.minigames.common.core.game.GameException;
Expand Down Expand Up @@ -38,6 +39,9 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.BossEvent;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionHand;
Expand All @@ -60,10 +64,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class CraftingBeeBehavior implements IGameBehavior {
Expand Down Expand Up @@ -201,6 +203,11 @@ private Stream<ItemStack> singleDecomposition(Ingredient ingredient) {
}

private ItemStack modifyCraftResult(ServerPlayer player, ItemStack result, CraftingInput craftingInput, CraftingRecipe recipe) {
GameTeamKey team = teams.getTeamForPlayer(player);
if (team == null || teamsWithoutTime.contains(team)) {
// Don't allow players to use their inventory to craft, either!
return ItemStack.EMPTY;
}
ItemContainerContents usedItems = ItemContainerContents.fromItems(craftingInput.items().stream()
.filter(stack -> !stack.isEmpty())
.map(stack -> stack.copyWithCount(1))
Expand All @@ -219,7 +226,10 @@ private void onCraft(Player player, ItemStack crafted, Container container) {
if (team == null || done) return;

var teamTasks = tasks.get(team);
var task = teamTasks.stream().filter(c -> ItemStack.isSameItemSameComponents(crafted, c.output)).findFirst().orElse(null);

var craftedStackToCompare = crafted.copy();
craftedStackToCompare.remove(CraftingBee.CRAFTED_USING);
var task = teamTasks.stream().filter(c -> ItemStack.isSameItemSameComponents(craftedStackToCompare, c.output)).findFirst().orElse(null);

if (task == null || task.done) return;

Expand All @@ -234,16 +244,45 @@ private void onCraft(Player player, ItemStack crafted, Container container) {
game.allPlayers().sendMessage(CraftingBeeTexts.TEAM_HAS_COMPLETED_RECIPES.apply(teamConfig.styledName(), completed, teamTasks.size()));
taskBars.get(team).setProgress(completed / (float) teamTasks.size());

PlayerSet teamPlayers = teams.getPlayersForTeam(team);
teamPlayers.playSound(SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.PLAYERS, 1.0f, 1.0f);
game.spectators().playSound(SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.PLAYERS, 1.0f, 1.0f);

PlayerSet otherPlayers = PlayerSet.difference(game.participants(), teamPlayers);
otherPlayers.playSound(SoundEvents.GHAST_SCREAM, SoundSource.PLAYERS, 0.5f, 0.5f);

if (completed == teamTasks.size()) {
game.invoker(GameLogicEvents.GAME_OVER).onGameWonBy(gameTeam);
triggerGameOver(new GameWinner.Team(gameTeam));
}
}

done = true;
private void triggerGameOver(GameWinner winner) {
done = true;
game.invoker(GameLogicEvents.GAME_OVER).onGameOver(winner);
game.allPlayers().forEach(ServerPlayer::closeContainer);

game.allPlayers().forEach(ServerPlayer::closeContainer);
game.scheduler().runAfterSeconds(1.5f, () -> {
game.allPlayers().playSound(SoundEvents.RESPAWN_ANCHOR_DEPLETE.value(), SoundSource.PLAYERS, 0.5f, 1.0f);

game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(teamConfig.styledName()).withStyle(ChatFormatting.GREEN), true));
game.scheduler().runAfterSeconds(5, () -> game.requestStop(GameStopReason.finished()));
}
if (winner instanceof GameWinner.Team(GameTeam team)) {
for (ServerPlayer winningPlayer : teams.getPlayersForTeam(team.key())) {
applyWinningPlayerEffects(winningPlayer, team);
}
game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(team.config().styledName()).withStyle(ChatFormatting.GREEN), true);
} else {
game.allPlayers().sendMessage(MinigameTexts.NOBODY_WON, true);
}
});

game.scheduler().runAfterSeconds(8, () -> game.requestStop(GameStopReason.finished()));
}

private void applyWinningPlayerEffects(ServerPlayer winningPlayer, GameTeam team) {
game.scheduler().runAfterSeconds(game.random().nextFloat(), () -> {
BlockPos fireworksPos = BlockPos.containing(winningPlayer.getEyePosition()).above();
FireworkPalette.forDye(team.config().dye()).spawn(fireworksPos, game.level());
});
winningPlayer.setGlowingTag(true);
}

private void tickRunning(IGamePhase game) {
Expand All @@ -261,27 +300,23 @@ private void tickRunning(IGamePhase game) {
bar.bar.setProgress(0);

teamsWithoutTime.add(team);
teams.getPlayersForTeam(team).forEach(ServerPlayer::closeContainer);

PlayerSet playersInTeam = teams.getPlayersForTeam(team);
playersInTeam.forEach(ServerPlayer::closeContainer);
playersInTeam.playSound(SoundEvents.END_PORTAL_SPAWN, SoundSource.PLAYERS, 0.5f, 0.25f);
playersInTeam.showTitle(CraftingBeeTexts.TIME_UP, null, 10, SharedConstants.TICKS_PER_SECOND * 2, 10);

if (teamsWithoutTime.size() == tasks.asMap().size()) {
int mx = tasks.asMap().values().stream().mapToInt(craftingTasks -> (int) craftingTasks.stream().filter(c -> c.done).count())
.max().orElse(0);
var withMax = tasks.asMap().entrySet().stream().filter(e -> e.getValue().stream().filter(c -> c.done).count() == mx)
.toList();
if (withMax.size() != 1) {
game.invoker(GameLogicEvents.GAME_OVER).onGameOver(new GameWinner.Nobody());

game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.NOBODY_WON, true));
triggerGameOver(new GameWinner.Nobody());
} else {
var gameTeam = teams.getTeamByKey(withMax.getFirst().getKey());
var teamConfig = gameTeam.config();
game.invoker(GameLogicEvents.GAME_OVER).onGameWonBy(gameTeam);

game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(teamConfig.styledName()).withStyle(ChatFormatting.GREEN), true));
triggerGameOver(new GameWinner.Team(gameTeam));
}

done = true;
game.scheduler().runAfterSeconds(5, () -> game.requestStop(GameStopReason.finished()));
}
}
}
Expand All @@ -301,25 +336,42 @@ private InteractionResult useBlock(ServerPlayer player, ServerLevel world, Block
// don't allow players to use the crafting table after the game was won
if (world.getBlockState(pos).is(Blocks.CRAFTING_TABLE) && (done || teamsWithoutTime.contains(teams.getTeamForPlayer(player)))) {
return InteractionResult.FAIL;
} else if (recyclingRegion.contains(pos)) {
var item = player.getItemInHand(hand);
CraftedUsing craftedUsing = item.get(CraftingBee.CRAFTED_USING);
if (craftedUsing == null) {
return InteractionResult.FAIL;
}
if (item.getCount() < craftedUsing.count()) {
return InteractionResult.FAIL;
}
}
ItemStack itemInHand = player.getItemInHand(hand);
if (recyclingRegion.contains(pos) && !itemInHand.isEmpty()) {
return useRecycler(player, itemInHand);
}
return InteractionResult.PASS;
}

item.shrink(craftedUsing.count());
craftedUsing.items().stream().forEach(player::addItem);
private InteractionResult useRecycler(ServerPlayer player, ItemStack itemToRecycle) {
CraftedUsing craftedUsing = itemToRecycle.get(CraftingBee.CRAFTED_USING);
if (craftedUsing == null) {
player.sendSystemMessage(CraftingBeeTexts.CANNOT_RECYCLE, true);
player.playNotifySound(SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0f, 1.0f);
return InteractionResult.FAIL;
}
if (itemToRecycle.getCount() < craftedUsing.count()) {
player.sendSystemMessage(CraftingBeeTexts.NOT_ENOUGH_TO_RECYCLE.apply(craftedUsing.count(), itemToRecycle.getHoverName()), true);
player.playNotifySound(SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0f, 1.0f);
return InteractionResult.FAIL;
}

timerBars.get(teams.getTeamForPlayer(player))
.state().increaseRemaining(-recyclingPenalty);
itemToRecycle.shrink(craftedUsing.count());
craftedUsing.items().stream().forEach(player::addItem);

return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
applyTimePenalty(player, recyclingPenalty);
player.playNotifySound(SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0f, 1.0f);

return InteractionResult.SUCCESS;
}

private void applyTimePenalty(ServerPlayer player, int penalty) {
timerBars.get(teams.getTeamForPlayer(player))
.state().increaseRemaining(-penalty);

Component subtitle = CraftingBeeTexts.TIME_PENALTY.apply(Mth.positiveCeilDiv(penalty, SharedConstants.TICKS_PER_SECOND));
teams.getPlayersOnSameTeam(player).showTitle(null, subtitle, 10, 20, 10);
}

private void sync(GameTeamKey team) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ public final class CraftingBeeTexts {
public static final Component DONT_CHEAT = KEYS.add("dont_cheat", "Don't cheat!").withStyle(ChatFormatting.RED);
public static final Component HINT = KEYS.add("hint", "Click to show a hint, displaying the position of a random number of ingredients");
public static final TranslationCollector.Fun1 HINTS_LEFT = KEYS.add1("hints_left", "You have %s hints left");
public static final Component CANNOT_RECYCLE = KEYS.add("cannot_recycle", "You can only recycle items that you have crafted!").withStyle(ChatFormatting.RED);
public static final Component TIME_UP = KEYS.add("time_up", "Time's up!").withStyle(ChatFormatting.GOLD);
public static final TranslationCollector.Fun2 NOT_ENOUGH_TO_RECYCLE = KEYS.add2("not_enough_to_recycle", "You need at least %s %s to recycle this").withStyle(ChatFormatting.RED);
public static final TranslationCollector.Fun1 TIME_PENALTY = KEYS.add1("time_penalty", "-%s seconds").withStyle(ChatFormatting.RED);
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,31 @@ public Iterator<ServerPlayer> iterator() {
};
}

static PlayerSet of(ServerPlayer player) {
return new PlayerSet() {
@Override
public boolean contains(UUID id) {
return id.equals(player.getUUID());
}

@Override
@Nullable
public ServerPlayer getPlayerBy(UUID id) {
return contains(id) ? player : null;
}

@Override
public int size() {
return 1;
}

@Override
public Iterator<ServerPlayer> iterator() {
return Collections.singletonList(player).iterator();
}
};
}

static PlayerSet intersection(PlayerSet left, PlayerSet right) {
return new PlayerSet() {
@Override
Expand All @@ -116,13 +141,7 @@ public ServerPlayer getPlayerBy(UUID id) {

@Override
public int size() {
int size = 0;
for (ServerPlayer player : left) {
if (right.contains(player)) {
size++;
}
}
return size;
return Iterators.size(iterator());
}

@Override
Expand All @@ -132,6 +151,31 @@ public Iterator<ServerPlayer> iterator() {
};
}

static PlayerSet difference(PlayerSet first, PlayerSet second) {
return new PlayerSet() {
@Override
public boolean contains(UUID id) {
return first.contains(id) && !second.contains(id);
}

@Override
@Nullable
public ServerPlayer getPlayerBy(UUID id) {
return !second.contains(id) ? first.getPlayerBy(id) : null;
}

@Override
public int size() {
return Iterators.size(iterator());
}

@Override
public Iterator<ServerPlayer> iterator() {
return Iterators.filter(first.iterator(), player -> !second.contains(player));
}
};
}

default boolean contains(Entity entity) {
return contains(entity.getUUID());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ public PlayerSet getPlayersForTeam(GameTeamKey team) {
return players != null ? players : PlayerSet.EMPTY;
}

public PlayerSet getPlayersOnSameTeam(ServerPlayer player) {
GameTeamKey team = getTeamForPlayer(player);
if (team == null) {
return PlayerSet.of(player);
}
return getPlayersForTeam(team);
}

private MutablePlayerSet getPlayersForTeamMutable(MinecraftServer server, GameTeamKey team) {
MutablePlayerSet players = playersByKey.get(team);
if (players == null) {
Expand Down

0 comments on commit 9463a4c

Please sign in to comment.