Use separate textures for each race icon, display the number of spells active in the hud, and change the spell dismiss screen to reflect the location of placed spells

This commit is contained in:
Sollace 2022-09-18 14:16:28 +02:00
parent 47db6d49ee
commit 7fc17d9f79
19 changed files with 107 additions and 67 deletions

View file

@ -115,6 +115,11 @@ public final class Race implements Affine {
return String.format("%s.race.%s", id.getNamespace(), id.getPath().toLowerCase());
}
public Identifier getIcon() {
Identifier id = REGISTRY.getId(this);
return new Identifier(id.getNamespace(), "textures/gui/race/" + id.getPath() + ".png");
}
public boolean isPermitted(@Nullable PlayerEntity sender) {
if (isOp() && (sender == null || !sender.getAbilities().creativeMode)) {
return false;

View file

@ -64,6 +64,8 @@ public interface SpellContainer {
Stream<Spell> stream(boolean update);
Stream<Spell> stream(@Nullable SpellPredicate<?> type, boolean update);
/**
* Removes all effects currently active in this slot.
*/

View file

@ -168,6 +168,10 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
return getWorld(source).map(castEntity::get);
}
public Optional<Vec3d> getPosition() {
return castEntity.getPosition();
}
public Optional<Attachment> getParticleEffectAttachment(Caster<?> source) {
return particlEffect.update(getUuid(), source, spawner -> {
source.getOriginVector().add(0, 5, 0);

View file

@ -11,11 +11,8 @@ import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.MsgRemoveSpell;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.client.util.math.MatrixStack;
@ -24,7 +21,7 @@ import net.minecraft.sound.SoundEvents;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.StringHelper;
import net.minecraft.util.math.Vector4f;
import net.minecraft.util.math.*;
public class DismissSpellScreen extends GameGui {
private final Pony pony = Pony.of(MinecraftClient.getInstance().player);
@ -41,11 +38,35 @@ public class DismissSpellScreen extends GameGui {
double azimuth = 0;
double ring = 2;
List<PlaceableSpell> placeableSpells = new ArrayList<>();
for (Spell spell : pony.getSpellSlot().stream(true).toList()) {
addDrawableChild(new Entry(spell, 75 * ring - 25, azimuth));
if (spell instanceof PlaceableSpell placeable) {
if (placeable.getPosition().isPresent()) {
placeableSpells.add(placeable);
continue;
}
}
addDrawableChild(new Entry(spell).ofRadial(75 * ring - 25, azimuth));
ring *= 1 + 0.03 / ring;
azimuth += Math.PI / (8 * ring);
}
double minimalDistance = 75 * (ring - 1) - 25;
Vec3d origin = pony.getOriginVector();
placeableSpells.forEach(placeable -> {
placeable.getPosition().ifPresent(position -> {
Vec3d relativePos = position.subtract(origin);
Vec3d cartesian = relativePos
.normalize()
.multiply(minimalDistance + relativePos.length())
.rotateY((pony.getEntity().getYaw() - 180) * MathHelper.RADIANS_PER_DEGREE);
addDrawableChild(new Entry(placeable).ofCartesian(cartesian));
});
});
}
@Override
@ -63,8 +84,7 @@ public class DismissSpellScreen extends GameGui {
DrawableUtil.drawArc(matrices, 160, 1600, 0, DrawableUtil.TAU, 0x00000020, false);
super.render(matrices, mouseX, mouseY, delta);
DrawableUtil.drawCircle(matrices, 2, 0, DrawableUtil.TAU, 0xFFAAFF99, false);
DrawableUtil.renderRaceIcon(matrices, pony.getSpecies(), 0, 0, 16);
matrices.pop();
DrawableUtil.drawLine(matrices, mouseX, mouseY - 4, mouseX, mouseY + 4, 0xFFAAFF99);
@ -96,12 +116,20 @@ public class DismissSpellScreen extends GameGui {
private final Vector4f copy = new Vector4f();
public Entry(Spell spell, double radius, double azimuth) {
public Entry(Spell spell) {
this.spell = spell;
this.actualSpell = getActualSpell();
}
public Entry ofRadial(double radius, double azimuth) {
SphereModel.convertToCartesianCoord(this, radius, azimuth, azimuth);
add(0, -(float)radius / 2F, 0, 0);
return this;
}
public Entry ofCartesian(Vec3d pos) {
add((float)pos.x, (float)pos.z, (float)pos.y, 1);
return this;
}
private Spell getActualSpell() {
@ -135,17 +163,18 @@ public class DismissSpellScreen extends GameGui {
var type = actualSpell.getType().withTraits(actualSpell.getTraits());
DrawableUtil.drawLine(matrices, 0, 0, (int)getX(), (int)getY(), 0xFFAAFF99);
DrawableUtil.renderItemIcon(actualSpell.isDead() ? UItems.BOTCHED_GEM.getDefaultStack() : type.getDefaultStack(),
copy.getX() - 8 + (copy.getX() - mouseX - 5) / 60D,
copy.getY() - 8 + (copy.getY() - mouseY - 5) / 60D,
copy.getX() - 8 + copy.getZ() / 20F,
copy.getY() - 8 + copy.getZ() / 20F,
1
);
int color = actualSpell.getType().getColor() << 2;
matrices.push();
matrices.translate(getX(), getY(), 0);
int color = actualSpell.getType().getColor() << 2;
DrawableUtil.drawArc(matrices, 7, 8, 0, DrawableUtil.TAU, color | 0x00000088, false);
if (isMouseOver(relativeMouseX, relativeMouseY)) {

View file

@ -1,8 +1,10 @@
package com.minelittlepony.unicopia.client.gui;
import com.minelittlepony.unicopia.Race;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferRenderer;
import net.minecraft.client.render.GameRenderer;
@ -44,6 +46,11 @@ public interface DrawableUtil {
RenderSystem.applyModelViewMatrix();
}
static void renderRaceIcon(MatrixStack matrices, Race race, int x, int y, int size) {
RenderSystem.setShaderTexture(0, race.getIcon());
DrawableHelper.drawTexture(matrices, x - size / 2, y - size / 2, 0, 0, 0, size, size, size, size);
}
static void drawLine(MatrixStack matrices, int x1, int y1, int x2, int y2, int color) {
RenderSystem.enableBlend();
RenderSystem.disableTexture();
@ -64,7 +71,7 @@ public interface DrawableUtil {
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR);
bufferBuilder.vertex(matrix, x1, y1, 0).color(r, g, b, k).next();
bufferBuilder.vertex(matrix, x2, y2, 0).color(r, g, b, k).next();
BufferRenderer.drawWithoutShader(bufferBuilder.end());
BufferRenderer.drawWithShader(bufferBuilder.end());
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}

View file

@ -146,14 +146,7 @@ public class LanSettingsScreen extends GameGui {
}
public static Style createStyle(Race race) {
int ordinal = Race.REGISTRY.getRawId(race);
return new Style()
.setIcon(new TextureSprite()
.setPosition(2, 2)
.setSize(16, 16)
.setTexture(TribeSelectionScreen.ICONS)
.setTextureOffset((16 * ordinal) % 256, (ordinal / 256) * 16)
)
return new Style().setIcon(TribeButton.createSprite(race, 2, 2, 15))
.setTooltip(race.getTranslationKey(), 0, 10);
}

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.client.gui;
import com.minelittlepony.common.client.gui.element.Button;
import com.minelittlepony.common.client.gui.sprite.ISprite;
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
import com.minelittlepony.unicopia.Race;
import com.mojang.blaze3d.platform.GlStateManager;
@ -22,19 +23,8 @@ public class TribeButton extends Button {
super(x, y, 70, 70);
this.screenWidth = screenWidth;
this.race = race;
int size = 32;
int textureSize = 512;
int ordinal = Race.REGISTRY.getRawId(race);
getStyle()
.setIcon(new TextureSprite()
.setPosition((70 - size) / 2, 0)
.setSize(size, size)
.setTextureSize(textureSize, textureSize)
.setTexture(TribeSelectionScreen.ICONS)
.setTextureOffset((size * ordinal) % textureSize, (ordinal / textureSize) * size)
)
.setText(race.getTranslationKey());
getStyle().setIcon(createSprite(race, (70 - 32) / 2, 0, 32)).setText(race.getTranslationKey());
}
@Override
@ -77,4 +67,12 @@ public class TribeButton extends Button {
renderForground(matrices, mc, mouseX, mouseY, foreColor | MathHelper.ceil(alpha * 255.0F) << 24);
}
public static ISprite createSprite(Race race, int x, int y, int size) {
return new TextureSprite()
.setPosition(x, y)
.setSize(size, size)
.setTextureSize(size, size)
.setTexture(race.getIcon());
}
}

View file

@ -17,7 +17,6 @@ import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
public class TribeSelectionScreen extends GameGui implements HidesHud {
static final Identifier ICONS = Unicopia.id("textures/gui/icons.png");
static final Identifier TEXTURE = Unicopia.id("textures/gui/tribe_selection.png");
final Set<Race> allowedRaces;

View file

@ -156,29 +156,40 @@ public class UHud extends DrawableHelper {
}
public void renderSpell(CustomisedSpellType<?> spell, double x, double y) {
if (!spell.isEmpty()) {
Pony pony = Pony.of(client.player);
if (spell.isEmpty()) {
return;
}
if (spell.isOn(pony)) {
MatrixStack modelStack = new MatrixStack();
Pony pony = Pony.of(client.player);
if (spell.isOn(pony)) {
MatrixStack modelStack = new MatrixStack();
modelStack.push();
modelStack.translate(x + 5.5, y + 5.5, 0);
int color = spell.type().getColor() | 0x000000FF;
double radius = 2 + Math.sin(client.player.age / 9D) / 4;
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU, color & 0xFFFFFF2F, false);
DrawableUtil.drawArc(modelStack, radius + 3, radius + 4, 0, DrawableUtil.TAU, color & 0xFFFFFFAF, false);
pony.getSpellSlot().get(spell.and(SpellPredicate.IS_TIMED), false).map(TimedSpell::getTimer).ifPresent(timer -> {
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU * timer.getPercentTimeRemaining(client.getTickDelta()), 0xFFFFFFFF, false);
});
long count = pony.getSpellSlot().stream(spell, false).count();
if (count > 1) {
modelStack.push();
modelStack.translate(x + 5.5, y + 5.5, 0);
int color = spell.type().getColor() | 0x000000FF;
double radius = 2 + Math.sin(client.player.age / 9D) / 4;
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU, color & 0xFFFFFF2F, false);
DrawableUtil.drawArc(modelStack, radius + 3, radius + 4, 0, DrawableUtil.TAU, color & 0xFFFFFFAF, false);
pony.getSpellSlot().get(spell.and(SpellPredicate.IS_TIMED), false).map(TimedSpell::getTimer).ifPresent(timer -> {
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU * timer.getPercentTimeRemaining(client.getTickDelta()), 0xFFFFFFFF, false);
});
modelStack.translate(1, 1, 900);
modelStack.scale(0.8F, 0.8F, 0.8F);
font.drawWithShadow(modelStack, count > 64 ? "64+" : String.valueOf(count), 0, 0, 0xFFFFFFFF);
modelStack.pop();
}
DrawableUtil.renderItemIcon(spell.getDefaultStack(), x, y, EQUIPPED_GEMSTONE_SCALE);
modelStack.pop();
}
DrawableUtil.renderItemIcon(spell.getDefaultStack(), x, y, EQUIPPED_GEMSTONE_SCALE);
}
private void renderMessage(MatrixStack matrices, float tickDelta) {

View file

@ -2,9 +2,6 @@ package com.minelittlepony.unicopia.client.gui.spellbook;
import com.minelittlepony.common.client.gui.IViewRoot;
import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.client.gui.*;
import com.minelittlepony.unicopia.entity.player.*;
@ -31,25 +28,15 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell
@Override
public void init(SpellbookScreen screen, Identifier pageId) {
Bounds bounds = screen.getFrameBounds();
Race race = pony.getSpecies();
int size = 32;
int textureSize = 512;
int ordinal = Race.REGISTRY.getRawId(race);
int x = screen.getX() + bounds.left + bounds.width / 4 - size + 10;
int y = screen.getY() + bounds.top + bounds.height / 2;
screen.addDrawable(new SpellbookScreen.ImageButton(x, y, size, size))
.getStyle()
.setIcon(new TextureSprite()
.setPosition(0, 0)
.setSize(size, size)
.setTextureSize(textureSize, textureSize)
.setTexture(Unicopia.id("textures/gui/icons.png"))
.setTextureOffset((size * ordinal) % textureSize, (ordinal / textureSize) * size)
)
.setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, size))
.setTooltip(ProfileTooltip.get(pony));

View file

@ -91,7 +91,12 @@ public class EffectSync implements SpellContainer {
@Override
public Stream<Spell> stream(boolean update) {
return read(null, update, true);
return stream(null, update);
}
@Override
public Stream<Spell> stream(@Nullable SpellPredicate<?> type, boolean update) {
return read(type, update, true);
}
@Override

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,010 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB