Skip to content

Commit 9463a4c

Browse files
committed
Add a bunch of text/sounds/flavour to Crafting Bee
1 parent 5053391 commit 9463a4c

File tree

7 files changed

+160
-44
lines changed

7 files changed

+160
-44
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ minecraft_version=1.21
55
neo_version=21.0.167
66
parchment_version=2024.06.23
77
registrate_version=1.3.0+50
8-
ltlib_version=[1.4.7,1.5)
8+
ltlib_version=[1.4.8,1.5)
99
ltextras_version=1.3.0-release+32
1010

1111
org.gradle.jvmargs=-Xmx1G

src/generated/resources/assets/ltminigames/lang/en_ud.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,14 @@
180180
"ltminigames.minigame.conservation_exploration": "uoıʇɐɹoןdxƎ uoıʇɐʌɹǝsuoƆ",
181181
"ltminigames.minigame.crab_hockey": "ʎǝʞɔoH qɐɹƆ",
182182
"ltminigames.minigame.crafting_bee": "ǝǝᗺ buıʇɟɐɹƆ",
183+
"ltminigames.minigame.crafting_bee.cannot_recycle": "¡pǝʇɟɐɹɔ ǝʌɐɥ noʎ ʇɐɥʇ sɯǝʇı ǝןɔʎɔǝɹ ʎןuo uɐɔ noʎ",
183184
"ltminigames.minigame.crafting_bee.dont_cheat": "¡ʇɐǝɥɔ ʇ,uoᗡ",
184185
"ltminigames.minigame.crafting_bee.hint": "sʇuǝıpǝɹbuı ɟo ɹǝqɯnu ɯopuɐɹ ɐ ɟo uoıʇısod ǝɥʇ buıʎɐןdsıp 'ʇuıɥ ɐ ʍoɥs oʇ ʞɔıןƆ",
185186
"ltminigames.minigame.crafting_bee.hints_left": "ʇɟǝן sʇuıɥ %s ǝʌɐɥ noʎ",
187+
"ltminigames.minigame.crafting_bee.not_enough_to_recycle": "sıɥʇ ǝןɔʎɔǝɹ oʇ %s %s ʇsɐǝן ʇɐ pǝǝu noʎ",
186188
"ltminigames.minigame.crafting_bee.team_has_completed_recipes": "sǝdıɔǝɹ %s ɟo ʇno %s pǝʇǝןdɯoɔ sɐɥ %s ɯɐǝ⟘",
189+
"ltminigames.minigame.crafting_bee.time_penalty": "spuoɔǝs %s-",
190+
"ltminigames.minigame.crafting_bee.time_up": "¡dn s,ǝɯı⟘",
187191
"ltminigames.minigame.donation.acid_rain": "uıɐᴚ pıɔⱯ",
188192
"ltminigames.minigame.donation.acid_rain.description": "¡ǝʇnuıɯ Ɩ ɹoɟ spɐǝɥ ,sɹǝʎɐןd ǝɥʇ uo uʍop pıɔɐ uıɐᴚ",
189193
"ltminigames.minigame.donation.acid_rain.toast": "¡ǝʇnuıɯ Ɩ ɹoɟ pıɔɐ buıuıɐɹ sı ʇI",

src/generated/resources/assets/ltminigames/lang/en_us.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,14 @@
180180
"ltminigames.minigame.conservation_exploration": "Conservation Exploration",
181181
"ltminigames.minigame.crab_hockey": "Crab Hockey",
182182
"ltminigames.minigame.crafting_bee": "Crafting Bee",
183+
"ltminigames.minigame.crafting_bee.cannot_recycle": "You can only recycle items that you have crafted!",
183184
"ltminigames.minigame.crafting_bee.dont_cheat": "Don't cheat!",
184185
"ltminigames.minigame.crafting_bee.hint": "Click to show a hint, displaying the position of a random number of ingredients",
185186
"ltminigames.minigame.crafting_bee.hints_left": "You have %s hints left",
187+
"ltminigames.minigame.crafting_bee.not_enough_to_recycle": "You need at least %s %s to recycle this",
186188
"ltminigames.minigame.crafting_bee.team_has_completed_recipes": "Team %s has completed %s out of %s recipes",
189+
"ltminigames.minigame.crafting_bee.time_penalty": "-%s seconds",
190+
"ltminigames.minigame.crafting_bee.time_up": "Time's up!",
187191
"ltminigames.minigame.donation.acid_rain": "Acid Rain",
188192
"ltminigames.minigame.donation.acid_rain.description": "Rain acid down on the players' heads for 1 minute!",
189193
"ltminigames.minigame.donation.acid_rain.toast": "It is raining acid for 1 minute!",

src/main/java/com/lovetropics/minigames/common/content/crafting_bee/CraftingBeeBehavior.java

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.common.collect.ListMultimap;
44
import com.google.common.collect.Multimaps;
55
import com.lovetropics.lib.BlockBox;
6+
import com.lovetropics.lib.entity.FireworkPalette;
67
import com.lovetropics.minigames.common.content.MinigameTexts;
78
import com.lovetropics.minigames.common.content.crafting_bee.ingredient.IngredientDecomposer;
89
import com.lovetropics.minigames.common.core.game.GameException;
@@ -38,6 +39,9 @@
3839
import net.minecraft.resources.ResourceLocation;
3940
import net.minecraft.server.level.ServerLevel;
4041
import net.minecraft.server.level.ServerPlayer;
42+
import net.minecraft.sounds.SoundEvents;
43+
import net.minecraft.sounds.SoundSource;
44+
import net.minecraft.util.Mth;
4145
import net.minecraft.world.BossEvent;
4246
import net.minecraft.world.Container;
4347
import net.minecraft.world.InteractionHand;
@@ -60,10 +64,8 @@
6064
import java.util.List;
6165
import java.util.Map;
6266
import java.util.Set;
63-
import java.util.function.Predicate;
6467
import java.util.function.Supplier;
6568
import java.util.stream.Collectors;
66-
import java.util.stream.IntStream;
6769
import java.util.stream.Stream;
6870

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

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

221228
var teamTasks = tasks.get(team);
222-
var task = teamTasks.stream().filter(c -> ItemStack.isSameItemSameComponents(crafted, c.output)).findFirst().orElse(null);
229+
230+
var craftedStackToCompare = crafted.copy();
231+
craftedStackToCompare.remove(CraftingBee.CRAFTED_USING);
232+
var task = teamTasks.stream().filter(c -> ItemStack.isSameItemSameComponents(craftedStackToCompare, c.output)).findFirst().orElse(null);
223233

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

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

247+
PlayerSet teamPlayers = teams.getPlayersForTeam(team);
248+
teamPlayers.playSound(SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.PLAYERS, 1.0f, 1.0f);
249+
game.spectators().playSound(SoundEvents.FIREWORK_ROCKET_LAUNCH, SoundSource.PLAYERS, 1.0f, 1.0f);
250+
251+
PlayerSet otherPlayers = PlayerSet.difference(game.participants(), teamPlayers);
252+
otherPlayers.playSound(SoundEvents.GHAST_SCREAM, SoundSource.PLAYERS, 0.5f, 0.5f);
253+
237254
if (completed == teamTasks.size()) {
238-
game.invoker(GameLogicEvents.GAME_OVER).onGameWonBy(gameTeam);
255+
triggerGameOver(new GameWinner.Team(gameTeam));
256+
}
257+
}
239258

240-
done = true;
259+
private void triggerGameOver(GameWinner winner) {
260+
done = true;
261+
game.invoker(GameLogicEvents.GAME_OVER).onGameOver(winner);
262+
game.allPlayers().forEach(ServerPlayer::closeContainer);
241263

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

244-
game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(teamConfig.styledName()).withStyle(ChatFormatting.GREEN), true));
245-
game.scheduler().runAfterSeconds(5, () -> game.requestStop(GameStopReason.finished()));
246-
}
267+
if (winner instanceof GameWinner.Team(GameTeam team)) {
268+
for (ServerPlayer winningPlayer : teams.getPlayersForTeam(team.key())) {
269+
applyWinningPlayerEffects(winningPlayer, team);
270+
}
271+
game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(team.config().styledName()).withStyle(ChatFormatting.GREEN), true);
272+
} else {
273+
game.allPlayers().sendMessage(MinigameTexts.NOBODY_WON, true);
274+
}
275+
});
276+
277+
game.scheduler().runAfterSeconds(8, () -> game.requestStop(GameStopReason.finished()));
278+
}
279+
280+
private void applyWinningPlayerEffects(ServerPlayer winningPlayer, GameTeam team) {
281+
game.scheduler().runAfterSeconds(game.random().nextFloat(), () -> {
282+
BlockPos fireworksPos = BlockPos.containing(winningPlayer.getEyePosition()).above();
283+
FireworkPalette.forDye(team.config().dye()).spawn(fireworksPos, game.level());
284+
});
285+
winningPlayer.setGlowingTag(true);
247286
}
248287

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

263302
teamsWithoutTime.add(team);
264-
teams.getPlayersForTeam(team).forEach(ServerPlayer::closeContainer);
303+
304+
PlayerSet playersInTeam = teams.getPlayersForTeam(team);
305+
playersInTeam.forEach(ServerPlayer::closeContainer);
306+
playersInTeam.playSound(SoundEvents.END_PORTAL_SPAWN, SoundSource.PLAYERS, 0.5f, 0.25f);
307+
playersInTeam.showTitle(CraftingBeeTexts.TIME_UP, null, 10, SharedConstants.TICKS_PER_SECOND * 2, 10);
265308

266309
if (teamsWithoutTime.size() == tasks.asMap().size()) {
267310
int mx = tasks.asMap().values().stream().mapToInt(craftingTasks -> (int) craftingTasks.stream().filter(c -> c.done).count())
268311
.max().orElse(0);
269312
var withMax = tasks.asMap().entrySet().stream().filter(e -> e.getValue().stream().filter(c -> c.done).count() == mx)
270313
.toList();
271314
if (withMax.size() != 1) {
272-
game.invoker(GameLogicEvents.GAME_OVER).onGameOver(new GameWinner.Nobody());
273-
274-
game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.NOBODY_WON, true));
315+
triggerGameOver(new GameWinner.Nobody());
275316
} else {
276317
var gameTeam = teams.getTeamByKey(withMax.getFirst().getKey());
277-
var teamConfig = gameTeam.config();
278-
game.invoker(GameLogicEvents.GAME_OVER).onGameWonBy(gameTeam);
279-
280-
game.scheduler().runAfterSeconds(1.5f, () -> game.allPlayers().sendMessage(MinigameTexts.TEAM_WON.apply(teamConfig.styledName()).withStyle(ChatFormatting.GREEN), true));
318+
triggerGameOver(new GameWinner.Team(gameTeam));
281319
}
282-
283-
done = true;
284-
game.scheduler().runAfterSeconds(5, () -> game.requestStop(GameStopReason.finished()));
285320
}
286321
}
287322
}
@@ -301,25 +336,42 @@ private InteractionResult useBlock(ServerPlayer player, ServerLevel world, Block
301336
// don't allow players to use the crafting table after the game was won
302337
if (world.getBlockState(pos).is(Blocks.CRAFTING_TABLE) && (done || teamsWithoutTime.contains(teams.getTeamForPlayer(player)))) {
303338
return InteractionResult.FAIL;
304-
} else if (recyclingRegion.contains(pos)) {
305-
var item = player.getItemInHand(hand);
306-
CraftedUsing craftedUsing = item.get(CraftingBee.CRAFTED_USING);
307-
if (craftedUsing == null) {
308-
return InteractionResult.FAIL;
309-
}
310-
if (item.getCount() < craftedUsing.count()) {
311-
return InteractionResult.FAIL;
312-
}
339+
}
340+
ItemStack itemInHand = player.getItemInHand(hand);
341+
if (recyclingRegion.contains(pos) && !itemInHand.isEmpty()) {
342+
return useRecycler(player, itemInHand);
343+
}
344+
return InteractionResult.PASS;
345+
}
313346

314-
item.shrink(craftedUsing.count());
315-
craftedUsing.items().stream().forEach(player::addItem);
347+
private InteractionResult useRecycler(ServerPlayer player, ItemStack itemToRecycle) {
348+
CraftedUsing craftedUsing = itemToRecycle.get(CraftingBee.CRAFTED_USING);
349+
if (craftedUsing == null) {
350+
player.sendSystemMessage(CraftingBeeTexts.CANNOT_RECYCLE, true);
351+
player.playNotifySound(SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0f, 1.0f);
352+
return InteractionResult.FAIL;
353+
}
354+
if (itemToRecycle.getCount() < craftedUsing.count()) {
355+
player.sendSystemMessage(CraftingBeeTexts.NOT_ENOUGH_TO_RECYCLE.apply(craftedUsing.count(), itemToRecycle.getHoverName()), true);
356+
player.playNotifySound(SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0f, 1.0f);
357+
return InteractionResult.FAIL;
358+
}
316359

317-
timerBars.get(teams.getTeamForPlayer(player))
318-
.state().increaseRemaining(-recyclingPenalty);
360+
itemToRecycle.shrink(craftedUsing.count());
361+
craftedUsing.items().stream().forEach(player::addItem);
319362

320-
return InteractionResult.SUCCESS;
321-
}
322-
return InteractionResult.PASS;
363+
applyTimePenalty(player, recyclingPenalty);
364+
player.playNotifySound(SoundEvents.UI_STONECUTTER_TAKE_RESULT, SoundSource.BLOCKS, 1.0f, 1.0f);
365+
366+
return InteractionResult.SUCCESS;
367+
}
368+
369+
private void applyTimePenalty(ServerPlayer player, int penalty) {
370+
timerBars.get(teams.getTeamForPlayer(player))
371+
.state().increaseRemaining(-penalty);
372+
373+
Component subtitle = CraftingBeeTexts.TIME_PENALTY.apply(Mth.positiveCeilDiv(penalty, SharedConstants.TICKS_PER_SECOND));
374+
teams.getPlayersOnSameTeam(player).showTitle(null, subtitle, 10, 20, 10);
323375
}
324376

325377
private void sync(GameTeamKey team) {

src/main/java/com/lovetropics/minigames/common/content/crafting_bee/CraftingBeeTexts.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ public final class CraftingBeeTexts {
1212
public static final Component DONT_CHEAT = KEYS.add("dont_cheat", "Don't cheat!").withStyle(ChatFormatting.RED);
1313
public static final Component HINT = KEYS.add("hint", "Click to show a hint, displaying the position of a random number of ingredients");
1414
public static final TranslationCollector.Fun1 HINTS_LEFT = KEYS.add1("hints_left", "You have %s hints left");
15+
public static final Component CANNOT_RECYCLE = KEYS.add("cannot_recycle", "You can only recycle items that you have crafted!").withStyle(ChatFormatting.RED);
16+
public static final Component TIME_UP = KEYS.add("time_up", "Time's up!").withStyle(ChatFormatting.GOLD);
17+
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);
18+
public static final TranslationCollector.Fun1 TIME_PENALTY = KEYS.add1("time_penalty", "-%s seconds").withStyle(ChatFormatting.RED);
1519
}

src/main/java/com/lovetropics/minigames/common/core/game/player/PlayerSet.java

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,31 @@ public Iterator<ServerPlayer> iterator() {
9696
};
9797
}
9898

99+
static PlayerSet of(ServerPlayer player) {
100+
return new PlayerSet() {
101+
@Override
102+
public boolean contains(UUID id) {
103+
return id.equals(player.getUUID());
104+
}
105+
106+
@Override
107+
@Nullable
108+
public ServerPlayer getPlayerBy(UUID id) {
109+
return contains(id) ? player : null;
110+
}
111+
112+
@Override
113+
public int size() {
114+
return 1;
115+
}
116+
117+
@Override
118+
public Iterator<ServerPlayer> iterator() {
119+
return Collections.singletonList(player).iterator();
120+
}
121+
};
122+
}
123+
99124
static PlayerSet intersection(PlayerSet left, PlayerSet right) {
100125
return new PlayerSet() {
101126
@Override
@@ -116,13 +141,7 @@ public ServerPlayer getPlayerBy(UUID id) {
116141

117142
@Override
118143
public int size() {
119-
int size = 0;
120-
for (ServerPlayer player : left) {
121-
if (right.contains(player)) {
122-
size++;
123-
}
124-
}
125-
return size;
144+
return Iterators.size(iterator());
126145
}
127146

128147
@Override
@@ -132,6 +151,31 @@ public Iterator<ServerPlayer> iterator() {
132151
};
133152
}
134153

154+
static PlayerSet difference(PlayerSet first, PlayerSet second) {
155+
return new PlayerSet() {
156+
@Override
157+
public boolean contains(UUID id) {
158+
return first.contains(id) && !second.contains(id);
159+
}
160+
161+
@Override
162+
@Nullable
163+
public ServerPlayer getPlayerBy(UUID id) {
164+
return !second.contains(id) ? first.getPlayerBy(id) : null;
165+
}
166+
167+
@Override
168+
public int size() {
169+
return Iterators.size(iterator());
170+
}
171+
172+
@Override
173+
public Iterator<ServerPlayer> iterator() {
174+
return Iterators.filter(first.iterator(), player -> !second.contains(player));
175+
}
176+
};
177+
}
178+
135179
default boolean contains(Entity entity) {
136180
return contains(entity.getUUID());
137181
}

src/main/java/com/lovetropics/minigames/common/core/game/state/team/TeamState.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ public PlayerSet getPlayersForTeam(GameTeamKey team) {
104104
return players != null ? players : PlayerSet.EMPTY;
105105
}
106106

107+
public PlayerSet getPlayersOnSameTeam(ServerPlayer player) {
108+
GameTeamKey team = getTeamForPlayer(player);
109+
if (team == null) {
110+
return PlayerSet.of(player);
111+
}
112+
return getPlayersForTeam(team);
113+
}
114+
107115
private MutablePlayerSet getPlayersForTeamMutable(MinecraftServer server, GameTeamKey team) {
108116
MutablePlayerSet players = playersByKey.get(team);
109117
if (players == null) {

0 commit comments

Comments
 (0)