diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index fb86e9bc..e6fbe11a 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -1,6 +1,7 @@ package com.minelittlepony.unicopia; import java.util.Arrays; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -102,6 +103,10 @@ public enum Race implements Affine { return new TranslatableText(getTranslationKey()); } + public Text getAltDisplayName() { + return new TranslatableText(getTranslationKey() + ".alt"); + } + public String getTranslationKey() { return String.format("unicopia.race.%s", name().toLowerCase()); } @@ -130,7 +135,7 @@ public enum Race implements Affine { return this; } - public Style getStyle() { + public Style createStyle() { return new Style() .setIcon(new TextureSprite() .setPosition(2, 2) @@ -160,6 +165,10 @@ public enum Race implements Affine { return def; } + public static Collection all() { + return REGISTRY.values(); + } + public static Race fromName(String name) { return fromName(name, EARTH); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/HidesHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/HidesHud.java new file mode 100644 index 00000000..baf12575 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/HidesHud.java @@ -0,0 +1,5 @@ +package com.minelittlepony.unicopia.client.gui; + +public interface HidesHud { + +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/SettingsScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/SettingsScreen.java index 9f9ae9c7..799c15e2 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/SettingsScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/SettingsScreen.java @@ -172,7 +172,7 @@ public class SettingsScreen extends GameGui { return v; }) .setEnabled(canEditWhitelist) - .setStyle(race.getStyle()); + .setStyle(race.createStyle()); ((TextureSprite)button.getStyle().getIcon()).setPosition(-20, 0); } @@ -220,12 +220,12 @@ public class SettingsScreen extends GameGui { } } }.setStyles( - Race.EARTH.getStyle(), - Race.UNICORN.getStyle(), - Race.PEGASUS.getStyle(), - Race.BAT.getStyle(), - Race.ALICORN.getStyle(), - Race.CHANGELING.getStyle() + Race.EARTH.createStyle(), + Race.UNICORN.createStyle(), + Race.PEGASUS.createStyle(), + Race.BAT.createStyle(), + Race.ALICORN.createStyle(), + Race.CHANGELING.createStyle() ).onChange(i -> { Unicopia.getConfig().preferredRace.set(Race.fromId(i + 1)); Unicopia.getConfig().save(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TextBlock.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TextBlock.java new file mode 100644 index 00000000..ae312a98 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TextBlock.java @@ -0,0 +1,35 @@ +package com.minelittlepony.unicopia.client.gui; + +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.common.client.gui.element.Label; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.OrderedText; + +public class TextBlock extends Label { + private final int maxWidth; + + public TextBlock(int x, int y, int width) { + super(x, y); + this.maxWidth = width; + this.render(null, x, y, width); + } + + @Override + public Bounds getBounds() { + Bounds bounds = super.getBounds(); + bounds.height = getFont().wrapLines(getStyle().getText(), maxWidth).size() * getFont().fontHeight; + return bounds; + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) { + int textY = (int)(y + MinecraftClient.getInstance().textRenderer.fontHeight/1.5F); + + for (OrderedText line : getFont().wrapLines(getStyle().getText(), maxWidth)) { + getFont().drawWithShadow(matrices, line, x, textY, getStyle().getColor()); + textY += getFont().fontHeight; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeButton.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeButton.java new file mode 100644 index 00000000..8e98ba8b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeButton.java @@ -0,0 +1,77 @@ +package com.minelittlepony.unicopia.client.gui; + +import com.minelittlepony.common.client.gui.element.Button; +import com.minelittlepony.common.client.gui.sprite.TextureSprite; +import com.minelittlepony.unicopia.Race; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.math.MathHelper; + +public class TribeButton extends Button { + + private final int screenWidth; + private final Race race; + + public TribeButton(int x, int y, int screenWidth, Race race) { + super(x, y, 70, 70); + this.screenWidth = screenWidth; + this.race = race; + int size = 32; + int textureSize = 512; + + getStyle() + .setIcon(new TextureSprite() + .setPosition((70 - size) / 2, 0) + .setSize(size, size) + .setTextureSize(textureSize, textureSize) + .setTexture(TribeSelectionScreen.ICONS) + .setTextureOffset((size * race.ordinal()) % textureSize, (race.ordinal() / textureSize) * size) + ) + .setText(race.getTranslationKey()); + } + + @Override + public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TribeSelectionScreen.TEXTURE); + RenderSystem.setShaderColor(1, 1, 1, alpha); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.blendFunc( + GlStateManager.SrcFactor.SRC_ALPHA, + GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA + ); + + MinecraftClient mc = MinecraftClient.getInstance(); + + drawTexture(matrices, x - 3, y - 13, 0, 0, 76, 69); + if (isHovered()) { + drawTexture(matrices, x - 4, y - 14, 76, 0, 78, 71); + + if (hovered && screenWidth > 0) { + drawCenteredText(matrices, getFont(), new TranslatableText("gui.unicopia.tribe_selection.describe." + race.name().toLowerCase()), screenWidth / 2, y + height, 0xFFFFFFFF); + } + } + + if (getStyle().hasIcon()) { + getStyle().getIcon().render(matrices, x, y, mouseX, mouseY, partialTicks); + } + + int foreColor = getStyle().getColor(); + if (!active) { + foreColor = 10526880; + } else if (isHovered()) { + foreColor = 16777120; + } + + setMessage(getStyle().getText()); + + + renderForground(matrices, mc, mouseX, mouseY, foreColor | MathHelper.ceil(alpha * 255.0F) << 24); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java new file mode 100644 index 00000000..8eec229b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java @@ -0,0 +1,129 @@ +package com.minelittlepony.unicopia.client.gui; + +import org.lwjgl.glfw.GLFW; + +import com.minelittlepony.common.client.gui.GameGui; +import com.minelittlepony.common.client.gui.element.Label; +import com.minelittlepony.unicopia.Race; +import com.mojang.blaze3d.systems.RenderSystem; + +import it.unimi.dsi.fastutil.booleans.BooleanConsumer; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Language; + +public class TribeConfirmationScreen extends GameGui implements HidesHud { + private final Race selection; + + private final BooleanConsumer callback; + + public TribeConfirmationScreen(BooleanConsumer callback, Race selection) { + super(new TranslatableText("gui.unicopia.tribe_selection")); + this.callback = callback; + this.selection = selection; + } + + @Override + protected void init() { + + final int columnHeight = 167; + final int columnWidth = 310; + final int padding = 15; + + int top = (height - columnHeight) / 2; + + addDrawableChild(new ButtonWidget(width / 2 + 5, top + columnHeight + padding, 100, 20, new TranslatableText("Join Tribe"), b -> callback.accept(true))); + addDrawableChild(new ButtonWidget(width / 2 - 105, top + columnHeight + padding, 100, 20, new TranslatableText("Go Back"), b -> callback.accept(false))); + + addDrawable(new Label(width / 2, top - 30).setCentered()).getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.confirm", selection.getDisplayName().shallowCopy().formatted(Formatting.YELLOW))); + + addDrawable(new TribeButton((width - 70) / 2, top, 0, selection)); + + top += 43; + + int left = (width - columnWidth) / 2 + padding; + + Text race = selection.getAltDisplayName().shallowCopy().formatted(Formatting.YELLOW); + + addDrawable(new Label(left - 3, top += 10)).getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.confirm.goods", race).formatted(Formatting.YELLOW)); + + top += 15; + + int maxWidth = 280; + + for (int i = 0; i < 5; i++) { + String key = String.format("gui.unicopia.tribe_selection.confirm.goods.%d.%s", i, selection.name().toLowerCase()); + if (Language.getInstance().hasTranslation(key)) { + TextBlock block = addDrawable(new TextBlock(left, top, maxWidth)); + block.getStyle().setText(new TranslatableText(key)); + top += block.getBounds().height; + } + } + + addDrawable(new Label(left - 3, top += 5)).getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.confirm.bads", race).formatted(Formatting.YELLOW)); + + top += 15; + + for (int i = 0; i < 5; i++) { + String key = String.format("gui.unicopia.tribe_selection.confirm.bads.%d.%s", i, selection.name().toLowerCase()); + if (Language.getInstance().hasTranslation(key)) { + TextBlock block = addDrawable(new TextBlock(left, top, maxWidth)); + block.getStyle().setText(new TranslatableText(key)); + top += block.getBounds().height; + } + } + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + renderBackground(matrices); + + RenderSystem.setShaderTexture(0, TribeSelectionScreen.TEXTURE); + + final int columnHeight = 180; + final int columnWidth = 310; + final int segmentWidth = 123; + + int top = (height - columnHeight) / 2; + int left = (width - columnWidth) / 2; + + top += 25; + + final int zOffset = 0; + + drawTexture(matrices, left + zOffset, top, 0, 70, 123, columnHeight); + + drawTexture(matrices, left + segmentWidth + zOffset, top, 20, 70, 123, columnHeight); + + drawTexture(matrices, width - left - segmentWidth + zOffset, top, 10, 70, 123, columnHeight); + + top -= 31; + + left = width / 2; + + drawTexture(matrices, left - 55, top, 140, 70, 21, 50); + + drawTexture(matrices, left - 35, top, 10, 70, 69, 50); + + drawTexture(matrices, left + 35, top, 148, 70, 21, 50); + + super.render(matrices, mouseX, mouseY, delta); + } + + @Override + public boolean shouldCloseOnEsc() { + return false; + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_ESCAPE) { + + return true; + } + return super.keyPressed(keyCode, scanCode, modifiers); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java new file mode 100644 index 00000000..b57c0ca0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeSelectionScreen.java @@ -0,0 +1,117 @@ +package com.minelittlepony.unicopia.client.gui; + +import java.util.List; +import java.util.Set; + +import com.minelittlepony.common.client.gui.GameGui; +import com.minelittlepony.common.client.gui.element.Label; +import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.client.UnicopiaClient; +import com.minelittlepony.unicopia.network.Channel; +import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange; + +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +public class TribeSelectionScreen extends GameGui implements HidesHud { + static final Identifier ICONS = new Identifier("unicopia", "textures/gui/icons.png"); + static final Identifier TEXTURE = new Identifier("unicopia", "textures/gui/tribe_selection.png"); + + final Set allowedRaces; + + private boolean finished; + + public TribeSelectionScreen(Set allowedRaces) { + super(new TranslatableText("gui.unicopia.tribe_selection")); + this.allowedRaces = allowedRaces; + } + + @Override + protected void init() { + final int pageWidth = 300; + final int left = (width - pageWidth) / 2; + + int top = 0; + + addDrawable(new Label(width / 2, top += 20).setCentered()).getStyle().setText(getTitle().shallowCopy().formatted(Formatting.YELLOW)); + + top += height / 8; + + TextBlock block = addDrawable(new TextBlock(left, top += 10, pageWidth)); + block.getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.welcome.journey")); + top += block.getBounds().height; + + block = addDrawable(new TextBlock(left, top += 7, pageWidth)); + block.getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.welcome.choice")); + top += block.getBounds().height; + + Race preference = UnicopiaClient.getPreferredRace(); + + top += 30; + + final int itemWidth = 70; + + List options = Race.all().stream().filter(race -> !race.isDefault() && !race.isOp()).toList(); + + int totalWidth = options.size() * (itemWidth + 10) - 10; + + int x = (width - totalWidth) / 2; + + for (Race race : options) { + addOption(race, x, top); + x += itemWidth + 10; + } + + top = height - 20; + + if (!preference.isDefault()) { + addDrawable(new Label(width / 2, top).setCentered()).getStyle().setText(new TranslatableText("gui.unicopia.tribe_selection.preference", preference.getDisplayName().shallowCopy().formatted(Formatting.YELLOW))); + } + } + + private void addOption(Race race, int x, int top) { + addDrawableChild(new TribeButton(x, top, width, race)).onClick(b -> { + finished = true; + client.openScreen(new TribeConfirmationScreen(result -> { + finished = false; + + if (result) { + Channel.CLIENT_REQUEST_SPECIES_CHANGE.send(new MsgRequestSpeciesChange(race, true)); + finish(); + } else { + client.openScreen(this); + } + }, race)); + }).setEnabled(allowedRaces.contains(race)); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + renderBackground(matrices); + super.render(matrices, mouseX, mouseY, delta); + } + + @Override + public void finish() { + finished = true; + onClose(); + } + + @Override + public boolean shouldCloseOnEsc() { + return false; + } + + @Override + public void removed() { + if (!finished && client != null) { + client.execute(() -> { + finished = true; + client.openScreen(this); + finished = false; + }); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index ae528db3..11de81dd 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -53,6 +53,10 @@ public class UHud extends DrawableHelper { public void render(InGameHud hud, MatrixStack matrices, float tickDelta) { + if (client.currentScreen instanceof HidesHud) { + return; + } + if (client.player == null || client.player.isSpectator() || client.options.hudHidden) { return; } 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 be8a98f7..b8933abf 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -24,7 +24,7 @@ import com.minelittlepony.unicopia.item.toxin.Toxicity; import com.minelittlepony.unicopia.item.toxin.Toxin; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.MsgOtherPlayerCapabilities; -import com.minelittlepony.unicopia.network.MsgRequestCapabilities; +import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange; import com.minelittlepony.unicopia.network.Transmittable; import com.minelittlepony.unicopia.util.Copieable; import com.minelittlepony.unicopia.util.MagicalDamageSource; @@ -210,7 +210,7 @@ public class Pony extends Living implements Transmittable, Copieab clientPreferredRace = race; if (race != getSpecies()) { - Channel.CLIENT_REQUEST_CAPABILITIES.send(new MsgRequestCapabilities(race)); + Channel.CLIENT_REQUEST_SPECIES_CHANGE.send(new MsgRequestSpeciesChange(race)); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/Channel.java b/src/main/java/com/minelittlepony/unicopia/network/Channel.java index 73aa6057..e69ee11f 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/Channel.java +++ b/src/main/java/com/minelittlepony/unicopia/network/Channel.java @@ -2,20 +2,31 @@ package com.minelittlepony.unicopia.network; import com.minelittlepony.unicopia.util.network.S2CBroadcastPacketType; import com.minelittlepony.unicopia.util.network.S2CPacketType; +import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.util.network.C2SPacketType; import com.minelittlepony.unicopia.util.network.SimpleNetworking; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.util.Identifier; public interface Channel { C2SPacketType> CLIENT_PLAYER_ABILITY = SimpleNetworking.clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new); - C2SPacketType CLIENT_REQUEST_CAPABILITIES = SimpleNetworking.clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new); + C2SPacketType CLIENT_REQUEST_SPECIES_CHANGE = SimpleNetworking.clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestSpeciesChange::new); S2CPacketType SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new); S2CPacketType SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new); S2CPacketType SERVER_BLOCK_DESTRUCTION = SimpleNetworking.serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new); + Identifier SERVER_SELECT_TRIBE_ID = new Identifier("unicopia", "select_tribe"); + S2CPacketType SERVER_SELECT_TRIBE = SimpleNetworking.serverToClient(SERVER_SELECT_TRIBE_ID, MsgTribeSelect::new); + S2CBroadcastPacketType SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new); - static void bootstrap() { } + static void bootstrap() { + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + if (!Pony.of(handler.player).isSpeciesPersisted()) { + sender.sendPacket(SERVER_SELECT_TRIBE_ID, new MsgTribeSelect(handler.player).toBuffer()); + } + }); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java b/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java index ed918af7..0ad7b961 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgBlockDestruction.java @@ -9,6 +9,9 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; +/** + * Sent by the server to update block destruction progress on the client. + */ public class MsgBlockDestruction implements Packet { private final Long2ObjectMap destructions; diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java index 937ec069..7d868c8f 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgOtherPlayerCapabilities.java @@ -6,6 +6,9 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; +/** + * Sent by the server to update other player's capabilities. + */ public class MsgOtherPlayerCapabilities extends MsgPlayerCapabilities { MsgOtherPlayerCapabilities(PacketByteBuf buffer) { diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerAbility.java b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerAbility.java index d5ffead6..3c25576e 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerAbility.java @@ -10,6 +10,9 @@ import net.minecraft.util.Identifier; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; +/** + * Sent to the server when a player activates an ability. + */ public class MsgPlayerAbility implements Packet { private final Ability power; diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java index c599e564..e4ad02cc 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgPlayerCapabilities.java @@ -17,6 +17,11 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; +/** + * Sent to the client to update various data pertaining to a particular player. + *

+ * Also used by the server to notify a race change. + */ public class MsgPlayerCapabilities implements Packet { protected final UUID playerId; diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgRequestCapabilities.java b/src/main/java/com/minelittlepony/unicopia/network/MsgRequestCapabilities.java deleted file mode 100644 index a372f776..00000000 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgRequestCapabilities.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.minelittlepony.unicopia.network; - -import com.minelittlepony.unicopia.Race; -import com.minelittlepony.unicopia.WorldTribeManager; -import com.minelittlepony.unicopia.entity.player.Pony; -import com.minelittlepony.unicopia.util.network.Packet; - -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; - -public class MsgRequestCapabilities implements Packet { - - private final Race clientPreferredRace; - - MsgRequestCapabilities(PacketByteBuf buffer) { - clientPreferredRace = Race.values()[buffer.readInt()]; - } - - public MsgRequestCapabilities(Race preferredRace) { - clientPreferredRace = preferredRace; - } - - @Override - public void toBuffer(PacketByteBuf buffer) { - buffer.writeInt(clientPreferredRace.ordinal()); - } - - @Override - public void handle(ServerPlayerEntity sender) { - Pony player = Pony.of(sender); - - Race worldDefaultRace = WorldTribeManager.forWorld((ServerWorld)player.getWorld()).getDefaultRace(); - - if (player.getSpecies().isDefault() || (player.getSpecies() == worldDefaultRace && !player.isSpeciesPersisted())) { - player.setSpecies(clientPreferredRace.isPermitted(sender) ? clientPreferredRace : worldDefaultRace); - } - - Channel.SERVER_PLAYER_CAPABILITIES.send(sender, new MsgPlayerCapabilities(true, player)); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgRequestSpeciesChange.java b/src/main/java/com/minelittlepony/unicopia/network/MsgRequestSpeciesChange.java new file mode 100644 index 00000000..c3fbcb14 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgRequestSpeciesChange.java @@ -0,0 +1,54 @@ +package com.minelittlepony.unicopia.network; + +import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.WorldTribeManager; +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.util.network.Packet; + +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; + +/** + * Sent to the server when a client wants to request a species change. + *

+ * The server responds back with the accepted capabilities and the race the client should use (if the preferred was not permitted) + */ +public class MsgRequestSpeciesChange implements Packet { + + private final boolean force; + private final Race newRace; + + MsgRequestSpeciesChange(PacketByteBuf buffer) { + force = buffer.readBoolean(); + newRace = Race.fromId(buffer.readInt()); + } + + public MsgRequestSpeciesChange(Race newRace) { + this(newRace, false); + } + + public MsgRequestSpeciesChange(Race newRace, boolean force) { + this.newRace = newRace; + this.force = force; + } + + @Override + public void toBuffer(PacketByteBuf buffer) { + buffer.writeBoolean(force); + buffer.writeInt(newRace.ordinal()); + } + + @Override + public void handle(ServerPlayerEntity sender) { + Pony player = Pony.of(sender); + + Race worldDefaultRace = WorldTribeManager.forWorld((ServerWorld)player.getWorld()).getDefaultRace(); + + if (force || player.getSpecies().isDefault() || (player.getSpecies() == worldDefaultRace && !player.isSpeciesPersisted())) { + player.setSpecies(newRace.isPermitted(sender) ? newRace : worldDefaultRace); + } + + Channel.SERVER_PLAYER_CAPABILITIES.send(sender, new MsgPlayerCapabilities(true, player)); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgSpawnProjectile.java b/src/main/java/com/minelittlepony/unicopia/network/MsgSpawnProjectile.java index 903200b3..1b1c8774 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/MsgSpawnProjectile.java +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgSpawnProjectile.java @@ -13,6 +13,9 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; +/** + * Sent by the server to spawn a projectile entity on the client. + */ public class MsgSpawnProjectile extends EntitySpawnS2CPacket implements Packet { MsgSpawnProjectile(PacketByteBuf buffer) { diff --git a/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java b/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java new file mode 100644 index 00000000..60e7d42f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/network/MsgTribeSelect.java @@ -0,0 +1,40 @@ +package com.minelittlepony.unicopia.network; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen; +import com.minelittlepony.unicopia.util.network.Packet; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.PacketByteBuf; + +public class MsgTribeSelect implements Packet { + private final Set availableRaces; + + public MsgTribeSelect(PlayerEntity player) { + availableRaces = Race.all().stream().filter(r -> r.isPermitted(player)).collect(Collectors.toSet()); + } + + public MsgTribeSelect(PacketByteBuf buffer) { + int len = buffer.readInt(); + availableRaces = new HashSet<>(); + while (len-- > 0) { + availableRaces.add(Race.fromId(buffer.readInt())); + } + } + + @Override + public void toBuffer(PacketByteBuf buffer) { + buffer.writeInt(availableRaces.size()); + availableRaces.forEach(race -> buffer.writeInt(race.ordinal())); + } + + @Override + public void handle(PlayerEntity sender) { + MinecraftClient.getInstance().openScreen(new TribeSelectionScreen(availableRaces)); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/util/ColorHelper.java b/src/main/java/com/minelittlepony/unicopia/util/ColorHelper.java new file mode 100644 index 00000000..6593ed9b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/ColorHelper.java @@ -0,0 +1,30 @@ +package com.minelittlepony.unicopia.util; + +public interface ColorHelper { + + static float[] changeSaturation(float red, float green, float blue, float intensity) { + float avg = (red + green + blue) / 3F; + float r = avg + (red - avg) * intensity; + float g = avg + (green - avg) * intensity; + float b = avg + (blue - avg) * intensity; + + if (r > 1) { + g -= r - 1; + b -= r - 1; + r = 1; + } + if (g > 1) { + r -= g - 1; + b -= g - 1; + g = 1; + } + if (b > 1) { + r -= b - 1; + g -= b - 1; + b = 1; + } + + return new float[] {r, g, b}; + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/util/network/Packet.java b/src/main/java/com/minelittlepony/unicopia/util/network/Packet.java index 717d1a89..e3131d11 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/network/Packet.java +++ b/src/main/java/com/minelittlepony/unicopia/util/network/Packet.java @@ -1,6 +1,6 @@ package com.minelittlepony.unicopia.util.network; -import io.netty.buffer.Unpooled; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; @@ -28,7 +28,7 @@ public interface Packet

{ * @return The resulting buffer for transmission */ default PacketByteBuf toBuffer() { - PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + PacketByteBuf buf = PacketByteBufs.create(); toBuffer(buf); return buf; } diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index d4af7876..ea135415 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -27,28 +27,28 @@ "item.unicopia.storm_cloud_jar": "Storm in a Jar", "item.unicopia.lightning_jar": "Lightning in a Jar", "item.unicopia.zap_apple_jam_jar": "Zap Apple Jam", - + "item.unicopia.crystal_heart": "Crystal Heart", "item.unicopia.crystal_shard": "Crystal Shard", "item.unicopia.gemstone": "Gemstone", "item.unicopia.gemstone.enchanted": "%s Gem", "item.unicopia.gemstone.obfuscated": "Mysterious Gem", - + "item.unicopia.pegasus_feather": "Pegasus Feather", "item.unicopia.gryphon_feather": "Gryphon Feather", "item.unicopia.golden_feather": "Golden Feather", "item.unicopia.golden_wing": "Golden Wing", - + "item.unicopia.mug": "Mug", "item.unicopia.cider": "Cider", "item.unicopia.juice": "Juice", "item.unicopia.burned_juice": "Burned Juice", - + "item.unicopia.daffodil_daisy_sandwich": "Daffodil Daisy Sandwich", "item.unicopia.hay_burger": "Hay Burger", "item.unicopia.hay_fries": "Hay Fries", "item.unicopia.wheat_worms": "Wheat Worms", - + "item.unicopia.pegasus_amulet": "Wings of Icarus", "item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it", "item.unicopia.amulet.energy": "Energy: %d / %d", @@ -99,7 +99,7 @@ "item.minecraft.splash_potion.effect.unicopia.tribe_swap_changeling": "Splash Potion of Changeling Metamorphosis", "item.minecraft.lingering_potion.effect.unicopia.tribe_swap_changeling": "Lingering Potion of Changeling Metamorphosis", "item.minecraft.tipped_arrow.effect.unicopia.tribe_swap_changeling": "Arrow of Changeling Metamorphosis", - + "effect.unicopia.change_race_bat": "Bat Pony Metamorphosis", "item.minecraft.potion.effect.unicopia.tribe_swap_bat": "Potion of Bat Pony Metamorphosis", "item.minecraft.splash_potion.effect.unicopia.tribe_swap_bat": "Splash Potion of Bat Pony Metamorphosis", @@ -117,28 +117,28 @@ "curse.unicopia.infernal": "Infernal", "curse.unicopia.infernal.lore": "Fire III", - + "spell.unicopia.shield": "Protective", "spell.unicopia.shield.lore": "Protection I", "curse.unicopia.repulse": "Repulsive", "curse.unicopia.repulse.lore": "Hostility I", - + "spell.unicopia.vortex": "Attractive", "spell.unicopia.vortex.lore": "Containment I", "curse.unicopia.suffer": "Suffering", "curse.unicopia.suffer.lore": "Torture I", - + "curse.unicopia.necromancy": "Resurrection", "curse.unicopia.necromancy.lore": "Resurrection I", - + "spell.unicopia.siphoning": "Siphoning", "spell.unicopia.siphoning.lore": "Energy II", "curse.unicopia.draining": "Siphoning", "curse.unicopia.draining.lore": "Energy III", - + "spell.unicopia.reveal": "Revealing", "spell.unicopia.reveal.lore": "Discovery II", @@ -170,6 +170,67 @@ "gui.unicopia": "Unicopia...", "gui.unicopia.page_num": "%d of %d", + "gui.unicopia.tribe_selection": "Select Your Tribe", + "gui.unicopia.tribe_selection.welcome": "Welcome to Equestria!", + "gui.unicopia.tribe_selection.welcome.journey": "A journey into magic and adventure awaits, traveller! But before you go, you must select your path.", + "gui.unicopia.tribe_selection.welcome.choice": "Choose wisely, for the choice you make now will change the world around you and the paths you may take.", + "gui.unicopia.tribe_selection.preference": "Your current preferred tribe is set to %s.", + "gui.unicopia.tribe_selection.options": "Available Tribes:", + "gui.unicopia.tribe_selection.options.disabled": "Option Unavailable", + + "gui.unicopia.tribe_selection.describe.earth": "Join the Earth Tribe", + "gui.unicopia.tribe_selection.describe.unicorn": "Join the Unicorn Tribe, master the arcane arts", + "gui.unicopia.tribe_selection.describe.pegasus": "Join the Pegasus Tribe, soar with the Wonderbolts", + "gui.unicopia.tribe_selection.describe.bat": "Join the Bat Tribe, become the darkest night", + "gui.unicopia.tribe_selection.describe.changeling": "Join the Changeling Hive, your Queen demands it", + + "gui.unicopia.tribe_selection.confirm": "You have selected %s", + "gui.unicopia.tribe_selection.confirm.goods": "%s enjoy the following perks:", + + "gui.unicopia.tribe_selection.confirm.goods.1.earth": " - Stronger knockback and resistance to magic", + "gui.unicopia.tribe_selection.confirm.goods.2.earth": " - Have extra weight makes them effective against magic and brute force", + "gui.unicopia.tribe_selection.confirm.goods.3.earth": " - A special connection to the earth that makes farming 10,000% more effective!", + + "gui.unicopia.tribe_selection.confirm.goods.1.unicorn": " - Able to teleport and cast powerful spells", + "gui.unicopia.tribe_selection.confirm.goods.2.unicorn": " - Research and craft magical artefacts that enhance their abilities", + "gui.unicopia.tribe_selection.confirm.goods.3.unicorn": " - Can use magic to detect or reveal nearby changelings", + "gui.unicopia.tribe_selection.confirm.goods.4.unicorn": " - Have pointy sticks on their heads", + + "gui.unicopia.tribe_selection.confirm.goods.1.pegasus": " - Flight and the ability to train to build endurace", + "gui.unicopia.tribe_selection.confirm.goods.2.pegasus": " - Use stored mana to perform a powerful rainboom", + "gui.unicopia.tribe_selection.confirm.goods.3.pegasus": " - Moves faster and takes less fall damage", + "gui.unicopia.tribe_selection.confirm.goods.4.pegasus": " - Can eat vegitables and certain types of fish", + + "gui.unicopia.tribe_selection.confirm.goods.1.bat": " - Flight and the ability to train to build endurance", + "gui.unicopia.tribe_selection.confirm.goods.2.bat": " - Sees better in the night", + "gui.unicopia.tribe_selection.confirm.goods.3.bat": " - Able to cling to the underside of blocks", + "gui.unicopia.tribe_selection.confirm.goods.4.bat": " - Has a terrifying, yet adorable, but still slightly annoying screech", + + "gui.unicopia.tribe_selection.confirm.goods.1.changeling": " - Able to fly and hover in place", + "gui.unicopia.tribe_selection.confirm.goods.2.changeling": " - Shapeshift and morph into nearly anyone or anyling", + "gui.unicopia.tribe_selection.confirm.goods.3.changeling": " - Is carnivorous. Can eat anything that doesn't make them sick", + + "gui.unicopia.tribe_selection.confirm.bads": "but they...", + "gui.unicopia.tribe_selection.confirm.bads.1.earth": " - Cannot fly", + "gui.unicopia.tribe_selection.confirm.bads.2.earth": " - Are weak to certain types of magic", + "gui.unicopia.tribe_selection.confirm.bads.3.earth": " - Can only eat plants and vegitables", + + "gui.unicopia.tribe_selection.confirm.bads.1.unicorn": " - Cannot fly", + "gui.unicopia.tribe_selection.confirm.bads.2.unicorn": " - Are weak to brute force attacks", + "gui.unicopia.tribe_selection.confirm.bads.3.unicorn": " - Can only eat plants and vegitables", + + "gui.unicopia.tribe_selection.confirm.bads.1.pegasus": " - Light weight makes them the weakest to brute force", + "gui.unicopia.tribe_selection.confirm.bads.2.pegasus": " - Must rest between flights to regain their strength", + + "gui.unicopia.tribe_selection.confirm.bads.1.bat": " - Light weight makes them weak to brute force attacks.", + "gui.unicopia.tribe_selection.confirm.bads.2.bat": " - Must rest between flights to regain their strength", + "gui.unicopia.tribe_selection.confirm.bads.3.bat": " - Is sometimes scared of even themselves", + "gui.unicopia.tribe_selection.confirm.bads.4.bat": " - Is carnivorous. Can eat anything that doesn't make them sick", + + "gui.unicopia.tribe_selection.confirm.bads.1.changeling": " - Are always starving", + "gui.unicopia.tribe_selection.confirm.bads.2.changeling": " - Require love, collected from ponies or other hostile mobs to subsidise their diet", + "gui.unicopia.tribe_selection.confirm.bads.3.changeling": " - Becomes sick from eating regular food and must eat love hasten a cure", + "unicopia.category.name": "Pony Abilities", "key.unicopia.primary": "Primary Ability", @@ -179,7 +240,7 @@ "key.unicopia.hud_page_dn": "Hud Previous Page", "key.unicopia.hud_page_up": "Hud Next Page", - + "enchantment.unicopia.gem_finder": "Gem Finder", "enchantment.unicopia.padded": "Padded", "enchantment.unicopia.clingy": "Clings", @@ -227,7 +288,7 @@ "commands.race.describe.changeling.1": "Beware the changeling, for they can appear when least expected.", "commands.race.describe.changeling.2": "Changelings can fly but but do not interact with clouds.", "commands.race.describe.changeling.3": "They have to feed on mobs and other players to eat.", - + "commands.race.describe.bat.1": "I am the night! EEEEEEEEEEEEE!!!", "commands.race.describe.bat.2": "Bat Ponies can fly but but do not interact with clouds.", "commands.race.describe.bat.3": "They love mangoes. Give them one, and they will follow you forever.", diff --git a/src/main/resources/assets/unicopia/textures/gui/container/book.png b/src/main/resources/assets/unicopia/textures/gui/container/book.png new file mode 100644 index 00000000..301777bf Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/gui/container/book.png differ diff --git a/src/main/resources/assets/unicopia/textures/gui/container/book_no_inventory.png b/src/main/resources/assets/unicopia/textures/gui/container/book_no_inventory.png new file mode 100644 index 00000000..191cd9a8 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/gui/container/book_no_inventory.png differ diff --git a/src/main/resources/assets/unicopia/textures/gui/tribe_selection.png b/src/main/resources/assets/unicopia/textures/gui/tribe_selection.png new file mode 100644 index 00000000..51ae0fb0 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/gui/tribe_selection.png differ