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
+767 -323

No files matched your search

@@ -146,6 +146,7 @@ public final class AntarchyConfigCatalog {
|| name.equals("portalGunMinFloorExitSpeed") || name.equals("portalGunMinFloorExitSpeed")
|| name.equals("portalGunMaxLiveViews") || name.equals("portalGunMaxLiveViews")
|| name.equals("portalGunMaxExitSpeed") || name.equals("portalGunMaxExitSpeed")
|| name.startsWith("portalGunMoon")
|| name.equals("hushweedSporeLifetimeSeconds") || name.equals("hushweedSporeLifetimeSeconds")
|| name.equals("elythiaFireflyParticlesEnabled") || name.equals("elythiaFireflyParticlesEnabled")
|| name.equals("duplicatorTreeEnabled") || name.equals("duplicatorTreeEnabled")
@@ -559,6 +559,9 @@ public final class AntarchySettings {
private static double portalGunMinFloorExitSpeed = 0.6D; private static double portalGunMinFloorExitSpeed = 0.6D;
private static int portalGunMaxLiveViews = 8; private static int portalGunMaxLiveViews = 8;
private static double portalGunMaxExitSpeed = 0.0D; 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 boolean elythiaFireflyParticlesEnabled = true;
private static int bloodCrystalArmorShieldRechargeTicks = 600; private static int bloodCrystalArmorShieldRechargeTicks = 600;
private static int bloodCrystalAppleShieldCount = 2; private static int bloodCrystalAppleShieldCount = 2;
@@ -1348,6 +1351,18 @@ public final class AntarchySettings {
portalGunMinFloorExitSpeed = Math.max(0.0D, Math.min(4.0D, value)); 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) { public static void setPortalGunMaxExitSpeed(double value) {
portalGunMaxExitSpeed = Math.max(0.0D, Math.min(100.0D, 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 double portalGunMinFloorExitSpeed() { return portalGunMinFloorExitSpeed; }
public static int portalGunMaxLiveViews() { return portalGunMaxLiveViews; } public static int portalGunMaxLiveViews() { return portalGunMaxLiveViews; }
public static double portalGunMaxExitSpeed() { return portalGunMaxExitSpeed; } 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) { public static void setBrownAntRequiresReagent(boolean value) {
brownAntRequiresReagent = 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(); modelViewStack.identity();
RenderSystem.applyModelViewMatrix(); RenderSystem.applyModelViewMatrix();
renderingScene = true; renderingScene = true;
boolean irisPipelineInstalled = IrisPortalSceneCompat.begin(renderer);
terrain.begin(minecraft); terrain.begin(minecraft);
try { try {
float renderDistance = minecraft.gameRenderer.getRenderDistance(); float renderDistance = minecraft.gameRenderer.getRenderDistance();
@@ -166,6 +167,7 @@ public final class PortalGunPortalSceneRenderer {
} }
} finally { } finally {
renderingScene = false; renderingScene = false;
IrisPortalSceneCompat.end(renderer, irisPipelineInstalled);
terrain.end(minecraft); terrain.end(minecraft);
state.antarchy$setRainSoundTime(previousRainSoundTime); state.antarchy$setRainSoundTime(previousRainSoundTime);
modelViewStack.popMatrix(); modelViewStack.popMatrix();
@@ -130,8 +130,9 @@ public final class PortalGunPortalViewRenderer {
} }
List<RootCandidate> candidates = new ArrayList<>(); List<RootCandidate> candidates = new ArrayList<>();
for (PortalGunPortalEntity portal : portals) { for (PortalGunPortalEntity portal : portals) {
PortalGunPortalEntity linked = portal.getLinkedPortal(); boolean moon = portal.isMoonPortal();
if (linked == null || !linked.isAlive() || !portal.shouldRenderFront(cameraPos)) { PortalGunPortalEntity linked = moon ? null : portal.getLinkedPortal();
if (!moon && (linked == null || !linked.isAlive()) || !portal.shouldRenderFront(cameraPos)) {
continue; continue;
} }
ScreenClip clip = computeScreenClip(cameraPos, rootViewMatrix, rootProjection, portal, partialTick, width, height); ScreenClip clip = computeScreenClip(cameraPos, rootViewMatrix, rootProjection, portal, partialTick, width, height);
@@ -173,7 +174,13 @@ public final class PortalGunPortalViewRenderer {
break; break;
} }
try { try {
if (directStencil) { 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, renderViewDirect(minecraft, cameraEntity, partialTick, rootContext, rootProjection, rootProjection,
candidate.portal(), candidate.linked(), 0, candidate.clip(), null, budget); candidate.portal(), candidate.linked(), 0, candidate.clip(), null, budget);
} else { } 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, private static void renderNestedViews(Minecraft minecraft, Entity cameraEntity, float partialTick, RenderContext viewContext,
Matrix4f rootProjection, Matrix4f viewProjection, PortalGunPortalEntity exit, Matrix4f rootProjection, Matrix4f viewProjection, PortalGunPortalEntity exit,
int level, ScreenClip viewClip, ViewBudget budget, int width, int height) { 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() { private AntarchyDamageSources() {
} }
} }
@@ -103,6 +103,12 @@ public final class AntarchyDamageTypes {
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hercules_beetle_obliteration") 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() { 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.TimeDilationApi;
import com.craisinlord.antarchy.content.time.TimeDilationFieldEntity; import com.craisinlord.antarchy.content.time.TimeDilationFieldEntity;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.entity.BlockSuction;
import java.util.UUID; import java.util.UUID;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
@@ -337,23 +338,10 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity {
} }
BlockState state = level.getBlockState(pos); BlockState state = level.getBlockState(pos);
if (state.isAir() || level.getBlockEntity(pos) != null if (!BlockSuction.canLift(level, pos, state)
|| state.getDestroySpeed(level, pos) < 0.0F || BlockSuction.lift(level, pos, state, center, 0.28D) == null) {
|| state.getBlock().getExplosionResistance() > 30.0F
|| state.getCollisionShape(level, pos).isEmpty()) {
continue; 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++; pulledThisTick++;
this.suckedBlocks++; 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.client.renderer.AnimatedHeldItemRenderer;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload; 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.PortalGunPlacement;
import com.craisinlord.antarchy.content.portalgun.PortalGunMoonMath;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunSavedData; 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 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 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 PortalGunPortalEntity>> portalType;
private final Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType;
private final Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType; private final Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType;
private final Supplier<? extends Block> portalMasterBlock; private final Supplier<? extends Block> portalMasterBlock;
private final Supplier<? extends Block> portalBaseBlock; private final Supplier<? extends Block> portalBaseBlock;
@@ -92,7 +91,6 @@ public class PortalGunItem extends Item implements GeoItem {
public PortalGunItem( public PortalGunItem(
Item.Properties properties, Item.Properties properties,
Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType, Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType,
Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType,
Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType, Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType,
Supplier<? extends Block> portalMasterBlock, Supplier<? extends Block> portalMasterBlock,
Supplier<? extends Block> portalBaseBlock, Supplier<? extends Block> portalBaseBlock,
@@ -101,7 +99,6 @@ public class PortalGunItem extends Item implements GeoItem {
super(properties); super(properties);
this.variant = variant; this.variant = variant;
this.portalType = portalType; this.portalType = portalType;
this.blackHoleType = blackHoleType;
this.projectileType = projectileType; this.projectileType = projectileType;
this.portalMasterBlock = portalMasterBlock; this.portalMasterBlock = portalMasterBlock;
this.portalBaseBlock = portalBaseBlock; this.portalBaseBlock = portalBaseBlock;
@@ -218,9 +215,9 @@ public class PortalGunItem extends Item implements GeoItem {
if (this.isMoonSideArmed(stack, side)) { if (this.isMoonSideArmed(stack, side)) {
this.setMoonSide(stack, null); this.setMoonSide(stack, null);
} }
if (shooter instanceof Player player && this.isMoonSideArmed(stack, this.otherSide(side))) { boolean moon = shooter instanceof Player && this.isMoonSideArmed(stack, this.otherSide(side));
this.spawnBlackHole(level, player, stack, side, placement.center()); if (moon) {
return; this.setMoonSide(stack, null);
} }
PortalGunPortalEntity portal = new PortalGunPortalEntity(this.portalType.get(), level); PortalGunPortalEntity portal = new PortalGunPortalEntity(this.portalType.get(), level);
portal.configure(portalOwnerId, gunId, this.variant, side, placement); 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); level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface"), SoundSource.PLAYERS, 0.55F, 1.0F);
return; return;
} }
if (moon) {
portal.openToMoon();
}
level.addFreshEntity(portal); level.addFreshEntity(portal);
PortalGunSavedData.setPortal(level, gunId, portalOwnerId, side, portal.getUUID()); PortalGunSavedData.setPortal(level, gunId, portalOwnerId, side, portal.getUUID());
PortalGunPortalEntity other = this.findCounterpart(level, gunId, side); PortalGunPortalEntity other = this.findCounterpart(level, gunId, side);
if (other != null && (moon || other.isMoonPortal())) {
other.discard();
other = null;
}
if (other != null) { if (other != null) {
portal.linkTo(other); portal.linkTo(other);
other.linkTo(portal); 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) { 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; 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) { if (existing != null) {
existing.discard(); existing.discard();
} }
this.setMoonSide(stack, side); 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.setLastSide(stack, side);
this.triggerFireAnimation(level, player, stack); this.triggerFireAnimation(level, player, stack);
if (this.damageGun(level, player, stack, offhand)) { if (this.damageGun(level, player, stack, offhand)) {
@@ -297,14 +308,11 @@ public class PortalGunItem extends Item implements GeoItem {
return true; return true;
} }
private boolean spawnBlackHole(ServerLevel level, Player player, ItemStack stack, PortalGunPortalEntity.PortalSide side, Vec3 spawnPos) { private boolean isAimingAtMoon(ServerLevel level, Player player) {
this.setMoonSide(stack, null); if (!level.dimensionType().hasSkyLight() || level.dimensionType().hasCeiling()) {
PortalGunBlackHoleEntity blackHole = new PortalGunBlackHoleEntity(this.blackHoleType.get(), level); return false;
blackHole.configure(player.getUUID()); }
blackHole.moveTo(spawnPos.x, spawnPos.y, spawnPos.z, 0.0F, 0.0F); return PortalGunMoonMath.isAimedAtMoon(this.worldLook(player), level.getTimeOfDay(1.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 void spawnShotTrail(ServerLevel level, Player player, Vec3 endPos, PortalGunPortalEntity.PortalSide side) { 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) { 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); net.minecraft.world.item.component.CustomData customData = stack.get(DataComponents.CUSTOM_DATA);
if (customData == null) { if (customData == null) {
return false; return null;
} }
String sideName = customData.copyTag().getString(MOON_SIDE_TAG); 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) { 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.item.PortalGunItem;
import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload; import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload;
import com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload; import com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@@ -27,18 +29,26 @@ public final class PortalGunIndicatorSync {
if (stack.isEmpty()) { if (stack.isEmpty()) {
return; return;
} }
boolean blue = PortalGunSavedData.getPortalId( ServerLevel level = player.serverLevel();
player.serverLevel().getServer(), Optional<UUID> blueId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.BLUE);
request.gunId(), Optional<UUID> orangeId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.ORANGE);
PortalGunPortalEntity.PortalSide.BLUE, PortalGunPortalEntity.PortalSide moonSide = PortalGunItem.getMoonSide(stack);
player.serverLevel().dimension().location() boolean blue = blueId.isPresent()
).isPresent(); || moonSide == PortalGunPortalEntity.PortalSide.BLUE
boolean orange = PortalGunSavedData.getPortalId( || isMoonPortal(level, orangeId);
player.serverLevel().getServer(), boolean orange = orangeId.isPresent()
request.gunId(), || moonSide == PortalGunPortalEntity.PortalSide.ORANGE
PortalGunPortalEntity.PortalSide.ORANGE, || isMoonPortal(level, blueId);
player.serverLevel().dimension().location()
).isPresent();
sender.accept(player, new PortalGunIndicatorPayload(request.gunId(), blue, orange)); 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.PortalGunPortalCellAccess;
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord; import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord;
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalMasterBlockEntity; 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.AbstractArrowAccessor;
import com.craisinlord.antarchy.mixins.FallingBlockEntityAccessor; import com.craisinlord.antarchy.mixins.FallingBlockEntityAccessor;
import com.craisinlord.antarchy.mixins.ServerGamePacketListenerTeleportAccessor; import com.craisinlord.antarchy.mixins.ServerGamePacketListenerTeleportAccessor;
@@ -23,6 +25,8 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; 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.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; 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.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; 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.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow; 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_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> 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<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 OPEN_ANIM = RawAnimation.begin().thenPlay("open");
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle"); private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final int OPEN_TICKS = 5; 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_START_ERROR_SQR = 1.0D;
private static final double MAX_CLIENT_TRANSIT_MOVEMENT_SQR = 100.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 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 AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private final Map<UUID, Integer> teleportCooldowns = new HashMap<>(); private final Map<UUID, Integer> teleportCooldowns = new HashMap<>();
private UUID ownerId; private UUID ownerId;
@@ -96,6 +120,8 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private int ageTicks; private int ageTicks;
private int lastOpeningAnimationId; private int lastOpeningAnimationId;
private int pairTime; private int pairTime;
private int moonTicks;
private int moonSuckedBlocks;
private BlockPos supportOrigin = BlockPos.ZERO; private BlockPos supportOrigin = BlockPos.ZERO;
private BlockPos masterPos = BlockPos.ZERO; private BlockPos masterPos = BlockPos.ZERO;
private BlockPos basePos = 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_WIDTH, 1);
builder.define(PORTAL_HEIGHT, 2); builder.define(PORTAL_HEIGHT, 2);
builder.define(OPENING_ANIMATION_ID, 0); builder.define(OPENING_ANIMATION_ID, 0);
builder.define(MOON, false);
} }
public void configure(UUID ownerId, UUID gunId, PortalGunVariant variant, PortalSide side, PortalGunPlacement placement) { 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; 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() { public PortalSide getPortalSide() {
int ordinal = this.entityData.get(SIDE); int ordinal = this.entityData.get(SIDE);
return ordinal == PortalSide.ORANGE.ordinal() ? PortalSide.ORANGE : PortalSide.BLUE; 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.yRotO = this.getYRot();
this.xRotO = this.getXRot(); this.xRotO = this.getXRot();
if (this.level().isClientSide) { if (this.level().isClientSide) {
if (this.isMoonPortal()) {
this.spawnMoonParticles();
}
return; return;
} }
if (!(this.level() instanceof ServerLevel serverLevel)) { if (!(this.level() instanceof ServerLevel serverLevel)) {
@@ -586,6 +629,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.discard(); this.discard();
return; return;
} }
if (this.isMoonPortal()) {
this.tickMoon(serverLevel);
return;
}
PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel); PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel);
if (linked == null || !linked.isAlive()) { if (linked == null || !linked.isAlive()) {
if (Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY) && this.ageTicks % 40 == 0) { if (Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY) && this.ageTicks % 40 == 0) {
@@ -603,6 +650,189 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.tickTeleport(linked); 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) { private boolean isStillRegistered(ServerLevel level) {
return PortalGunSavedData.isRegistered(level, this.gunId, this.getPortalSide(), this.getUUID()); 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("AgeTicks", this.ageTicks);
tag.putInt("PairTime", this.pairTime); 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("Side", this.getPortalSide().ordinal());
tag.putInt("Facing", this.getFacingDirection().get3DDataValue()); tag.putInt("Facing", this.getFacingDirection().get3DDataValue());
tag.putInt("UpAxis", this.getUpAxis().get3DDataValue()); tag.putInt("UpAxis", this.getUpAxis().get3DDataValue());
@@ -887,6 +1122,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
this.ageTicks = tag.getInt("AgeTicks"); this.ageTicks = tag.getInt("AgeTicks");
this.pairTime = tag.getInt("PairTime"); 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(SIDE, tag.getInt("Side"));
this.entityData.set(FACING, tag.getInt("Facing")); this.entityData.set(FACING, tag.getInt("Facing"));
this.entityData.set(UP_AXIS, tag.getInt("UpAxis")); this.entityData.set(UP_AXIS, tag.getInt("UpAxis"));
@@ -927,6 +927,8 @@
"advancements.antarchy.bugged_out.description": "Defeat the Alpha Mantis.", "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": "%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.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.", "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": "%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", "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.DIMENSIONAL_TEAR.get(), DimensionalTearRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.PORTAL_GUN_PORTAL.get(), PortalGunPortalRenderer::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.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.PORTAL_GUN_PROJECTILE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunProjectileRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new); EntityRendererRegistry.register(AntarchyFabricEntities.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new);
EntityRendererRegistry.register(AntarchyFabricEntities.LUCID.get(), context -> withTemporalGeoLayer(new LucidRenderer(context))); EntityRendererRegistry.register(AntarchyFabricEntities.LUCID.get(), context -> withTemporalGeoLayer(new LucidRenderer(context)));
@@ -427,12 +427,6 @@ public final class AntarchyFabricEntities {
.updateInterval(1) .updateInterval(1)
.build("portal_gun_portal")); .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", public static final DeferredHolder<EntityType<?>, EntityType<PortalGunProjectileEntity>> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile",
() -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC) () -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC)
.sized(0.25F, 0.25F) .sized(0.25F, 0.25F)
@@ -1563,7 +1563,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL, AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1573,7 +1572,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL, AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1583,7 +1581,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL, AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1593,7 +1590,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL, AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1603,7 +1599,6 @@ public final class AntarchyFabricItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyFabricEntities.PORTAL_GUN_PORTAL, AntarchyFabricEntities.PORTAL_GUN_PORTAL,
AntarchyFabricEntities.PORTAL_GUN_BLACK_HOLE,
AntarchyFabricEntities.PORTAL_GUN_PROJECTILE, AntarchyFabricEntities.PORTAL_GUN_PROJECTILE,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyFabricBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -674,6 +674,9 @@ public final class AntarchyConfigModuleNeoforge {
AntarchySettings.setPortalGunMinFloorExitSpeed(AntarchyMiscConfig.portalGunMinFloorExitSpeed()); AntarchySettings.setPortalGunMinFloorExitSpeed(AntarchyMiscConfig.portalGunMinFloorExitSpeed());
AntarchySettings.setPortalGunMaxLiveViews(AntarchyMiscConfig.portalGunMaxLiveViews()); AntarchySettings.setPortalGunMaxLiveViews(AntarchyMiscConfig.portalGunMaxLiveViews());
AntarchySettings.setPortalGunMaxExitSpeed(AntarchyMiscConfig.portalGunMaxExitSpeed()); AntarchySettings.setPortalGunMaxExitSpeed(AntarchyMiscConfig.portalGunMaxExitSpeed());
AntarchySettings.setPortalGunMoonPullsBlocks(AntarchyMiscConfig.portalGunMoonPullsBlocks());
AntarchySettings.setPortalGunMoonPortalSeconds(AntarchyMiscConfig.portalGunMoonPortalSeconds());
AntarchySettings.setPortalGunMoonBlockCap(AntarchyMiscConfig.portalGunMoonBlockCap());
// Misc // Misc
@@ -42,6 +42,9 @@ public final class AntarchyMiscConfig {
private static final ModConfigSpec.DoubleValue PORTAL_GUN_MIN_FLOOR_EXIT_SPEED; 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.IntValue PORTAL_GUN_MAX_LIVE_VIEWS;
private static final ModConfigSpec.DoubleValue PORTAL_GUN_MAX_EXIT_SPEED; 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 // Diamond Minecart
private static final ModConfigSpec.BooleanValue DIAMOND_MINECART_ENABLED; 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_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_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_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(); b.pop();
@@ -229,6 +235,9 @@ public final class AntarchyMiscConfig {
public static double portalGunMinFloorExitSpeed() { return PORTAL_GUN_MIN_FLOOR_EXIT_SPEED.get(); } 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 int portalGunMaxLiveViews() { return PORTAL_GUN_MAX_LIVE_VIEWS.get(); }
public static double portalGunMaxExitSpeed() { return PORTAL_GUN_MAX_EXIT_SPEED.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 diamondMinecartEnabled() { return DIAMOND_MINECART_ENABLED.get(); }
static boolean diamondMinecartPlacesRails() { return DIAMOND_MINECART_PLACES_RAILS.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.NIGHTMARE_PORTAL.get(), NightmarePortalRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.DIMENSIONAL_TEAR.get(), DimensionalTearRenderer::new); event.registerEntityRenderer(AntarchyNeoforgeEntites.DIMENSIONAL_TEAR.get(), DimensionalTearRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL.get(), PortalGunPortalRenderer::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.PORTAL_GUN_PROJECTILE.get(), com.craisinlord.antarchy.content.client.renderer.PortalGunProjectileRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new); event.registerEntityRenderer(AntarchyNeoforgeEntites.NIGHTMARE_BITE.get(), NightmareBiteRenderer::new);
event.registerEntityRenderer(AntarchyNeoforgeEntites.LUCID.get(), context -> withParalyzedGeoLayer(new LucidRenderer(context))); event.registerEntityRenderer(AntarchyNeoforgeEntites.LUCID.get(), context -> withParalyzedGeoLayer(new LucidRenderer(context)));
@@ -350,12 +350,6 @@ public final class AntarchyNeoforgeEntites {
.updateInterval(1) .updateInterval(1)
.build("portal_gun_portal")); .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", public static final DeferredHolder<EntityType<?>, EntityType<PortalGunProjectileEntity>> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile",
() -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC) () -> EntityType.Builder.<PortalGunProjectileEntity>of(PortalGunProjectileEntity::new, MobCategory.MISC)
.sized(0.25F, 0.25F) .sized(0.25F, 0.25F)
@@ -1041,7 +1041,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1051,7 +1050,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1061,7 +1059,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1071,7 +1068,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,
@@ -1081,7 +1077,6 @@ public final class AntarchyNeoforgeItems {
() -> new PortalGunItem( () -> new PortalGunItem(
new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE), new Item.Properties().stacksTo(1).durability(256).rarity(Rarity.RARE),
AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL, AntarchyNeoforgeEntites.PORTAL_GUN_PORTAL,
AntarchyNeoforgeEntites.PORTAL_GUN_BLACK_HOLE,
AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE, AntarchyNeoforgeEntites.PORTAL_GUN_PROJECTILE,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_MASTER,
AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE, AntarchyNeoforgeBlocks.PORTAL_GUN_PORTAL_BASE,