mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 19:46:42 +01:00
Added a gui for selecting your starting race when first joining a world
This commit is contained in:
parent
e132246516
commit
aa89e883ad
24 changed files with 616 additions and 68 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.minelittlepony.unicopia.client.gui;
|
||||||
|
|
||||||
|
public interface HidesHud {
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
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 |
Loading…
Reference in a new issue