MINIONS... TONIGHT WE STEAL THE MOON
This commit is contained in:
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("portalGunMaxLiveViews")
|
||||
|| name.equals("portalGunMaxExitSpeed")
|
||||
|| name.startsWith("portalGunMoon")
|
||||
|| name.equals("hushweedSporeLifetimeSeconds")
|
||||
|| name.equals("elythiaFireflyParticlesEnabled")
|
||||
|| name.equals("duplicatorTreeEnabled")
|
||||
|
||||
@@ -559,6 +559,9 @@ public final class AntarchySettings {
|
||||
private static double portalGunMinFloorExitSpeed = 0.6D;
|
||||
private static int portalGunMaxLiveViews = 8;
|
||||
private static double portalGunMaxExitSpeed = 0.0D;
|
||||
private static boolean portalGunMoonPullsBlocks = true;
|
||||
private static int portalGunMoonPortalSeconds = 10;
|
||||
private static int portalGunMoonBlockCap = 500;
|
||||
private static boolean elythiaFireflyParticlesEnabled = true;
|
||||
private static int bloodCrystalArmorShieldRechargeTicks = 600;
|
||||
private static int bloodCrystalAppleShieldCount = 2;
|
||||
@@ -1348,6 +1351,18 @@ public final class AntarchySettings {
|
||||
portalGunMinFloorExitSpeed = Math.max(0.0D, Math.min(4.0D, value));
|
||||
}
|
||||
|
||||
public static void setPortalGunMoonPullsBlocks(boolean value) {
|
||||
portalGunMoonPullsBlocks = value;
|
||||
}
|
||||
|
||||
public static void setPortalGunMoonPortalSeconds(int value) {
|
||||
portalGunMoonPortalSeconds = Math.max(1, Math.min(120, value));
|
||||
}
|
||||
|
||||
public static void setPortalGunMoonBlockCap(int value) {
|
||||
portalGunMoonBlockCap = Math.max(0, Math.min(2000, value));
|
||||
}
|
||||
|
||||
public static void setPortalGunMaxExitSpeed(double value) {
|
||||
portalGunMaxExitSpeed = Math.max(0.0D, Math.min(100.0D, value));
|
||||
}
|
||||
@@ -1367,6 +1382,9 @@ public final class AntarchySettings {
|
||||
public static double portalGunMinFloorExitSpeed() { return portalGunMinFloorExitSpeed; }
|
||||
public static int portalGunMaxLiveViews() { return portalGunMaxLiveViews; }
|
||||
public static double portalGunMaxExitSpeed() { return portalGunMaxExitSpeed; }
|
||||
public static boolean portalGunMoonPullsBlocks() { return portalGunMoonPullsBlocks; }
|
||||
public static int portalGunMoonPortalSeconds() { return portalGunMoonPortalSeconds; }
|
||||
public static int portalGunMoonBlockCap() { return portalGunMoonBlockCap; }
|
||||
|
||||
public static void setBrownAntRequiresReagent(boolean value) {
|
||||
brownAntRequiresReagent = value;
|
||||
|
||||
-25
@@ -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");
|
||||
}
|
||||
}
|
||||
+61
@@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
-28
@@ -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));
|
||||
}
|
||||
}
|
||||
+216
@@ -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);
|
||||
}
|
||||
}
|
||||
+2
@@ -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();
|
||||
|
||||
+52
-3
@@ -130,8 +130,9 @@ public final class PortalGunPortalViewRenderer {
|
||||
}
|
||||
List<RootCandidate> candidates = new ArrayList<>();
|
||||
for (PortalGunPortalEntity portal : portals) {
|
||||
PortalGunPortalEntity linked = portal.getLinkedPortal();
|
||||
if (linked == null || !linked.isAlive() || !portal.shouldRenderFront(cameraPos)) {
|
||||
boolean moon = portal.isMoonPortal();
|
||||
PortalGunPortalEntity linked = moon ? null : portal.getLinkedPortal();
|
||||
if (!moon && (linked == null || !linked.isAlive()) || !portal.shouldRenderFront(cameraPos)) {
|
||||
continue;
|
||||
}
|
||||
ScreenClip clip = computeScreenClip(cameraPos, rootViewMatrix, rootProjection, portal, partialTick, width, height);
|
||||
@@ -173,7 +174,13 @@ public final class PortalGunPortalViewRenderer {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
if (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) {
|
||||
|
||||
+10
@@ -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() {
|
||||
}
|
||||
}
|
||||
+6
@@ -103,6 +103,12 @@ public final class AntarchyDamageTypes {
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "hercules_beetle_obliteration")
|
||||
);
|
||||
|
||||
public static final ResourceKey<DamageType> MOON_VACUUM =
|
||||
ResourceKey.create(
|
||||
Registries.DAMAGE_TYPE,
|
||||
ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moon_vacuum")
|
||||
);
|
||||
|
||||
private AntarchyDamageTypes() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.craisinlord.antarchy.content.entity;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public final class BlockSuction {
|
||||
private static final float MAX_EXPLOSION_RESISTANCE = 30.0F;
|
||||
|
||||
private BlockSuction() {
|
||||
}
|
||||
|
||||
public static boolean canLift(ServerLevel level, BlockPos pos, BlockState state) {
|
||||
return canLift(level, pos, state, false);
|
||||
}
|
||||
|
||||
public static boolean canLift(ServerLevel level, BlockPos pos, BlockState state, boolean allowCollisionless) {
|
||||
return !state.isAir()
|
||||
&& level.getBlockEntity(pos) == null
|
||||
&& state.getDestroySpeed(level, pos) >= 0.0F
|
||||
&& state.getBlock().getExplosionResistance() <= MAX_EXPLOSION_RESISTANCE
|
||||
&& (allowCollisionless ? state.getFluidState().isEmpty() : !state.getCollisionShape(level, pos).isEmpty());
|
||||
}
|
||||
|
||||
public static FallingBlockEntity lift(ServerLevel level, BlockPos pos, BlockState state, Vec3 target, double speed) {
|
||||
FallingBlockEntity falling = FallingBlockEntity.fall(level, pos, state);
|
||||
if (falling == null) {
|
||||
return null;
|
||||
}
|
||||
Vec3 towardTarget = target.subtract(falling.position());
|
||||
if (towardTarget.lengthSqr() > 0.001D) {
|
||||
falling.setDeltaMovement(towardTarget.normalize().scale(speed));
|
||||
}
|
||||
falling.hasImpulse = true;
|
||||
falling.hurtMarked = true;
|
||||
return falling;
|
||||
}
|
||||
}
|
||||
+3
-15
@@ -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++;
|
||||
}
|
||||
|
||||
+37
-20
@@ -9,8 +9,8 @@ import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
|
||||
import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer;
|
||||
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
|
||||
import com.craisinlord.antarchy.content.network.PortalGunPrimaryPayload;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunBlackHoleEntity;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunPlacement;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunMoonMath;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunProjectileEntity;
|
||||
import com.craisinlord.antarchy.content.portalgun.PortalGunSavedData;
|
||||
@@ -82,7 +82,6 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
private static final ResourceLocation MODEL_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/portal_gun.geo.json");
|
||||
private static final ResourceLocation ANIMATION_LOCATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/portal_gun.animation.json");
|
||||
private final Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType;
|
||||
private final Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType;
|
||||
private final Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType;
|
||||
private final Supplier<? extends Block> portalMasterBlock;
|
||||
private final Supplier<? extends Block> portalBaseBlock;
|
||||
@@ -92,7 +91,6 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
public PortalGunItem(
|
||||
Item.Properties properties,
|
||||
Supplier<? extends EntityType<? extends PortalGunPortalEntity>> portalType,
|
||||
Supplier<? extends EntityType<? extends PortalGunBlackHoleEntity>> blackHoleType,
|
||||
Supplier<? extends EntityType<? extends PortalGunProjectileEntity>> projectileType,
|
||||
Supplier<? extends Block> portalMasterBlock,
|
||||
Supplier<? extends Block> portalBaseBlock,
|
||||
@@ -101,7 +99,6 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
super(properties);
|
||||
this.variant = variant;
|
||||
this.portalType = portalType;
|
||||
this.blackHoleType = blackHoleType;
|
||||
this.projectileType = projectileType;
|
||||
this.portalMasterBlock = portalMasterBlock;
|
||||
this.portalBaseBlock = portalBaseBlock;
|
||||
@@ -218,9 +215,9 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
if (this.isMoonSideArmed(stack, side)) {
|
||||
this.setMoonSide(stack, null);
|
||||
}
|
||||
if (shooter instanceof Player player && this.isMoonSideArmed(stack, this.otherSide(side))) {
|
||||
this.spawnBlackHole(level, player, stack, side, placement.center());
|
||||
return;
|
||||
boolean moon = shooter instanceof Player && this.isMoonSideArmed(stack, this.otherSide(side));
|
||||
if (moon) {
|
||||
this.setMoonSide(stack, null);
|
||||
}
|
||||
PortalGunPortalEntity portal = new PortalGunPortalEntity(this.portalType.get(), level);
|
||||
portal.configure(portalOwnerId, gunId, this.variant, side, placement);
|
||||
@@ -230,9 +227,16 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface"), SoundSource.PLAYERS, 0.55F, 1.0F);
|
||||
return;
|
||||
}
|
||||
if (moon) {
|
||||
portal.openToMoon();
|
||||
}
|
||||
level.addFreshEntity(portal);
|
||||
PortalGunSavedData.setPortal(level, gunId, portalOwnerId, side, portal.getUUID());
|
||||
PortalGunPortalEntity other = this.findCounterpart(level, gunId, side);
|
||||
if (other != null && (moon || other.isMoonPortal())) {
|
||||
other.discard();
|
||||
other = null;
|
||||
}
|
||||
if (other != null) {
|
||||
portal.linkTo(other);
|
||||
other.linkTo(portal);
|
||||
@@ -277,14 +281,21 @@ public class PortalGunItem extends Item implements GeoItem {
|
||||
}
|
||||
|
||||
private boolean tryArmMoonShot(ServerLevel level, Player player, ItemStack stack, PortalGunPortalEntity.PortalSide side, boolean offhand) {
|
||||
if (!level.dimensionType().hasSkyLight() || !level.isNight() || player.getXRot() > -40.0F) {
|
||||
if (!this.isAimingAtMoon(level, player)) {
|
||||
return false;
|
||||
}
|
||||
PortalGunPortalEntity existing = this.findPlacedPortal(level, this.ensureGunId(stack, player.getUUID()), side);
|
||||
UUID gunId = this.ensureGunId(stack, player.getUUID());
|
||||
PortalGunPortalEntity existing = this.findPlacedPortal(level, gunId, side);
|
||||
if (existing != null) {
|
||||
existing.discard();
|
||||
}
|
||||
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) {
|
||||
|
||||
-196
@@ -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;
|
||||
}
|
||||
}
|
||||
+22
-12
@@ -3,8 +3,10 @@ package com.craisinlord.antarchy.content.portalgun;
|
||||
import com.craisinlord.antarchy.content.item.PortalGunItem;
|
||||
import com.craisinlord.antarchy.content.network.PortalGunIndicatorPayload;
|
||||
import com.craisinlord.antarchy.content.network.PortalGunIndicatorRequestPayload;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
@@ -27,18 +29,26 @@ public final class PortalGunIndicatorSync {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean blue = PortalGunSavedData.getPortalId(
|
||||
player.serverLevel().getServer(),
|
||||
request.gunId(),
|
||||
PortalGunPortalEntity.PortalSide.BLUE,
|
||||
player.serverLevel().dimension().location()
|
||||
).isPresent();
|
||||
boolean orange = PortalGunSavedData.getPortalId(
|
||||
player.serverLevel().getServer(),
|
||||
request.gunId(),
|
||||
PortalGunPortalEntity.PortalSide.ORANGE,
|
||||
player.serverLevel().dimension().location()
|
||||
).isPresent();
|
||||
ServerLevel level = player.serverLevel();
|
||||
Optional<UUID> blueId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.BLUE);
|
||||
Optional<UUID> orangeId = portalId(level, request.gunId(), PortalGunPortalEntity.PortalSide.ORANGE);
|
||||
PortalGunPortalEntity.PortalSide moonSide = PortalGunItem.getMoonSide(stack);
|
||||
boolean blue = blueId.isPresent()
|
||||
|| moonSide == PortalGunPortalEntity.PortalSide.BLUE
|
||||
|| isMoonPortal(level, orangeId);
|
||||
boolean orange = orangeId.isPresent()
|
||||
|| moonSide == PortalGunPortalEntity.PortalSide.ORANGE
|
||||
|| isMoonPortal(level, blueId);
|
||||
sender.accept(player, new PortalGunIndicatorPayload(request.gunId(), blue, orange));
|
||||
}
|
||||
|
||||
private static Optional<UUID> portalId(ServerLevel level, UUID gunId, PortalGunPortalEntity.PortalSide side) {
|
||||
return PortalGunSavedData.getPortalId(level.getServer(), gunId, side, level.dimension().location());
|
||||
}
|
||||
|
||||
private static boolean isMoonPortal(ServerLevel level, Optional<UUID> portalId) {
|
||||
return portalId.isPresent()
|
||||
&& level.getEntity(portalId.get()) instanceof PortalGunPortalEntity portal
|
||||
&& portal.isMoonPortal();
|
||||
}
|
||||
}
|
||||
+22
@@ -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;
|
||||
}
|
||||
}
|
||||
+238
@@ -7,6 +7,8 @@ import com.craisinlord.antarchy.content.block.entity.PortalGunPortalBaseBlockEnt
|
||||
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalCellAccess;
|
||||
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalFaceRecord;
|
||||
import com.craisinlord.antarchy.content.block.entity.PortalGunPortalMasterBlockEntity;
|
||||
import com.craisinlord.antarchy.content.damage.AntarchyDamageSources;
|
||||
import com.craisinlord.antarchy.content.entity.BlockSuction;
|
||||
import com.craisinlord.antarchy.mixins.AbstractArrowAccessor;
|
||||
import com.craisinlord.antarchy.mixins.FallingBlockEntityAccessor;
|
||||
import com.craisinlord.antarchy.mixins.ServerGamePacketListenerTeleportAccessor;
|
||||
@@ -23,6 +25,8 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
@@ -37,10 +41,15 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.ExperienceOrb;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.item.PrimedTnt;
|
||||
import net.minecraft.world.entity.vehicle.VehicleEntity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.AbstractArrow;
|
||||
@@ -78,6 +87,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
private static final EntityDataAccessor<Integer> PORTAL_WIDTH = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Integer> PORTAL_HEIGHT = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Integer> OPENING_ANIMATION_ID = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
|
||||
private static final EntityDataAccessor<Boolean> MOON = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open");
|
||||
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
|
||||
private static final int OPEN_TICKS = 5;
|
||||
@@ -88,6 +98,20 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
private static final double MAX_CLIENT_TRANSIT_START_ERROR_SQR = 1.0D;
|
||||
private static final double MAX_CLIENT_TRANSIT_MOVEMENT_SQR = 100.0D;
|
||||
private static final double PROJECTILE_PLANE_TOLERANCE = 0.1D;
|
||||
private static final double MOON_RANGE = 14.0D;
|
||||
private static final double MOON_SPREAD = 0.9D;
|
||||
private static final double MOON_PULL_STRENGTH = 0.15D;
|
||||
private static final double MOON_MAX_SPEED = 1.8D;
|
||||
private static final double MOON_MOUTH_DEPTH = 0.9D;
|
||||
private static final double MOON_HOLD_DEPTH = 0.65D;
|
||||
private static final int MOON_BLOCK_INTERVAL = 1;
|
||||
private static final int MOON_BLOCKS_PER_PULL = 4;
|
||||
private static final int MOON_BLOCK_RAYS = 16;
|
||||
private static final double MOON_RAY_STEP = 0.4D;
|
||||
private static final double MOON_BLOCK_SPEED = 0.6D;
|
||||
private static final int MOON_VACUUM_INTERVAL = 10;
|
||||
private static final float MOON_VACUUM_DAMAGE = 2.0F;
|
||||
private static final int MOON_WIND_INTERVAL = 40;
|
||||
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
|
||||
private final Map<UUID, Integer> teleportCooldowns = new HashMap<>();
|
||||
private UUID ownerId;
|
||||
@@ -96,6 +120,8 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
private int ageTicks;
|
||||
private int lastOpeningAnimationId;
|
||||
private int pairTime;
|
||||
private int moonTicks;
|
||||
private int moonSuckedBlocks;
|
||||
private BlockPos supportOrigin = BlockPos.ZERO;
|
||||
private BlockPos masterPos = BlockPos.ZERO;
|
||||
private BlockPos basePos = BlockPos.ZERO;
|
||||
@@ -128,6 +154,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
builder.define(PORTAL_WIDTH, 1);
|
||||
builder.define(PORTAL_HEIGHT, 2);
|
||||
builder.define(OPENING_ANIMATION_ID, 0);
|
||||
builder.define(MOON, false);
|
||||
}
|
||||
|
||||
public void configure(UUID ownerId, UUID gunId, PortalGunVariant variant, PortalSide side, PortalGunPlacement placement) {
|
||||
@@ -162,6 +189,19 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
this.pairTime = pairTime;
|
||||
}
|
||||
|
||||
public void openToMoon() {
|
||||
this.linkedPortalId = null;
|
||||
this.entityData.set(LINKED_PORTAL, Optional.empty());
|
||||
this.entityData.set(LINKED_PORTAL_ENTITY_ID, -1);
|
||||
this.entityData.set(MOON, true);
|
||||
this.moonTicks = 0;
|
||||
this.moonSuckedBlocks = 0;
|
||||
}
|
||||
|
||||
public boolean isMoonPortal() {
|
||||
return this.entityData.get(MOON);
|
||||
}
|
||||
|
||||
public PortalSide getPortalSide() {
|
||||
int ordinal = this.entityData.get(SIDE);
|
||||
return ordinal == PortalSide.ORANGE.ordinal() ? PortalSide.ORANGE : PortalSide.BLUE;
|
||||
@@ -572,6 +612,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
if (this.level().isClientSide) {
|
||||
if (this.isMoonPortal()) {
|
||||
this.spawnMoonParticles();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!(this.level() instanceof ServerLevel serverLevel)) {
|
||||
@@ -586,6 +629,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
this.discard();
|
||||
return;
|
||||
}
|
||||
if (this.isMoonPortal()) {
|
||||
this.tickMoon(serverLevel);
|
||||
return;
|
||||
}
|
||||
PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel);
|
||||
if (linked == null || !linked.isAlive()) {
|
||||
if (Boolean.getBoolean(DEBUG_TRAVERSAL_PROPERTY) && this.ageTicks % 40 == 0) {
|
||||
@@ -603,6 +650,189 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
this.tickTeleport(linked);
|
||||
}
|
||||
|
||||
private void tickMoon(ServerLevel level) {
|
||||
this.moonTicks++;
|
||||
if (this.moonTicks >= AntarchySettings.portalGunMoonPortalSeconds() * 20) {
|
||||
level.playSound(null, this.getX(), this.getY(), this.getZ(), sound("portal_fizzle"), SoundSource.BLOCKS, 1.0F, 0.6F);
|
||||
this.discard();
|
||||
return;
|
||||
}
|
||||
if (this.moonTicks % MOON_WIND_INTERVAL == 1) {
|
||||
level.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.ELYTRA_FLYING, SoundSource.BLOCKS, 1.4F, 0.55F);
|
||||
}
|
||||
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
|
||||
Player owner = this.getOwnerId() == null ? null : level.getPlayerByUUID(this.getOwnerId());
|
||||
this.pullMoonEntities(level, shape, owner);
|
||||
if (AntarchySettings.portalGunMoonPullsBlocks() && this.moonTicks % MOON_BLOCK_INTERVAL == 0) {
|
||||
this.pullMoonBlocks(level, shape, owner);
|
||||
}
|
||||
}
|
||||
|
||||
private static double moonLateralLimit(PortalGunWorldPortalShape shape, double depth) {
|
||||
return Math.max(shape.halfWidth(), shape.halfHeight()) + 0.5D + Math.max(0.0D, depth) * MOON_SPREAD;
|
||||
}
|
||||
|
||||
private void pullMoonEntities(ServerLevel level, PortalGunWorldPortalShape shape, Player owner) {
|
||||
Vec3 center = shape.center();
|
||||
AABB area = new AABB(center, center.add(shape.normal().scale(MOON_RANGE))).inflate(moonLateralLimit(shape, MOON_RANGE));
|
||||
Vec3 target = center.add(shape.normal().scale(0.3D));
|
||||
boolean vacuumTick = this.moonTicks % MOON_VACUUM_INTERVAL == 0;
|
||||
for (Entity entity : level.getEntities(this, area, this::canMoonAffect)) {
|
||||
Vec3 position = entity.getBoundingBox().getCenter();
|
||||
PortalGunWorldPortalShape.PortalLocalCoords local = shape.localCoords(position);
|
||||
double depth = local.depth();
|
||||
double lateral = Math.sqrt(local.horizontal() * local.horizontal() + local.vertical() * local.vertical());
|
||||
if (depth < -0.5D || depth > MOON_RANGE || lateral > moonLateralLimit(shape, depth)) {
|
||||
continue;
|
||||
}
|
||||
boolean atMouth = depth <= MOON_MOUTH_DEPTH + entity.getBbWidth() * 0.5D
|
||||
&& Math.abs(local.horizontal()) <= shape.halfWidth() + 0.25D
|
||||
&& Math.abs(local.vertical()) <= shape.halfHeight() + 0.25D;
|
||||
if (atMouth) {
|
||||
if (!this.swallowIntoSpace(level, entity, owner)) {
|
||||
this.holdInVacuum(level, entity, shape, owner, vacuumTick);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
double falloff = 1.0D - depth / MOON_RANGE;
|
||||
double strength = MOON_PULL_STRENGTH * (0.35D + falloff * falloff * 1.6D);
|
||||
Vec3 worldMotion = PortalGunTransitMath.entityVelocityToWorld(entity, entity.getDeltaMovement())
|
||||
.scale(0.92D)
|
||||
.add(target.subtract(position).normalize().scale(strength));
|
||||
if (worldMotion.length() > MOON_MAX_SPEED) {
|
||||
worldMotion = worldMotion.normalize().scale(MOON_MAX_SPEED);
|
||||
}
|
||||
applyMoonMotion(entity, worldMotion);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canMoonAffect(Entity entity) {
|
||||
if (!entity.isAlive() || entity.isPassenger() || entity.isSpectator()
|
||||
|| entity instanceof PortalGunPortalEntity || entity instanceof PortalGunProjectileEntity) {
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player player && player.isCreative()) {
|
||||
return false;
|
||||
}
|
||||
return entity instanceof LivingEntity || entity instanceof ItemEntity || entity instanceof ExperienceOrb
|
||||
|| entity instanceof FallingBlockEntity || entity instanceof Projectile
|
||||
|| entity instanceof VehicleEntity || entity instanceof PrimedTnt;
|
||||
}
|
||||
|
||||
private boolean swallowIntoSpace(ServerLevel level, Entity entity, Player owner) {
|
||||
if (entity instanceof Player || entity instanceof VehicleEntity) {
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof LivingEntity living) {
|
||||
living.hurt(AntarchyDamageSources.moonVacuum(level, owner), Float.MAX_VALUE);
|
||||
return !living.isAlive();
|
||||
}
|
||||
entity.discard();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void holdInVacuum(ServerLevel level, Entity entity, PortalGunWorldPortalShape shape, Player owner, boolean vacuumTick) {
|
||||
Vec3 hold = shape.center().add(shape.normal().scale(MOON_HOLD_DEPTH + entity.getBbWidth() * 0.5D));
|
||||
applyMoonMotion(entity, hold.subtract(entity.getBoundingBox().getCenter()).scale(0.45D));
|
||||
if (vacuumTick && entity instanceof LivingEntity living) {
|
||||
living.hurt(AntarchyDamageSources.moonVacuum(level, owner == entity ? null : owner), MOON_VACUUM_DAMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyMoonMotion(Entity entity, Vec3 worldMotion) {
|
||||
entity.setDeltaMovement(PortalGunTransitMath.entityVelocityFromWorld(entity, worldMotion));
|
||||
entity.hasImpulse = true;
|
||||
entity.fallDistance = 0.0F;
|
||||
if (entity instanceof LivingEntity) {
|
||||
entity.hurtMarked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void pullMoonBlocks(ServerLevel level, PortalGunWorldPortalShape shape, Player owner) {
|
||||
int cap = AntarchySettings.portalGunMoonBlockCap();
|
||||
int pulled = 0;
|
||||
for (int ray = 0; ray < MOON_BLOCK_RAYS && pulled < MOON_BLOCKS_PER_PULL && this.moonSuckedBlocks < cap; ray++) {
|
||||
double limit = moonLateralLimit(shape, MOON_RANGE);
|
||||
double horizontal = (this.random.nextDouble() * 2.0D - 1.0D) * limit;
|
||||
double vertical = (this.random.nextDouble() * 2.0D - 1.0D) * limit;
|
||||
if (horizontal * horizontal + vertical * vertical > limit * limit) {
|
||||
continue;
|
||||
}
|
||||
Vec3 start = shape.center()
|
||||
.add(shape.right().scale((this.random.nextDouble() * 2.0D - 1.0D) * shape.halfWidth()))
|
||||
.add(shape.up().scale((this.random.nextDouble() * 2.0D - 1.0D) * shape.halfHeight()))
|
||||
.add(shape.normal().scale(0.5D));
|
||||
Vec3 end = shape.center()
|
||||
.add(shape.right().scale(horizontal))
|
||||
.add(shape.up().scale(vertical))
|
||||
.add(shape.normal().scale(MOON_RANGE));
|
||||
BlockPos hit = this.firstBlockAlong(level, shape, start, end);
|
||||
if (hit == null) {
|
||||
continue;
|
||||
}
|
||||
BlockState state = loadedState(level, hit);
|
||||
if (state == null || !BlockSuction.canLift(level, hit, state, true)
|
||||
|| owner != null && !level.mayInteract(owner, hit)) {
|
||||
continue;
|
||||
}
|
||||
FallingBlockEntity falling = BlockSuction.lift(level, hit, state, shape.center(), MOON_BLOCK_SPEED);
|
||||
if (falling == null) {
|
||||
continue;
|
||||
}
|
||||
falling.setNoGravity(true);
|
||||
pulled++;
|
||||
this.moonSuckedBlocks++;
|
||||
}
|
||||
}
|
||||
|
||||
private BlockPos firstBlockAlong(ServerLevel level, PortalGunWorldPortalShape shape, Vec3 start, Vec3 end) {
|
||||
Vec3 delta = end.subtract(start);
|
||||
int steps = Math.max(1, (int) Math.ceil(delta.length() / MOON_RAY_STEP));
|
||||
BlockPos previous = null;
|
||||
for (int step = 0; step <= steps; step++) {
|
||||
BlockPos pos = BlockPos.containing(start.add(delta.scale((double) step / steps)));
|
||||
if (pos.equals(previous)) {
|
||||
continue;
|
||||
}
|
||||
previous = pos;
|
||||
if (shape.localCoords(Vec3.atCenterOf(pos)).depth() < 0.5D) {
|
||||
continue;
|
||||
}
|
||||
if (!level.isInWorldBounds(pos) || !level.getWorldBorder().isWithinBounds(pos)) {
|
||||
return null;
|
||||
}
|
||||
BlockState state = loadedState(level, pos);
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
if (!state.isAir()) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BlockState loadedState(ServerLevel level, BlockPos pos) {
|
||||
net.minecraft.world.level.chunk.LevelChunk chunk = level.getChunkSource()
|
||||
.getChunkNow(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
|
||||
return chunk == null ? null : chunk.getBlockState(pos);
|
||||
}
|
||||
|
||||
private void spawnMoonParticles() {
|
||||
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
|
||||
Vec3 center = shape.center();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
double depth = 1.0D + this.random.nextDouble() * MOON_RANGE * 0.6D;
|
||||
double limit = moonLateralLimit(shape, depth);
|
||||
Vec3 start = center
|
||||
.add(shape.right().scale((this.random.nextDouble() * 2.0D - 1.0D) * limit))
|
||||
.add(shape.up().scale((this.random.nextDouble() * 2.0D - 1.0D) * limit))
|
||||
.add(shape.normal().scale(depth));
|
||||
Vec3 velocity = center.subtract(start).normalize().scale(0.35D + this.random.nextDouble() * 0.3D);
|
||||
this.level().addParticle(ParticleTypes.CLOUD, start.x, start.y, start.z, velocity.x, velocity.y, velocity.z);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isStillRegistered(ServerLevel level) {
|
||||
return PortalGunSavedData.isRegistered(level, this.gunId, this.getPortalSide(), this.getUUID());
|
||||
}
|
||||
@@ -838,6 +1068,11 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
}
|
||||
tag.putInt("AgeTicks", this.ageTicks);
|
||||
tag.putInt("PairTime", this.pairTime);
|
||||
if (this.isMoonPortal()) {
|
||||
tag.putBoolean("Moon", true);
|
||||
tag.putInt("MoonTicks", this.moonTicks);
|
||||
tag.putInt("MoonSuckedBlocks", this.moonSuckedBlocks);
|
||||
}
|
||||
tag.putInt("Side", this.getPortalSide().ordinal());
|
||||
tag.putInt("Facing", this.getFacingDirection().get3DDataValue());
|
||||
tag.putInt("UpAxis", this.getUpAxis().get3DDataValue());
|
||||
@@ -887,6 +1122,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
|
||||
}
|
||||
this.ageTicks = tag.getInt("AgeTicks");
|
||||
this.pairTime = tag.getInt("PairTime");
|
||||
this.entityData.set(MOON, tag.getBoolean("Moon"));
|
||||
this.moonTicks = tag.getInt("MoonTicks");
|
||||
this.moonSuckedBlocks = tag.getInt("MoonSuckedBlocks");
|
||||
this.entityData.set(SIDE, tag.getInt("Side"));
|
||||
this.entityData.set(FACING, tag.getInt("Facing"));
|
||||
this.entityData.set(UP_AXIS, tag.getInt("UpAxis"));
|
||||
|
||||
@@ -927,6 +927,8 @@
|
||||
"advancements.antarchy.bugged_out.description": "Defeat the Alpha Mantis.",
|
||||
"death.attack.bed_bug_bite": "%1$s got bit by the bed bugs",
|
||||
"death.attack.bed_bug_bite.player": "%1$s got bit by the bed bugs while fighting %2$s",
|
||||
"death.attack.moon_vacuum": "%1$s was pulled into the vacuum of space",
|
||||
"death.attack.moon_vacuum.player": "%1$s was pulled into the vacuum of space by %2$s",
|
||||
"message.antarchy.dread_too_scared_to_sleep": "You are too scared to sleep.",
|
||||
"death.attack.kraken_mauling": "%1$s was dragged under by the Kraken",
|
||||
"death.attack.kraken_mauling.player": "%1$s was dragged under by the Kraken while fighting %2$s",
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 270 B |
BIN
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"
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user