diff --git a/src/main/java/eu/pb4/destroythemonument/blocks/DtmBlocks.java b/src/main/java/eu/pb4/destroythemonument/blocks/DtmBlocks.java index 41317d2..b392326 100644 --- a/src/main/java/eu/pb4/destroythemonument/blocks/DtmBlocks.java +++ b/src/main/java/eu/pb4/destroythemonument/blocks/DtmBlocks.java @@ -15,9 +15,7 @@ public class DtmBlocks { public static final Block WEAK_GLASS = register("weak_glass", AbstractBlock.Settings.copy(Blocks.GLASS).strength(0.2f, 0).dropsNothing(), WeakGlassBlock::new); public static final Block LADDER = register("ladder", AbstractBlock.Settings.copy(Blocks.LADDER), FloatingLadderBlock::new); - public static void register() { - - } + public static void register() {} private static T register(String name, AbstractBlock.Settings settings, Function func) { var id = DtmUtil.id(name); diff --git a/src/main/java/eu/pb4/destroythemonument/game/logic/BaseGameLogic.java b/src/main/java/eu/pb4/destroythemonument/game/logic/BaseGameLogic.java index 0de74bc..0c6c457 100644 --- a/src/main/java/eu/pb4/destroythemonument/game/logic/BaseGameLogic.java +++ b/src/main/java/eu/pb4/destroythemonument/game/logic/BaseGameLogic.java @@ -57,11 +57,13 @@ import xyz.nucleoid.plasmid.api.game.GameActivity; import xyz.nucleoid.plasmid.api.game.GameCloseReason; import xyz.nucleoid.plasmid.api.game.GameSpace; +import xyz.nucleoid.plasmid.api.game.GameSpaceState; +import xyz.nucleoid.plasmid.api.game.common.PlayerLimiter; import xyz.nucleoid.plasmid.api.game.common.team.GameTeamKey; import xyz.nucleoid.plasmid.api.game.common.team.TeamChat; import xyz.nucleoid.plasmid.api.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents; -import xyz.nucleoid.plasmid.api.game.player.PlayerSet; +import xyz.nucleoid.plasmid.api.game.player.*; import xyz.nucleoid.plasmid.api.game.rule.GameRuleType; import xyz.nucleoid.plasmid.api.game.stats.GameStatisticBundle; import xyz.nucleoid.plasmid.api.game.stats.StatisticKeys; @@ -139,6 +141,7 @@ public BaseGameLogic(GameSpace gameSpace, GameMap map, GameConfig config, Object } public void setupGame(GameActivity game, GameMap map, GameConfig config, Multimap playerTeams) { + PlayerLimiter.addTo(game, config.players().playerConfig()); game.setRule(GameRuleType.CRAFTING, EventResult.DENY); game.setRule(GameRuleType.PORTALS, EventResult.DENY); game.setRule(GameRuleType.PVP, EventResult.PASS); @@ -151,11 +154,13 @@ public void setupGame(GameActivity game, GameMap map, GameConfig config, Multima game.listen(GameActivityEvents.CREATE, this::onOpen); game.listen(GameActivityEvents.DESTROY, this::onClose); - game.listen(GamePlayerEvents.ACCEPT, offer -> offer.teleport(map.world, map.getRandomSpawnPosAsVec3d())); + game.listen(GamePlayerEvents.ACCEPT, this::handleAccept); game.listen(GamePlayerEvents.ADD, this::addPlayer); + game.listen(GamePlayerEvents.OFFER, this::handleOffer); game.listen(GamePlayerEvents.LEAVE, this::removePlayer); game.listen(GameActivityEvents.TICK, this::tick); + game.listen(GameActivityEvents.STATE_UPDATE, this::updateState); game.listen(BlockBreakEvent.EVENT, this::onPlayerBreakBlock); game.listen(BlockPlaceEvent.BEFORE, this::onPlayerPlaceBlock); game.listen(BlockPunchEvent.EVENT, this::onBlockPunch); @@ -184,10 +189,6 @@ public void setupGame(GameActivity game, GameMap map, GameConfig config, Multima } protected EventResult onBlockPunch(ServerPlayerEntity player, Direction direction, BlockPos blockPos) { - PlayerData data = this.participants.get(PlayerRef.of(player)); - if (data != null && player.getWorld().getBlockState(blockPos).calcBlockBreakingDelta(player, player.getWorld(), blockPos) < 0.5) { - data.activeClass.updateMainTool(player, player.getWorld().getBlockState(blockPos)); - } return EventResult.PASS; } @@ -362,14 +363,38 @@ protected void onClose(GameCloseReason reason) { } } + + protected GameSpaceState.Builder updateState(GameSpaceState.Builder builder) { + return builder.canPlay(this.config.allowJoiningInGame() && builder.canPlay()); + } + + protected JoinOfferResult handleOffer(JoinOffer joinOffer) { + if (joinOffer.intent() == JoinIntent.PLAY && !this.config.allowJoiningInGame()) { + return joinOffer.reject(Text.translatable("text.destroy_the_monument.cant_join_while_active")); + } + + return joinOffer.pass(); + } + + protected JoinAcceptorResult handleAccept(JoinAcceptor offer) { + return offer.teleport(this.gameMap.world, this.gameMap.getRandomSpawnPosAsVec3d()); + } + protected void addPlayer(ServerPlayerEntity player) { - if (!this.participants.containsKey(PlayerRef.of(player))) { - if (this.config.allowJoiningInGame() && this.participants.size() < this.config.players().playerConfig().maxPlayers().orElse(99999)) { - this.globalSidebar.addPlayer(player); - PlayOrSpectateUI.open(player, this); - } + if (this.gameSpace.getPlayers().spectators().contains(player)) { + this.globalSidebar.addPlayer(player); this.spawnSpectator(player); } else { + this.globalSidebar.removePlayer(player); + var playerData = this.participants.computeIfAbsent(PlayerRef.of(player), (ref) -> { + var data = new PlayerData(this.defaultKit); + GameTeamKey team = this.teams.getSmallestTeam(); + data.teamData = this.teams.getData(team); + this.teams.addPlayer(player, team); + return data; + }); + + this.setPlayerSidebar(player, playerData); this.spawnParticipant(player); } @@ -378,17 +403,6 @@ protected void addPlayer(ServerPlayerEntity player) { } } - public void addNewParticipant(ServerPlayerEntity player) { - this.globalSidebar.removePlayer(player); - GameTeamKey team = this.teams.getSmallestTeam(); - PlayerData playerData = new PlayerData(this.defaultKit); - playerData.teamData = this.teams.getData(team); - this.participants.put(PlayerRef.of(player), playerData); - this.teams.addPlayer(player, team); - this.setPlayerSidebar(player, playerData); - this.spawnParticipant(player); - } - protected void removePlayer(ServerPlayerEntity player) { PlayerData dtmPlayer = this.participants.remove(PlayerRef.of(player)); if (dtmPlayer != null) { diff --git a/src/main/java/eu/pb4/destroythemonument/game/logic/StandardGameLogic.java b/src/main/java/eu/pb4/destroythemonument/game/logic/StandardGameLogic.java index 80245c3..c3e4307 100644 --- a/src/main/java/eu/pb4/destroythemonument/game/logic/StandardGameLogic.java +++ b/src/main/java/eu/pb4/destroythemonument/game/logic/StandardGameLogic.java @@ -13,6 +13,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.minecraft.network.packet.s2c.play.ExplosionS2CPacket; import net.minecraft.particle.ParticleTypes; +import net.minecraft.scoreboard.number.BlankNumberFormat; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; @@ -20,12 +21,10 @@ import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.text.TextColor; -import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; -import net.minecraft.world.explosion.Explosion; import xyz.nucleoid.plasmid.api.game.GameActivity; import xyz.nucleoid.plasmid.api.game.GameSpace; import xyz.nucleoid.plasmid.api.game.common.team.GameTeamKey; @@ -68,7 +67,7 @@ public void setupGame(GameActivity game, GameMap map, GameConfig config, Multima protected void maybeEliminate(TeamData teamData) { if (teamData.aliveMonuments.size() <= 0) { - for (ServerPlayerEntity player : this.gameSpace.getPlayers()) { + for (ServerPlayerEntity player : this.gameSpace.getPlayers().players()) { PlayerData dtmPlayer = this.participants.get(PlayerRef.of(player)); if (dtmPlayer != null && dtmPlayer.teamData == teamData) { player.changeGameMode(GameMode.SPECTATOR); @@ -210,7 +209,7 @@ protected void buildSidebar() { boolean compact = (monumentsSize + 1) * this.sidebarTeams.size() > 11; this.globalSidebar.setTitle(DtmUtil.getText("sidebar", "standard_title").setStyle(Style.EMPTY.withColor(Formatting.GOLD).withBold(true))); - + this.globalSidebar.setDefaultNumberFormat(BlankNumberFormat.INSTANCE); this.globalSidebar.set(b -> { b.add(Text.empty()); diff --git a/src/main/java/eu/pb4/destroythemonument/game/playerclass/PlayerClass.java b/src/main/java/eu/pb4/destroythemonument/game/playerclass/PlayerClass.java index 5bd25df..61e4732 100644 --- a/src/main/java/eu/pb4/destroythemonument/game/playerclass/PlayerClass.java +++ b/src/main/java/eu/pb4/destroythemonument/game/playerclass/PlayerClass.java @@ -33,7 +33,6 @@ public record PlayerClass( String name, ItemStack icon, Map, Double> attributes, - ItemStack pickaxe, ItemStack axe, List armorVisual, List items, List restockableItems, int blocksToPlanks @@ -44,8 +43,6 @@ public record PlayerClass( Codec.STRING.fieldOf("class_name").forGetter(PlayerClass::name), MoreCodecs.ITEM_STACK.fieldOf("icon").forGetter(PlayerClass::icon), Codec.unboundedMap(Registries.ATTRIBUTE.getEntryCodec(), Codec.DOUBLE).optionalFieldOf("attributes", Map.of()).forGetter(PlayerClass::attributes), - MoreCodecs.ITEM_STACK.fieldOf("pickaxe_tool").forGetter(PlayerClass::pickaxe), - MoreCodecs.ITEM_STACK.fieldOf("axe_tool").forGetter(PlayerClass::axe), Codec.list(MoreCodecs.ITEM_STACK).fieldOf("armor").forGetter(PlayerClass::armorVisual), Codec.list(MoreCodecs.ITEM_STACK).fieldOf("items").forGetter(PlayerClass::items), Codec.list(RestockableItem.CODEC).fieldOf("restockable_items").forGetter(PlayerClass::restockableItems), @@ -57,12 +54,6 @@ public void setupPlayer(ServerPlayerEntity player, TeamData team) { player.getAttributes().getCustomInstance(x.getKey()).setBaseValue(x.getValue()); } - player.getInventory().insertStack(ItemStackBuilder.of(this.pickaxe) - .addModifier(EntityAttributes.ATTACK_DAMAGE, new EntityAttributeModifier(Item.BASE_ATTACK_DAMAGE_MODIFIER_ID, 0, EntityAttributeModifier.Operation.ADD_MULTIPLIED_TOTAL), AttributeModifierSlot.MAINHAND) - .setUnbreakable() - .setRepairCost(TOOL_REPAIR_COST) - .build()); - for (ItemStack itemStack : this.items) { player.getInventory().insertStack(ItemStackBuilder.of(itemStack).setUnbreakable().build()); } @@ -91,31 +82,6 @@ public void setupPlayer(ServerPlayerEntity player, TeamData team) { player.equipStack(EquipmentSlot.OFFHAND, new ItemStack(DtmItems.MAP)); } - public void updateMainTool(ServerPlayerEntity player, BlockState state) { - ItemStack stack = player.getMainHandStack(); - if (stack.getOrDefault(DataComponentTypes.REPAIR_COST, 0) == TOOL_REPAIR_COST) { - ItemStack base = null; - if (state.isIn(BlockTags.AXE_MINEABLE)) { - if (!(stack.getItem() instanceof AxeItem)) { - base = this.axe; - } - } else if (state.isIn(BlockTags.PICKAXE_MINEABLE)) { - if (!(stack.getItem() instanceof PickaxeItem)) { - base = this.pickaxe; - } - } - - if (base != null && !base.isEmpty()) { - player.getInventory().setStack(player.getInventory().selectedSlot, ItemStackBuilder.of(base) - .addModifier(EntityAttributes.ATTACK_DAMAGE, new EntityAttributeModifier(Item.BASE_ATTACK_DAMAGE_MODIFIER_ID, 0, EntityAttributeModifier.Operation.ADD_MULTIPLIED_TOTAL ), AttributeModifierSlot.MAINHAND) - .setUnbreakable() - .setRepairCost(TOOL_REPAIR_COST) - .build()); - } - - } - } - public void maybeRestockPlayer(ServerPlayerEntity player, PlayerData playerData) { for (RestockableItem ri : this.restockableItems) { var timer = playerData.restockTimers.getInt(ri); diff --git a/src/main/java/eu/pb4/destroythemonument/items/DtmItems.java b/src/main/java/eu/pb4/destroythemonument/items/DtmItems.java index 51f9cf7..884a436 100644 --- a/src/main/java/eu/pb4/destroythemonument/items/DtmItems.java +++ b/src/main/java/eu/pb4/destroythemonument/items/DtmItems.java @@ -6,6 +6,8 @@ import eu.pb4.polymer.core.api.item.SimplePolymerItem; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ToolComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -13,10 +15,12 @@ import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Rarity; +import java.util.List; import java.util.function.Function; public class DtmItems { @@ -35,6 +39,18 @@ public Text getName(ItemStack stack) { public static final Item LADDER = register("ladder", (settings) -> new PolymerBlockItem(DtmBlocks.LADDER, settings.useBlockPrefixedTranslationKey(), Items.LADDER)); public static final Item MAP = register("map", DtmMapItem::new); public static final Item TNT = register("tnt", DtmTntItem::new); + public static final Item MINING_TOOL = register("mining_tool", settings -> { + var lookup = Registries.createEntryLookup(Registries.BLOCK); + return new SimplePolymerItem( + settings.component(DataComponentTypes.TOOL, new ToolComponent(List.of( + ToolComponent.Rule.ofNeverDropping(lookup.getOrThrow(BlockTags.INCORRECT_FOR_DIAMOND_TOOL)), + ToolComponent.Rule.ofAlwaysDropping(lookup.getOrThrow(BlockTags.PICKAXE_MINEABLE), 7.5F), + ToolComponent.Rule.ofAlwaysDropping(lookup.getOrThrow(BlockTags.AXE_MINEABLE), 6.0F), + ToolComponent.Rule.ofAlwaysDropping(lookup.getOrThrow(BlockTags.SHOVEL_MINEABLE), 2.5F), + ToolComponent.Rule.ofAlwaysDropping(lookup.getOrThrow(BlockTags.HOE_MINEABLE), 2.5F) + ), 1.0F, 1) + ), Items.IRON_PICKAXE); + }); public static void registerItems() { diff --git a/src/main/java/eu/pb4/destroythemonument/ui/PlayOrSpectateUI.java b/src/main/java/eu/pb4/destroythemonument/ui/PlayOrSpectateUI.java index ea97237..514c610 100644 --- a/src/main/java/eu/pb4/destroythemonument/ui/PlayOrSpectateUI.java +++ b/src/main/java/eu/pb4/destroythemonument/ui/PlayOrSpectateUI.java @@ -19,15 +19,15 @@ public PlayOrSpectateUI(ServerPlayerEntity player, BaseGameLogic game) { this.setTitle(DtmUtil.getText("ui", "join_selector.title")); this.setSlot(11, new GuiElementBuilder(Items.DIAMOND_SWORD) .setName(DtmUtil.getText("ui", "join_selector.play").formatted(Formatting.GOLD)) - .hideFlags() + .hideDefaultTooltip() .setCallback((x, y, z, p) -> { this.allowClosing = true; this.close(); - game.addNewParticipant(player); + //game.addNewParticipant(player); })); this.setSlot(15, new GuiElementBuilder(Items.ENDER_EYE) - .hideFlags() + .hideDefaultTooltip() .setName(DtmUtil.getText("ui", "join_selector.spectate").formatted(Formatting.GOLD)) .setCallback((x, y, z, p) -> { this.allowClosing = true; diff --git a/src/main/resources/data/destroy_the_monument/class_dtm/archer.json b/src/main/resources/data/destroy_the_monument/class_dtm/archer.json index 725f289..630b73c 100644 --- a/src/main/resources/data/destroy_the_monument/class_dtm/archer.json +++ b/src/main/resources/data/destroy_the_monument/class_dtm/archer.json @@ -6,8 +6,6 @@ "movement_speed": 0.13, "armor": 9 }, - "pickaxe_tool": "diamond_pickaxe", - "axe_tool": "iron_axe", "armor": [ "leather_helmet", "chainmail_chestplate", @@ -15,6 +13,7 @@ "golden_boots" ], "items": [ + "destroy_the_monument:mining_tool", { "id": "golden_sword", "count": 1, diff --git a/src/main/resources/data/destroy_the_monument/class_dtm/berserker.json b/src/main/resources/data/destroy_the_monument/class_dtm/berserker.json index bddad20..ecce19d 100644 --- a/src/main/resources/data/destroy_the_monument/class_dtm/berserker.json +++ b/src/main/resources/data/destroy_the_monument/class_dtm/berserker.json @@ -7,7 +7,6 @@ "movement_speed": 0.13, "armor": 3 }, - "axe_tool": "air", "armor": [ "iron_helmet", "leather_chestplate", @@ -15,6 +14,7 @@ "leather_boots" ], "items": [ + "destroy_the_monument:mining_tool", "iron_axe" ], "restockable_items": [ diff --git a/src/main/resources/data/destroy_the_monument/class_dtm/constructor.json b/src/main/resources/data/destroy_the_monument/class_dtm/constructor.json index 2b9f2b2..787cb03 100644 --- a/src/main/resources/data/destroy_the_monument/class_dtm/constructor.json +++ b/src/main/resources/data/destroy_the_monument/class_dtm/constructor.json @@ -15,6 +15,7 @@ "iron_boots" ], "items": [ + "destroy_the_monument:mining_tool", { "id": "stone_sword", "count": 1 diff --git a/src/main/resources/data/destroy_the_monument/class_dtm/tank.json b/src/main/resources/data/destroy_the_monument/class_dtm/tank.json index 80cc761..9674bea 100644 --- a/src/main/resources/data/destroy_the_monument/class_dtm/tank.json +++ b/src/main/resources/data/destroy_the_monument/class_dtm/tank.json @@ -16,6 +16,7 @@ "netherite_boots" ], "items": [ + "destroy_the_monument:mining_tool", { "id": "iron_sword", "Count": 1 diff --git a/src/main/resources/data/destroy_the_monument/class_dtm/warrior.json b/src/main/resources/data/destroy_the_monument/class_dtm/warrior.json index 7f45c39..e305dfc 100644 --- a/src/main/resources/data/destroy_the_monument/class_dtm/warrior.json +++ b/src/main/resources/data/destroy_the_monument/class_dtm/warrior.json @@ -5,8 +5,6 @@ "armor": 8, "movement_speed": 0.11 }, - "pickaxe_tool": "diamond_pickaxe", - "axe_tool": "iron_axe", "armor": [ "leather_helmet", "iron_chestplate", @@ -14,6 +12,7 @@ "iron_boots" ], "items": [ + "destroy_the_monument:mining_tool", { "id": "diamond_sword", "count": 1, diff --git a/src/main/resources/data/destroy_the_monument/lang/en_us.json b/src/main/resources/data/destroy_the_monument/lang/en_us.json index 560b5f6..71a392c 100644 --- a/src/main/resources/data/destroy_the_monument/lang/en_us.json +++ b/src/main/resources/data/destroy_the_monument/lang/en_us.json @@ -15,6 +15,7 @@ "item.destroy_the_monument.multi_block": "Multi Block", "item.destroy_the_monument.map": "Map", "item.destroy_the_monument.tnt": "TNT", + "item.destroy_the_monument.mining_tool": "Pickaxe", "block.destroy_the_monument.weak_glass": "Weak Glass Block", "block.destroy_the_monument.ladder": "Ladder", @@ -66,6 +67,8 @@ "ui.destroy_the_monument.join_selector.play": "Join the game", "ui.destroy_the_monument.join_selector.spectate": "Stay as spectator", + "text.destroy_the_monument.cant_join_while_active": "You can't join this game while it's active!", + "map.destroy_the_monument.concrete": "Destroy The Monument: Concrete", "map.destroy_the_monument.cubes": "Destroy The Monument: Cubes", "map.destroy_the_monument.honey": "Destroy The Monument: Honey",