MINIONS... TONIGHT WE STEAL THE MOON

This commit is contained in:
craisinlord committed 2026-10-09 17:28:51 -05:00
1 parent 6ee542609d
commit e3b4e50f2b
32 files changed
+765 -321

No files matched your search

@@ -146,6 +146,7 @@ public final class AntarchyConfigCatalog {
|| name.equals("portalGunMinFloorExitSpeed")
|| name.equals("portalGunMaxLiveViews")
|| name.equals("portalGunMaxExitSpeed")
|| name.startsWith("portalGunMoon")
|| name.equals("hushweedSporeLifetimeSeconds")
|| name.equals("elythiaFireflyParticlesEnabled")
|| name.equals("duplicatorTreeEnabled")
@@ -559,6 +559,9 @@ public final class AntarchySettings {
private static double portalGunMinFloorExitSpeed = 0.6D;
private static int portalGunMaxLiveViews = 8;
private static double portalGunMaxExitSpeed = 0.0D;
private static boolean portalGunMoonPullsBlocks = true;
private static int portalGunMoonPortalSeconds = 10;
private static int portalGunMoonBlockCap = 500;
private static boolean elythiaFireflyParticlesEnabled = true;
private static int bloodCrystalArmorShieldRechargeTicks = 600;
private static int bloodCrystalAppleShieldCount = 2;
@@ -1348,6 +1351,18 @@ public final class AntarchySettings {
portalGunMinFloorExitSpeed = Math.max(0.0D, Math.min(4.0D, value));
}
public static void setPortalGunMoonPullsBlocks(boolean value) {
portalGunMoonPullsBlocks = value;
}
public static void setPortalGunMoonPortalSeconds(int value) {
portalGunMoonPortalSeconds = Math.max(1, Math.min(120, value));
}
public static void setPortalGunMoonBlockCap(int value) {
portalGunMoonBlockCap = Math.max(0, Math.min(2000, value));
}
public static void setPortalGunMaxExitSpeed(double value) {
portalGunMaxExitSpeed = Math.max(0.0D, Math.min(100.0D, value));
}
@@ -1367,6 +1382,9 @@ public final class AntarchySettings {
public static double portalGunMinFloorExitSpeed() { return portalGunMinFloorExitSpeed; }
public static int portalGunMaxLiveViews() { return portalGunMaxLiveViews; }
public static double portalGunMaxExitSpeed() { return portalGunMaxExitSpeed; }
public static boolean portalGunMoonPullsBlocks() { return portalGunMoonPullsBlocks; }
public static int portalGunMoonPortalSeconds() { return portalGunMoonPortalSeconds; }
public static int portalGunMoonBlockCap() { return portalGunMoonBlockCap; }
public static void setBrownAntRequiresReagent(boolean value) {
brownAntRequiresReagent = value;
@@ -1,25 +0,0 @@
package com.craisinlord.antarchy.content.client.model;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.model.GeoModel;
public class PortalGunBlackHoleModel extends GeoModel<PortalGunBlackHoleEntity> {
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_black_hole.png");
@Override
public ResourceLocation getModelResource(PortalGunBlackHoleEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/portal_gun_portal.geo.json");
}
@Override
public ResourceLocation getTextureResource(PortalGunBlackHoleEntity animatable) {
return TEXTURE;
}
@Override
public ResourceLocation getAnimationResource(PortalGunBlackHoleEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/portal_gun_portal.animation.json");
}
}
@@ -0,0 +1,61 @@
package com.craisinlord.antarchy.content.client.renderer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import net.minecraft.client.renderer.LevelRenderer;
final class IrisPortalSceneCompat {
private static final Field PIPELINE_FIELD;
private static final Method GET_PIPELINE_MANAGER;
private static final Method GET_PIPELINE;
static {
Field field = null;
Method manager = null;
Method pipeline = null;
try {
Class<?> iris = Class.forName("net.irisshaders.iris.Iris");
manager = iris.getMethod("getPipelineManager");
pipeline = manager.getReturnType().getMethod("getPipelineNullable");
field = LevelRenderer.class.getDeclaredField("pipeline");
field.setAccessible(true);
} catch (ReflectiveOperationException | RuntimeException | LinkageError ignored) {
field = null;
}
PIPELINE_FIELD = field;
GET_PIPELINE_MANAGER = field == null ? null : manager;
GET_PIPELINE = field == null ? null : pipeline;
}
private IrisPortalSceneCompat() {
}
static boolean begin(LevelRenderer renderer) {
if (PIPELINE_FIELD == null) {
return false;
}
try {
if (PIPELINE_FIELD.get(renderer) != null) {
return false;
}
Object pipeline = GET_PIPELINE.invoke(GET_PIPELINE_MANAGER.invoke(null));
if (pipeline == null) {
return false;
}
PIPELINE_FIELD.set(renderer, pipeline);
return true;
} catch (ReflectiveOperationException | RuntimeException ignored) {
return false;
}
}
static void end(LevelRenderer renderer, boolean installed) {
if (!installed) {
return;
}
try {
PIPELINE_FIELD.set(renderer, null);
} catch (ReflectiveOperationException | RuntimeException ignored) {
}
}
}
@@ -1,28 +0,0 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.model.PortalGunBlackHoleModel;
import com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class PortalGunBlackHoleRenderer extends GeoEntityRenderer<PortalGunBlackHoleEntity> {
public PortalGunBlackHoleRenderer(EntityRendererProvider.Context context) {
super(context, new PortalGunBlackHoleModel());
this.shadowRadius = 0.0F;
}
@Override
public void render(PortalGunBlackHoleEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) {
super.render(entity, entityYaw, partialTick, poseStack, bufferSource, 0xF000F0);
}
@Override
public @Nullable RenderType getRenderType(PortalGunBlackHoleEntity animatable, ResourceLocation texture, @Nullable MultiBufferSource bufferSource, float partialTick) {
return RenderType.entityTranslucent(this.getTextureLocation(animatable));
}
}
@@ -0,0 +1,216 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferUploader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexSorting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
import org.joml.Matrix4fStack;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;
public final class PortalGunMoonViewRenderer {
private static final ResourceLocation EARTH = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/environment/moon_view/earth.png");
private static final double SKY_DISTANCE = 100.0D;
private static final double EARTH_HALF_SIZE = 32.0D;
private static final double EARTH_PLANET_FRACTION = 0.5D;
private static final double EARTH_ELEVATION = Math.toRadians(10.0D);
private static final int STAR_COUNT = 1800;
private static final Vec3 EXIT_NORMAL = new Vec3(0.0D, 0.0D, 1.0D);
private static final Vec3 EXIT_UP = new Vec3(0.0D, 1.0D, 0.0D);
private static float[] stars;
private PortalGunMoonViewRenderer() {
}
public static void render(Minecraft minecraft, PortalGunWorldPortalShape source, Vec3 cameraPos, Vec3 look, Vec3 up,
Matrix4f rootProjection, float partialTick) {
PortalGunWorldPortalShape exit = new PortalGunWorldPortalShape(Vec3.ZERO, EXIT_NORMAL, EXIT_UP, EXIT_NORMAL.cross(EXIT_UP),
source.halfWidth(), source.halfHeight(), source.halfDepth());
Vec3 moonLook = PortalGunTransformUtil.transformVector(source, exit, look).normalize();
Vec3 moonUp = PortalGunTransformUtil.transformVector(source, exit, up).normalize();
Matrix4f view = new Matrix4f().rotation(PortalGunTransformUtil.orientationQuaternion(moonLook, moonUp).conjugate(new Quaternionf()));
Vec3 earthDirection = new Vec3(0.0D, Math.sin(EARTH_ELEVATION), Math.cos(EARTH_ELEVATION));
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
Matrix4f previousProjection = new Matrix4f(RenderSystem.getProjectionMatrix());
VertexSorting previousSorting = RenderSystem.getVertexSorting();
int previousDepthFunction = GL11.glGetInteger(GL11.GL_DEPTH_FUNC);
modelViewStack.pushMatrix();
try {
fillBlack();
RenderSystem.disableCull();
RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
modelViewStack.identity();
modelViewStack.mul(view);
RenderSystem.applyModelViewMatrix();
RenderSystem.setProjectionMatrix(rootProjection, VertexSorting.DISTANCE_TO_ORIGIN);
drawStars();
drawEarth(earthDirection);
} finally {
GL11.glDepthFunc(previousDepthFunction);
RenderSystem.setProjectionMatrix(previousProjection, previousSorting);
modelViewStack.popMatrix();
RenderSystem.applyModelViewMatrix();
RenderSystem.defaultBlendFunc();
RenderSystem.disableBlend();
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
}
}
private static void fillBlack() {
Matrix4f previousProjection = new Matrix4f(RenderSystem.getProjectionMatrix());
VertexSorting previousSorting = RenderSystem.getVertexSorting();
BufferBuilder buffer = Tesselator.getInstance().begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION);
buffer.addVertex(-1.0F, -1.0F, 0.99999F);
buffer.addVertex(3.0F, -1.0F, 0.99999F);
buffer.addVertex(-1.0F, 3.0F, 0.99999F);
MeshData mesh = buffer.build();
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
modelViewStack.pushMatrix();
try {
modelViewStack.identity();
RenderSystem.applyModelViewMatrix();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
RenderSystem.colorMask(true, true, true, true);
RenderSystem.disableBlend();
RenderSystem.disableCull();
GL11.glDepthFunc(GL11.GL_ALWAYS);
RenderSystem.setProjectionMatrix(new Matrix4f(), previousSorting);
RenderSystem.setShader(GameRenderer::getPositionShader);
RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
if (mesh != null) {
BufferUploader.drawWithShader(mesh);
}
} finally {
GL11.glDepthFunc(GL11.GL_LEQUAL);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setProjectionMatrix(previousProjection, previousSorting);
modelViewStack.popMatrix();
RenderSystem.applyModelViewMatrix();
}
}
private static float[] stars() {
if (stars == null) {
RandomSource random = RandomSource.create(7342L);
float[] data = new float[STAR_COUNT * 5];
int count = 0;
while (count < STAR_COUNT) {
Vector3f direction = new Vector3f(random.nextFloat() * 2.0F - 1.0F, random.nextFloat() * 2.0F - 1.0F, random.nextFloat() * 2.0F - 1.0F);
float lengthSquared = direction.lengthSquared();
if (lengthSquared < 1.0E-4F || lengthSquared > 1.0F) {
continue;
}
direction.normalize();
data[count * 5] = direction.x;
data[count * 5 + 1] = direction.y;
data[count * 5 + 2] = direction.z;
data[count * 5 + 3] = 0.12F + random.nextFloat() * 0.22F;
data[count * 5 + 4] = 0.35F + random.nextFloat() * 0.65F;
count++;
}
stars = data;
}
return stars;
}
private static void drawStars() {
float[] data = stars();
BufferBuilder buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
for (int i = 0; i < STAR_COUNT; i++) {
Vec3 direction = new Vec3(data[i * 5], data[i * 5 + 1], data[i * 5 + 2]);
double size = data[i * 5 + 3];
int brightness = (int) (255.0F * data[i * 5 + 4]);
Vec3[] basis = basis(direction);
Vec3 center = direction.scale(SKY_DISTANCE);
Vec3 right = basis[0].scale(size);
Vec3 upward = basis[1].scale(size);
addColored(buffer, center.subtract(right).subtract(upward), brightness);
addColored(buffer, center.subtract(right).add(upward), brightness);
addColored(buffer, center.add(right).add(upward), brightness);
addColored(buffer, center.add(right).subtract(upward), brightness);
}
MeshData mesh = buffer.build();
if (mesh == null) {
return;
}
RenderSystem.disableBlend();
RenderSystem.setShader(GameRenderer::getPositionColorShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
BufferUploader.drawWithShader(mesh);
}
private static void drawEarth(Vec3 earthDirection) {
Vec3[] basis = basis(earthDirection);
Vec3 center = earthDirection.scale(SKY_DISTANCE);
Vec3 right = basis[0];
Vec3 upward = basis[1];
double planet = EARTH_HALF_SIZE * EARTH_PLANET_FRACTION;
BufferBuilder backing = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
addColored(backing, center.subtract(right.scale(planet)).subtract(upward.scale(planet)), 0);
addColored(backing, center.subtract(right.scale(planet)).add(upward.scale(planet)), 0);
addColored(backing, center.add(right.scale(planet)).add(upward.scale(planet)), 0);
addColored(backing, center.add(right.scale(planet)).subtract(upward.scale(planet)), 0);
MeshData backingMesh = backing.build();
if (backingMesh != null) {
RenderSystem.disableBlend();
RenderSystem.setShader(GameRenderer::getPositionColorShader);
BufferUploader.drawWithShader(backingMesh);
}
BufferBuilder buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
addTextured(buffer, center.subtract(right.scale(EARTH_HALF_SIZE)).subtract(upward.scale(EARTH_HALF_SIZE)), 0.0F, 1.0F);
addTextured(buffer, center.subtract(right.scale(EARTH_HALF_SIZE)).add(upward.scale(EARTH_HALF_SIZE)), 0.0F, 0.0F);
addTextured(buffer, center.add(right.scale(EARTH_HALF_SIZE)).add(upward.scale(EARTH_HALF_SIZE)), 1.0F, 0.0F);
addTextured(buffer, center.add(right.scale(EARTH_HALF_SIZE)).subtract(upward.scale(EARTH_HALF_SIZE)), 1.0F, 1.0F);
MeshData mesh = buffer.build();
if (mesh == null) {
return;
}
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE,
GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, EARTH);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
BufferUploader.drawWithShader(mesh);
RenderSystem.defaultBlendFunc();
RenderSystem.disableBlend();
}
private static Vec3[] basis(Vec3 direction) {
Vec3 reference = Math.abs(direction.y) > 0.9D ? new Vec3(1.0D, 0.0D, 0.0D) : EXIT_UP;
Vec3 right = direction.cross(reference).normalize();
Vec3 upward = right.cross(direction).normalize();
return new Vec3[] {right, upward};
}
private static void addColored(BufferBuilder buffer, Vec3 position, int brightness) {
buffer.addVertex((float) position.x, (float) position.y, (float) position.z).setColor(brightness, brightness, brightness, 255);
}
private static void addTextured(BufferBuilder buffer, Vec3 position, float u, float v) {
buffer.addVertex((float) position.x, (float) position.y, (float) position.z).setUv(u, v);
}
}
@@ -75,6 +75,7 @@ public final class PortalGunPortalSceneRenderer {
modelViewStack.identity();
RenderSystem.applyModelViewMatrix();
renderingScene = true;
boolean irisPipelineInstalled = IrisPortalSceneCompat.begin(renderer);
terrain.begin(minecraft);
try {
float renderDistance = minecraft.gameRenderer.getRenderDistance();
@@ -166,6 +167,7 @@ public final class PortalGunPortalSceneRenderer {
}
} finally {
renderingScene = false;
IrisPortalSceneCompat.end(renderer, irisPipelineInstalled);
terrain.end(minecraft);
state.antarchy$setRainSoundTime(previousRainSoundTime);
modelViewStack.popMatrix();
@@ -130,8 +130,9 @@ public final class PortalGunPortalViewRenderer {
}
List<RootCandidate> candidates = new ArrayList<>();
for (PortalGunPortalEntity portal : portals) {
PortalGunPortalEntity linked = portal.getLinkedPortal();
if (linked == null || !linked.isAlive() || !portal.shouldRenderFront(cameraPos)) {
boolean moon = portal.isMoonPortal();
PortalGunPortalEntity linked = moon ? null : portal.getLinkedPortal();
if (!moon && (linked == null || !linked.isAlive()) || !portal.shouldRenderFront(cameraPos)) {
continue;
}
ScreenClip clip = computeScreenClip(cameraPos, rootViewMatrix, rootProjection, portal, partialTick, width, height);
@@ -173,7 +174,13 @@ public final class PortalGunPortalViewRenderer {
break;
}
try {
if (candidate.linked() == null) {
if (directStencil) {
renderMoonViewDirect(minecraft, partialTick, rootContext, rootProjection, candidate.portal(), candidate.clip());
} else {
renderMoonViewOffscreen(minecraft, partialTick, rootContext, rootProjection, candidate.portal(), candidate.clip());
}
} else if (directStencil) {
renderViewDirect(minecraft, cameraEntity, partialTick, rootContext, rootProjection, rootProjection,
candidate.portal(), candidate.linked(), 0, candidate.clip(), null, budget);
} else {
@@ -259,6 +266,48 @@ public final class PortalGunPortalViewRenderer {
}
}
private static void renderMoonViewDirect(Minecraft minecraft, float partialTick, RenderContext context,
Matrix4f rootProjection, PortalGunPortalEntity source, ScreenClip clip) {
PortalStencilTarget.pushAperture(0, () -> drawPortalMask(context.cameraPos(), context.viewMatrix(), rootProjection, source, partialTick));
try {
RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height());
PortalGunMoonViewRenderer.render(minecraft, source.getWorldPortalShape(), context.cameraPos(), context.look(), context.up(),
rootProjection, partialTick);
} finally {
try {
PortalStencilTarget.drawInside(1);
PortalGunPortalRim.drawOverView(source, context.cameraPos(), context.viewMatrix(), rootProjection, partialTick);
} finally {
PortalStencilTarget.popAperture(0,
() -> restorePortalApertureDepth(context.cameraPos(), context.viewMatrix(), rootProjection, source, partialTick));
RenderSystem.disableScissor();
}
}
}
private static void renderMoonViewOffscreen(Minecraft minecraft, float partialTick, RenderContext context,
Matrix4f rootProjection, PortalGunPortalEntity source, ScreenClip clip) {
RenderTarget mainTarget = minecraft.getMainRenderTarget();
TextureTarget target = ensureOffscreenTarget(mainTarget.width, mainTarget.height);
MinecraftMainRenderTargetAccessor targetAccessor = (MinecraftMainRenderTargetAccessor) minecraft;
targetAccessor.antarchy$setMainRenderTarget(target);
try {
target.bindWrite(true);
RenderSystem.disableScissor();
target.clear(Minecraft.ON_OSX);
target.bindWrite(true);
RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height());
PortalGunMoonViewRenderer.render(minecraft, source.getWorldPortalShape(), context.cameraPos(), context.look(), context.up(),
rootProjection, partialTick);
} finally {
RenderSystem.disableScissor();
targetAccessor.antarchy$setMainRenderTarget(mainTarget);
mainTarget.bindWrite(true);
}
RenderSystem.setProjectionMatrix(rootProjection, VertexSorting.DISTANCE_TO_ORIGIN);
drawPortalComposite(context.cameraPos(), context.viewMatrix(), rootProjection, source, partialTick, target.getColorTextureId());
}
private static void renderNestedViews(Minecraft minecraft, Entity cameraEntity, float partialTick, RenderContext viewContext,
Matrix4f rootProjection, Matrix4f viewProjection, PortalGunPortalEntity exit,
int level, ScreenClip viewClip, ViewBudget budget, int width, int height) {
@@ -153,6 +153,16 @@ public final class AntarchyDamageSources {
);
}
public static DamageSource moonVacuum(ServerLevel level, @Nullable Entity causingEntity) {
return new DamageSource(
level.registryAccess()
.registryOrThrow(Registries.DAMAGE_TYPE)
.getHolderOrThrow(AntarchyDamageTypes.MOON_VACUUM),
null,
causingEntity
);
}
private AntarchyDamageSources() {
}
}
@@ -103,6 +103,12 @@ public final class AntarchyDamageTypes {
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hercules_beetle_obliteration")
);
public static final ResourceKey<DamageType> MOON_VACUUM =
ResourceKey.create(
Registries.DAMAGE_TYPE,
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moon_vacuum")
);
private AntarchyDamageTypes() {
}
}
@@ -0,0 +1,40 @@
package com.craisinlord.antarchy.content.entity;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
public final class BlockSuction {
private static final float MAX_EXPLOSION_RESISTANCE = 30.0F;
private BlockSuction() {
}
public static boolean canLift(ServerLevel level, BlockPos pos, BlockState state) {
return canLift(level, pos, state, false);
}
public static boolean canLift(ServerLevel level, BlockPos pos, BlockState state, boolean allowCollisionless) {
return !state.isAir()
&& level.getBlockEntity(pos) == null
&& state.getDestroySpeed(level, pos) >= 0.0F
&& state.getBlock().getExplosionResistance() <= MAX_EXPLOSION_RESISTANCE
&& (allowCollisionless ? state.getFluidState().isEmpty() : !state.getCollisionShape(level, pos).isEmpty());
}
public static FallingBlockEntity lift(ServerLevel level, BlockPos pos, BlockState state, Vec3 target, double speed) {
FallingBlockEntity falling = FallingBlockEntity.fall(level, pos, state);
if (falling == null) {
return null;
}
Vec3 towardTarget = target.subtract(falling.position());
if (towardTarget.lengthSqr() > 0.001D) {
falling.setDeltaMovement(towardTarget.normalize().scale(speed));
}
falling.hasImpulse = true;
falling.hurtMarked = true;
return falling;
}
}
@@ -4,6 +4,7 @@ import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.time.TimeDilationApi;
import com.craisinlord.antarchy.content.time.TimeDilationFieldEntity;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.entity.BlockSuction;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
@@ -337,23 +338,10 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
}
BlockState state = level.getBlockState(pos);
if (state.isAir() || level.getBlockEntity(pos) != null
|| state.getDestroySpeed(level, pos) < 0.0F
|| state.getBlock().getExplosionResistance() > 30.0F
|| state.getCollisionShape(level, pos).isEmpty()) {
if (!BlockSuction.canLift(level, pos, state)
|| BlockSuction.lift(level, pos, state, center, 0.28D) == null) {
continue;
}
FallingBlockEntity falling = FallingBlockEntity.fall(level, pos, state);
if (falling == null) {
continue;
}
Vec3 towardCenter = center.subtract(falling.position());
if (towardCenter.lengthSqr() > 0.001D) {
falling.setDeltaMovement(towardCenter.normalize().scale(0.28D));
}
falling.hasImpulse = true;
falling.hurtMarked = true;
pulledThisTick++;
this.suckedBlocks++;
}
@@ -9,8 +9,8 @@ import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload;
import com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunPlacement;
import com.craisinlord.antarchy.content.portalgun.PortalGunMoonMath;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunSavedData;
@@ -82,7 +82,6 @@ public class PortalGunItem extends Item implements GeoItem {
private static final ResourceLocation MODEL_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/portal_gun.geo.json");
private static final ResourceLocation ANIMATION_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/portal_gun.animation.json");
private final Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType;
private final Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType;
private final Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType;
private final Supplier<? extends Block> portalMasterBlock;
private final Supplier<? extends Block> portalBaseBlock;
@@ -92,7 +91,6 @@ public class PortalGunItem extends Item implements GeoItem {
public PortalGunItem(
Item.Properties properties,
Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType,
Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType,
Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType,
Supplier<? extends Block> portalMasterBlock,
Supplier<? extends Block> portalBaseBlock,
@@ -101,7 +99,6 @@ public class PortalGunItem extends Item implements GeoItem {
super(properties);
this.variant = variant;
this.portalType = portalType;
this.blackHoleType = blackHoleType;
this.projectileType = projectileType;
this.portalMasterBlock = portalMasterBlock;
this.portalBaseBlock = portalBaseBlock;
@@ -218,9 +215,9 @@ public class PortalGunItem extends Item implements GeoItem {
if (this.isMoonSideArmed(stack, side)) {
this.setMoonSide(stack, null);
}
if (shooter instanceof Player player && this.isMoonSideArmed(stack, this.otherSide(side))) {
this.spawnBlackHole(level, player, stack, side, placement.center());
return;
boolean moon = shooter instanceof Player && this.isMoonSideArmed(stack, this.otherSide(side));
if (moon) {
this.setMoonSide(stack, null);
}
PortalGunPortalEntity portal = new PortalGunPortalEntity(this.portalType.get(), level);
portal.configure(portalOwnerId, gunId, this.variant, side, placement);
@@ -230,9 +227,16 @@ public class PortalGunItem extends Item implements GeoItem {
level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface"), SoundSource.PLAYERS, 0.55F, 1.0F);
return;
}
if (moon) {
portal.openToMoon();
}
level.addFreshEntity(portal);
PortalGunSavedData.setPortal(level, gunId, portalOwnerId, side, portal.getUUID());
PortalGunPortalEntity other = this.findCounterpart(level, gunId, side);
if (other != null && (moon || other.isMoonPortal())) {
other.discard();
other = null;
}
if (other != null) {
portal.linkTo(other);
other.linkTo(portal);
@@ -277,14 +281,21 @@ public class PortalGunItem extends Item implements GeoItem {
}
private boolean tryArmMoonShot(ServerLevel level, Player player, ItemStack stack, PortalGunPortalEntity.PortalSide side, boolean offhand) {
if (!level.dimensionType().hasSkyLight() || !level.isNight() || player.getXRot() > -40.0F) {
if (!this.isAimingAtMoon(level, player)) {
return false;
}
PortalGunPortalEntity existing = this.findPlacedPortal(level, this.ensureGunId(stack, player.getUUID()), side);
UUID gunId = this.ensureGunId(stack, player.getUUID());
PortalGunPortalEntity existing = this.findPlacedPortal(level, gunId, side);
if (existing != null) {
existing.discard();
}
PortalGunPortalEntity counterpart = this.findPlacedPortal(level, gunId, this.otherSide(side));
if (counterpart != null && counterpart.isAlive() && !counterpart.isMoonPortal()) {
counterpart.openToMoon();
this.setMoonSide(stack, null);
} else {
this.setMoonSide(stack, side);
}
this.setLastSide(stack, side);
this.triggerFireAnimation(level, player, stack);
if (this.damageGun(level, player, stack, offhand)) {
@@ -297,14 +308,11 @@ public class PortalGunItem extends Item implements GeoItem {
return true;
}
private boolean spawnBlackHole(ServerLevel level, Player player, ItemStack stack, PortalGunPortalEntity.PortalSide side, Vec3 spawnPos) {
this.setMoonSide(stack, null);
PortalGunBlackHoleEntity blackHole = new PortalGunBlackHoleEntity(this.blackHoleType.get(), level);
blackHole.configure(player.getUUID());
blackHole.moveTo(spawnPos.x, spawnPos.y, spawnPos.z, 0.0F, 0.0F);
level.addFreshEntity(blackHole);
level.playSound(null, spawnPos.x, spawnPos.y, spawnPos.z, PortalGunPortalEntity.sound("portal_open_orange"), SoundSource.PLAYERS, 0.6F, 0.6F);
return true;
private boolean isAimingAtMoon(ServerLevel level, Player player) {
if (!level.dimensionType().hasSkyLight() || level.dimensionType().hasCeiling()) {
return false;
}
return PortalGunMoonMath.isAimedAtMoon(this.worldLook(player), level.getTimeOfDay(1.0F));
}
private void spawnShotTrail(ServerLevel level, Player player, Vec3 endPos, PortalGunPortalEntity.PortalSide side) {
@@ -652,12 +660,21 @@ public class PortalGunItem extends Item implements GeoItem {
}
private boolean isMoonSideArmed(ItemStack stack, PortalGunPortalEntity.PortalSide side) {
return side == getMoonSide(stack);
}
public static PortalGunPortalEntity.PortalSide getMoonSide(ItemStack stack) {
net.minecraft.world.item.component.CustomData customData = stack.get(DataComponents.CUSTOM_DATA);
if (customData == null) {
return false;
return null;
}
String sideName = customData.copyTag().getString(MOON_SIDE_TAG);
return side.name().equals(sideName);
for (PortalGunPortalEntity.PortalSide side : PortalGunPortalEntity.PortalSide.values()) {
if (side.name().equals(sideName)) {
return side;
}
}
return null;
}
public static UUID getGunId(ItemStack stack) {
@@ -1,196 +0,0 @@
package com.craisinlord.antarchy.content.portalgun;
import java.util.List;
import java.util.UUID;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.animation.AnimationController;
import software.bernie.geckolib.animation.AnimationState;
import software.bernie.geckolib.animation.PlayState;
import software.bernie.geckolib.animation.RawAnimation;
import software.bernie.geckolib.util.GeckoLibUtil;
public class PortalGunBlackHoleEntity extends Entity implements GeoEntity {
private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open");
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation CLOSE_ANIM = RawAnimation.begin().thenPlay("close");
private static final int OPEN_TICKS = 10;
private static final int CLOSE_TICKS = 12;
private static final int LIFETIME_TICKS = 20 * 12;
private static final double PULL_RADIUS = 6.0D;
private static final double CONSUME_RADIUS = 0.6D;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private UUID ownerId;
private int ageTicks;
private boolean closing;
public PortalGunBlackHoleEntity(EntityType<? extends PortalGunBlackHoleEntity> entityType, Level level) {
super(entityType, level);
this.setInvulnerable(true);
this.noPhysics = true;
this.noCulling = true;
}
@Override
protected void defineSynchedData(net.minecraft.network.syncher.SynchedEntityData.Builder builder) {
}
public void configure(UUID ownerId) {
this.ownerId = ownerId;
}
@Override
public void tick() {
super.tick();
this.ageTicks++;
this.setYRot(this.getYRot() + 6.0F);
if (this.level().isClientSide) {
return;
}
if (!(this.level() instanceof ServerLevel serverLevel)) {
return;
}
if (this.ageTicks >= LIFETIME_TICKS - CLOSE_TICKS) {
this.closing = true;
}
if (this.ageTicks >= LIFETIME_TICKS) {
this.discard();
return;
}
this.pullNearby(serverLevel);
if (this.ageTicks % 10 == 0) {
serverLevel.playSound(null, this.blockPosition(), PortalGunPortalEntity.sound("portal_ambient"), SoundSource.HOSTILE, 0.5F, 0.6F);
}
}
private void pullNearby(ServerLevel level) {
AABB pullBox = this.getBoundingBox().inflate(PULL_RADIUS);
List<Entity> nearby = level.getEntities(this, pullBox, this::canAffect);
for (Entity entity : nearby) {
Vec3 toCenter = this.position().subtract(entity.position());
double distance = toCenter.length();
if (distance < 1.0E-4D) {
continue;
}
if (distance <= CONSUME_RADIUS) {
this.consume(entity);
continue;
}
double strength = 0.09D * (1.0D - Math.min(distance / PULL_RADIUS, 1.0D)) + 0.02D;
Vec3 pull = toCenter.normalize().scale(strength);
entity.setDeltaMovement(entity.getDeltaMovement().add(pull));
entity.hasImpulse = true;
entity.fallDistance = 0.0F;
}
}
private boolean canAffect(Entity entity) {
if (!entity.isAlive() || entity instanceof PortalGunPortalEntity || entity instanceof PortalGunBlackHoleEntity) {
return false;
}
if (entity instanceof Player player && player.isCreative()) {
return false;
}
return entity instanceof ItemEntity || entity instanceof LivingEntity;
}
private void consume(Entity entity) {
if (entity instanceof ItemEntity itemEntity) {
itemEntity.discard();
} else if (entity instanceof Player) {
entity.teleportTo(this.getX(), this.getY(), this.getZ());
entity.setDeltaMovement(Vec3.ZERO);
} else if (entity instanceof LivingEntity living) {
living.hurt(this.damageSources().magic(), 4.0F);
entity.setDeltaMovement(entity.getDeltaMovement().scale(0.1D));
}
}
@Override
public AABB getBoundingBoxForCulling() {
return this.getBoundingBox().inflate(2.0D);
}
@Override
protected AABB makeBoundingBox() {
return new AABB(this.getX() - 0.6D, this.getY() - 0.6D, this.getZ() - 0.6D, this.getX() + 0.6D, this.getY() + 0.6D, this.getZ() + 0.6D);
}
@Override
public void addAdditionalSaveData(CompoundTag tag) {
if (this.ownerId != null) {
tag.putUUID("OwnerId", this.ownerId);
}
tag.putInt("AgeTicks", this.ageTicks);
}
@Override
public void readAdditionalSaveData(CompoundTag tag) {
if (tag.hasUUID("OwnerId")) {
this.ownerId = tag.getUUID("OwnerId");
}
this.ageTicks = tag.getInt("AgeTicks");
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return true;
}
@Override
public boolean fireImmune() {
return true;
}
@Override
public void lavaHurt() {
}
@Override
public boolean isPushable() {
return false;
}
@Override
public boolean canBeCollidedWith() {
return false;
}
@Override
public boolean isPickable() {
return false;
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController<>(this, "black_hole_controller", 0, this::blackHoleController));
}
private PlayState blackHoleController(AnimationState<PortalGunBlackHoleEntity> state) {
if (this.closing) {
return state.setAndContinue(CLOSE_ANIM);
}
if (this.ageTicks < OPEN_TICKS) {
return state.setAndContinue(OPEN_ANIM);
}
return state.setAndContinue(IDLE_ANIM);
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
}
@@ -3,8 +3,10 @@ package com.craisinlord.antarchy.content.portalgun;
import com.craisinlord.antarchy.content.item.PortalGunItem;
import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload;
import com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload;
import java.util.Optional;
import java.util.UUID;
import java.util.function.BiConsumer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
@@ -27,18 +29,26 @@ public final class PortalGunIndicatorSync {
if (stack.isEmpty()) {
return;
}
boolean blue = PortalGunSavedData.getPortalId(
player.serverLevel().getServer(),
request.gunId(),
PortalGunPortalEntity.PortalSide.BLUE,
player.serverLevel().dimension().location()
).isPresent();
boolean orange = PortalGunSavedData.getPortalId(
player.serverLevel().getServer(),
request.gunId(),
PortalGunPortalEntity.PortalSide.ORANGE,
player.serverLevel().dimension().location()
).isPresent();
ServerLevel level = player.serverLevel();
Optional<UUID> blueId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.BLUE);
Optional<UUID> orangeId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.ORANGE);
PortalGunPortalEntity.PortalSide moonSide = PortalGunItem.getMoonSide(stack);
boolean blue = blueId.isPresent()
|| moonSide == PortalGunPortalEntity.PortalSide.BLUE
|| isMoonPortal(level, orangeId);
boolean orange = orangeId.isPresent()
|| moonSide == PortalGunPortalEntity.PortalSide.ORANGE
|| isMoonPortal(level, blueId);
sender.accept(player, new PortalGunIndicatorPayload(request.gunId(), blue, orange));
}
private static Optional<UUID> portalId(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) {
return PortalGunSavedData.getPortalId(level.getServer(), gunId, side, level.dimension().location());
}
private static boolean isMoonPortal(ServerLevel level, Optional<UUID> portalId) {
return portalId.isPresent()
&& level.getEntity(portalId.get()) instanceof PortalGunPortalEntity portal
&& portal.isMoonPortal();
}
}
@@ -0,0 +1,22 @@
package com.craisinlord.antarchy.content.portalgun;
import net.minecraft.world.phys.Vec3;
public final class PortalGunMoonMath {
public static final double AIM_TOLERANCE_DEGREES = 12.0D;
private static final double AIM_COSINE = Math.cos(Math.toRadians(AIM_TOLERANCE_DEGREES));
private static final double MIN_MOON_HEIGHT = 0.05D;
private PortalGunMoonMath() {
}
public static Vec3 moonDirection(double timeOfDay) {
double angle = timeOfDay * Math.PI * 2.0D;
return new Vec3(Math.sin(angle), -Math.cos(angle), 0.0D);
}
public static boolean isAimedAtMoon(Vec3 look, double timeOfDay) {
Vec3 moon = moonDirection(timeOfDay);
return moon.y > MIN_MOON_HEIGHT && look.normalize().dot(moon) >= AIM_COSINE;
}
}
@@ -7,6 +7,8 @@ import com.craisinlord.antarchy.content.block.entity.PortalGunPortalBaseBlockEnt
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalCellAccess;
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord;
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalMasterBlockEntity;
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
import com.craisinlord.antarchy.content.entity.BlockSuction;
import com.craisinlord.antarchy.mixins.AbstractArrowAccessor;
import com.craisinlord.antarchy.mixins.FallingBlockEntityAccessor;
import com.craisinlord.antarchy.mixins.ServerGamePacketListenerTeleportAccessor;
@@ -23,6 +25,8 @@ import java.util.Set;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
@@ -37,10 +41,15 @@ import net.minecraft.util.Mth;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.item.PrimedTnt;
import net.minecraft.world.entity.vehicle.VehicleEntity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
@@ -78,6 +87,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private static final EntityDataAccessor<Integer> PORTAL_WIDTH = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> PORTAL_HEIGHT = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> OPENING_ANIMATION_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Boolean> MOON = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.BOOLEAN);
private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open");
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final int OPEN_TICKS = 5;
@@ -88,6 +98,20 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private static final double MAX_CLIENT_TRANSIT_START_ERROR_SQR = 1.0D;
private static final double MAX_CLIENT_TRANSIT_MOVEMENT_SQR = 100.0D;
private static final double PROJECTILE_PLANE_TOLERANCE = 0.1D;
private static final double MOON_RANGE = 14.0D;
private static final double MOON_SPREAD = 0.9D;
private static final double MOON_PULL_STRENGTH = 0.15D;
private static final double MOON_MAX_SPEED = 1.8D;
private static final double MOON_MOUTH_DEPTH = 0.9D;
private static final double MOON_HOLD_DEPTH = 0.65D;
private static final int MOON_BLOCK_INTERVAL = 1;
private static final int MOON_BLOCKS_PER_PULL = 4;
private static final int MOON_BLOCK_RAYS = 16;
private static final double MOON_RAY_STEP = 0.4D;
private static final double MOON_BLOCK_SPEED = 0.6D;
private static final int MOON_VACUUM_INTERVAL = 10;
private static final float MOON_VACUUM_DAMAGE = 2.0F;
private static final int MOON_WIND_INTERVAL = 40;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private final Map<UUID, Integer> teleportCooldowns = new HashMap<>();
private UUID ownerId;
@@ -96,6 +120,8 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private int ageTicks;
private int lastOpeningAnimationId;
private int pairTime;
private int moonTicks;
private int moonSuckedBlocks;
private BlockPos supportOrigin = BlockPos.ZERO;
private BlockPos masterPos = BlockPos.ZERO;
private BlockPos basePos = BlockPos.ZERO;
@@ -128,6 +154,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
builder.define(PORTAL_WIDTH, 1);
builder.define(PORTAL_HEIGHT, 2);
builder.define(OPENING_ANIMATION_ID, 0);
builder.define(MOON, false);
}
public void configure(UUID ownerId, UUID gunId, PortalGunVariant variant, PortalSide side, PortalGunPlacement placement) {
@@ -162,6 +189,19 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.pairTime = pairTime;
}
public void openToMoon() {
this.linkedPortalId = null;
this.entityData.set(LINKED_PORTAL, Optional.empty());
this.entityData.set(LINKED_PORTAL_ENTITY_ID, -1);
this.entityData.set(MOON, true);
this.moonTicks = 0;
this.moonSuckedBlocks = 0;
}
public boolean isMoonPortal() {
return this.entityData.get(MOON);
}
public PortalSide getPortalSide() {
int ordinal = this.entityData.get(SIDE);
return ordinal == PortalSide.ORANGE.ordinal() ? PortalSide.ORANGE : PortalSide.BLUE;
@@ -572,6 +612,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
if (this.level().isClientSide) {
if (this.isMoonPortal()) {
this.spawnMoonParticles();
}
return;
}
if (!(this.level() instanceof ServerLevel serverLevel)) {
@@ -586,6 +629,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.discard();
return;
}
if (this.isMoonPortal()) {
this.tickMoon(serverLevel);
return;
}
PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel);
if (linked == null || !linked.isAlive()) {
if (Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY) && this.ageTicks % 40 == 0) {
@@ -603,6 +650,189 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.tickTeleport(linked);
}
private void tickMoon(ServerLevel level) {
this.moonTicks++;
if (this.moonTicks >= AntarchySettings.portalGunMoonPortalSeconds() * 20) {
level.playSound(null, this.getX(), this.getY(), this.getZ(), sound("portal_fizzle"), SoundSource.BLOCKS, 1.0F, 0.6F);
this.discard();
return;
}
if (this.moonTicks % MOON_WIND_INTERVAL == 1) {
level.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ELYTRA_FLYING, SoundSource.BLOCKS, 1.4F, 0.55F);
}
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
Player owner = this.getOwnerId() == null ? null : level.getPlayerByUUID(this.getOwnerId());
this.pullMoonEntities(level, shape, owner);
if (AntarchySettings.portalGunMoonPullsBlocks() && this.moonTicks % MOON_BLOCK_INTERVAL == 0) {
this.pullMoonBlocks(level, shape, owner);
}
}
private static double moonLateralLimit(PortalGunWorldPortalShape shape, double depth) {
return Math.max(shape.halfWidth(), shape.halfHeight()) + 0.5D + Math.max(0.0D, depth) * MOON_SPREAD;
}
private void pullMoonEntities(ServerLevel level, PortalGunWorldPortalShape shape, Player owner) {
Vec3 center = shape.center();
AABB area = new AABB(center, center.add(shape.normal().scale(MOON_RANGE))).inflate(moonLateralLimit(shape, MOON_RANGE));
Vec3 target = center.add(shape.normal().scale(0.3D));
boolean vacuumTick = this.moonTicks % MOON_VACUUM_INTERVAL == 0;
for (Entity entity : level.getEntities(this, area, this::canMoonAffect)) {
Vec3 position = entity.getBoundingBox().getCenter();
PortalGunWorldPortalShape.PortalLocalCoords local = shape.localCoords(position);
double depth = local.depth();
double lateral = Math.sqrt(local.horizontal() * local.horizontal() + local.vertical() * local.vertical());
if (depth < -0.5D || depth > MOON_RANGE || lateral > moonLateralLimit(shape, depth)) {
continue;
}
boolean atMouth = depth <= MOON_MOUTH_DEPTH + entity.getBbWidth() * 0.5D
&& Math.abs(local.horizontal()) <= shape.halfWidth() + 0.25D
&& Math.abs(local.vertical()) <= shape.halfHeight() + 0.25D;
if (atMouth) {
if (!this.swallowIntoSpace(level, entity, owner)) {
this.holdInVacuum(level, entity, shape, owner, vacuumTick);
}
continue;
}
double falloff = 1.0D - depth / MOON_RANGE;
double strength = MOON_PULL_STRENGTH * (0.35D + falloff * falloff * 1.6D);
Vec3 worldMotion = PortalGunTransitMath.entityVelocityToWorld(entity, entity.getDeltaMovement())
.scale(0.92D)
.add(target.subtract(position).normalize().scale(strength));
if (worldMotion.length() > MOON_MAX_SPEED) {
worldMotion = worldMotion.normalize().scale(MOON_MAX_SPEED);
}
applyMoonMotion(entity, worldMotion);
}
}
private boolean canMoonAffect(Entity entity) {
if (!entity.isAlive() || entity.isPassenger() || entity.isSpectator()
|| entity instanceof PortalGunPortalEntity || entity instanceof PortalGunProjectileEntity) {
return false;
}
if (entity instanceof Player player && player.isCreative()) {
return false;
}
return entity instanceof LivingEntity || entity instanceof ItemEntity || entity instanceof ExperienceOrb
|| entity instanceof FallingBlockEntity || entity instanceof Projectile
|| entity instanceof VehicleEntity || entity instanceof PrimedTnt;
}
private boolean swallowIntoSpace(ServerLevel level, Entity entity, Player owner) {
if (entity instanceof Player || entity instanceof VehicleEntity) {
return false;
}
if (entity instanceof LivingEntity living) {
living.hurt(AntarchyDamageSources.moonVacuum(level, owner), Float.MAX_VALUE);
return !living.isAlive();
}
entity.discard();
return true;
}
private void holdInVacuum(ServerLevel level, Entity entity, PortalGunWorldPortalShape shape, Player owner, boolean vacuumTick) {
Vec3 hold = shape.center().add(shape.normal().scale(MOON_HOLD_DEPTH + entity.getBbWidth() * 0.5D));
applyMoonMotion(entity, hold.subtract(entity.getBoundingBox().getCenter()).scale(0.45D));
if (vacuumTick && entity instanceof LivingEntity living) {
living.hurt(AntarchyDamageSources.moonVacuum(level, owner == entity ? null : owner), MOON_VACUUM_DAMAGE);
}
}
private static void applyMoonMotion(Entity entity, Vec3 worldMotion) {
entity.setDeltaMovement(PortalGunTransitMath.entityVelocityFromWorld(entity, worldMotion));
entity.hasImpulse = true;
entity.fallDistance = 0.0F;
if (entity instanceof LivingEntity) {
entity.hurtMarked = true;
}
}
private void pullMoonBlocks(ServerLevel level, PortalGunWorldPortalShape shape, Player owner) {
int cap = AntarchySettings.portalGunMoonBlockCap();
int pulled = 0;
for (int ray = 0; ray < MOON_BLOCK_RAYS && pulled < MOON_BLOCKS_PER_PULL && this.moonSuckedBlocks < cap; ray++) {
double limit = moonLateralLimit(shape, MOON_RANGE);
double horizontal = (this.random.nextDouble() * 2.0D - 1.0D) * limit;
double vertical = (this.random.nextDouble() * 2.0D - 1.0D) * limit;
if (horizontal * horizontal + vertical * vertical > limit * limit) {
continue;
}
Vec3 start = shape.center()
.add(shape.right().scale((this.random.nextDouble() * 2.0D - 1.0D) * shape.halfWidth()))
.add(shape.up().scale((this.random.nextDouble() * 2.0D - 1.0D) * shape.halfHeight()))
.add(shape.normal().scale(0.5D));
Vec3 end = shape.center()
.add(shape.right().scale(horizontal))
.add(shape.up().scale(vertical))
.add(shape.normal().scale(MOON_RANGE));
BlockPos hit = this.firstBlockAlong(level, shape, start, end);
if (hit == null) {
continue;
}
BlockState state = loadedState(level, hit);
if (state == null || !BlockSuction.canLift(level, hit, state, true)
|| owner != null && !level.mayInteract(owner, hit)) {
continue;
}
FallingBlockEntity falling = BlockSuction.lift(level, hit, state, shape.center(), MOON_BLOCK_SPEED);
if (falling == null) {
continue;
}
falling.setNoGravity(true);
pulled++;
this.moonSuckedBlocks++;
}
}
private BlockPos firstBlockAlong(ServerLevel level, PortalGunWorldPortalShape shape, Vec3 start, Vec3 end) {
Vec3 delta = end.subtract(start);
int steps = Math.max(1, (int) Math.ceil(delta.length() / MOON_RAY_STEP));
BlockPos previous = null;
for (int step = 0; step <= steps; step++) {
BlockPos pos = BlockPos.containing(start.add(delta.scale((double) step / steps)));
if (pos.equals(previous)) {
continue;
}
previous = pos;
if (shape.localCoords(Vec3.atCenterOf(pos)).depth() < 0.5D) {
continue;
}
if (!level.isInWorldBounds(pos) || !level.getWorldBorder().isWithinBounds(pos)) {
return null;
}
BlockState state = loadedState(level, pos);
if (state == null) {
return null;
}
if (!state.isAir()) {
return pos;
}
}
return null;
}
private static BlockState loadedState(ServerLevel level, BlockPos pos) {
net.minecraft.world.level.chunk.LevelChunk chunk = level.getChunkSource()
.getChunkNow(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
return chunk == null ? null : chunk.getBlockState(pos);
}
private void spawnMoonParticles() {
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
Vec3 center = shape.center();
for (int i = 0; i < 4; i++) {
double depth = 1.0D + this.random.nextDouble() * MOON_RANGE * 0.6D;
double limit = moonLateralLimit(shape, depth);
Vec3 start = center
.add(shape.right().scale((this.random.nextDouble() * 2.0D - 1.0D) * limit))
.add(shape.up().scale((this.random.nextDouble() * 2.0D - 1.0D) * limit))
.add(shape.normal().scale(depth));
Vec3 velocity = center.subtract(start).normalize().scale(0.35D + this.random.nextDouble() * 0.3D);
this.level().addParticle(ParticleTypes.CLOUD, start.x, start.y, start.z, velocity.x, velocity.y, velocity.z);
}
}
private boolean isStillRegistered(ServerLevel level) {
return PortalGunSavedData.isRegistered(level, this.gunId, this.getPortalSide(), this.getUUID());
}
@@ -838,6 +1068,11 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
tag.putInt("AgeTicks", this.ageTicks);
tag.putInt("PairTime", this.pairTime);
if (this.isMoonPortal()) {
tag.putBoolean("Moon", true);
tag.putInt("MoonTicks", this.moonTicks);
tag.putInt("MoonSuckedBlocks", this.moonSuckedBlocks);
}
tag.putInt("Side", this.getPortalSide().ordinal());
tag.putInt("Facing", this.getFacingDirection().get3DDataValue());
tag.putInt("UpAxis", this.getUpAxis().get3DDataValue());
@@ -887,6 +1122,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
this.ageTicks = tag.getInt("AgeTicks");
this.pairTime = tag.getInt("PairTime");
this.entityData.set(MOON, tag.getBoolean("Moon"));
this.moonTicks = tag.getInt("MoonTicks");
this.moonSuckedBlocks = tag.getInt("MoonSuckedBlocks");
this.entityData.set(SIDE, tag.getInt("Side"));
this.entityData.set(FACING, tag.getInt("Facing"));
this.entityData.set(UP_AXIS, tag.getInt("UpAxis"));
@@ -927,6 +927,8 @@
"advancements.antarchy.bugged_out.description": "Defeat the Alpha Mantis.",
"death.attack.bed_bug_bite": "%1$s got bit by the bed bugs",
"death.attack.bed_bug_bite.player": "%1$s got bit by the bed bugs while fighting %2$s",
"death.attack.moon_vacuum": "%1$s was pulled into the vacuum of space",
"death.attack.moon_vacuum.player": "%1$s was pulled into the vacuum of space by %2$s",
"message.antarchy.dread_too_scared_to_sleep": "You are too scared to sleep.",
"death.attack.kraken_mauling": "%1$s was dragged under by the Kraken",
"death.attack.kraken_mauling.player": "%1$s was dragged under by the Kraken while fighting %2$s",
Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,7 @@
{
"message_id": "moon_vacuum",
"scaling": "never",
"exhaustion": 0.0,
"effects": "hurt",
"death_message_type": "default"
}
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:moon_vacuum"
]
}
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:moon_vacuum"
]
}
@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"antarchy:moon_vacuum"
]
}
@@ -163,7 +163,6 @@ public final class AntarchyFabricClientBootstrap {
EntityRendererRegistry.register(AntarchyFabricEntities.DIMENSIONAL_TEAR.get(), DimensionalTearRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.PORTAL_GUN_PORTAL.get(), PortalGunPortalRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.HOVERBOARD.get(), com.craisinlord.antarchy.content.client.renderer.HoverboardRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunBlackHoleRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.PORTAL_GUN_PROJECTILE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunProjectileRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.LUCID.get(), context -> withTemporalGeoLayer(new LucidRenderer(context)));
@@ -427,12 +427,6 @@ public final class AntarchyFabricEntities {
.updateInterval(1)
.build("portal_gun_portal"));
public static final DeferredHolder<EntityType<?>, EntityType<com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity>> PORTAL_GUN_BLACK_HOLE = ENTITY_TYPES.register("portal_gun_black_hole",
() -> EntityType.Builder.of(com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity::new, MobCategory.MISC)
.sized(1.2F, 1.2F)
.clientTrackingRange(10)
.updateInterval(1)
.build("portal_gun_black_hole"));
public static final DeferredHolder<EntityType<?>, EntityType<PortalGunProjectileEntity>> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile",
() -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC)
.sized(0.25F, 0.25F)
@@ -1563,7 +1563,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1573,7 +1572,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1583,7 +1581,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1593,7 +1590,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1603,7 +1599,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -674,6 +674,9 @@ public final class AntarchyConfigModuleNeoforge {
AntarchySettings.setPortalGunMinFloorExitSpeed(AntarchyMiscConfig.portalGunMinFloorExitSpeed());
AntarchySettings.setPortalGunMaxLiveViews(AntarchyMiscConfig.portalGunMaxLiveViews());
AntarchySettings.setPortalGunMaxExitSpeed(AntarchyMiscConfig.portalGunMaxExitSpeed());
AntarchySettings.setPortalGunMoonPullsBlocks(AntarchyMiscConfig.portalGunMoonPullsBlocks());
AntarchySettings.setPortalGunMoonPortalSeconds(AntarchyMiscConfig.portalGunMoonPortalSeconds());
AntarchySettings.setPortalGunMoonBlockCap(AntarchyMiscConfig.portalGunMoonBlockCap());
// Misc
@@ -42,6 +42,9 @@ public final class AntarchyMiscConfig {
private static final ModConfigSpec.DoubleValue PORTAL_GUN_MIN_FLOOR_EXIT_SPEED;
private static final ModConfigSpec.IntValue PORTAL_GUN_MAX_LIVE_VIEWS;
private static final ModConfigSpec.DoubleValue PORTAL_GUN_MAX_EXIT_SPEED;
private static final ModConfigSpec.BooleanValue PORTAL_GUN_MOON_PULLS_BLOCKS;
private static final ModConfigSpec.IntValue PORTAL_GUN_MOON_PORTAL_SECONDS;
private static final ModConfigSpec.IntValue PORTAL_GUN_MOON_BLOCK_CAP;
// Diamond Minecart
private static final ModConfigSpec.BooleanValue DIAMOND_MINECART_ENABLED;
@@ -150,6 +153,9 @@ public final class AntarchyMiscConfig {
PORTAL_GUN_MAX_LIVE_VIEWS = b.comment("How many portals can show a live see-through view at once. Each one re-renders the world, so higher values cost frame rate. 0 shows only the animated surface.").defineInRange("maxLiveViews", 8, 0, 32);
PORTAL_GUN_MIN_FLOOR_EXIT_SPEED = b.comment("Minimum speed in blocks/tick when leaving an upward-facing portal, so the traveller clears it. 0 disables.").defineInRange("minFloorExitSpeed", 0.6D, 0.0D, 4.0D);
PORTAL_GUN_MAX_EXIT_SPEED = b.comment("Maximum speed in blocks/tick when leaving a portal. 0 keeps momentum uncapped.").defineInRange("maxExitSpeed", 0.0D, 0.0D, 100.0D);
PORTAL_GUN_MOON_PULLS_BLOCKS = b.comment("Whether a portal opened by shooting the moon rips blocks loose and pulls them into space.").define("moonPullsBlocks", true);
PORTAL_GUN_MOON_PORTAL_SECONDS = b.comment("How long a moon portal stays open, in seconds.").defineInRange("moonPortalSeconds", 10, 1, 120);
PORTAL_GUN_MOON_BLOCK_CAP = b.comment("Maximum number of blocks a single moon portal can pull in.").defineInRange("moonBlockCap", 500, 0, 2000);
b.pop();
@@ -229,6 +235,9 @@ public final class AntarchyMiscConfig {
public static double portalGunMinFloorExitSpeed() { return PORTAL_GUN_MIN_FLOOR_EXIT_SPEED.get(); }
public static int portalGunMaxLiveViews() { return PORTAL_GUN_MAX_LIVE_VIEWS.get(); }
public static double portalGunMaxExitSpeed() { return PORTAL_GUN_MAX_EXIT_SPEED.get(); }
public static boolean portalGunMoonPullsBlocks() { return PORTAL_GUN_MOON_PULLS_BLOCKS.get(); }
public static int portalGunMoonPortalSeconds() { return PORTAL_GUN_MOON_PORTAL_SECONDS.get(); }
public static int portalGunMoonBlockCap() { return PORTAL_GUN_MOON_BLOCK_CAP.get(); }
static boolean diamondMinecartEnabled() { return DIAMOND_MINECART_ENABLED.get(); }
static boolean diamondMinecartPlacesRails() { return DIAMOND_MINECART_PLACES_RAILS.get(); }
@@ -172,7 +172,6 @@ public final class AntarchyNeoForgeClient {
event.registerEntityRenderer(AntarchyNeoforgeEntites.NIGHTMARE_PORTAL.get(), NightmarePortalRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.DIMENSIONAL_TEAR.get(), DimensionalTearRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL.get(), PortalGunPortalRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunBlackHoleRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunProjectileRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.LUCID.get(), context -> withParalyzedGeoLayer(new LucidRenderer(context)));
@@ -350,12 +350,6 @@ public final class AntarchyNeoforgeEntites {
.updateInterval(1)
.build("portal_gun_portal"));
public static final DeferredHolder<EntityType<?>, EntityType<com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity>> PORTAL_GUN_BLACK_HOLE = ENTITY_TYPES.register("portal_gun_black_hole",
() -> EntityType.Builder.of(com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity::new, MobCategory.MISC)
.sized(1.2F, 1.2F)
.clientTrackingRange(10)
.updateInterval(1)
.build("portal_gun_black_hole"));
public static final DeferredHolder<EntityType<?>, EntityType<PortalGunProjectileEntity>> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile",
() -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC)
.sized(0.25F, 0.25F)
@@ -1041,7 +1041,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1051,7 +1050,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1061,7 +1059,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1071,7 +1068,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1081,7 +1077,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,