HexCasting/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/StaffCastEnv.java

122 lines
4.7 KiB
Java

package at.petrak.hexcasting.api.casting.eval.env;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.casting.ParticleSpray;
import at.petrak.hexcasting.api.casting.eval.CastResult;
import at.petrak.hexcasting.api.casting.eval.ExecutionClientView;
import at.petrak.hexcasting.api.casting.eval.ResolvedPattern;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.casting.math.HexCoord;
import at.petrak.hexcasting.api.mod.HexStatistics;
import at.petrak.hexcasting.api.pigment.FrozenPigment;
import at.petrak.hexcasting.common.network.MsgNewSpellPatternAck;
import at.petrak.hexcasting.common.network.MsgNewSpellPatternSyn;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.Vec3;
import java.util.HashSet;
import java.util.List;
public class StaffCastEnv extends PlayerBasedCastEnv {
private final InteractionHand castingHand;
public StaffCastEnv(ServerPlayer caster, InteractionHand castingHand) {
super(caster, castingHand);
this.castingHand = castingHand;
}
@Override
public void postExecution(CastResult result) {
super.postExecution(result);
// we always want to play this sound one at a time
var sound = result.getSound().sound();
if (sound != null) {
var soundPos = this.caster.position();
this.world.playSound(null, soundPos.x, soundPos.y, soundPos.z,
sound, SoundSource.PLAYERS, 1f, 1f);
}
}
@Override
public long extractMedia(long cost) {
if (this.caster.isCreative())
return 0;
var canOvercast = this.canOvercast();
var remaining = this.extractMediaFromInventory(cost, canOvercast);
if (remaining > 0 && !canOvercast) {
this.caster.sendSystemMessage(Component.translatable("hexcasting.message.cant_overcast"));
}
return remaining;
}
@Override
public InteractionHand getCastingHand() {
return castingHand;
}
@Override
public FrozenPigment getColorizer() {
return HexAPI.instance().getColorizer(this.caster);
}
public static void handleNewPatternOnServer(ServerPlayer sender, MsgNewSpellPatternSyn msg) {
boolean cheatedPatternOverlap = false;
List<ResolvedPattern> resolvedPatterns = msg.resolvedPatterns();
if (!resolvedPatterns.isEmpty()) {
var allPoints = new HashSet<HexCoord>();
for (int i = 0; i < resolvedPatterns.size() - 1; i++) {
ResolvedPattern pat = resolvedPatterns.get(i);
allPoints.addAll(pat.getPattern().positions(pat.getOrigin()));
}
var currentResolvedPattern = resolvedPatterns.get(resolvedPatterns.size() - 1);
var currentSpellPoints = currentResolvedPattern.getPattern()
.positions(currentResolvedPattern.getOrigin());
if (currentSpellPoints.stream().anyMatch(allPoints::contains)) {
cheatedPatternOverlap = true;
}
}
if (cheatedPatternOverlap) {
return;
}
sender.awardStat(HexStatistics.PATTERNS_DRAWN);
var vm = IXplatAbstractions.INSTANCE.getStaffcastVM(sender, msg.handUsed());
// TODO: do we reset the number of evals run via the staff? because each new pat is a new tick.
ExecutionClientView clientInfo = vm.queueExecuteAndWrapIota(new PatternIota(msg.pattern()), sender.getLevel());
if (clientInfo.isStackClear()) {
IXplatAbstractions.INSTANCE.setStaffcastImage(sender, null);
IXplatAbstractions.INSTANCE.setPatterns(sender, List.of());
} else {
IXplatAbstractions.INSTANCE.setStaffcastImage(sender, vm.getImage());
if (!resolvedPatterns.isEmpty()) {
resolvedPatterns.get(resolvedPatterns.size() - 1).setType(clientInfo.getResolutionType());
}
IXplatAbstractions.INSTANCE.setPatterns(sender, resolvedPatterns);
}
IXplatAbstractions.INSTANCE.sendPacketToPlayer(sender,
new MsgNewSpellPatternAck(clientInfo, resolvedPatterns.size() - 1));
if (clientInfo.getResolutionType().getSuccess()) {
// Somehow we lost spraying particles on each new pattern, so do it here
// this also nicely prevents particle spam on trinkets
new ParticleSpray(sender.position(), new Vec3(0.0, 1.5, 0.0), 0.4, Math.PI / 3, 30)
.sprayParticles(sender.getLevel(), IXplatAbstractions.INSTANCE.getColorizer(sender));
}
}
}