移植部分激光代码
This commit is contained in:
parent
38cd812f4f
commit
a631173551
6 changed files with 557 additions and 0 deletions
|
@ -0,0 +1,19 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber()
|
||||
public class CapabilityHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerCapabilities(AttachCapabilitiesEvent<Entity> event) {
|
||||
if (event.getObject() instanceof Player) {
|
||||
event.addCapability(LaserCapability.ID, new LaserCapability.LaserCapabilityProvider());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LaserCapability {
|
||||
|
||||
public static ResourceLocation ID = ModUtils.loc("laser_capability");
|
||||
|
||||
public interface ILaserCapability extends INBTSerializable<CompoundTag> {
|
||||
|
||||
void init(LaserHandler handler);
|
||||
|
||||
void start();
|
||||
|
||||
void tick();
|
||||
|
||||
void stop();
|
||||
|
||||
}
|
||||
|
||||
public static class LaserCapabilityImpl implements ILaserCapability {
|
||||
|
||||
public LaserHandler laserHandler;
|
||||
|
||||
@Override
|
||||
public void init(LaserHandler handler) {
|
||||
this.laserHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.laserHandler.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (this.laserHandler != null) {
|
||||
this.laserHandler.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
if (this.laserHandler != null) {
|
||||
tag.put("Laser", this.laserHandler.writeNBT());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
if (nbt.contains("Laser") && this.laserHandler != null) {
|
||||
this.laserHandler.readNBT(nbt.getCompound("Laser"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LaserCapabilityProvider implements ICapabilityProvider, ICapabilitySerializable<CompoundTag> {
|
||||
|
||||
private final LazyOptional<LaserCapabilityImpl> instance = LazyOptional.of(LaserCapabilityImpl::new);
|
||||
|
||||
@Override
|
||||
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||
return ModCapabilities.LASER_CAPABILITY.orEmpty(cap, instance.cast());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
return instance.orElseThrow(NullPointerException::new).serializeNBT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
instance.orElseThrow(NullPointerException::new).deserializeNBT(nbt);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.projectile.AbstractLaserEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class LaserHandler {
|
||||
|
||||
public final int coolingTick;
|
||||
public boolean isUsing;
|
||||
public final LivingEntity entity;
|
||||
public final AbstractLaserEntity laserEntity;
|
||||
private int tick;
|
||||
|
||||
public LaserHandler(LivingEntity entity, AbstractLaserEntity laserEntity, int coolingTick) {
|
||||
this.coolingTick = coolingTick;
|
||||
this.entity = entity;
|
||||
this.laserEntity = laserEntity;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.tick = 0;
|
||||
this.isUsing = true;
|
||||
|
||||
if (this.entity.level() instanceof ServerLevel level) {
|
||||
level.addFreshEntity(this.laserEntity);
|
||||
}
|
||||
this.entity.swing(InteractionHand.MAIN_HAND, true);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (this.isUsing) {
|
||||
this.tick++;
|
||||
|
||||
if (this.tick > laserEntity.getDuration()) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (!this.isUsing) return;
|
||||
|
||||
this.isUsing = false;
|
||||
this.tick = 0;
|
||||
if (this.laserEntity != null) {
|
||||
this.laserEntity.discard();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTick() {
|
||||
return this.tick;
|
||||
}
|
||||
|
||||
public CompoundTag writeNBT() {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
if (this.isUsing) {
|
||||
compoundTag.putInt("Tick", this.tick);
|
||||
}
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
public void readNBT(Tag nbt) {
|
||||
CompoundTag compoundTag = (CompoundTag) nbt;
|
||||
this.isUsing = compoundTag.contains("Tick");
|
||||
if (this.isUsing) {
|
||||
this.tick = compoundTag.getInt("Tick");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUsable() {
|
||||
return !this.isUsing;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.atsuishio.superbwarfare.capability;
|
||||
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||
|
||||
public class ModCapabilities {
|
||||
|
||||
public static final Capability<LaserCapability.ILaserCapability> LASER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>() {
|
||||
});
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.atsuishio.superbwarfare.client;
|
||||
|
||||
/**
|
||||
* Code based on @EEEAB's EEEABsMobs and @Mercurows's DreamaticVoyage
|
||||
*/
|
||||
public class AnimationTicker {
|
||||
|
||||
private int tick;
|
||||
private int prevTick;
|
||||
private int duration;
|
||||
|
||||
public AnimationTicker(int duration) {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public int getTick() {
|
||||
return this.tick;
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
return this.tick == 0 && this.prevTick == 0;
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return this.tick == this.duration || this.prevTick == this.duration;
|
||||
}
|
||||
|
||||
public int getPrevTick() {
|
||||
return this.prevTick;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public void changeTimer(boolean flag) {
|
||||
changeTimer(flag, 1);
|
||||
}
|
||||
|
||||
public void changeTimer(boolean add, int time) {
|
||||
if (add) {
|
||||
increaseTimer(time);
|
||||
} else {
|
||||
decreaseTimer(time);
|
||||
}
|
||||
}
|
||||
|
||||
public void increaseTimer(int time) {
|
||||
int newTime = this.tick + time;
|
||||
if (newTime <= duration && newTime >= 0) {
|
||||
this.tick = newTime;
|
||||
} else {
|
||||
this.tick = newTime < 0 ? 0 : duration;
|
||||
}
|
||||
}
|
||||
|
||||
public void decreaseTimer(int time) {
|
||||
if (this.tick - time > 0.0D) {
|
||||
this.tick -= time;
|
||||
} else {
|
||||
this.tick = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePrevTimer() {
|
||||
this.prevTick = this.tick;
|
||||
}
|
||||
|
||||
public void resetTimer() {
|
||||
this.tick = 0;
|
||||
this.prevTick = 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
package com.atsuishio.superbwarfare.entity.projectile;
|
||||
|
||||
import com.atsuishio.superbwarfare.client.AnimationTicker;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.TraceableEntity;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import net.minecraft.world.phys.*;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Code based on @BobMowzie's MowziesMobs, @EEEAB's EEEABsMobs and @Mercurows's DreamaticVoyage
|
||||
*/
|
||||
public abstract class AbstractLaserEntity extends Entity implements TraceableEntity {
|
||||
|
||||
public LivingEntity caster;
|
||||
public float yaw, pitch;
|
||||
public float preYaw, prePitch;
|
||||
public double endPosX, endPosY, endPosZ;
|
||||
public double collidePosX, collidePosY, collidePosZ;
|
||||
public double prevCollidePosX, prevCollidePosY, prevCollidePosZ;
|
||||
public Direction blockSide = null;
|
||||
public boolean on = true;
|
||||
public AnimationTicker ticker = new AnimationTicker(3);
|
||||
|
||||
private static final EntityDataAccessor<Integer> DATA_CASTER_ID = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Float> DATA_YAW = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Float> DATA_PITCH = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.FLOAT);
|
||||
private static final EntityDataAccessor<Integer> DATA_DURATION = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Integer> DATA_COUNT_DOWN = SynchedEntityData.defineId(AbstractLaserEntity.class, EntityDataSerializers.INT);
|
||||
|
||||
public AbstractLaserEntity(EntityType<?> type, Level level, int countDown) {
|
||||
super(type, level);
|
||||
this.setCountDown(countDown);
|
||||
noCulling = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
this.prevCollidePosX = this.collidePosX;
|
||||
this.prevCollidePosY = this.collidePosY;
|
||||
this.prevCollidePosZ = this.collidePosZ;
|
||||
this.preYaw = this.yaw;
|
||||
this.prePitch = this.pitch;
|
||||
this.yaw = this.getYaw();
|
||||
this.pitch = this.getPitch();
|
||||
this.xo = this.getX();
|
||||
this.yo = this.getY();
|
||||
this.zo = this.getZ();
|
||||
if (this.tickCount == 1 && this.level().isClientSide) {
|
||||
this.caster = (LivingEntity) this.level().getEntity(getCasterId());
|
||||
}
|
||||
|
||||
this.beamTick();
|
||||
|
||||
if ((!this.on && this.ticker.isStopped()) || (this.caster != null && !caster.isAlive())) {
|
||||
this.discard();
|
||||
}
|
||||
this.ticker.changeTimer(this.on && this.isAccumulating());
|
||||
|
||||
if (this.tickCount - this.getCountDown() > this.getDuration()) {
|
||||
this.on = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
return NetworkHooks.getEntitySpawningPacket(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readAdditionalSaveData(CompoundTag pCompound) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(CompoundTag pCompound) {
|
||||
|
||||
}
|
||||
|
||||
protected void beamTick() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LivingEntity getOwner() {
|
||||
return caster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPickable() {
|
||||
return super.isPickable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(Entity entityIn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PushReaction getPistonPushReaction() {
|
||||
return PushReaction.IGNORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
this.entityData.define(DATA_CASTER_ID, -1);
|
||||
this.entityData.define(DATA_YAW, 0F);
|
||||
this.entityData.define(DATA_PITCH, 0F);
|
||||
this.entityData.define(DATA_DURATION, 0);
|
||||
this.entityData.define(DATA_COUNT_DOWN, 0);
|
||||
}
|
||||
|
||||
public void setCasterId(int id) {
|
||||
this.entityData.set(DATA_CASTER_ID, id);
|
||||
}
|
||||
|
||||
public int getCasterId() {
|
||||
return this.entityData.get(DATA_CASTER_ID);
|
||||
}
|
||||
|
||||
public boolean isAccumulating() {
|
||||
return this.tickCount > this.getCountDown();
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return getEntityData().get(DATA_YAW);
|
||||
}
|
||||
|
||||
public void setYaw(float rotAngle) {
|
||||
getEntityData().set(DATA_YAW, rotAngle);
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return getEntityData().get(DATA_PITCH);
|
||||
}
|
||||
|
||||
public void setPitch(float rotAngle) {
|
||||
getEntityData().set(DATA_PITCH, rotAngle);
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return getEntityData().get(DATA_DURATION);
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
getEntityData().set(DATA_DURATION, duration);
|
||||
}
|
||||
|
||||
public int getCountDown() {
|
||||
return getEntityData().get(DATA_COUNT_DOWN);
|
||||
}
|
||||
|
||||
public void setCountDown(int countDown) {
|
||||
getEntityData().set(DATA_COUNT_DOWN, countDown);
|
||||
}
|
||||
|
||||
protected void calculateEndPos(double radius) {
|
||||
if (level().isClientSide()) {
|
||||
endPosX = getX() + radius * Math.cos(yaw) * Math.cos(pitch);
|
||||
endPosZ = getZ() + radius * Math.sin(yaw) * Math.cos(pitch);
|
||||
endPosY = getY() + radius * Math.sin(pitch);
|
||||
} else {
|
||||
endPosX = getX() + radius * Math.cos(getYaw()) * Math.cos(getPitch());
|
||||
endPosZ = getZ() + radius * Math.sin(getYaw()) * Math.cos(getPitch());
|
||||
endPosY = getY() + radius * Math.sin(getPitch());
|
||||
}
|
||||
}
|
||||
|
||||
public CustomHitResult raytraceEntities(Level world, Vec3 from, Vec3 to) {
|
||||
CustomHitResult result = new CustomHitResult();
|
||||
result.setBlockHit(world.clip(new ClipContext(from, to, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)));
|
||||
if (result.getBlockHit() != null) {
|
||||
Vec3 hitVec = result.getBlockHit().getLocation();
|
||||
collidePosX = hitVec.x;
|
||||
collidePosY = hitVec.y;
|
||||
collidePosZ = hitVec.z;
|
||||
blockSide = result.getBlockHit().getDirection();
|
||||
} else {
|
||||
collidePosX = endPosX;
|
||||
collidePosY = endPosY;
|
||||
collidePosZ = endPosZ;
|
||||
blockSide = null;
|
||||
}
|
||||
List<LivingEntity> entities = world.getEntitiesOfClass(LivingEntity.class, new AABB(Math.min(getX(), collidePosX), Math.min(getY(), collidePosY), Math.min(getZ(), collidePosZ), Math.max(getX(), collidePosX), Math.max(getY(), collidePosY), Math.max(getZ(), collidePosZ)).inflate(1, 1, 1));
|
||||
for (LivingEntity entity : entities) {
|
||||
if (entity == this.caster) {
|
||||
continue;
|
||||
}
|
||||
float pad = entity.getPickRadius() + getBaseScale();
|
||||
AABB aabb = entity.getBoundingBox().inflate(pad, pad, pad);
|
||||
Optional<Vec3> hit = aabb.clip(from, to);
|
||||
if (aabb.contains(from)) {
|
||||
result.addEntityHit(entity);
|
||||
} else if (hit.isPresent()) {
|
||||
result.addEntityHit(entity);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean displayFireAnimation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onHit(HitResult hitResult) {
|
||||
HitResult.Type hitresult$type = hitResult.getType();
|
||||
if (hitresult$type == HitResult.Type.ENTITY) {
|
||||
this.onHitEntity((EntityHitResult) hitResult);
|
||||
this.level().gameEvent(GameEvent.PROJECTILE_LAND, hitResult.getLocation(), GameEvent.Context.of(this, null));
|
||||
} else if (hitresult$type == HitResult.Type.BLOCK) {
|
||||
BlockHitResult blockhitresult = (BlockHitResult) hitResult;
|
||||
this.onHitBlock(blockhitresult);
|
||||
BlockPos blockpos = blockhitresult.getBlockPos();
|
||||
this.level().gameEvent(GameEvent.PROJECTILE_LAND, blockpos, GameEvent.Context.of(this, this.level().getBlockState(blockpos)));
|
||||
}
|
||||
}
|
||||
|
||||
protected void onHitEntity(EntityHitResult result) {
|
||||
}
|
||||
|
||||
protected void onHitBlock(BlockHitResult result) {
|
||||
}
|
||||
|
||||
protected float getBaseScale() {
|
||||
return 0.5F;
|
||||
}
|
||||
|
||||
public static class CustomHitResult {
|
||||
|
||||
private BlockHitResult blockHit;
|
||||
private final List<LivingEntity> entities = new ArrayList<>();
|
||||
|
||||
public BlockHitResult getBlockHit() {
|
||||
return blockHit;
|
||||
}
|
||||
|
||||
public List<LivingEntity> getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
public void setBlockHit(HitResult rayTraceResult) {
|
||||
if (rayTraceResult.getType() == HitResult.Type.BLOCK)
|
||||
this.blockHit = (BlockHitResult) rayTraceResult;
|
||||
}
|
||||
|
||||
public void addEntityHit(LivingEntity entity) {
|
||||
entities.add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue