This commit is contained in:
parent
5cc87d537c
commit
befb1eae2f
@ -9,11 +9,11 @@ import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Material;
|
import net.minecraft.block.Material;
|
||||||
|
import net.minecraft.block.MaterialColor;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||||
import net.minecraft.sound.BlockSoundGroup;
|
|
||||||
import net.minecraft.state.StateManager;
|
import net.minecraft.state.StateManager;
|
||||||
import net.minecraft.state.property.BooleanProperty;
|
import net.minecraft.state.property.BooleanProperty;
|
||||||
import net.minecraft.state.property.Properties;
|
import net.minecraft.state.property.Properties;
|
||||||
@ -26,7 +26,7 @@ public class DefensiveLaserBlock extends EnergyProviderBlock {
|
|||||||
public static final BooleanProperty POWERED = Properties.POWERED;
|
public static final BooleanProperty POWERED = Properties.POWERED;
|
||||||
|
|
||||||
public DefensiveLaserBlock() {
|
public DefensiveLaserBlock() {
|
||||||
super(FabricBlockSettings.of(Material.GLASS).sounds(BlockSoundGroup.GLASS).nonOpaque().strength(0.3f).allowsSpawning((state, world, pos, type) -> false).solidBlock((state, world, pos) -> false).suffocates((state, world, pos) -> false));
|
super(FabricBlockSettings.of(Material.GLASS, MaterialColor.BLACK).requiresTool().strength(50.0F, 1200.0F).nonOpaque().allowsSpawning((state, world, pos, type) -> false).solidBlock((state, world, pos) -> false).suffocates((state, world, pos) -> false));
|
||||||
setDefaultState(getDefaultState().with(POWERED, false));
|
setDefaultState(getDefaultState().with(POWERED, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,47 +5,32 @@ import com.thebrokenrail.energonrelics.EnergonRelics;
|
|||||||
import com.thebrokenrail.energonrelics.block.DefensiveLaserBlock;
|
import com.thebrokenrail.energonrelics.block.DefensiveLaserBlock;
|
||||||
import com.thebrokenrail.energonrelics.energy.core.EnergyReceiverBlockEntity;
|
import com.thebrokenrail.energonrelics.energy.core.EnergyReceiverBlockEntity;
|
||||||
import com.thebrokenrail.energonrelics.energy.core.util.Action;
|
import com.thebrokenrail.energonrelics.energy.core.util.Action;
|
||||||
import com.thebrokenrail.energonrelics.util.MissingCaseException;
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.entity.BlockEntityType;
|
import net.minecraft.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.ItemEntity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
import net.minecraft.util.math.Box;
|
import net.minecraft.util.math.Box;
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.RayTraceContext;
|
import net.minecraft.world.RayTraceContext;
|
||||||
|
import net.minecraft.world.explosion.Explosion;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
||||||
private static final float MAX_PITCH = 0;
|
private static final float ROTATION_INCREMENT = 4;
|
||||||
private static final float MIN_PITCH = -70;
|
|
||||||
|
|
||||||
private static final float ROTATION_INCREMENT = 2;
|
|
||||||
|
|
||||||
private static final int COUNTDOWN = 6;
|
|
||||||
|
|
||||||
public final Rotation rotation = new Rotation(0, 0, "Rotation");
|
public final Rotation rotation = new Rotation(0, 0, "Rotation");
|
||||||
private LivingEntity target;
|
|
||||||
private int countdown = 0;
|
|
||||||
|
|
||||||
private final Predicate<LivingEntity> predicate = entity -> {
|
|
||||||
if (entity.getBlockPos().isWithinDistance(getPos(), Config.DEFENSIVE_LASER_RANGE)) {
|
|
||||||
Vec3d start = getPosVec().add(rotation.getRayVector());
|
|
||||||
Vec3d end = entity.getPos();
|
|
||||||
HitResult result = entity.getEntityWorld().rayTrace(new RayTraceContext(start, end, RayTraceContext.ShapeType.COLLIDER, RayTraceContext.FluidHandling.ANY, entity));
|
|
||||||
return result.getType() == HitResult.Type.MISS;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private Vec3d getPosVec() {
|
private Vec3d getPosVec() {
|
||||||
return new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d);
|
return new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d);
|
||||||
@ -109,13 +94,7 @@ public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Vec3d getRayVector() {
|
private Vec3d getRayVector() {
|
||||||
float pitch = this.pitch * (float) DEG2RAD;
|
return DefensiveLaserBlockEntity.getRayVector(yaw, pitch);
|
||||||
float yaw = this.yaw * (float) DEG2RAD;
|
|
||||||
float cosYaw = MathHelper.cos(yaw);
|
|
||||||
float sinYaw = MathHelper.sin(yaw);
|
|
||||||
float cosPitch = MathHelper.cos(pitch);
|
|
||||||
float sinPitch = MathHelper.sin(pitch);
|
|
||||||
return new Vec3d(sinYaw * cosPitch, -sinPitch, cosYaw * cosPitch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getAngleChange(float from, float to) {
|
private float getAngleChange(float from, float to) {
|
||||||
@ -130,6 +109,16 @@ public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Vec3d getRayVector(float yaw, float pitch) {
|
||||||
|
float pitchRad = pitch * (float) DEG2RAD;
|
||||||
|
float yawRad = yaw * (float) DEG2RAD;
|
||||||
|
float cosYaw = MathHelper.cos(yawRad);
|
||||||
|
float sinYaw = MathHelper.sin(yawRad);
|
||||||
|
float cosPitch = MathHelper.cos(pitchRad);
|
||||||
|
float sinPitch = MathHelper.sin(pitchRad);
|
||||||
|
return new Vec3d(sinYaw * cosPitch, -sinPitch, cosYaw * cosPitch);
|
||||||
|
}
|
||||||
|
|
||||||
public DefensiveLaserBlockEntity(BlockEntityType<?> type) {
|
public DefensiveLaserBlockEntity(BlockEntityType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
}
|
}
|
||||||
@ -137,51 +126,124 @@ public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
|||||||
public static final double DEG2RAD = Math.PI / 180d;
|
public static final double DEG2RAD = Math.PI / 180d;
|
||||||
private static final double RAD2DEG = 180d / Math.PI;
|
private static final double RAD2DEG = 180d / Math.PI;
|
||||||
|
|
||||||
private float getTargetPitch(double x, double y, double z) {
|
private float getTargetPitch(Vec3d targetPos) {
|
||||||
Vec3d pos = getPosVec();
|
Vec3d pos = getPosVec();
|
||||||
double diffX = x - pos.getX();
|
double diffX = targetPos.getX() - pos.getX();
|
||||||
double diffY = y - pos.getY();
|
double diffY = targetPos.getY() - pos.getY();
|
||||||
double diffZ = z - pos.getZ();
|
double diffZ = targetPos.getZ() - pos.getZ();
|
||||||
double g = MathHelper.sqrt(diffX * diffX + diffZ * diffZ);
|
double g = MathHelper.sqrt(diffX * diffX + diffZ * diffZ);
|
||||||
return (float) -(MathHelper.atan2(diffY, g) * RAD2DEG);
|
return (float) -(MathHelper.atan2(diffY, g) * RAD2DEG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getTargetYaw(double x, double z) {
|
private float getTargetYaw(Vec3d targetPos) {
|
||||||
Vec3d pos = getPosVec();
|
Vec3d pos = getPosVec();
|
||||||
double diffX = x - pos.getX();
|
double diffX = targetPos.getX() - pos.getX();
|
||||||
double diffZ = z - pos.getZ();
|
double diffZ = targetPos.getZ() - pos.getZ();
|
||||||
return (float) (MathHelper.atan2(diffZ, diffX) * RAD2DEG) - 90.0F;
|
return -((float) (MathHelper.atan2(diffZ, diffX) * RAD2DEG) - 90.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int COUNTDOWN = 28;
|
||||||
|
|
||||||
|
private LivingEntity target;
|
||||||
|
private int countdown = 0;
|
||||||
|
|
||||||
|
private boolean firing = false;
|
||||||
|
|
||||||
|
private Predicate<LivingEntity> getTargetPredicate(boolean useCurrentRotation) {
|
||||||
|
return entity -> {
|
||||||
|
if (entity.isAlive() && (!(entity instanceof PlayerEntity) || !((PlayerEntity) entity).isCreative()) && !entity.isInvisible() && entity.getPos().distanceTo(getPosVec()) <= Config.DEFENSIVE_LASER_RANGE) {
|
||||||
|
Vec3d entityPos = entity.getPos();
|
||||||
|
Vec3d start;
|
||||||
|
if (useCurrentRotation) {
|
||||||
|
start = rotation.getRayVector().add(getPosVec());
|
||||||
|
} else {
|
||||||
|
start = getRayVector(getTargetYaw(entityPos), getTargetPitch(entityPos)).add(getPosVec());
|
||||||
|
}
|
||||||
|
HitResult result = entity.getEntityWorld().rayTrace(new RayTraceContext(start, entityPos, RayTraceContext.ShapeType.COLLIDER, RayTraceContext.FluidHandling.ANY, getDummyEntity()));
|
||||||
|
return result.getType() == HitResult.Type.MISS;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<LivingEntity> getEntities(Predicate<LivingEntity> predicate) {
|
||||||
|
return Objects.requireNonNull(getWorld()).getEntities(LivingEntity.class, new Box(getPos()).expand(Config.DEFENSIVE_LASER_RANGE), predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entity getDummyEntity() {
|
||||||
|
Vec3d posVec = getPosVec();
|
||||||
|
return new ItemEntity(getWorld(), posVec.getX(), posVec.getY(), posVec.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tickEnergy() {
|
protected void tickEnergy() {
|
||||||
assert getWorld() != null;
|
assert getWorld() != null;
|
||||||
Vec3d vec = rotation.getRayVector().add(getPosVec());
|
|
||||||
((ServerWorld) getWorld()).spawnParticles(ParticleTypes.END_ROD, vec.getX(), vec.getY(), vec.getZ(), 1, 0, 0, 0, 0);
|
|
||||||
addAction(Action.createBlockStatePropertyAction(Config.DEFENSIVE_LASER_IDLE_ENERGY_REQUIRED, DefensiveLaserBlock.POWERED, true, false));
|
addAction(Action.createBlockStatePropertyAction(Config.DEFENSIVE_LASER_IDLE_ENERGY_REQUIRED, DefensiveLaserBlock.POWERED, true, false));
|
||||||
if (getCachedState().get(DefensiveLaserBlock.POWERED)) {
|
if (getCachedState().get(DefensiveLaserBlock.POWERED)) {
|
||||||
if (countdown > 0) {
|
if (countdown > 0) {
|
||||||
countdown--;
|
countdown--;
|
||||||
}
|
}
|
||||||
if (countdown == 1) {
|
if (countdown == 1) {
|
||||||
// Fire!
|
addAction(new Action(Config.DEFENSIVE_LASER_FIRE_ENERGY_REQUIRED, (world, pos, state) -> {
|
||||||
|
firing = false;
|
||||||
|
|
||||||
|
List<LivingEntity> entities = getEntities(entity -> true);
|
||||||
|
Vec3d posVec = getPosVec();
|
||||||
|
Vec3d collision = null;
|
||||||
|
for (LivingEntity entity : entities) {
|
||||||
|
Optional<Vec3d> optional = entity.getBoundingBox().rayTrace(getPosVec(), getPosVec().add(rotation.getRayVector().multiply(Config.DEFENSIVE_LASER_RANGE)));
|
||||||
|
if (optional.isPresent()) {
|
||||||
|
Vec3d vec = optional.get();
|
||||||
|
if (collision == null || vec.distanceTo(posVec) < collision.distanceTo(posVec)) {
|
||||||
|
collision = optional.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d rotationVec = rotation.getRayVector();
|
||||||
|
Vec3d start = rotationVec.add(posVec);
|
||||||
|
Vec3d end = rotationVec.multiply(Config.DEFENSIVE_LASER_RANGE).add(posVec);
|
||||||
|
HitResult result = world.rayTrace(new RayTraceContext(start, end, RayTraceContext.ShapeType.COLLIDER, RayTraceContext.FluidHandling.ANY, getDummyEntity()));
|
||||||
|
if (result.getType() != HitResult.Type.MISS && (collision == null || result.getPos().distanceTo(posVec) < collision.distanceTo(posVec))) {
|
||||||
|
collision = result.getPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
double distance;
|
||||||
|
if (collision != null) {
|
||||||
|
world.createExplosion(null, collision.getX(), collision.getY(), collision.getZ(), 4, Explosion.DestructionType.NONE);
|
||||||
|
|
||||||
|
distance = posVec.distanceTo(collision);
|
||||||
|
} else {
|
||||||
|
distance = Config.DEFENSIVE_LASER_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
double multiplier = 6d;
|
||||||
|
distance = distance * multiplier;
|
||||||
|
for (int i = 0; i < distance; i++) {
|
||||||
|
Vec3d vec = rotationVec.multiply(i / multiplier).add(posVec);
|
||||||
|
((ServerWorld) getWorld()).spawnParticles(ParticleTypes.END_ROD, vec.getX(), vec.getY(), vec.getZ(), 1, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}, (world, pos, state) -> firing = false));
|
||||||
target = null;
|
target = null;
|
||||||
} else if (countdown < 1) {
|
firing = true;
|
||||||
|
} else if (countdown < 1 && !firing) {
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
List<LivingEntity> entities = getWorld().getEntities(LivingEntity.class, new Box(getPos()).expand(Config.DEFENSIVE_LASER_RANGE), predicate);
|
List<LivingEntity> entities = getEntities(getTargetPredicate(false));
|
||||||
if (entities.size() > 0) {
|
if (entities.size() > 0) {
|
||||||
Collections.shuffle(entities);
|
Vec3d posVec = getPosVec();
|
||||||
|
entities.sort(Comparator.comparingDouble(entity -> entity.getPos().distanceTo(posVec)));
|
||||||
target = entities.get(0);
|
target = entities.get(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (predicate.test(target)) {
|
if (getTargetPredicate(false).test(target)) {
|
||||||
Optional<Vec3d> optional = target.getBoundingBox().rayTrace(getPosVec(), getPosVec().add(rotation.getRayVector().multiply(Config.DEFENSIVE_LASER_RANGE)));
|
Optional<Vec3d> optional = target.getBoundingBox().rayTrace(getPosVec(), getPosVec().add(rotation.getRayVector().multiply(Config.DEFENSIVE_LASER_RANGE)));
|
||||||
if (optional.isPresent()) {
|
if (optional.isPresent() && getTargetPredicate(true).test(target)) {
|
||||||
countdown = COUNTDOWN;
|
countdown = COUNTDOWN;
|
||||||
} else {
|
} else {
|
||||||
Vec3d targetPos = target.getPos();
|
Vec3d targetPos = target.getPos();
|
||||||
float targetYaw = getTargetYaw(targetPos.getX(), targetPos.getZ());
|
float targetYaw = getTargetYaw(targetPos);
|
||||||
float targetPitch = getTargetPitch(targetPos.getX(), targetPos.getY(), targetPos.getZ());
|
float targetPitch = getTargetPitch(targetPos);
|
||||||
rotation.target(targetYaw, targetPitch);
|
rotation.target(targetYaw, targetPitch);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -205,5 +267,6 @@ public class DefensiveLaserBlockEntity extends EnergyReceiverBlockEntity {
|
|||||||
super.fromTag(state, tag);
|
super.fromTag(state, tag);
|
||||||
rotation.fromTag(tag);
|
rotation.fromTag(tag);
|
||||||
countdown = tag.getInt("Countdown");
|
countdown = tag.getInt("Countdown");
|
||||||
|
firing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ import net.minecraft.block.entity.BlockEntity;
|
|||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||||
import net.minecraft.client.render.entity.feature.HeadFeatureRenderer;
|
|
||||||
import net.minecraft.client.render.entity.feature.ShulkerHeadFeatureRenderer;
|
|
||||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.client.util.math.Vector3f;
|
import net.minecraft.client.util.math.Vector3f;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"parent": "minecraft:block/cube_all",
|
"parent": "minecraft:block/cube_all",
|
||||||
"textures": {
|
"textures": {
|
||||||
"all": "energonrelics:block/defensive_laser_base"
|
"all": "energonrelics:block/defensive_laser"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 775 B |
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"#G#",
|
||||||
|
"GLG",
|
||||||
|
"#G#"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"#": {
|
||||||
|
"item": "minecraft:obsidian"
|
||||||
|
},
|
||||||
|
"G": {
|
||||||
|
"item": "minecraft:glass"
|
||||||
|
},
|
||||||
|
"L": {
|
||||||
|
"item": "energonrelics:defensive_laser_core"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "energonrelics:defensive_laser",
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"#I#",
|
||||||
|
"IGI",
|
||||||
|
"#I#"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"#": {
|
||||||
|
"item": "energonrelics:circuit_board"
|
||||||
|
},
|
||||||
|
"I": {
|
||||||
|
"item": "minecraft:gold_ingot"
|
||||||
|
},
|
||||||
|
"G": {
|
||||||
|
"item": "minecraft:gunpowder"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "energonrelics:defensive_laser_core",
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user