Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom particles #32

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.denizenscript.clientizen.access;

public interface BillboardParticleMixinAccess {

float clientizen$getScale();

void clientizen$setScale(Float scale);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.denizenscript.clientizen.access;

import com.denizenscript.denizencore.flags.MapTagFlagTracker;
import net.minecraft.particle.ParticleType;

import java.util.UUID;

public interface ParticleMixinAccess {

UUID clientizen$getUUID();

ParticleType<?> clientizen$getType();

void clientizen$setType(ParticleType<?> type);

MapTagFlagTracker clientizen$getFlagTracker();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.denizenscript.clientizen.access;

import net.minecraft.util.Identifier;

public interface RegistryMixinAccess {

void clientizen$unfreeze();

void clientizen$remove(Identifier toRemove);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.denizenscript.clientizen.mixin;

import com.denizenscript.clientizen.access.RegistryMixinAccess;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsRuntimeException;
import com.mojang.serialization.Lifecycle;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.SimpleRegistry;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.entry.RegistryEntryInfo;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.IdentityHashMap;
import java.util.Map;

@Mixin(SimpleRegistry.class)
public abstract class RegistryMixin<T> implements RegistryMixinAccess {

@Unique
boolean clientizen$isIntrusive;

@Shadow
private boolean frozen;
@Shadow
public abstract RegistryKey<? extends Registry<T>> getKey();
@Shadow
private @Nullable Map<T, RegistryEntry.Reference<T>> intrusiveValueToEntry;
@Shadow
@Final
private ObjectList<RegistryEntry.Reference<T>> rawIdToEntry;
@Shadow
@Final
private Map<Identifier, RegistryEntry.Reference<T>> idToEntry;
@Shadow
@Final
private Reference2IntMap<T> entryToRawId;
@Shadow
@Final
private Map<RegistryKey<T>, RegistryEntry.Reference<T>> keyToEntry;
@Shadow
@Final
private Map<T, RegistryEntry.Reference<T>> valueToEntry;
@Shadow
@Final
private Map<RegistryKey<T>, RegistryEntryInfo> keyToEntryInfo;

@Override
public void clientizen$unfreeze() {
if (!frozen) {
return;
}
frozen = false;
if (clientizen$isIntrusive) {
intrusiveValueToEntry = new IdentityHashMap<>();
}
}

@Override
public void clientizen$remove(Identifier toRemove) {
RegistryEntry.Reference<T> value = idToEntry.get(toRemove);
if (value == null) {
throw new InvalidArgumentsRuntimeException("Unable to remove '" + toRemove + "' from registry '" + getKey() + "': registry has no value by that key.");
}
RegistryKey<T> key = RegistryKey.of(getKey(), toRemove);
keyToEntry.remove(key);
idToEntry.remove(toRemove);
valueToEntry.remove(value.value());
rawIdToEntry.remove(value);
entryToRawId.removeInt(value.value());
keyToEntryInfo.remove(key);
}

@Inject(method = "<init>(Lnet/minecraft/registry/RegistryKey;Lcom/mojang/serialization/Lifecycle;Z)V", at = @At("TAIL"))
private void clientizen$saveIsIntrusive(RegistryKey<?> key, Lifecycle lifecycle, boolean intrusive, CallbackInfo ci) {
clientizen$isIntrusive = intrusive;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.denizenscript.clientizen.mixin.particle;

import com.denizenscript.clientizen.access.BillboardParticleMixinAccess;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.particle.BillboardParticle;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(BillboardParticle.class)
public abstract class BillboardParticleMixin implements BillboardParticleMixinAccess {

@Shadow
protected float scale;

@Unique
Float clientizen$scale;

@Override
public float clientizen$getScale() {
return clientizen$scale != null ? clientizen$scale : scale;
}

@Override
public void clientizen$setScale(Float scale) {
clientizen$scale = scale;
}

@WrapOperation(
method = "buildGeometry",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/BillboardParticle;getSize(F)F")
)
private float clientizen$overrideScale(BillboardParticle particle, float tickDelta, Operation<Float> original) {
return clientizen$scale != null ? clientizen$scale : original.call(particle, tickDelta);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.denizenscript.clientizen.mixin.particle;

import net.minecraft.client.particle.Particle;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(Particle.class)
public interface ParticleAccessor {

// MCDev plugin bug, need to specify the name in the annotation to avoid IDE errors
@Accessor("x")
double getX();

@Accessor("y")
double getY();

@Accessor("z")
double getZ();

@Accessor
double getVelocityX();

@Accessor
double getVelocityY();

@Accessor
double getVelocityZ();

@Accessor
float getRed();

@Accessor
float getGreen();

@Accessor
float getBlue();

@Accessor
float getAlpha();

@Invoker
void invokeSetAlpha(float alpha);

@Accessor
boolean isOnGround();

@Accessor("collidesWithWorld")
boolean collidesWithWorld();

@Accessor
void setCollidesWithWorld(boolean collidesWithWorld);

@Accessor
int getAge();

@Accessor
void setAge(int age);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.denizenscript.clientizen.mixin.particle;

import net.minecraft.client.particle.ParticleManager;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.util.Map;

@Mixin(ParticleManager.class)
public interface ParticleManagerAccessor {

@Accessor("spriteAwareFactories")
Map<Identifier, ParticleManager.SimpleSpriteProvider> getSpriteProviderMap();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.denizenscript.clientizen.mixin.particle;

import com.denizenscript.clientizen.access.ParticleMixinAccess;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.particle.ParticleEffect;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(ParticleManager.class)
public abstract class ParticleManagerMixin {

@Inject(method = "createParticle", at = @At("RETURN"))
private <T extends ParticleEffect> void clientizen$storeParticleType(T parameters, double x, double y, double z, double velocityX, double velocityY, double velocityZ, CallbackInfoReturnable<Particle> cir) {
if (cir.getReturnValue() instanceof ParticleMixinAccess particle) {
particle.clientizen$setType(parameters.getType());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.denizenscript.clientizen.mixin.particle;

import com.denizenscript.clientizen.access.ParticleMixinAccess;
import com.denizenscript.clientizen.objects.ParticleTag;
import com.denizenscript.denizencore.flags.MapTagFlagTracker;
import net.minecraft.client.particle.Particle;
import net.minecraft.particle.ParticleType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.UUID;

@Mixin(Particle.class)
public abstract class ParticleMixin implements ParticleMixinAccess {

@Unique
final UUID clientizen$id = UUID.randomUUID();
@Unique
ParticleType<?> clientizen$particleType;
@Unique
MapTagFlagTracker clientizen$flagMap;

@Inject(method = "<init>(Lnet/minecraft/client/world/ClientWorld;DDD)V", at = @At("TAIL"))
private void clientizen$onParticleCreated(CallbackInfo ci) {
ParticleTag.particles.put(clientizen$id, (Particle) (Object) this);
}

@Inject(method = "markDead", at = @At("TAIL"))
private void clientizen$onParticleRemoved(CallbackInfo ci) {
ParticleTag.particles.remove(clientizen$id);
}

@Override
public UUID clientizen$getUUID() {
return clientizen$id;
}

@Override
public ParticleType<?> clientizen$getType() {
return clientizen$particleType;
}

@Override
public void clientizen$setType(ParticleType<?> type) {
clientizen$particleType = type;
}

@Override
public MapTagFlagTracker clientizen$getFlagTracker() {
if (clientizen$flagMap == null) {
clientizen$flagMap = new MapTagFlagTracker();
}
return clientizen$flagMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.denizenscript.clientizen.mixin.particle;

import net.minecraft.client.particle.SpriteBillboardParticle;
import net.minecraft.client.texture.Sprite;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(SpriteBillboardParticle.class)
public interface SpriteBillboardParticleAccessor {

@Accessor
Sprite getSprite();

@Invoker
void invokeSetSprite(Sprite sprite);
}
Loading