diff --git a/src/main/java/com/minelittlepony/unicopia/Config.java b/src/main/java/com/minelittlepony/unicopia/Config.java index 0321e45b..146b8511 100644 --- a/src/main/java/com/minelittlepony/unicopia/Config.java +++ b/src/main/java/com/minelittlepony/unicopia/Config.java @@ -1,17 +1,13 @@ package com.minelittlepony.unicopia; +import java.util.HashSet; import java.util.Set; -import com.google.gson.GsonBuilder; import com.minelittlepony.common.util.GamePaths; import com.minelittlepony.common.util.settings.*; public class Config extends com.minelittlepony.common.util.settings.Config { - private static final Adapter ADAPTER = new HeirarchicalJsonConfigAdapter(new GsonBuilder() - .registerTypeAdapter(Race.class, RegistryTypeAdapter.of(Race.REGISTRY)) - ); - - public final Setting> speciesWhiteList = value("server", "speciesWhiteList", Set.of()) + public final Setting> speciesWhiteList = value("server", "speciesWhiteList", (Set)new HashSet()) .addComment("A whitelist of races permitted on the server") .addComment("Races added to this list can be used by anyone,") .addComment("whilst any ones left off are not permitted") @@ -35,6 +31,6 @@ public class Config extends com.minelittlepony.common.util.settings.Config { .addComment("Turn this ON if you're using another mod that does something similar of if you encounter copatibility issues with other mods."); public Config() { - super(ADAPTER, GamePaths.getConfigDirectory().resolve("unicopia.json")); + super(HEIRARCHICAL_JSON_ADAPTER, GamePaths.getConfigDirectory().resolve("unicopia.json")); } } diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index 61277735..7a7a8815 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -1,8 +1,10 @@ package com.minelittlepony.unicopia; import java.util.Set; +import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; +import org.spongepowered.include.com.google.common.base.Objects; import com.google.common.base.Strings; import com.minelittlepony.unicopia.ability.magic.Affine; @@ -102,6 +104,11 @@ public final class Race implements Affine { return canFly() && this != CHANGELING && this != BAT; } + public Identifier getId() { + Identifier id = REGISTRY.getId(this); + return id; + } + public Text getDisplayName() { return Text.translatable(getTranslationKey()); } @@ -111,12 +118,12 @@ public final class Race implements Affine { } public String getTranslationKey() { - Identifier id = REGISTRY.getId(this); + Identifier id = getId(); return String.format("%s.race.%s", id.getNamespace(), id.getPath().toLowerCase()); } public Identifier getIcon() { - Identifier id = REGISTRY.getId(this); + Identifier id = getId(); return new Identifier(id.getNamespace(), "textures/gui/race/" + id.getPath() + ".png"); } @@ -125,11 +132,11 @@ public final class Race implements Affine { return false; } - Set whitelist = Unicopia.getConfig().speciesWhiteList.get(); + Set whitelist = Unicopia.getConfig().speciesWhiteList.get(); return isDefault() || whitelist.isEmpty() - || whitelist.contains(this); + || whitelist.contains(getId().toString()); } public Race validate(PlayerEntity sender) { @@ -144,8 +151,23 @@ public final class Race implements Affine { return this; } + @Override + public int hashCode() { + return getId().hashCode(); + } + + @Override + public boolean equals(Object o) { + return o instanceof Race race && Objects.equal(race.getId(), getId()); + } + + @Override + public String toString() { + return "Race{ " + getId().toString() + " }"; + } + public boolean equals(String s) { - return REGISTRY.getId(this).toString().equalsIgnoreCase(s) + return getId().toString().equalsIgnoreCase(s) || getTranslationKey().equalsIgnoreCase(s); } @@ -171,6 +193,10 @@ public final class Race implements Affine { Identifier id = context.getArgument(name, RegistryKey.class).getValue(); return REGISTRY.getOrEmpty(id).orElseThrow(() -> UNKNOWN_RACE_EXCEPTION.create(id)); } + + public static Set allPermitted(PlayerEntity player) { + return REGISTRY.stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet()); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/WorldTribeManager.java b/src/main/java/com/minelittlepony/unicopia/WorldTribeManager.java index 2746bc4d..afd1f492 100644 --- a/src/main/java/com/minelittlepony/unicopia/WorldTribeManager.java +++ b/src/main/java/com/minelittlepony/unicopia/WorldTribeManager.java @@ -22,7 +22,9 @@ public class WorldTribeManager extends PersistentState { } public Race setDefaultRace(Race race) { - return defaultRace = race; + defaultRace = race; + markDirty(); + return defaultRace; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/LanSettingsScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/LanSettingsScreen.java index 476a9eaf..4e82b8db 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/LanSettingsScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/LanSettingsScreen.java @@ -84,13 +84,13 @@ public class LanSettingsScreen extends GameGui { }) .getStyle().setText("unicopia.options.cheats"); - Set whitelist = config.speciesWhiteList.get(); + Set whitelist = config.speciesWhiteList.get(); boolean whitelistEnabled = (forceShowWhitelist || !whitelist.isEmpty()) && !forceHideWhitelist; if (whitelist.isEmpty() && forceShowWhitelist) { for (Race r : Race.REGISTRY) { if (!r.isDefault()) { - whitelist.add(r); + whitelist.add(r.getId().toString()); } } } @@ -116,12 +116,12 @@ public class LanSettingsScreen extends GameGui { if (!race.isDefault()) { Bounds bound = WHITELIST_GRID_PACKER.next(); - Button button = content.addButton(new Toggle(LEFT + bound.left + 10, row + bound.top, whitelist.contains(race))) + Button button = content.addButton(new Toggle(LEFT + bound.left + 10, row + bound.top, whitelist.contains(race.getId().toString()))) .onChange(v -> { if (v) { - whitelist.add(race); + whitelist.add(race.getId().toString()); } else { - whitelist.remove(race); + whitelist.remove(race.getId().toString()); } return v; }) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java index 0d12cee8..2abe8028 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java @@ -7,7 +7,6 @@ import com.minelittlepony.common.client.gui.GameGui; import com.minelittlepony.common.client.gui.element.Label; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.client.UnicopiaClient; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange; @@ -46,33 +45,34 @@ public class TribeSelectionScreen extends GameGui implements HidesHud { block = addDrawable(new TextBlock(left, top += 7, pageWidth)); block.getStyle().setText(Text.translatable("gui.unicopia.tribe_selection.welcome.choice")); top += block.getBounds().height; - - Race preference = UnicopiaClient.getPreferredRace(); - top += 30; - final int itemWidth = 70; + final int itemWidth = 70 + 10; List options = Race.REGISTRY.stream().filter(race -> !race.isDefault() && !race.isOp()).toList(); - int totalWidth = options.size() * (itemWidth + 10) - 10; + int columns = Math.min(width / itemWidth, options.size()); - int x = (width - totalWidth) / 2; + int x = (width - (columns * itemWidth)) / 2; + int y = top; + + int column = 0; + int row = 0; for (Race race : options) { - addOption(race, x, top); - x += itemWidth + 10; + addOption(race, x + (column * itemWidth), y + (row * itemWidth)); + column++; + if (column >= columns) { + column = 0; + row++; + } } top = height - 20; - - if (!preference.isDefault()) { - addDrawable(new Label(width / 2, top).setCentered()).getStyle().setText(Text.translatable("gui.unicopia.tribe_selection.preference", preference.getDisplayName().copy().formatted(Formatting.YELLOW))); - } } - private void addOption(Race race, int x, int top) { - addDrawableChild(new TribeButton(x, top, width, race)).onClick(b -> { + private void addOption(Race race, int x, int y) { + addDrawableChild(new TribeButton(x, y, width, race)).onClick(b -> { finished = true; client.setScreen(new TribeConfirmationScreen(result -> { finished = false; diff --git a/src/main/java/com/minelittlepony/unicopia/command/RacelistCommand.java b/src/main/java/com/minelittlepony/unicopia/command/RacelistCommand.java index 3560df6a..dfeeb37d 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/RacelistCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/RacelistCommand.java @@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.command; import java.util.function.Function; -import com.minelittlepony.unicopia.Race; -import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.*; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; @@ -24,7 +23,7 @@ class RacelistCommand { builder.then(CommandManager.literal("allow") .then(CommandManager.argument("race", raceArgument) .executes(context -> toggle(context.getSource(), context.getSource().getPlayer(), Race.fromArgument(context, "race"), "allowed", race -> { - boolean result = Unicopia.getConfig().speciesWhiteList.get().add(race); + boolean result = Unicopia.getConfig().speciesWhiteList.get().add(race.getId().toString()); Unicopia.getConfig().save(); @@ -34,7 +33,7 @@ class RacelistCommand { builder.then(CommandManager.literal("disallow") .then(CommandManager.argument("race", raceArgument) .executes(context -> toggle(context.getSource(), context.getSource().getPlayer(), Race.fromArgument(context, "race"), "disallowed", race -> { - boolean result = Unicopia.getConfig().speciesWhiteList.get().remove(race); + boolean result = Unicopia.getConfig().speciesWhiteList.get().remove(race.getId().toString()); Unicopia.getConfig().save(); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index a3768fbe..a246a828 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -9,7 +9,6 @@ import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; -import com.minelittlepony.unicopia.client.UnicopiaClient; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.*; import com.minelittlepony.unicopia.ability.AbilityDispatcher; @@ -30,7 +29,6 @@ import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.MsgOtherPlayerCapabilities; import com.minelittlepony.unicopia.network.MsgPlayerAnimationChange; -import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange; import com.minelittlepony.unicopia.network.datasync.Transmittable; import com.minelittlepony.unicopia.util.*; import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback; @@ -94,7 +92,6 @@ public class Pony extends Living implements Transmittable, Copieab private final Interpolator interpolator = new LinearInterpolator(); private boolean dirty; - private boolean speciesSet; private boolean speciesPersisted; private Optional hangingPosition = Optional.empty(); @@ -168,6 +165,10 @@ public class Pony extends Living implements Transmittable, Copieab @Override public Race getSpecies() { + if (UItems.ALICORN_AMULET.isApplicable(entity)) { + return Race.ALICORN; + } + return getSpellSlot() .get(SpellPredicate.IS_MIMIC, true) .map(AbstractDisguiseSpell::getDisguise) @@ -184,7 +185,6 @@ public class Pony extends Living implements Transmittable, Copieab @Override public void setSpecies(Race race) { race = race.validate(entity); - speciesSet = true; ticksInSun = 0; entity.getDataTracker().set(RACE, Race.REGISTRY.getId(race).toString()); @@ -297,19 +297,6 @@ public class Pony extends Living implements Transmittable, Copieab @Override public boolean beforeUpdate() { - - if (isClientPlayer() && !speciesSet) { - Race race = UnicopiaClient.getPreferredRace(); - - if (race != clientPreferredRace) { - clientPreferredRace = race; - - if (race != getActualSpecies()) { - Channel.CLIENT_REQUEST_SPECIES_CHANGE.send(new MsgRequestSpeciesChange(race)); - } - } - } - if (isClient()) { if (entity.hasVehicle() && entity.isSneaking()) { @@ -596,7 +583,7 @@ public class Pony extends Living implements Transmittable, Copieab @Override public void copyFrom(Pony oldPlayer) { - speciesPersisted = oldPlayer.speciesPersisted; + speciesPersisted = true; if (!oldPlayer.getEntity().isRemoved()) { oldPlayer.getSpellSlot().stream(true).forEach(getSpellSlot()::put); } else { diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index 3e46e70b..9eeb1643 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -2,7 +2,7 @@ package com.minelittlepony.unicopia.network; import com.minelittlepony.unicopia.util.network.S2CBroadcastPacketType; import com.minelittlepony.unicopia.util.network.S2CPacketType; -import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.*; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.util.network.C2SPacketType; import com.minelittlepony.unicopia.util.network.SimpleNetworking; @@ -38,8 +38,18 @@ public interface Channel { static void bootstrap() { ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - if (!Pony.of(handler.player).isSpeciesPersisted()) { - sender.sendPacket(SERVER_SELECT_TRIBE.getId(), new MsgTribeSelect(handler.player).toBuffer()); + Pony pony = Pony.of(handler.player); + if (!pony.isSpeciesPersisted()) { + Race race = WorldTribeManager.forWorld(handler.player.getWorld()).getDefaultRace(); + if (!race.isPermitted(handler.player)) { + race = Race.HUMAN; + } + if (race.isUsable()) { + pony.setSpecies(race); + Unicopia.LOGGER.info("Setting {}'s race to {} due to host setting", handler.player.getDisplayName().getString(), Race.REGISTRY.getId(race).toString()); + } else { + sender.sendPacket(SERVER_SELECT_TRIBE.getId(), new MsgTribeSelect(handler.player).toBuffer()); + } } sender.sendPacket(SERVER_RESOURCES_SEND.getId(), new MsgServerResources().toBuffer()); }); diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java b/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java index dc56d48f..d3dcecff 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.network; import java.util.HashSet; import java.util.Set; -import java.util.stream.Collectors; import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; @@ -15,7 +14,7 @@ public class MsgTribeSelect implements Packet { private final Set availableRaces; public MsgTribeSelect(PlayerEntity player) { - availableRaces = Race.REGISTRY.stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet()); + availableRaces = Race.allPermitted(player); } public MsgTribeSelect(PacketByteBuf buffer) {