Compare commits
4 commits
main
...
famos-amos
Author | SHA1 | Date | |
---|---|---|---|
994aec97a4 | |||
6a4c254ed0 | |||
19f35e1205 | |||
79cbfabb48 |
|
@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
|
|||
import at.petrak.hexcasting.api.misc.DiscoveryHandlers;
|
||||
import at.petrak.hexcasting.api.player.Sentinel;
|
||||
import at.petrak.hexcasting.client.ClientTickCounter;
|
||||
import at.petrak.hexcasting.client.render.patternado.PatternadosTracker;
|
||||
import at.petrak.hexcasting.xplat.IXplatAbstractions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
@ -26,12 +27,15 @@ import net.minecraft.util.Mth;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class HexAdditionalRenderers {
|
||||
private static final float PATTERNADO_SPEEN_SPEED = 0.01f;
|
||||
|
||||
public static void overlayLevel(PoseStack ps, float partialTick) {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
|
@ -46,6 +50,74 @@ public class HexAdditionalRenderers {
|
|||
tryRenderScryingLensOverlay(ps, partialTicks);
|
||||
}
|
||||
|
||||
public static void renderPatternado(LocalPlayer player, PoseStack ps, float partialTicks) {
|
||||
var me = Minecraft.getInstance().player;
|
||||
if (me == player && !Minecraft.getInstance().options.getCameraType().isFirstPerson()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pats = PatternadosTracker.getPatterns(player.getUUID());
|
||||
if (pats == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldShader = RenderSystem.getShader();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
RenderSystem.enableDepthTest();
|
||||
RenderSystem.disableCull();
|
||||
ps.pushPose();
|
||||
|
||||
float time = player.level.getGameTime() + partialTicks;
|
||||
var col = IXplatAbstractions.INSTANCE.getColorizer(player).getColorProvider();
|
||||
|
||||
for (var spinner : pats) {
|
||||
// So it stops moving near the end?
|
||||
float lifetimeOffset = spinner.getLifetime() <= 5 ? (5f - spinner.getLifetime()) / 5f : 0f;
|
||||
{
|
||||
ps.mulPose(Vector3f.YP.rotationDegrees(time * spinner.getLifetime() * PATTERNADO_SPEEN_SPEED));
|
||||
// X: sideways, don't move it
|
||||
// Y: up/down, each pattern stays on its own ring
|
||||
// Z: in/out, it's mostly determined by the idx but also slowly drifts in/out
|
||||
ps.translate(
|
||||
0,
|
||||
Mth.sin(spinner.getIdx() * 0.75f),
|
||||
0.75f + (Mth.cos(spinner.getIdx() / 8f) * 0.25f) + Mth.cos(time) / (7f + (spinner.getIdx() / 4f)) * 0.065f
|
||||
);
|
||||
var scale = 1f / 24f * (1 - lifetimeOffset);
|
||||
ps.scale(scale, scale, scale);
|
||||
// Don't know why amo did this in two translate calls
|
||||
ps.translate(
|
||||
0,
|
||||
Mth.floor(spinner.getIdx() / 8f) + Mth.sin(time) / (7f + (spinner.getIdx() / 8f)),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
var pat = spinner.getPattern();
|
||||
var lines = RenderLib.getCenteredPattern(pat, 1, 1, 3.8f).getSecond();
|
||||
|
||||
float variance = 0.65f;
|
||||
float speed = 0.1f;
|
||||
List<Vec2> zappy = RenderLib.makeZappy(lines, RenderLib.findDupIndices(pat.positions()),
|
||||
5, variance, speed, 0.2f, 0f,
|
||||
1f, spinner.getUuid().hashCode());
|
||||
int outer = col.getColor(ClientTickCounter.getTotal() / 2f, Vec3.ZERO);
|
||||
int rgbOnly = outer & 0x00FFFFFF;
|
||||
int newAlpha = outer >>> 24;
|
||||
if (spinner.getLifetime() <= 60) {
|
||||
newAlpha = (int) Math.floor(spinner.getLifetime() / 60f * 255);
|
||||
}
|
||||
int newARGB = (newAlpha << 24) | rgbOnly;
|
||||
int inner = RenderLib.screen(newARGB);
|
||||
RenderLib.drawLineSeq(ps.last().pose(), zappy, 0.35f, 0f, newARGB, newARGB);
|
||||
RenderLib.drawLineSeq(ps.last().pose(), zappy, 0.14f, 0.01f, inner, inner);
|
||||
}
|
||||
|
||||
ps.popPose();
|
||||
RenderSystem.setShader(() -> oldShader);
|
||||
RenderSystem.enableCull();
|
||||
}
|
||||
|
||||
private static void renderSentinel(Sentinel sentinel, LocalPlayer owner,
|
||||
PoseStack ps, float partialTicks) {
|
||||
ps.pushPose();
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package at.petrak.hexcasting.client.render.patternado;
|
||||
|
||||
import at.petrak.hexcasting.common.casting.patternado.PatternadoPatInstance;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Keeps track of the patterns swirling around each player
|
||||
*/
|
||||
public class PatternadosTracker {
|
||||
// god i'm really calling this a patternado what is wrong with me
|
||||
private static final Map<UUID, PlayerPats> PATTERNADOS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Get notified of a new pattern around a player.
|
||||
*/
|
||||
public static void getNewPat(UUID owner, PatternadoPatInstance newPat) {
|
||||
var nado = PATTERNADOS.get(owner);
|
||||
if (nado == null) {
|
||||
nado = PATTERNADOS.put(owner, PlayerPats.empty());
|
||||
}
|
||||
nado.pats.put(newPat.getUuid(), newPat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a pattern by its uuid. (More accurately, enqueue it for being removed after ticking)
|
||||
*/
|
||||
public static void removePat(UUID owner, UUID pattern) {
|
||||
var nado = PATTERNADOS.get(owner);
|
||||
if (nado == null) {
|
||||
return;
|
||||
}
|
||||
nado.pats.remove(pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a player fresh.
|
||||
*/
|
||||
public static void clobberPatterns(UUID owner, List<PatternadoPatInstance> pats) {
|
||||
PATTERNADOS.put(owner, PlayerPats.newFromList(pats));
|
||||
}
|
||||
|
||||
public static @Nullable Collection<PatternadoPatInstance> getPatterns(UUID owner) {
|
||||
var pats = PATTERNADOS.get(owner);
|
||||
if (pats == null) {
|
||||
return null;
|
||||
}
|
||||
return pats.pats.values();
|
||||
}
|
||||
|
||||
// TODO: this might cause a memory leak if you view tons and tons of players.
|
||||
// Perhaps find some way to remove entries from this map if they're not in view?
|
||||
|
||||
public static void tick() {
|
||||
for (var nados : PATTERNADOS.values()) {
|
||||
var toRemove = new ArrayList<UUID>();
|
||||
for (var pat : nados.pats.values()) {
|
||||
pat.tick();
|
||||
if (pat.getLifetime() == 0) {
|
||||
toRemove.add(pat.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
for (var uuid : toRemove) {
|
||||
nados.pats.remove(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record PlayerPats(Map<UUID, PatternadoPatInstance> pats) {
|
||||
static PlayerPats newFromList(List<PatternadoPatInstance> pats) {
|
||||
var map = new HashMap<UUID, PatternadoPatInstance>();
|
||||
for (var pat : pats) {
|
||||
map.put(pat.getUuid(), pat);
|
||||
}
|
||||
return new PlayerPats(map);
|
||||
}
|
||||
|
||||
static PlayerPats empty() {
|
||||
return new PlayerPats(new HashMap<>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package at.petrak.hexcasting.common.casting.patternado;
|
||||
|
||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* The patterns swirling around a particular player.
|
||||
* <p>
|
||||
* The canonical version of each player's patternado is stored on the server. When a new pattern is added on the server,
|
||||
* the client hears about the addition. Clients remove patterns once they've run out of time themselves.
|
||||
* <p>
|
||||
* Also there's something about loading a brand new patternado when meeting a player for the first time
|
||||
*/
|
||||
public class Patternado {
|
||||
private static final int MAX_IDX = 300;
|
||||
|
||||
private static final String TAG_PATS = "patterns",
|
||||
TAG_IDX_COUNTER = "idx_counter";
|
||||
|
||||
private Player owner;
|
||||
private Deque<PatternadoPatInstance> pats;
|
||||
private int idxCounter;
|
||||
|
||||
public Patternado(Player owner) {
|
||||
this.owner = owner;
|
||||
this.pats = new ArrayDeque<>();
|
||||
this.idxCounter = 0;
|
||||
}
|
||||
|
||||
public void addPattern(HexPattern pattern, int lifetime) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package at.petrak.hexcasting.common.casting.patternado;
|
||||
|
||||
import at.petrak.hexcasting.api.casting.math.HexPattern;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PatternadoPatInstance {
|
||||
private static final RandomSource RANDOM = RandomSource.create();
|
||||
|
||||
private final HexPattern pattern;
|
||||
// Idx is used to determine where to draw it
|
||||
private final int idx;
|
||||
// -1 == infinite
|
||||
private int lifetime;
|
||||
// Use this so we can remove particular pats once a player finishes staffcasting
|
||||
private UUID uuid;
|
||||
|
||||
public PatternadoPatInstance(HexPattern pattern, int lifetime, int idx) {
|
||||
this.pattern = pattern;
|
||||
this.lifetime = lifetime;
|
||||
this.idx = idx;
|
||||
this.uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
private PatternadoPatInstance(HexPattern pattern, int lifetime, int idx, UUID uuid) {
|
||||
this.pattern = pattern;
|
||||
this.lifetime = lifetime;
|
||||
this.idx = idx;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public HexPattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public int getLifetime() {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
public int getIdx() {
|
||||
return this.idx;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.lifetime > 0) {
|
||||
this.lifetime--;
|
||||
}
|
||||
}
|
||||
|
||||
// we need to go through and make the ser/de names consistent
|
||||
public static PatternadoPatInstance loadFromWire(FriendlyByteBuf buf) {
|
||||
var pattern = HexPattern.fromNBT(buf.readNbt());
|
||||
var lifetime = buf.readVarInt();
|
||||
var idx = buf.readVarInt();
|
||||
var uuid = buf.readUUID();
|
||||
return new PatternadoPatInstance(pattern, lifetime, idx, uuid);
|
||||
}
|
||||
|
||||
public void saveToWire(FriendlyByteBuf buf) {
|
||||
buf.writeNbt(this.pattern.serializeToNBT());
|
||||
buf.writeVarInt(this.lifetime);
|
||||
buf.writeInt(this.idx);
|
||||
buf.writeUUID(this.uuid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Thanks to Amo for writing the original code for this.
|
||||
|
||||
https://github.com/amoooooo/Jinx/tree/main
|
|
@ -0,0 +1,44 @@
|
|||
package at.petrak.hexcasting.common.msgs;
|
||||
|
||||
import at.petrak.hexcasting.client.render.patternado.PatternadosTracker;
|
||||
import at.petrak.hexcasting.common.casting.patternado.PatternadoPatInstance;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
public record MsgNewPatternadoPatS2C(UUID owner, PatternadoPatInstance newPat) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("nado1");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgNewPatternadoPatS2C deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
|
||||
var owner = buf.readUUID();
|
||||
var pat = PatternadoPatInstance.loadFromWire(buf);
|
||||
return new MsgNewPatternadoPatS2C(owner, pat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeUUID(this.owner);
|
||||
this.newPat.saveToWire(buf);
|
||||
}
|
||||
|
||||
public static void handle(MsgNewPatternadoPatS2C msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PatternadosTracker.getNewPat(msg.owner, msg.newPat);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package at.petrak.hexcasting.common.msgs;
|
||||
|
||||
import at.petrak.hexcasting.client.render.patternado.PatternadosTracker;
|
||||
import at.petrak.hexcasting.common.casting.patternado.PatternadoPatInstance;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static at.petrak.hexcasting.api.HexAPI.modLoc;
|
||||
|
||||
/**
|
||||
* Set the patternado of a given player to this, overwrite the previous
|
||||
*/
|
||||
public record MsgOverridePatternadoS2C(UUID owner, List<PatternadoPatInstance> pats) implements IMessage {
|
||||
public static final ResourceLocation ID = modLoc("nados");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public static MsgOverridePatternadoS2C deserialize(ByteBuf buffer) {
|
||||
var buf = new FriendlyByteBuf(buffer);
|
||||
var owner = buf.readUUID();
|
||||
var pats = buf.readCollection(ArrayList::new, PatternadoPatInstance::loadFromWire);
|
||||
return new MsgOverridePatternadoS2C(owner, pats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(FriendlyByteBuf buf) {
|
||||
buf.writeUUID(this.owner);
|
||||
buf.writeCollection(this.pats, (bf, it) -> it.saveToWire(bf));
|
||||
}
|
||||
|
||||
public static void handle(MsgOverridePatternadoS2C msg) {
|
||||
Minecraft.getInstance().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PatternadosTracker.clobberPatterns(msg.owner, msg.pats);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -42,11 +42,11 @@ public class HexCardinalComponents implements EntityComponentInitializer, ItemCo
|
|||
CCSentinel.class);
|
||||
public static final ComponentKey<CCFlight> FLIGHT = ComponentRegistry.getOrCreate(modLoc("flight"),
|
||||
CCFlight.class);
|
||||
|
||||
public static final ComponentKey<CCAltiora> ALTIORA = ComponentRegistry.getOrCreate(modLoc("altiora"),
|
||||
CCAltiora.class);
|
||||
|
||||
public static final ComponentKey<CCStaffcastImage> STAFFCAST_IMAGE = ComponentRegistry.getOrCreate(modLoc(
|
||||
"harness"),
|
||||
"harness"),
|
||||
CCStaffcastImage.class);
|
||||
public static final ComponentKey<CCPatterns> PATTERNS = ComponentRegistry.getOrCreate(modLoc("patterns"),
|
||||
CCPatterns.class);
|
||||
|
|
|
@ -29,6 +29,7 @@ public class CapSyncers {
|
|||
x.setAltiora(player, x.getAltiora(proto));
|
||||
x.setSentinel(player, x.getSentinel(proto));
|
||||
x.setColorizer(player, x.getColorizer(proto));
|
||||
// TODO: do we want staff stuff to remain on death?
|
||||
x.setStaffcastImage(player, x.getStaffcastVM(proto, InteractionHand.MAIN_HAND).getImage());
|
||||
x.setPatterns(player, x.getPatternsSavedInUi(proto));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue