diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java index 5289b5d0..c22179ea 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchyConfigCatalog.java @@ -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") diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java index e65a7a0c..17a5c964 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java @@ -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; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/PortalGunBlackHoleModel.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/PortalGunBlackHoleModel.java deleted file mode 100644 index bada5a4b..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/model/PortalGunBlackHoleModel.java +++ /dev/null @@ -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 { - 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"); - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/IrisPortalSceneCompat.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/IrisPortalSceneCompat.java new file mode 100644 index 00000000..5dea9bef --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/IrisPortalSceneCompat.java @@ -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) { + } + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunBlackHoleRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunBlackHoleRenderer.java deleted file mode 100644 index 18b4bcc7..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunBlackHoleRenderer.java +++ /dev/null @@ -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 { - 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)); - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunMoonViewRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunMoonViewRenderer.java new file mode 100644 index 00000000..c8d29a8d --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunMoonViewRenderer.java @@ -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); + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java index c7210f43..e9f62769 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalSceneRenderer.java @@ -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(); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java index cdf42ae2..cb7fee3b 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/PortalGunPortalViewRenderer.java @@ -130,8 +130,9 @@ public final class PortalGunPortalViewRenderer { } List 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 (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, 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) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageSources.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageSources.java index bb3d943a..c2090c58 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageSources.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageSources.java @@ -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() { } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageTypes.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageTypes.java index ff7096a4..b4761631 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageTypes.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/damage/AntarchyDamageTypes.java @@ -103,6 +103,12 @@ public final class AntarchyDamageTypes { ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hercules_beetle_obliteration") ); + public static final ResourceKey MOON_VACUUM = + ResourceKey.create( + Registries.DAMAGE_TYPE, + ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moon_vacuum") + ); + private AntarchyDamageTypes() { } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/BlockSuction.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/BlockSuction.java new file mode 100644 index 00000000..6e19b54b --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/BlockSuction.java @@ -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; + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java index ed289d0c..2a287cab 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java @@ -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++; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java index 7ed30953..dbc1478c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/item/PortalGunItem.java @@ -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> portalType; - private final Supplier> blackHoleType; private final Supplier> projectileType; private final Supplier portalMasterBlock; private final Supplier portalBaseBlock; @@ -92,7 +91,6 @@ public class PortalGunItem extends Item implements GeoItem { public PortalGunItem( Item.Properties properties, Supplier> portalType, - Supplier> blackHoleType, Supplier> projectileType, Supplier portalMasterBlock, Supplier 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(); } - 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.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) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunBlackHoleEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunBlackHoleEntity.java deleted file mode 100644 index 33b326e4..00000000 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunBlackHoleEntity.java +++ /dev/null @@ -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 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 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 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; - } -} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java index d5333c4f..5d4fcafd 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunIndicatorSync.java @@ -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 blueId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.BLUE); + Optional 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 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 portalId) { + return portalId.isPresent() + && level.getEntity(portalId.get()) instanceof PortalGunPortalEntity portal + && portal.isMoonPortal(); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunMoonMath.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunMoonMath.java new file mode 100644 index 00000000..a961dc97 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunMoonMath.java @@ -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; + } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java index c8219617..eed48480 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portalgun/PortalGunPortalEntity.java @@ -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 PORTAL_WIDTH = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor PORTAL_HEIGHT = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor OPENING_ANIMATION_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); + private static final EntityDataAccessor 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 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")); diff --git a/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json b/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json index 9d672f69..0f6b120e 100644 --- a/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json +++ b/common-1.21.1/src/main/resources/assets/antarchy/lang/en_us.json @@ -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", diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/environment/moon_view/earth.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/environment/moon_view/earth.png new file mode 100644 index 00000000..985a7165 Binary files /dev/null and b/common-1.21.1/src/main/resources/assets/antarchy/textures/environment/moon_view/earth.png differ diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/vfx/portal_gun_black_hole.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/vfx/portal_gun_black_hole.png deleted file mode 100644 index 2661e379..00000000 Binary files a/common-1.21.1/src/main/resources/assets/antarchy/textures/vfx/portal_gun_black_hole.png and /dev/null differ diff --git a/common-1.21.1/src/main/resources/data/antarchy/damage_type/moon_vacuum.json b/common-1.21.1/src/main/resources/data/antarchy/damage_type/moon_vacuum.json new file mode 100644 index 00000000..ef0a6c68 --- /dev/null +++ b/common-1.21.1/src/main/resources/data/antarchy/damage_type/moon_vacuum.json @@ -0,0 +1,7 @@ +{ + "message_id": "moon_vacuum", + "scaling": "never", + "exhaustion": 0.0, + "effects": "hurt", + "death_message_type": "default" +} diff --git a/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_armor.json b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_armor.json new file mode 100644 index 00000000..7fbead91 --- /dev/null +++ b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_armor.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "antarchy:moon_vacuum" + ] +} diff --git a/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_shield.json b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_shield.json new file mode 100644 index 00000000..7fbead91 --- /dev/null +++ b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/bypasses_shield.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "antarchy:moon_vacuum" + ] +} diff --git a/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/no_knockback.json b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/no_knockback.json new file mode 100644 index 00000000..7fbead91 --- /dev/null +++ b/common-1.21.1/src/main/resources/data/minecraft/tags/damage_type/no_knockback.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "antarchy:moon_vacuum" + ] +} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java index fd945a85..801772d8 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java @@ -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))); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java index 66fe23ac..7dcc02e4 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricEntities.java @@ -427,12 +427,6 @@ public final class AntarchyFabricEntities { .updateInterval(1) .build("portal_gun_portal")); - public static final DeferredHolder, EntityType> 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> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile", () -> EntityType.Builder.of(PortalGunProjectileEntity::new, MobCategory.MISC) .sized(0.25F, 0.25F) diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java index 71aa84e3..7df52327 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java @@ -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, diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java index 0236328d..13a9b34b 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java @@ -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 diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java index f54e5950..db6811c4 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMiscConfig.java @@ -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(); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java index ea1f378e..19422740 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java @@ -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))); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java index c75709f4..0590a476 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeEntites.java @@ -350,12 +350,6 @@ public final class AntarchyNeoforgeEntites { .updateInterval(1) .build("portal_gun_portal")); - public static final DeferredHolder, EntityType> 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> PORTAL_GUN_PROJECTILE = ENTITY_TYPES.register("portal_gun_projectile", () -> EntityType.Builder.of(PortalGunProjectileEntity::new, MobCategory.MISC) .sized(0.25F, 0.25F) diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java index e5e8690c..6f923881 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java @@ -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,