Added a gui for selecting your starting race when first joining a world

This commit is contained in:
Sollace 2021-08-06 01:06:57 +02:00
parent e132246516
commit aa89e883ad
24 changed files with 616 additions and 68 deletions

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia; package com.minelittlepony.unicopia;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@ -102,6 +103,10 @@ public enum Race implements Affine {
return new TranslatableText(getTranslationKey()); return new TranslatableText(getTranslationKey());
} }
public Text getAltDisplayName() {
return new TranslatableText(getTranslationKey() + ".alt");
}
public String getTranslationKey() { public String getTranslationKey() {
return String.format("unicopia.race.%s", name().toLowerCase()); return String.format("unicopia.race.%s", name().toLowerCase());
} }
@ -130,7 +135,7 @@ public enum Race implements Affine {
return this; return this;
} }
public Style getStyle() { public Style createStyle() {
return new Style() return new Style()
.setIcon(new TextureSprite() .setIcon(new TextureSprite()
.setPosition(2, 2) .setPosition(2, 2)
@ -160,6 +165,10 @@ public enum Race implements Affine {
return def; return def;
} }
public static Collection<Race> all() {
return REGISTRY.values();
}
public static Race fromName(String name) { public static Race fromName(String name) {
return fromName(name, EARTH); return fromName(name, EARTH);
} }

View file

@ -0,0 +1,5 @@
package com.minelittlepony.unicopia.client.gui;
public interface HidesHud {
}

View file

@ -172,7 +172,7 @@ public class SettingsScreen extends GameGui {
return v; return v;
}) })
.setEnabled(canEditWhitelist) .setEnabled(canEditWhitelist)
.setStyle(race.getStyle()); .setStyle(race.createStyle());
((TextureSprite)button.getStyle().getIcon()).setPosition(-20, 0); ((TextureSprite)button.getStyle().getIcon()).setPosition(-20, 0);
} }
@ -220,12 +220,12 @@ public class SettingsScreen extends GameGui {
} }
} }
}.setStyles( }.setStyles(
Race.EARTH.getStyle(), Race.EARTH.createStyle(),
Race.UNICORN.getStyle(), Race.UNICORN.createStyle(),
Race.PEGASUS.getStyle(), Race.PEGASUS.createStyle(),
Race.BAT.getStyle(), Race.BAT.createStyle(),
Race.ALICORN.getStyle(), Race.ALICORN.createStyle(),
Race.CHANGELING.getStyle() Race.CHANGELING.createStyle()
).onChange(i -> { ).onChange(i -> {
Unicopia.getConfig().preferredRace.set(Race.fromId(i + 1)); Unicopia.getConfig().preferredRace.set(Race.fromId(i + 1));
Unicopia.getConfig().save(); Unicopia.getConfig().save();

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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<Race> allowedRaces;
private boolean finished;
public TribeSelectionScreen(Set<Race> 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<Race> 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;
});
}
}
}

View file

@ -53,6 +53,10 @@ public class UHud extends DrawableHelper {
public void render(InGameHud hud, MatrixStack matrices, float tickDelta) { 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) { if (client.player == null || client.player.isSpectator() || client.options.hudHidden) {
return; return;
} }

View file

@ -24,7 +24,7 @@ import com.minelittlepony.unicopia.item.toxin.Toxicity;
import com.minelittlepony.unicopia.item.toxin.Toxin; import com.minelittlepony.unicopia.item.toxin.Toxin;
import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.MsgOtherPlayerCapabilities; 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.network.Transmittable;
import com.minelittlepony.unicopia.util.Copieable; import com.minelittlepony.unicopia.util.Copieable;
import com.minelittlepony.unicopia.util.MagicalDamageSource; import com.minelittlepony.unicopia.util.MagicalDamageSource;
@ -210,7 +210,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
clientPreferredRace = race; clientPreferredRace = race;
if (race != getSpecies()) { if (race != getSpecies()) {
Channel.CLIENT_REQUEST_CAPABILITIES.send(new MsgRequestCapabilities(race)); Channel.CLIENT_REQUEST_SPECIES_CHANGE.send(new MsgRequestSpeciesChange(race));
} }
} }
} }

View file

@ -2,20 +2,31 @@ package com.minelittlepony.unicopia.network;
import com.minelittlepony.unicopia.util.network.S2CBroadcastPacketType; import com.minelittlepony.unicopia.util.network.S2CBroadcastPacketType;
import com.minelittlepony.unicopia.util.network.S2CPacketType; 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.C2SPacketType;
import com.minelittlepony.unicopia.util.network.SimpleNetworking; import com.minelittlepony.unicopia.util.network.SimpleNetworking;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public interface Channel { public interface Channel {
C2SPacketType<MsgPlayerAbility<?>> CLIENT_PLAYER_ABILITY = SimpleNetworking.clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new); C2SPacketType<MsgPlayerAbility<?>> CLIENT_PLAYER_ABILITY = SimpleNetworking.clientToServer(new Identifier("unicopia", "player_ability"), MsgPlayerAbility::new);
C2SPacketType<MsgRequestCapabilities> CLIENT_REQUEST_CAPABILITIES = SimpleNetworking.clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestCapabilities::new); C2SPacketType<MsgRequestSpeciesChange> CLIENT_REQUEST_SPECIES_CHANGE = SimpleNetworking.clientToServer(new Identifier("unicopia", "request_capabilities"), MsgRequestSpeciesChange::new);
S2CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new); S2CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(new Identifier("unicopia", "player_capabilities"), MsgPlayerCapabilities::new);
S2CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new); S2CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(new Identifier("unicopia", "projectile_entity"), MsgSpawnProjectile::new);
S2CPacketType<MsgBlockDestruction> SERVER_BLOCK_DESTRUCTION = SimpleNetworking.serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new); S2CPacketType<MsgBlockDestruction> SERVER_BLOCK_DESTRUCTION = SimpleNetworking.serverToClient(new Identifier("unicopia", "block_destruction"), MsgBlockDestruction::new);
Identifier SERVER_SELECT_TRIBE_ID = new Identifier("unicopia", "select_tribe");
S2CPacketType<MsgTribeSelect> SERVER_SELECT_TRIBE = SimpleNetworking.serverToClient(SERVER_SELECT_TRIBE_ID, MsgTribeSelect::new);
S2CBroadcastPacketType<MsgOtherPlayerCapabilities> SERVER_OTHER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClients(new Identifier("unicopia", "other_player_capabilities"), MsgOtherPlayerCapabilities::new); S2CBroadcastPacketType<MsgOtherPlayerCapabilities> 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());
}
});
}
} }

View file

@ -9,6 +9,9 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
/**
* Sent by the server to update block destruction progress on the client.
*/
public class MsgBlockDestruction implements Packet<PlayerEntity> { public class MsgBlockDestruction implements Packet<PlayerEntity> {
private final Long2ObjectMap<Integer> destructions; private final Long2ObjectMap<Integer> destructions;

View file

@ -6,6 +6,9 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
/**
* Sent by the server to update other player's capabilities.
*/
public class MsgOtherPlayerCapabilities extends MsgPlayerCapabilities { public class MsgOtherPlayerCapabilities extends MsgPlayerCapabilities {
MsgOtherPlayerCapabilities(PacketByteBuf buffer) { MsgOtherPlayerCapabilities(PacketByteBuf buffer) {

View file

@ -10,6 +10,9 @@ import net.minecraft.util.Identifier;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
/**
* Sent to the server when a player activates an ability.
*/
public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntity> { public class MsgPlayerAbility<T extends Hit> implements Packet<ServerPlayerEntity> {
private final Ability<T> power; private final Ability<T> power;

View file

@ -17,6 +17,11 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtIo;
/**
* Sent to the client to update various data pertaining to a particular player.
* <p>
* Also used by the server to notify a race change.
*/
public class MsgPlayerCapabilities implements Packet<PlayerEntity> { public class MsgPlayerCapabilities implements Packet<PlayerEntity> {
protected final UUID playerId; protected final UUID playerId;

View file

@ -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<ServerPlayerEntity> {
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));
}
}

View file

@ -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.
* <p>
* 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<ServerPlayerEntity> {
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));
}
}

View file

@ -13,6 +13,9 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; 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<PlayerEntity> { public class MsgSpawnProjectile extends EntitySpawnS2CPacket implements Packet<PlayerEntity> {
MsgSpawnProjectile(PacketByteBuf buffer) { MsgSpawnProjectile(PacketByteBuf buffer) {

View file

@ -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<PlayerEntity> {
private final Set<Race> 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));
}
}

View file

@ -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};
}
}

View file

@ -1,6 +1,6 @@
package com.minelittlepony.unicopia.util.network; 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.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
@ -28,7 +28,7 @@ public interface Packet<P extends PlayerEntity> {
* @return The resulting buffer for transmission * @return The resulting buffer for transmission
*/ */
default PacketByteBuf toBuffer() { default PacketByteBuf toBuffer() {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); PacketByteBuf buf = PacketByteBufs.create();
toBuffer(buf); toBuffer(buf);
return buf; return buf;
} }

View file

@ -27,28 +27,28 @@
"item.unicopia.storm_cloud_jar": "Storm in a Jar", "item.unicopia.storm_cloud_jar": "Storm in a Jar",
"item.unicopia.lightning_jar": "Lightning in a Jar", "item.unicopia.lightning_jar": "Lightning in a Jar",
"item.unicopia.zap_apple_jam_jar": "Zap Apple Jam", "item.unicopia.zap_apple_jam_jar": "Zap Apple Jam",
"item.unicopia.crystal_heart": "Crystal Heart", "item.unicopia.crystal_heart": "Crystal Heart",
"item.unicopia.crystal_shard": "Crystal Shard", "item.unicopia.crystal_shard": "Crystal Shard",
"item.unicopia.gemstone": "Gemstone", "item.unicopia.gemstone": "Gemstone",
"item.unicopia.gemstone.enchanted": "%s Gem", "item.unicopia.gemstone.enchanted": "%s Gem",
"item.unicopia.gemstone.obfuscated": "Mysterious Gem", "item.unicopia.gemstone.obfuscated": "Mysterious Gem",
"item.unicopia.pegasus_feather": "Pegasus Feather", "item.unicopia.pegasus_feather": "Pegasus Feather",
"item.unicopia.gryphon_feather": "Gryphon Feather", "item.unicopia.gryphon_feather": "Gryphon Feather",
"item.unicopia.golden_feather": "Golden Feather", "item.unicopia.golden_feather": "Golden Feather",
"item.unicopia.golden_wing": "Golden Wing", "item.unicopia.golden_wing": "Golden Wing",
"item.unicopia.mug": "Mug", "item.unicopia.mug": "Mug",
"item.unicopia.cider": "Cider", "item.unicopia.cider": "Cider",
"item.unicopia.juice": "Juice", "item.unicopia.juice": "Juice",
"item.unicopia.burned_juice": "Burned Juice", "item.unicopia.burned_juice": "Burned Juice",
"item.unicopia.daffodil_daisy_sandwich": "Daffodil Daisy Sandwich", "item.unicopia.daffodil_daisy_sandwich": "Daffodil Daisy Sandwich",
"item.unicopia.hay_burger": "Hay Burger", "item.unicopia.hay_burger": "Hay Burger",
"item.unicopia.hay_fries": "Hay Fries", "item.unicopia.hay_fries": "Hay Fries",
"item.unicopia.wheat_worms": "Wheat Worms", "item.unicopia.wheat_worms": "Wheat Worms",
"item.unicopia.pegasus_amulet": "Wings of Icarus", "item.unicopia.pegasus_amulet": "Wings of Icarus",
"item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it", "item.unicopia.pegasus_amulet.lore": "Grants temporary flight to whoever wears it",
"item.unicopia.amulet.energy": "Energy: %d / %d", "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.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.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", "item.minecraft.tipped_arrow.effect.unicopia.tribe_swap_changeling": "Arrow of Changeling Metamorphosis",
"effect.unicopia.change_race_bat": "Bat Pony Metamorphosis", "effect.unicopia.change_race_bat": "Bat Pony Metamorphosis",
"item.minecraft.potion.effect.unicopia.tribe_swap_bat": "Potion of 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", "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": "Infernal",
"curse.unicopia.infernal.lore": "Fire III", "curse.unicopia.infernal.lore": "Fire III",
"spell.unicopia.shield": "Protective", "spell.unicopia.shield": "Protective",
"spell.unicopia.shield.lore": "Protection I", "spell.unicopia.shield.lore": "Protection I",
"curse.unicopia.repulse": "Repulsive", "curse.unicopia.repulse": "Repulsive",
"curse.unicopia.repulse.lore": "Hostility I", "curse.unicopia.repulse.lore": "Hostility I",
"spell.unicopia.vortex": "Attractive", "spell.unicopia.vortex": "Attractive",
"spell.unicopia.vortex.lore": "Containment I", "spell.unicopia.vortex.lore": "Containment I",
"curse.unicopia.suffer": "Suffering", "curse.unicopia.suffer": "Suffering",
"curse.unicopia.suffer.lore": "Torture I", "curse.unicopia.suffer.lore": "Torture I",
"curse.unicopia.necromancy": "Resurrection", "curse.unicopia.necromancy": "Resurrection",
"curse.unicopia.necromancy.lore": "Resurrection I", "curse.unicopia.necromancy.lore": "Resurrection I",
"spell.unicopia.siphoning": "Siphoning", "spell.unicopia.siphoning": "Siphoning",
"spell.unicopia.siphoning.lore": "Energy II", "spell.unicopia.siphoning.lore": "Energy II",
"curse.unicopia.draining": "Siphoning", "curse.unicopia.draining": "Siphoning",
"curse.unicopia.draining.lore": "Energy III", "curse.unicopia.draining.lore": "Energy III",
"spell.unicopia.reveal": "Revealing", "spell.unicopia.reveal": "Revealing",
"spell.unicopia.reveal.lore": "Discovery II", "spell.unicopia.reveal.lore": "Discovery II",
@ -170,6 +170,67 @@
"gui.unicopia": "Unicopia...", "gui.unicopia": "Unicopia...",
"gui.unicopia.page_num": "%d of %d", "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", "unicopia.category.name": "Pony Abilities",
"key.unicopia.primary": "Primary Ability", "key.unicopia.primary": "Primary Ability",
@ -179,7 +240,7 @@
"key.unicopia.hud_page_dn": "Hud Previous Page", "key.unicopia.hud_page_dn": "Hud Previous Page",
"key.unicopia.hud_page_up": "Hud Next Page", "key.unicopia.hud_page_up": "Hud Next Page",
"enchantment.unicopia.gem_finder": "Gem Finder", "enchantment.unicopia.gem_finder": "Gem Finder",
"enchantment.unicopia.padded": "Padded", "enchantment.unicopia.padded": "Padded",
"enchantment.unicopia.clingy": "Clings", "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.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.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.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.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.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.", "commands.race.describe.bat.3": "They love mangoes. Give them one, and they will follow you forever.",

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB