Skip to content
Merged
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
Expand Up @@ -7,10 +7,14 @@
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.particle.ParticleTextureSheet;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.particle.ParticleGroup;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.Map;
import java.util.Queue;
Expand All @@ -25,6 +29,9 @@ public abstract class ParticleManagerMixin {
@Shadow
private Queue<Particle> newParticles;

@Shadow
protected abstract void addTo(ParticleGroup group, int count);

@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Ljava/util/Queue;poll()Ljava/lang/Object;"))
public Object changeMaxParticles(Queue<Object> queue) {
// 不需要判断 EnabledParticleCountInject 了,已在注入时判断,关这个一般都是因为会注入失败,所以不用担心
Expand All @@ -34,13 +41,29 @@ public Object changeMaxParticles(Queue<Object> queue) {
Queue<Particle> queue1 = particles.computeIfAbsent(particle.getType(),
sheet -> EvictingQueue.create(limit));
// limit 在程序生命周期内不会改变,这里可以直接判断
if (queue1.size() < limit) {
queue1.add(particle);
} else {
if (queue1.size() == limit) {
// 这样驱逐队列就没用了但是可以避免内存泄漏
particle.markDead();
Particle poll = queue1.poll();
if (poll != null) onEvict(poll);
}
queue1.add(particle);
}
return null;
}

@Inject(method = "clearParticles", at = @At("HEAD"))
public void clearParticles(CallbackInfo ci) {
particles.values().forEach(q -> q.forEach(this::onEvict));
newParticles.forEach(this::onEvict);
}

@Unique
private void onEvict(Particle p) {
// 这是原版 bug,但本模组会放大这个问题所以有必要修复一下
// 判断 isAlive 以保证幂等性(其他模组可能注入类似方法)
if (p.isAlive()) {
p.markDead();
p.getGroup().ifPresent(group -> addTo(group, -1));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cn.coostack.cooparticlesapi.config

import kotlin.math.max

class APIConfig {
/**
* 是否启用ParticleManagerMixin 对粒子数量上限进行修改
Expand All @@ -12,4 +14,5 @@ class APIConfig {
* 原版上限为65536
*/
var particleCountLimit = 65536
get() = max(field, 1)
}