Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ e0e1dcbc8d0051dfd2185f9902fef371ba7e7ff0 data/bingo/bingo/tag/build.json
ec0fed5926df047e2433eb011817907108d7bf88 data/bingo/bingo/tag/end.json
e3afeb62cdd4266a49147832aa67f9e14d2f7246 data/bingo/bingo/tag/finish.json
f8ad1ef69be0bbac9da8bba2cf794b6a6519e50c data/bingo/bingo/tag/item.json
aae72d460b7547e879e02ee32031ab4aa1597a0e data/bingo/bingo/tag/lockout_inflictable.json
ddddf8256baebcc4d250a5006d09d57acbb4ba8c data/bingo/bingo/tag/nether.json
8039ae633d3d0066f7387790117273e7f6f2c64e data/bingo/bingo/tag/never.json
70db5d2846993435adc1455b5d3829590162a48e data/bingo/bingo/tag/ocean.json
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"difficulty_max": [
1.0
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public class BingoCommand {
);
};

private static final CommandSwitch<Boolean> ALLOW_NEVER_GOALS_IN_LOCKOUT = CommandSwitch.storeTrue("--allow-never-goals-in-lockout");
private static final CommandSwitch<Boolean> REQUIRE_CLIENT = CommandSwitch.storeTrue("--require-client");
private static final CommandSwitch<Boolean> CONTINUE_AFTER_WIN = CommandSwitch.storeTrue("--continue-after-win");
private static final CommandSwitch<Boolean> INCLUDE_INACTIVE_TEAMS = CommandSwitch.storeTrue("--include-inactive-teams");
Expand Down Expand Up @@ -358,6 +359,7 @@ public Component getDisplayName() {
{
final CommandNode<CommandSourceStack> startCommand = bingoCommand.getChild("start");

ALLOW_NEVER_GOALS_IN_LOCKOUT.addTo(startCommand);
REQUIRE_CLIENT.addTo(startCommand);
CONTINUE_AFTER_WIN.addTo(startCommand);
INCLUDE_INACTIVE_TEAMS.addTo(startCommand);
Expand Down Expand Up @@ -399,6 +401,7 @@ private static int startGame(CommandContext<CommandSourceStack> context, int tea
final var excludedTags = EXCLUDE_TAG.get(context);
final int size = SIZE.get(context);
final var gamemode = GAMEMODE.get(context).value();
final boolean allowNeverGoalsInLockout = ALLOW_NEVER_GOALS_IN_LOCKOUT.get(context);
final boolean requireClient = REQUIRE_CLIENT.get(context);
final boolean continueAfterWin = CONTINUE_AFTER_WIN.get(context);
final boolean includeInactiveTeams = INCLUDE_INACTIVE_TEAMS.get(context);
Expand Down Expand Up @@ -439,6 +442,7 @@ private static int startGame(CommandContext<CommandSourceStack> context, int tea
gamemode::isGoalAllowed,
requiredGoals,
excludedTags,
allowNeverGoalsInLockout,
requireClient,
registries
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class TeamValue {

int totalScore = 0;
for (final BingoBoard.Teams state : clientGame.states()) {
if (state.any()) {
if (state.count() == 1) {
totalScore++;
teams[state.getFirstIndex()].score++;
}
Expand Down Expand Up @@ -243,20 +243,18 @@ public static void renderBingo(GuiGraphics graphics, boolean mouseHover, Positio
renderer.renderDecorations(icon, minecraft.font, graphics, slotX, slotY);
final BingoBoard.Teams state = clientGame.getState(sx, sy);
boolean isGoalCompleted = state.and(clientTeam);
int incompleteColor = Objects.requireNonNullElse(goal.specialType().incompleteColor, 0);

final Integer color = switch (clientGame.renderMode()) {
case FANCY -> isGoalCompleted ? Integer.valueOf(0x55ff55) : goal.specialType().incompleteColor;
case ALL_TEAMS -> {
if (!state.any()) {
yield null;
}
final BingoBoard.Teams team = isGoalCompleted ? clientTeam : state;
final Integer maybeColor = clientGame.teams()[team.getFirstIndex()].getColor().getColor();
yield maybeColor != null ? maybeColor : 0x55ff55;
}
final int[] colors = switch (clientGame.renderMode()) {
case FANCY -> new int[]{(isGoalCompleted ? 0x55ff55 : incompleteColor)};
case ALL_TEAMS -> state.stream().map((team) -> clientGame.teams()[team].getColor().getColor()).toArray();
};
if (color != null) {
graphics.fill(slotX, slotY, slotX + 16, slotY + 16, 0xA0000000 | color);
for (int i = 0; i < colors.length; ++i) {
int color = colors[i];
int start = 16 * i / colors.length;
int end = 16 * (i + 1) / colors.length;
int base = (colors.length == 1) ? 0xA0000000 : 0x50000000;
graphics.fill(slotX + start, slotY, slotX + end, slotY + 16, base | color);
}

GoalProgress progress = clientGame.getProgress(sx, sy);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public final class BingoTags {
public static final ResourceKey<BingoTag> END = createKey("end");
public static final ResourceKey<BingoTag> FINISH = createKey("finish");
public static final ResourceKey<BingoTag> ITEM = createKey("item");
public static final ResourceKey<BingoTag> LOCKOUT_INFLICTABLE = createKey("lockout_inflictable");
public static final ResourceKey<BingoTag> NETHER = createKey("nether");
public static final ResourceKey<BingoTag> NEVER = createKey("never");
public static final ResourceKey<BingoTag> OCEAN = createKey("ocean");
Expand All @@ -36,6 +37,7 @@ public static void bootstrap(BootstrapContext<BingoTag> context) {
.build()
);
context.register(ITEM, BingoTag.builder().difficultyMax(25, 25, 20, 20, 20).build());
context.register(LOCKOUT_INFLICTABLE, BingoTag.builder().markerTag().build());
context.register(NETHER, BingoTag.builder().difficultyMax(0, 2, 5, 10, 15).build());
context.register(NEVER, BingoTag.builder()
.difficultyMax(3, 3, 3, 2, 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.gaming32.bingo.data.goal;

import io.github.gaming32.bingo.data.BingoTags;
import io.github.gaming32.bingo.game.ActiveGoal;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
Expand All @@ -26,6 +27,7 @@ public ActiveGoal build(RandomSource rand) {
goal.buildRequiredCount(context),
Optional.of(goal.getDifficulty()),
goal.getRequirements(),
goal.getTags().stream().anyMatch(holder -> holder.is(BingoTags.LOCKOUT_INFLICTABLE)),
goal.getSpecialType(),
goal.getProgress()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public record ActiveGoal(
int requiredCount,
Optional<Holder<BingoDifficulty>> difficulty,
AdvancementRequirements requirements,
Boolean isLockoutInflictable,
BingoTag.SpecialType specialType,
ProgressTracker progress
) {
Expand All @@ -61,6 +62,7 @@ public record ActiveGoal(
.fieldOf("difficulty")
.forGetter(ActiveGoal::difficulty),
AdvancementRequirements.CODEC.fieldOf("requirements").forGetter(ActiveGoal::requirements),
Codec.BOOL.fieldOf("isLockoutInflictable").forGetter(ActiveGoal::isLockoutInflictable),
BingoTag.SpecialType.CODEC
.optionalFieldOf("special_type", BingoTag.SpecialType.NONE)
.forGetter(ActiveGoal::specialType),
Expand All @@ -75,6 +77,7 @@ public record ActiveGoal(
ComponentSerialization.TRUSTED_OPTIONAL_STREAM_CODEC, ActiveGoal::tooltip,
ResourceLocation.STREAM_CODEC.apply(ByteBufCodecs::optional), ActiveGoal::tooltipIcon,
GoalIcon.STREAM_CODEC, ActiveGoal::icon,
ByteBufCodecs.BOOL, ActiveGoal::isLockoutInflictable,
BingoTag.SpecialType.STREAM_CODEC, ActiveGoal::specialType,
ActiveGoal::forClient
);
Expand All @@ -85,12 +88,13 @@ public static ActiveGoal forClient(
Optional<Component> tooltip,
Optional<ResourceLocation> tooltipIcon,
GoalIcon icon,
boolean isLockoutInflictable,
BingoTag.SpecialType specialType
) {
return new ActiveGoal(
id, name, tooltip, tooltipIcon, icon,
Map.of(), 1, Optional.empty(), AdvancementRequirements.EMPTY,
specialType,
isLockoutInflictable, specialType,
EmptyProgressTracker.INSTANCE
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import java.util.NavigableSet;
import java.util.Queue;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.BiPredicate;
import java.util.stream.IntStream;

public class BingoBoard {
Expand Down Expand Up @@ -83,9 +83,10 @@ public static BingoBoard generate(
int difficulty,
int teamCount,
RandomSource rand,
Predicate<GoalHolder> isAllowedGoal,
BiPredicate<GoalHolder, Boolean> isAllowedGoal,
Collection<GoalHolder> requiredGoals,
HolderSet<BingoTag> excludedTags,
boolean allowNeverGoalsInLockout,
boolean allowsClientRequired,
HolderLookup.Provider registries
) {
Expand All @@ -98,6 +99,7 @@ public static BingoBoard generate(
isAllowedGoal,
requiredGoals,
excludedTags,
allowNeverGoalsInLockout,
allowsClientRequired
);
for (int i = 0; i < size * size; i++) {
Expand All @@ -122,9 +124,10 @@ public static GoalHolder[] generateGoals(
int size,
int difficulty,
RandomSource rand,
Predicate<GoalHolder> isAllowedGoal,
BiPredicate<GoalHolder, Boolean> isAllowedGoal,
Collection<GoalHolder> requiredGoals,
HolderSet<BingoTag> excludedTags,
boolean allowNeverGoalsInLockout,
boolean allowsClientRequired
) {
final Queue<GoalHolder> requiredGoalQueue = new ArrayDeque<>(requiredGoals);
Expand Down Expand Up @@ -176,7 +179,7 @@ public static GoalHolder[] generateGoals(

final GoalHolder goalCandidate = possibleGoals.get(rand.nextInt(possibleGoals.size()));

if (!isAllowedGoal.test(goalCandidate)) {
if (!isAllowedGoal.test(goalCandidate, allowNeverGoalsInLockout)) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ private void updateTeamBoard(ServerPlayer player, ActiveGoal goal, boolean revok
final boolean isLoss = isNever ^ revoke;
board[index] = isLoss ? board[index].andNot(team) : board[index].or(team);
notifyTeam(player, team, goal, player.server.getPlayerList(), index, isLoss);
if (!isLoss) {
if (!isLoss || isNever) {
checkForWin(player.server.getPlayerList());
}
}
Expand Down Expand Up @@ -617,12 +617,16 @@ private void notifyTeam(
teamComponent = teamComponent.copy().withStyle(playerTeam.getColor());
}
final Component lockoutMessage = Bingo.translatable(
"bingo.goal_lost.lockout",
isLoss ? "bingo.goal_lost_other.lockout" : "bingo.goal_lost.lockout",
teamComponent, goal.name().copy().withStyle(ChatFormatting.GOLD)
);
for (final ServerPlayer player : playerList.getPlayers()) {
if (player.isAlliedTo(playerTeam)) continue;
player.playNotifySound(SoundEvents.RESPAWN_ANCHOR_DEPLETE.value(), SoundSource.MASTER, 0.5f, 1f);
player.playNotifySound(
isLoss ? SoundEvents.NOTE_BLOCK_CHIME.value() : SoundEvents.RESPAWN_ANCHOR_DEPLETE.value(),
SoundSource.MASTER,
0.5f, 1f
);
player.sendSystemMessage(lockoutMessage);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ default CommandSyntaxException checkAllowedConfig(GameConfig config) {

boolean canGetGoal(BingoBoard board, int index, BingoBoard.Teams team, boolean isNever);

default boolean isGoalAllowed(GoalHolder goal) {
default boolean isGoalAllowed(GoalHolder goal, boolean allowNeverGoalsInLockout) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public boolean canGetGoal(BingoBoard board, int index, BingoBoard.Teams team, bo
}

@Override
public boolean isGoalAllowed(GoalHolder goal) {
public boolean isGoalAllowed(GoalHolder goal, boolean allowNeverGoalsInLockout) {
return goal.goal().getTags().stream().allMatch(g -> g.value().specialType() == BingoTag.SpecialType.NONE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.gaming32.bingo.Bingo;
import io.github.gaming32.bingo.data.BingoTag;
import io.github.gaming32.bingo.data.goal.GoalHolder;
import io.github.gaming32.bingo.game.ActiveGoal;
import io.github.gaming32.bingo.game.BingoBoard;
import net.minecraft.ChatFormatting;
import net.minecraft.world.scores.PlayerTeam;
Expand Down Expand Up @@ -61,16 +62,23 @@ class TeamValue {
}

int totalHeld = 0;
for (final BingoBoard.Teams state : board.getStates()) {
if (state.any()) {
totalHeld++;
teams[state.getFirstIndex()].goalsHeld++;
boolean nonStalemateGoalsLeft = false;
for (int x = 0; x < board.getSize(); x++) {
for (int y = 0; y < board.getSize(); y++) {
BingoBoard.Teams state = board.getState(x, y);
if (state.count() == 1) {
totalHeld++;
teams[state.getFirstIndex()].goalsHeld++;
} else if (!nonStalemateGoalsLeft) {
ActiveGoal activeGoal = board.getGoal(x, y);
nonStalemateGoalsLeft = activeGoal.specialType() != BingoTag.SpecialType.NEVER || activeGoal.isLockoutInflictable();
}
}
}

Arrays.sort(teams, Comparator.comparing(v -> -v.goalsHeld)); // Sort in reverse

final int totalGoals = board.getSize() * board.getSize();
final int totalGoals = nonStalemateGoalsLeft ? board.getSize() * board.getSize() : totalHeld;
if (totalGoals - totalHeld < teams[0].goalsHeld - teams[1].goalsHeld) {
return teams[0].team;
}
Expand All @@ -91,12 +99,24 @@ class TeamValue {

@Override
public boolean canGetGoal(BingoBoard board, int index, BingoBoard.Teams team, boolean isNever) {
return !board.getStates()[index].any();
if (!isNever) {
return !board.getStates()[index].any();
} else {
return board.getStates()[index].count() > 1 && board.getStates()[index].and(team);
}
}

@Override
public boolean isGoalAllowed(GoalHolder goal) {
return goal.goal().getTags().stream().allMatch(g -> g.value().specialType() == BingoTag.SpecialType.NONE);
public boolean isGoalAllowed(GoalHolder goal, boolean allowNeverGoalsInLockout) {
return goal.goal().getTags().stream().allMatch((g) -> {
if (g.value().specialType() == BingoTag.SpecialType.NONE) {
return true;
}
if (g.value().specialType() == BingoTag.SpecialType.NEVER) {
return allowNeverGoalsInLockout;
}
return false;
});
}

@Override
Expand Down
1 change: 1 addition & 0 deletions common/src/main/resources/assets/bingo/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@
"bingo.goal_lost": "%s lost the goal %s for your team.",
"bingo.goal_lost.single": "You lost the goal %s.",
"bingo.goal_lost.lockout": "%s got the goal %s.",
"bingo.goal_lost_other.lockout": "%s lost the goal %s.",
"bingo.duplicate_teams": "Cannot start a bingo with the same team twice (%s)!",
"bingo.unknown_difficulty": "Unknown difficulty %s",
"bingo.unknown_goal": "Unknown goal %s",
Expand Down
1 change: 1 addition & 0 deletions common/src/main/resources/assets/bingo/lang/ru_ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
"bingo.goal_obtained": "%s получил цель %s для вашей команды.",
"bingo.goal_lost": "%s потерял цель %s для вашей команды.",
"bingo.goal_lost.lockout": "%s получил цель %s.",
"bingo.goal_lost_other.lockout": "%s потерял цель %s.",
"bingo.duplicate_teams": "Нельзя дважды начинать игру в бинго с одной и той же командой (%s)!",
"bingo.unknown_difficulty": "Неизвестная сложность %s",
"bingo.unknown_goal": "Неизвестная цель %s",
Expand Down