tuft model change

typhonite textures
This commit is contained in:
craisinlord committed 2026-08-24 21:56:38 -05:00
1 parent 0b75b1ab1d
commit 53f223a86c
98 files changed
+3201 -2668

No files matched your search

@@ -0,0 +1,101 @@
package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil;
import java.util.ArrayDeque;
import java.util.Deque;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
public final class PortalGunEntityTransformationStack {
private final Entity entity;
private final Deque<EntityTransformation> stack = new ArrayDeque<>();
public PortalGunEntityTransformationStack(Entity entity) {
this.entity = entity;
}
public void push() {
this.stack.push(EntityTransformation.capture(this.entity));
}
public void pop() {
if (!this.stack.isEmpty()) {
this.stack.pop().restore(this.entity);
}
}
public Vec3 moveEntity(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, float partialTick) {
Vec3 interpolated = new Vec3(
net.minecraft.util.Mth.lerp(partialTick, this.entity.xo, this.entity.getX()),
net.minecraft.util.Mth.lerp(partialTick, this.entity.yo, this.entity.getY()),
net.minecraft.util.Mth.lerp(partialTick, this.entity.zo, this.entity.getZ())
);
Vec3 previous = new Vec3(this.entity.xo, this.entity.yo, this.entity.zo);
Vec3 transformed = destinationPortal.position().add(PortalGunTransformUtil.transformPosition(sourcePortal, destinationPortal, interpolated.subtract(sourcePortal.position())));
Vec3 transformedPrevious = destinationPortal.position().add(PortalGunTransformUtil.transformPosition(sourcePortal, destinationPortal, previous.subtract(sourcePortal.position())));
Vec3 look = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, this.entity.getLookAngle()).normalize();
Vec3 velocity = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, this.entity.getDeltaMovement());
float yaw = PortalGunTransformUtil.yawFromLook(look);
float pitch = PortalGunTransformUtil.pitchFromLook(look);
this.entity.setPos(transformed.x, transformed.y, transformed.z);
this.entity.xo = transformedPrevious.x;
this.entity.yo = transformedPrevious.y;
this.entity.zo = transformedPrevious.z;
this.entity.setYRot(yaw);
this.entity.setXRot(pitch);
this.entity.yRotO = yaw;
this.entity.xRotO = pitch;
this.entity.setDeltaMovement(velocity);
if (this.entity instanceof LivingEntity living) {
living.setYHeadRot(yaw);
living.setYBodyRot(yaw);
}
return transformed;
}
public void reset() {
while (!this.stack.isEmpty()) {
this.pop();
}
}
private record EntityTransformation(
double x,
double y,
double z,
double xo,
double yo,
double zo,
float yRot,
float xRot,
float yRotO,
float xRotO,
float yHeadRot,
float yBodyRot,
Vec3 deltaMovement
) {
private static EntityTransformation capture(Entity entity) {
float yHeadRot = entity instanceof LivingEntity living ? living.getYHeadRot() : entity.getYRot();
float yBodyRot = entity instanceof LivingEntity living ? living.yBodyRot : entity.getYRot();
return new EntityTransformation(entity.getX(), entity.getY(), entity.getZ(), entity.xo, entity.yo, entity.zo, entity.getYRot(), entity.getXRot(), entity.yRotO, entity.xRotO, yHeadRot, yBodyRot, entity.getDeltaMovement());
}
private void restore(Entity entity) {
entity.setPos(this.x, this.y, this.z);
entity.xo = this.xo;
entity.yo = this.yo;
entity.zo = this.zo;
entity.setYRot(this.yRot);
entity.setXRot(this.xRot);
entity.yRotO = this.yRotO;
entity.xRotO = this.xRotO;
entity.setDeltaMovement(this.deltaMovement);
if (entity instanceof LivingEntity living) {
living.setYHeadRot(this.yHeadRot);
living.setYBodyRot(this.yBodyRot);
}
}
}
}
@@ -3,10 +3,14 @@ package com.craisinlord.antarchy.content.client;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape; import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
public final class PortalGunPortalRenderState { public final class PortalGunPortalRenderState {
private static final ThreadLocal<Deque<PortalGunWorldPortalShape>> ACTIVE_DESTINATION_SHAPES = ThreadLocal.withInitial(ArrayDeque::new); private static final ThreadLocal<Deque<PortalGunWorldPortalShape>> ACTIVE_DESTINATION_SHAPES = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<Deque<PortalGunWorldPortalShape>> ACTIVE_SOURCE_SHAPES = ThreadLocal.withInitial(ArrayDeque::new); private static final ThreadLocal<Deque<PortalGunWorldPortalShape>> ACTIVE_SOURCE_SHAPES = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<Deque<PortalRenderContext>> ACTIVE_CONTEXTS = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<Integer> RENDER_ALL_DEPTH = ThreadLocal.withInitial(() -> 0); private static final ThreadLocal<Integer> RENDER_ALL_DEPTH = ThreadLocal.withInitial(() -> 0);
private PortalGunPortalRenderState() { private PortalGunPortalRenderState() {
@@ -20,6 +24,11 @@ public final class PortalGunPortalRenderState {
} }
} }
public static void pushPortalView(PortalRenderContext context) {
ACTIVE_CONTEXTS.get().push(context);
pushPortalView(context.sourceShape(), context.destinationShape(), context.renderAll());
}
public static void popPortalView(boolean renderAll) { public static void popPortalView(boolean renderAll) {
Deque<PortalGunWorldPortalShape> sourceShapes = ACTIVE_SOURCE_SHAPES.get(); Deque<PortalGunWorldPortalShape> sourceShapes = ACTIVE_SOURCE_SHAPES.get();
if (!sourceShapes.isEmpty()) { if (!sourceShapes.isEmpty()) {
@@ -43,6 +52,13 @@ public final class PortalGunPortalRenderState {
RENDER_ALL_DEPTH.set(depth); RENDER_ALL_DEPTH.set(depth);
} }
} }
Deque<PortalRenderContext> contexts = ACTIVE_CONTEXTS.get();
if (!contexts.isEmpty()) {
contexts.pop();
}
if (contexts.isEmpty()) {
ACTIVE_CONTEXTS.remove();
}
} }
public static void pushDestinationShape(PortalGunWorldPortalShape shape) { public static void pushDestinationShape(PortalGunWorldPortalShape shape) {
@@ -69,7 +85,55 @@ public final class PortalGunPortalRenderState {
return shapes.isEmpty() ? null : shapes.peek(); return shapes.isEmpty() ? null : shapes.peek();
} }
public static PortalRenderContext getContext() {
Deque<PortalRenderContext> contexts = ACTIVE_CONTEXTS.get();
return contexts.isEmpty() ? null : contexts.peek();
}
public static int getRenderLevel() {
return ACTIVE_CONTEXTS.get().size();
}
public static boolean renderAll() { public static boolean renderAll() {
return RENDER_ALL_DEPTH.get() > 0; return RENDER_ALL_DEPTH.get() > 0;
} }
public static boolean shouldRenderBounds(AABB bounds) {
if (renderAll()) {
return true;
}
PortalRenderContext context = getContext();
if (context == null) {
PortalGunWorldPortalShape destinationShape = getDestinationShape();
PortalGunWorldPortalShape sourceShape = getSourceShape();
return destinationShape == null || shouldRenderBounds(bounds, sourceShape, destinationShape, false);
}
return shouldRenderBounds(bounds, context.sourceShape(), context.destinationShape(), context.renderAll());
}
private static boolean shouldRenderBounds(AABB bounds, PortalGunWorldPortalShape sourceShape, PortalGunWorldPortalShape destinationShape, boolean renderAll) {
if (renderAll) {
return true;
}
if (!destinationShape.intersectsFront(bounds, 0.125D)) {
return false;
}
if (!destinationShape.intersectsPortalColumn(bounds, 1.5D, 1.5D, destinationShape.halfDepth() + 96.0D)) {
return false;
}
return sourceShape == null || !sourceShape.intersectsFront(bounds, -0.02D);
}
public record PortalRenderContext(
PortalGunWorldPortalShape sourceShape,
PortalGunWorldPortalShape destinationShape,
Vec3 cameraPos,
Vec3 look,
Vec3 up,
Matrix4f viewMatrix,
Matrix4f projectionMatrix,
int renderLevel,
boolean renderAll
) {
}
} }
@@ -8,10 +8,9 @@ import java.util.UUID;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
public final class PortalGunRollClientState { public final class PortalGunRollClientState {
private static final int TELEPORT_COOLDOWN_TICKS = 15; private static final int TELEPORT_COOLDOWN_TICKS = 40;
private static final float ROLL_DECAY = 0.85F; private static final float ROLL_DECAY = 0.85F;
private static final float ROLL_EPSILON = 0.05F; private static final float ROLL_EPSILON = 0.05F;
private static final Map<UUID, Long> TELEPORT_COOLDOWNS = new HashMap<>(); private static final Map<UUID, Long> TELEPORT_COOLDOWNS = new HashMap<>();
@@ -82,10 +81,11 @@ public final class PortalGunRollClientState {
if (!canTeleport(cameraEntity, gameTime)) { if (!canTeleport(cameraEntity, gameTime)) {
continue; continue;
} }
if (portal.resolveCrossingProbe(cameraEntity) == null) { Vec3 crossingProbe = portal.resolveCrossingProbe(cameraEntity);
if (crossingProbe == null) {
continue; continue;
} }
applyPredictedTeleport(cameraEntity, portal, linkedPortal, gameTime); applyPredictedTeleport(cameraEntity, portal, linkedPortal, crossingProbe, gameTime);
break; break;
} }
} }
@@ -98,11 +98,26 @@ public final class PortalGunRollClientState {
return cooldownUntil <= gameTime; return cooldownUntil <= gameTime;
} }
private static void applyPredictedTeleport(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, long gameTime) { private static void applyPredictedTeleport(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 currentProbe, long gameTime) {
Quaternionf transform = PortalGunTransformUtil.createTransform(sourcePortal, destinationPortal); Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.getLookAngle()).normalize();
Vec3 transformedLook = PortalGunTransformUtil.transform(entity.getLookAngle(), transform).normalize(); Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, PortalGunTransformUtil.upVectorFromLookAndRoll(entity.getLookAngle(), rollDegrees)).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transform(PortalGunTransformUtil.upVectorFromLookAndRoll(entity.getLookAngle(), rollDegrees), transform).normalize(); Vec3 relativeProbe = currentProbe.subtract(sourcePortal.position());
Vec3 transformedProbe = PortalGunTransformUtil.transformPosition(sourcePortal, destinationPortal, relativeProbe);
Vec3 transformedEntityOffset = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.position().subtract(currentProbe));
Vec3 destinationNormal = destinationPortal.getNormalVec().normalize();
double exitClearance = Math.max(0.35D, entity.getBbWidth() * 0.5D + 0.16D);
Vec3 exitProbe = destinationPortal.position().add(transformedProbe).add(destinationNormal.scale(exitClearance - transformedProbe.dot(destinationNormal)));
Vec3 exitPos = exitProbe.add(transformedEntityOffset);
Vec3 transformedMotion = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.getDeltaMovement());
double outward = transformedMotion.dot(destinationNormal);
if (outward < 0.42D) {
transformedMotion = transformedMotion.add(destinationNormal.scale(0.42D - outward));
}
rollDegrees = PortalGunTransformUtil.rollFromOrientation(transformedLook, transformedUp); rollDegrees = PortalGunTransformUtil.rollFromOrientation(transformedLook, transformedUp);
entity.teleportTo(exitPos.x, exitPos.y, exitPos.z);
entity.setDeltaMovement(transformedMotion);
entity.setYRot(PortalGunTransformUtil.yawFromLook(transformedLook));
entity.setXRot(PortalGunTransformUtil.pitchFromLook(transformedLook));
TELEPORT_COOLDOWNS.put(entity.getUUID(), gameTime + TELEPORT_COOLDOWN_TICKS); TELEPORT_COOLDOWNS.put(entity.getUUID(), gameTime + TELEPORT_COOLDOWN_TICKS);
} }
} }
@@ -3,15 +3,16 @@ package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.model.PortalGunPortalModel; import com.craisinlord.antarchy.content.client.model.PortalGunPortalModel;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.core.Direction; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f; import org.joml.Matrix4f;
import org.joml.Quaternionf;
import software.bernie.geckolib.renderer.GeoEntityRenderer; import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class PortalGunPortalRenderer extends GeoEntityRenderer<PortalGunPortalEntity> { public class PortalGunPortalRenderer extends GeoEntityRenderer<PortalGunPortalEntity> {
@@ -22,20 +23,39 @@ public class PortalGunPortalRenderer extends GeoEntityRenderer<PortalGunPortalEn
@Override @Override
public void render(PortalGunPortalEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) { public void render(PortalGunPortalEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) {
super.render(entity, entityYaw, partialTick, poseStack, bufferSource, 0xF000F0); poseStack.pushPose();
VertexConsumer consumer = bufferSource.getBuffer(RenderType.entityTranslucent(this.getTextureLocation(entity)));
Matrix4f pose = poseStack.last().pose();
putPortalVertex(consumer, pose, entity, -0.5F, -1.0F, 0.0F, 1.0F, false);
putPortalVertex(consumer, pose, entity, -0.5F, 1.0F, 0.0F, 0.0F, false);
putPortalVertex(consumer, pose, entity, 0.5F, 1.0F, 1.0F, 0.0F, false);
putPortalVertex(consumer, pose, entity, 0.5F, -1.0F, 1.0F, 1.0F, false);
VertexConsumer edge = bufferSource.getBuffer(RenderType.entityTranslucent(this.getTextureLocation(entity)));
putPortalVertex(edge, pose, entity, -0.56F, -1.07F, 0.0F, 1.0F, true);
putPortalVertex(edge, pose, entity, -0.56F, 1.07F, 0.0F, 0.0F, true);
putPortalVertex(edge, pose, entity, 0.56F, 1.07F, 1.0F, 0.0F, true);
putPortalVertex(edge, pose, entity, 0.56F, -1.07F, 1.0F, 1.0F, true);
poseStack.popPose();
}
private static void putPortalVertex(VertexConsumer consumer, Matrix4f pose, PortalGunPortalEntity entity, float horizontal, float vertical, float u, float v, boolean channelTint) {
Vec3 position = entity.getWidthVec().normalize().scale(horizontal)
.add(entity.getUpVec().normalize().scale(vertical))
.add(entity.getNormalVec().normalize().scale(0.03125D));
int red = channelTint ? entity.getChannelRed() : 255;
int green = channelTint ? entity.getChannelGreen() : 255;
int blue = channelTint ? entity.getChannelBlue() : 255;
int alpha = channelTint ? 150 : 210;
consumer.addVertex(pose, (float) position.x, (float) position.y, (float) position.z)
.setColor(red, green, blue, alpha)
.setUv(u, v)
.setOverlay(OverlayTexture.NO_OVERLAY)
.setLight(LightTexture.FULL_BRIGHT)
.setNormal((float) entity.getNormalVec().x, (float) entity.getNormalVec().y, (float) entity.getNormalVec().z);
} }
@Override @Override
protected void applyRotations(PortalGunPortalEntity animatable, PoseStack poseStack, float ageInTicks, float rotationYaw, float partialTick, float nativeScale) { protected void applyRotations(PortalGunPortalEntity animatable, PoseStack poseStack, float ageInTicks, float rotationYaw, float partialTick, float nativeScale) {
Vec3 width = animatable.getWidthVec();
Vec3 up = animatable.getUpVec();
Vec3 normal = animatable.getNormalVec();
Matrix3f basis = new Matrix3f(
(float) width.x, (float) up.x, (float) -normal.x,
(float) width.y, (float) up.y, (float) -normal.y,
(float) width.z, (float) up.z, (float) -normal.z
);
poseStack.mulPose(basis.getNormalizedRotation(new Quaternionf()));
} }
@Override @Override
@@ -1,9 +1,11 @@
package com.craisinlord.antarchy.content.client.renderer; package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.client.PortalGunEntityTransformationStack;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState; import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil; import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@@ -11,6 +13,7 @@ import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferUploader; import com.mojang.blaze3d.vertex.BufferUploader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.ArrayList; import java.util.ArrayList;
@@ -18,6 +21,7 @@ import java.util.List;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker; import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@@ -36,24 +40,36 @@ public final class PortalGunPortalViewRenderer {
private static final ResourceLocation ORANGE_OVERLAY = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_orange.png"); private static final ResourceLocation ORANGE_OVERLAY = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/vfx/portal_gun_portal_orange.png");
private static final TextureTarget[] PORTAL_TARGETS = new TextureTarget[MAX_RECURSION_DEPTH + 1]; private static final TextureTarget[] PORTAL_TARGETS = new TextureTarget[MAX_RECURSION_DEPTH + 1];
private static boolean renderingPortalView; private static boolean renderingPortalView;
private static long lastRenderLogTick = Long.MIN_VALUE;
private static long lastHookLogTick = Long.MIN_VALUE;
private PortalGunPortalViewRenderer() { private PortalGunPortalViewRenderer() {
} }
public static boolean isEnabled() {
return false;
}
public static void render(Camera camera, Matrix4f poseMatrix, DeltaTracker tickCounter) { public static void render(Camera camera, Matrix4f poseMatrix, DeltaTracker tickCounter) {
if (!isEnabled()) {
return;
}
if (renderingPortalView) { if (renderingPortalView) {
return; return;
} }
Minecraft minecraft = Minecraft.getInstance(); Minecraft minecraft = Minecraft.getInstance();
if (minecraft.level == null || minecraft.gameRenderer == null || camera == null || poseMatrix == null || tickCounter == null) { if (minecraft.level == null || minecraft.gameRenderer == null || camera == null || poseMatrix == null || tickCounter == null) {
logRenderUnavailable(minecraft, camera, poseMatrix, tickCounter);
return; return;
} }
logRenderHook(minecraft, camera);
Entity cameraEntity = minecraft.getCameraEntity(); Entity cameraEntity = minecraft.getCameraEntity();
if (cameraEntity == null) { if (cameraEntity == null) {
return; return;
} }
List<PortalGunPortalEntity> portals = collectVisiblePortals(minecraft, camera); List<PortalGunPortalEntity> portals = collectVisiblePortals(minecraft, camera);
if (portals.isEmpty()) { if (portals.isEmpty()) {
logRenderEmpty(minecraft, camera.getPosition());
return; return;
} }
ensureTargets(minecraft); ensureTargets(minecraft);
@@ -67,18 +83,60 @@ public final class PortalGunPortalViewRenderer {
RenderContext rootContext = new RenderContext(cameraPos, rootLook, rootUp, rootViewMatrix); RenderContext rootContext = new RenderContext(cameraPos, rootLook, rootUp, rootViewMatrix);
renderingPortalView = true; renderingPortalView = true;
RenderSystem.backupProjectionMatrix(); RenderSystem.backupProjectionMatrix();
for (PortalGunPortalEntity portal : portals) { try {
PortalGunPortalEntity linkedPortal = portal.getLinkedPortal(); logRenderCollection(minecraft, cameraPos, portals);
if (linkedPortal == null || !linkedPortal.isAlive()) { for (PortalGunPortalEntity portal : portals) {
continue; PortalGunPortalEntity linkedPortal = portal.getLinkedPortal();
if (linkedPortal == null || !linkedPortal.isAlive()) {
logRenderSkip(minecraft, portal);
minecraft.getMainRenderTarget().bindWrite(true);
drawPortalOverlay(minecraft, cameraPos, poseMatrix, portal);
continue;
}
int textureId = renderPortalSurface(minecraft, cameraEntity, tickCounter, rootContext, portal, linkedPortal, 0);
RenderSystem.restoreProjectionMatrix();
RenderSystem.backupProjectionMatrix();
minecraft.getMainRenderTarget().bindWrite(true);
drawPortalQuad(cameraPos, poseMatrix, portal, textureId);
minecraft.getEntityRenderDispatcher().prepare(minecraft.level, camera, cameraEntity);
drawPortalOverlay(minecraft, cameraPos, poseMatrix, portal);
} }
int textureId = renderPortalSurface(minecraft, cameraEntity, tickCounter, rootContext, portal, linkedPortal, 0); } catch (RuntimeException exception) {
minecraft.getMainRenderTarget().bindWrite(true); Antarchy.LOGGER.error("Portal gun portal view render failed", exception);
drawPortalQuad(cameraPos, poseMatrix, portal, textureId); } finally {
drawPortalOverlay(minecraft, cameraPos, poseMatrix, portal); RenderSystem.restoreProjectionMatrix();
renderingPortalView = false;
} }
RenderSystem.restoreProjectionMatrix(); }
renderingPortalView = false;
private static void logRenderUnavailable(Minecraft minecraft, Camera camera, Matrix4f poseMatrix, DeltaTracker tickCounter) {
if (minecraft.level == null) {
return;
}
long gameTime = minecraft.level.getGameTime();
if (lastHookLogTick != Long.MIN_VALUE && gameTime - lastHookLogTick < 100L) {
return;
}
lastHookLogTick = gameTime;
Antarchy.LOGGER.info("Portal gun render unavailable level={} gameRenderer={} camera={} pose={} tickCounter={}", minecraft.level != null, minecraft.gameRenderer != null, camera != null, poseMatrix != null, tickCounter != null);
}
private static void logRenderHook(Minecraft minecraft, Camera camera) {
if (minecraft.level == null) {
return;
}
long gameTime = minecraft.level.getGameTime();
if (lastHookLogTick != Long.MIN_VALUE && gameTime - lastHookLogTick < 100L) {
return;
}
lastHookLogTick = gameTime;
int portalCount = 0;
for (Entity entity : minecraft.level.entitiesForRendering()) {
if (entity instanceof PortalGunPortalEntity portal && portal.isAlive()) {
portalCount++;
}
}
Antarchy.LOGGER.info("Portal gun render hook tick stage camera={} portals={}", camera.getPosition(), portalCount);
} }
private static List<PortalGunPortalEntity> collectVisiblePortals(Minecraft minecraft, Camera camera) { private static List<PortalGunPortalEntity> collectVisiblePortals(Minecraft minecraft, Camera camera) {
@@ -91,10 +149,7 @@ public final class PortalGunPortalViewRenderer {
if (!(entity instanceof PortalGunPortalEntity portal) || !portal.isAlive()) { if (!(entity instanceof PortalGunPortalEntity portal) || !portal.isAlive()) {
continue; continue;
} }
if (portal.getLinkedPortalId() == null) { if (portal.distanceToSqr(cameraPos) > 16384.0D) {
continue;
}
if (!portal.shouldRenderFront(cameraPos)) {
continue; continue;
} }
portals.add(portal); portals.add(portal);
@@ -103,6 +158,61 @@ public final class PortalGunPortalViewRenderer {
return portals; return portals;
} }
private static void logRenderEmpty(Minecraft minecraft, Vec3 cameraPos) {
if (minecraft.level == null) {
return;
}
long gameTime = minecraft.level.getGameTime();
if (lastRenderLogTick != Long.MIN_VALUE && gameTime - lastRenderLogTick < 100L) {
return;
}
lastRenderLogTick = gameTime;
int portalCount = 0;
int linkedCount = 0;
int frontCount = 0;
for (Entity entity : minecraft.level.entitiesForRendering()) {
if (!(entity instanceof PortalGunPortalEntity portal) || !portal.isAlive()) {
continue;
}
portalCount++;
if (portal.getLinkedPortalId() != null) {
linkedCount++;
}
if (portal.shouldRenderFront(cameraPos)) {
frontCount++;
}
}
Antarchy.LOGGER.info("Portal gun render collected count=0 totalPortals={} linkedPortals={} frontPortals={} camera={}", portalCount, linkedCount, frontCount, cameraPos);
}
private static void logRenderCollection(Minecraft minecraft, Vec3 cameraPos, List<PortalGunPortalEntity> portals) {
if (minecraft.level == null) {
return;
}
long gameTime = minecraft.level.getGameTime();
if (lastRenderLogTick != Long.MIN_VALUE && gameTime - lastRenderLogTick < 100L) {
return;
}
lastRenderLogTick = gameTime;
Antarchy.LOGGER.info("Portal gun render collected count={} camera={}", portals.size(), cameraPos);
for (PortalGunPortalEntity portal : portals) {
PortalGunWorldPortalShape.PortalLocalCoords coords = portal.getWorldPortalShape().localCoords(cameraPos);
Antarchy.LOGGER.info("Portal gun render portal portal={} side={} linked={} center={} facing={} up={} cameraDepth={} cameraHorizontal={} cameraVertical={}", portal.getUUID(), portal.getPortalSide(), portal.getLinkedPortalId(), portal.position(), portal.getFacingDirection(), portal.getUpAxis(), coords.depth(), coords.horizontal(), coords.vertical());
}
}
private static void logRenderSkip(Minecraft minecraft, PortalGunPortalEntity portal) {
if (minecraft.level == null) {
return;
}
long gameTime = minecraft.level.getGameTime();
if (lastRenderLogTick != Long.MIN_VALUE && gameTime - lastRenderLogTick < 20L) {
return;
}
lastRenderLogTick = gameTime;
Antarchy.LOGGER.info("Portal gun render skipped missing linked portal portal={} side={} linked={}", portal.getUUID(), portal.getPortalSide(), portal.getLinkedPortalId());
}
private static void ensureTargets(Minecraft minecraft) { private static void ensureTargets(Minecraft minecraft) {
int width = minecraft.getWindow().getWidth(); int width = minecraft.getWindow().getWidth();
int height = minecraft.getWindow().getHeight(); int height = minecraft.getWindow().getHeight();
@@ -148,10 +258,24 @@ public final class PortalGunPortalViewRenderer {
if (clipEnabled) { if (clipEnabled) {
RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height()); RenderSystem.enableScissor(clip.x(), clip.y(), clip.width(), clip.height());
} }
PortalGunPortalRenderState.pushPortalView(sourcePortal.getWorldPortalShape(), destinationPortal.getWorldPortalShape(), renderAll); PortalGunPortalRenderState.PortalRenderContext portalRenderContext = new PortalGunPortalRenderState.PortalRenderContext(
sourcePortal.getWorldPortalShape(),
destinationPortal.getWorldPortalShape(),
transformedContext.cameraPos(),
transformedContext.look(),
transformedContext.up(),
transformedContext.viewMatrix(),
clippedProjectionMatrix,
depth,
renderAll
);
PortalGunPortalRenderState.pushPortalView(portalRenderContext);
try { try {
minecraft.levelRenderer.prepareCullFrustum(portalCamera.getPosition(), transformedContext.viewMatrix(), clippedProjectionMatrix); minecraft.levelRenderer.prepareCullFrustum(portalCamera.getPosition(), transformedContext.viewMatrix(), clippedProjectionMatrix);
minecraft.levelRenderer.renderLevel(tickCounter, false, portalCamera, minecraft.gameRenderer, minecraft.gameRenderer.lightTexture(), transformedContext.viewMatrix(), clippedProjectionMatrix); minecraft.levelRenderer.renderLevel(tickCounter, false, portalCamera, minecraft.gameRenderer, minecraft.gameRenderer.lightTexture(), transformedContext.viewMatrix(), clippedProjectionMatrix);
target.bindWrite(true);
minecraft.getEntityRenderDispatcher().prepare(minecraft.level, portalCamera, cameraEntity);
renderPortalTransitionEntities(minecraft, transformedContext.cameraPos(), tickCounter.getGameTimeDeltaPartialTick(true), sourcePortal, destinationPortal);
if (depth < MAX_RECURSION_DEPTH) { if (depth < MAX_RECURSION_DEPTH) {
List<PortalGunPortalEntity> nestedPortals = collectVisiblePortals(minecraft, transformedContext.cameraPos()); List<PortalGunPortalEntity> nestedPortals = collectVisiblePortals(minecraft, transformedContext.cameraPos());
Matrix4f nestedPose = new Matrix4f().identity(); Matrix4f nestedPose = new Matrix4f().identity();
@@ -164,6 +288,8 @@ public final class PortalGunPortalViewRenderer {
continue; continue;
} }
int nestedTextureId = renderPortalSurface(minecraft, cameraEntity, tickCounter, transformedContext, nestedPortal, nestedLinked, depth + 1); int nestedTextureId = renderPortalSurface(minecraft, cameraEntity, tickCounter, transformedContext, nestedPortal, nestedLinked, depth + 1);
RenderSystem.restoreProjectionMatrix();
RenderSystem.backupProjectionMatrix();
target.bindWrite(true); target.bindWrite(true);
drawPortalQuad(transformedContext.cameraPos(), nestedPose, nestedPortal, nestedTextureId); drawPortalQuad(transformedContext.cameraPos(), nestedPose, nestedPortal, nestedTextureId);
drawPortalOverlay(minecraft, transformedContext.cameraPos(), nestedPose, nestedPortal); drawPortalOverlay(minecraft, transformedContext.cameraPos(), nestedPose, nestedPortal);
@@ -179,7 +305,6 @@ public final class PortalGunPortalViewRenderer {
} }
private static RenderContext transformContext(RenderContext currentContext, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal) { private static RenderContext transformContext(RenderContext currentContext, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal) {
Quaternionf transform = PortalGunTransformUtil.createTransform(sourcePortal, destinationPortal);
Vec3 destinationNormal = destinationPortal.getNormalVec().normalize(); Vec3 destinationNormal = destinationPortal.getNormalVec().normalize();
Vec3 relativeEye = currentContext.cameraPos().subtract(sourcePortal.position()); Vec3 relativeEye = currentContext.cameraPos().subtract(sourcePortal.position());
double depthOffset = Math.max(CAMERA_OFFSET, relativeEye.dot(sourcePortal.getNormalVec().normalize())); double depthOffset = Math.max(CAMERA_OFFSET, relativeEye.dot(sourcePortal.getNormalVec().normalize()));
@@ -187,8 +312,8 @@ public final class PortalGunPortalViewRenderer {
Vec3 destinationEye = destinationPortal.position() Vec3 destinationEye = destinationPortal.position()
.add(transformedEyeOffset) .add(transformedEyeOffset)
.add(destinationNormal.scale(depthOffset + CAMERA_OFFSET - transformedEyeOffset.dot(destinationNormal))); .add(destinationNormal.scale(depthOffset + CAMERA_OFFSET - transformedEyeOffset.dot(destinationNormal)));
Vec3 transformedLook = PortalGunTransformUtil.transform(currentContext.look(), transform).normalize(); Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, currentContext.look()).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transform(currentContext.up(), transform).normalize(); Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, currentContext.up()).normalize();
Matrix4f viewMatrix = new Matrix4f().rotation(PortalGunTransformUtil.orientationQuaternion(transformedLook, transformedUp).conjugate(new Quaternionf())); Matrix4f viewMatrix = new Matrix4f().rotation(PortalGunTransformUtil.orientationQuaternion(transformedLook, transformedUp).conjugate(new Quaternionf()));
return new RenderContext(destinationEye, transformedLook, transformedUp, viewMatrix); return new RenderContext(destinationEye, transformedLook, transformedUp, viewMatrix);
} }
@@ -290,6 +415,66 @@ public final class PortalGunPortalViewRenderer {
drawTexturedPortal(cameraPos, poseMatrix, portal, textureId, SURFACE_OFFSET, 1.0F, 1.0F, 1.0F, 1.0F, false); drawTexturedPortal(cameraPos, poseMatrix, portal, textureId, SURFACE_OFFSET, 1.0F, 1.0F, 1.0F, 1.0F, false);
} }
private static void renderPortalTransitionEntities(Minecraft minecraft, Vec3 cameraPos, float partialTick, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal) {
if (minecraft.level == null || minecraft.getEntityRenderDispatcher() == null || minecraft.renderBuffers() == null) {
return;
}
MultiBufferSource.BufferSource bufferSource = minecraft.renderBuffers().bufferSource();
PoseStack poseStack = new PoseStack();
for (Entity entity : minecraft.level.entitiesForRendering()) {
if (!shouldRenderTransitionEntity(entity, sourcePortal, destinationPortal)) {
continue;
}
renderTransitionEntity(minecraft, cameraPos, partialTick, sourcePortal, destinationPortal, entity, poseStack, bufferSource);
for (Entity passenger : entity.getPassengers()) {
if (shouldRenderTransitionEntity(passenger, sourcePortal, destinationPortal)) {
renderTransitionEntity(minecraft, cameraPos, partialTick, sourcePortal, destinationPortal, passenger, poseStack, bufferSource);
}
}
}
bufferSource.endBatch();
}
private static boolean shouldRenderTransitionEntity(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal) {
return entity != null
&& entity.isAlive()
&& !(entity instanceof PortalGunPortalEntity)
&& entity != sourcePortal
&& entity != destinationPortal
&& sourcePortal.intersectsEntityBounds(entity);
}
private static void renderTransitionEntity(Minecraft minecraft, Vec3 cameraPos, float partialTick, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Entity entity, PoseStack poseStack, MultiBufferSource.BufferSource bufferSource) {
PortalGunEntityTransformationStack transformationStack = new PortalGunEntityTransformationStack(entity);
transformationStack.push();
try {
Vec3 transformedPosition = transformationStack.moveEntity(sourcePortal, destinationPortal, partialTick);
Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.getLookAngle()).normalize();
float yaw = PortalGunTransformUtil.yawFromLook(transformedLook);
int light = minecraft.getEntityRenderDispatcher().getPackedLightCoords(entity, partialTick);
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
PortalGunPortalRenderState.pushDestinationShape(destinationPortal.getWorldPortalShape());
try {
minecraft.getEntityRenderDispatcher().render(
entity,
transformedPosition.x - cameraPos.x,
transformedPosition.y - cameraPos.y,
transformedPosition.z - cameraPos.z,
yaw,
partialTick,
poseStack,
bufferSource,
light
);
} finally {
PortalGunPortalRenderState.popDestinationShape();
}
} finally {
transformationStack.pop();
}
}
private static int widthTimesHeight(Minecraft minecraft) { private static int widthTimesHeight(Minecraft minecraft) {
return minecraft.getWindow().getWidth() * minecraft.getWindow().getHeight(); return minecraft.getWindow().getWidth() * minecraft.getWindow().getHeight();
} }
@@ -298,13 +483,16 @@ public final class PortalGunPortalViewRenderer {
float time = (minecraft.level.getGameTime() + minecraft.getTimer().getGameTimeDeltaPartialTick(false)) * 0.075F; float time = (minecraft.level.getGameTime() + minecraft.getTimer().getGameTimeDeltaPartialTick(false)) * 0.075F;
float pulse = 0.72F + 0.18F * (float) Math.sin(time); float pulse = 0.72F + 0.18F * (float) Math.sin(time);
float edge = 0.38F + 0.08F * (float) Math.cos(time * 1.7F); float edge = 0.38F + 0.08F * (float) Math.cos(time * 1.7F);
float channelRed = portal.getChannelRed() / 255.0F;
float channelGreen = portal.getChannelGreen() / 255.0F;
float channelBlue = portal.getChannelBlue() / 255.0F;
if (portal.getPortalSide() == PortalGunPortalEntity.PortalSide.BLUE) { if (portal.getPortalSide() == PortalGunPortalEntity.PortalSide.BLUE) {
drawTexturedPortal(cameraPos, poseMatrix, portal, BLUE_OVERLAY, OVERLAY_OFFSET, 0.78F, 0.94F, 1.0F, pulse, false); drawTexturedPortal(cameraPos, poseMatrix, portal, BLUE_OVERLAY, OVERLAY_OFFSET, 0.78F, 0.94F, 1.0F, pulse, false);
drawTexturedPortal(cameraPos, poseMatrix, portal, BLUE_OVERLAY, OVERLAY_OFFSET + 0.0008D, 0.26F, 0.62F, 1.0F, edge, true); drawTexturedPortal(cameraPos, poseMatrix, portal, BLUE_OVERLAY, OVERLAY_OFFSET + 0.0008D, channelRed, channelGreen, channelBlue, edge, true);
return; return;
} }
drawTexturedPortal(cameraPos, poseMatrix, portal, ORANGE_OVERLAY, OVERLAY_OFFSET, 1.0F, 0.84F, 0.46F, pulse, false); drawTexturedPortal(cameraPos, poseMatrix, portal, ORANGE_OVERLAY, OVERLAY_OFFSET, 1.0F, 0.84F, 0.46F, pulse, false);
drawTexturedPortal(cameraPos, poseMatrix, portal, ORANGE_OVERLAY, OVERLAY_OFFSET + 0.0008D, 1.0F, 0.48F, 0.16F, edge, true); drawTexturedPortal(cameraPos, poseMatrix, portal, ORANGE_OVERLAY, OVERLAY_OFFSET + 0.0008D, channelRed, channelGreen, channelBlue, edge, true);
} }
private static void drawTexturedPortal(Vec3 cameraPos, Matrix4f poseMatrix, PortalGunPortalEntity portal, ResourceLocation texture, double offset, float red, float green, float blue, float alpha, boolean additive) { private static void drawTexturedPortal(Vec3 cameraPos, Matrix4f poseMatrix, PortalGunPortalEntity portal, ResourceLocation texture, double offset, float red, float green, float blue, float alpha, boolean additive) {
@@ -324,6 +512,7 @@ public final class PortalGunPortalViewRenderer {
RenderSystem.defaultBlendFunc(); RenderSystem.defaultBlendFunc();
} }
RenderSystem.depthMask(false); RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
RenderSystem.disableCull(); RenderSystem.disableCull();
RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, texture); RenderSystem.setShaderTexture(0, texture);
@@ -340,6 +529,7 @@ public final class PortalGunPortalViewRenderer {
} }
RenderSystem.enableCull(); RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true); RenderSystem.depthMask(true);
RenderSystem.disableBlend(); RenderSystem.disableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
@@ -362,6 +552,7 @@ public final class PortalGunPortalViewRenderer {
RenderSystem.defaultBlendFunc(); RenderSystem.defaultBlendFunc();
} }
RenderSystem.depthMask(false); RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
RenderSystem.disableCull(); RenderSystem.disableCull();
RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, textureId); RenderSystem.setShaderTexture(0, textureId);
@@ -378,6 +569,7 @@ public final class PortalGunPortalViewRenderer {
} }
RenderSystem.enableCull(); RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true); RenderSystem.depthMask(true);
RenderSystem.disableBlend(); RenderSystem.disableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
@@ -26,15 +26,17 @@ public class PortalGunProjectileRenderer extends EntityRenderer<PortalGunProject
poseStack.pushPose(); poseStack.pushPose();
poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation()); poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation());
float age = entity.tickCount + partialTick; float age = entity.tickCount + partialTick;
float syncedDistance = entity.getSyncedDistance() + partialTick;
float pulse = 0.8F + 0.2F * (float) Math.sin(age * 0.9F); float pulse = 0.8F + 0.2F * (float) Math.sin(age * 0.9F);
float trailStretch = 1.1F + (float) Math.min(entity.getDeltaMovement().length() * 0.3D, 1.4D); float travelPulse = 0.82F + 0.18F * (float) Math.sin(syncedDistance * 0.55F);
float trailStretch = 1.1F + (float) Math.min(entity.getSyncedVelocity().length() * 0.42D, 1.8D);
float baseScale = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.44F : 0.48F; float baseScale = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.44F : 0.48F;
ResourceLocation texture = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? BLUE_TEXTURE : ORANGE_TEXTURE; ResourceLocation texture = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? BLUE_TEXTURE : ORANGE_TEXTURE;
float red = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.55F : 1.0F; float red = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.55F : 1.0F;
float green = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.82F : 0.56F; float green = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 0.82F : 0.56F;
float blue = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 1.0F : 0.18F; float blue = entity.getPortalSide() == com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity.PortalSide.BLUE ? 1.0F : 0.18F;
poseStack.scale(baseScale * trailStretch, baseScale, baseScale); poseStack.scale(baseScale * trailStretch, baseScale * travelPulse, baseScale * travelPulse);
PoseStack.Pose pose = poseStack.last(); PoseStack.Pose pose = poseStack.last();
Matrix4f matrix = pose.pose(); Matrix4f matrix = pose.pose();
VertexConsumer core = bufferSource.getBuffer(RenderType.entityTranslucent(texture)); VertexConsumer core = bufferSource.getBuffer(RenderType.entityTranslucent(texture));
@@ -50,7 +52,7 @@ public class PortalGunProjectileRenderer extends EntityRenderer<PortalGunProject
glow = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)); glow = bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture));
addQuad(glow, pose, matrix, 1.0F, 1.0F, 1.0F, 0.52F * pulse, 0xF000F0, -0.62F, -1.15F, 0.62F, 1.15F); addQuad(glow, pose, matrix, 1.0F, 1.0F, 1.0F, 0.52F * pulse, 0xF000F0, -0.62F, -1.15F, 0.62F, 1.15F);
poseStack.popPose(); poseStack.popPose();
} }
@Override @Override
protected int getBlockLightLevel(PortalGunProjectileEntity entity, BlockPos pos) { protected int getBlockLightLevel(PortalGunProjectileEntity entity, BlockPos pos) {
@@ -49,9 +49,9 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
private static final double ACCELERATION = 0.08D; private static final double ACCELERATION = 0.08D;
private static final double MAX_SPEED = 1.8D; private static final double MAX_SPEED = 1.8D;
private static final double ASCEND_SPEED = 0.15D; private static final double ASCEND_SPEED = 0.15D;
private static final double SETTLE_DESCEND_SPEED = 0.08D;
private static final double DAMPING = 0.955D; private static final double DAMPING = 0.955D;
private static final double RIDER_Y_OFFSET = 0.65D; private static final double RIDER_Y_OFFSET = 0.65D;
private static final float RIDER_FORWARD_HEAD_OFFSET = 90.0F;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@@ -153,15 +153,11 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
this.yBodyRot = this.getYRot(); this.yBodyRot = this.getYRot();
this.yHeadRot = this.getYRot(); this.yHeadRot = this.getYRot();
this.setXRot(0.0F); this.setXRot(0.0F);
rider.setYHeadRot(rider.getYRot() + RIDER_FORWARD_HEAD_OFFSET);
Vec3 look = Vec3.directionFromRotation(0.0F, this.getYRot()); Vec3 look = Vec3.directionFromRotation(0.0F, this.getYRot());
float forward = rider.zza; float forward = rider.zza;
boolean holdingJump = ((LivingEntityJumpingAccessor) rider).antarchy$isJumping(); boolean holdingJump = ((LivingEntityJumpingAccessor) rider).antarchy$isJumping();
double ascend = holdingJump ? ASCEND_SPEED : (rider.isShiftKeyDown() ? -ASCEND_SPEED : 0.0D); double verticalMotion = this.resolveVerticalMotion(holdingJump);
double groundHeight = this.findGroundHeight();
double maxY = groundHeight + MAX_HOVER_HEIGHT;
Vec3 currentHorizontal = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z); Vec3 currentHorizontal = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z);
Vec3 horizontalMotion = currentHorizontal.scale(DAMPING).add(look.scale(forward * ACCELERATION)); Vec3 horizontalMotion = currentHorizontal.scale(DAMPING).add(look.scale(forward * ACCELERATION));
@@ -172,23 +168,30 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
horizontalMotion = new Vec3(horizontalMotion.x * scale, 0.0D, horizontalMotion.z * scale); horizontalMotion = new Vec3(horizontalMotion.x * scale, 0.0D, horizontalMotion.z * scale);
} }
double verticalMotion = ascend;
if (this.getY() >= maxY && verticalMotion > 0.0D) {
verticalMotion = 0.0D;
}
if (this.getY() <= groundHeight && verticalMotion < 0.0D) {
verticalMotion = 0.0D;
}
this.setDeltaMovement(horizontalMotion.x, verticalMotion, horizontalMotion.z); this.setDeltaMovement(horizontalMotion.x, verticalMotion, horizontalMotion.z);
this.move(MoverType.SELF, this.getDeltaMovement()); this.move(MoverType.SELF, this.getDeltaMovement());
return; return;
} }
this.setDeltaMovement(this.getDeltaMovement().scale(DAMPING)); double verticalMotion = this.resolveVerticalMotion(false);
Vec3 horizontalMotion = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z).scale(DAMPING);
this.setDeltaMovement(horizontalMotion.x, verticalMotion, horizontalMotion.z);
this.move(MoverType.SELF, this.getDeltaMovement()); this.move(MoverType.SELF, this.getDeltaMovement());
} }
private double resolveVerticalMotion(boolean holdingJump) {
double groundHeight = this.findGroundHeight();
double maxY = groundHeight + MAX_HOVER_HEIGHT;
if (this.getY() > maxY) {
return -SETTLE_DESCEND_SPEED;
}
if (holdingJump) {
return this.getY() >= maxY ? 0.0D : ASCEND_SPEED;
}
return this.getY() <= groundHeight ? 0.0D : -SETTLE_DESCEND_SPEED;
}
private double findGroundHeight() { private double findGroundHeight() {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()));
int minY = this.level().getMinBuildHeight(); int minY = this.level().getMinBuildHeight();
@@ -141,10 +141,12 @@ public class PortalGunItem extends Item implements GeoItem {
PortalGunPortalEntity existing = this.findPlacedPortal(level, player.getUUID(), side); PortalGunPortalEntity existing = this.findPlacedPortal(level, player.getUUID(), side);
PortalGunPlacement placement = this.findPlacement(level, player, side, hitResult, existing); PortalGunPlacement placement = this.findPlacement(level, player, side, hitResult, existing);
if (placement == null) { if (placement == null) {
Antarchy.LOGGER.info("Portal gun placement failed owner={} side={} hitBlock={} hitFace={} hitLocation={}", player.getUUID(), side, hitResult.getBlockPos(), hitResult.getDirection(), hitResult.getLocation());
level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface", SoundEvents.DISPENSER_FAIL), SoundSource.PLAYERS, 0.55F, 1.0F); level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface", SoundEvents.DISPENSER_FAIL), SoundSource.PLAYERS, 0.55F, 1.0F);
return; return;
} }
if (existing != null) { if (existing != null) {
Antarchy.LOGGER.info("Portal gun replacing existing portal owner={} side={} oldPortal={}", player.getUUID(), side, existing.getUUID());
existing.discard(); existing.discard();
} }
if (this.isMoonSideArmed(stack, side)) { if (this.isMoonSideArmed(stack, side)) {
@@ -158,17 +160,22 @@ public class PortalGunItem extends Item implements GeoItem {
portal.configure(player.getUUID(), side, placement); portal.configure(player.getUUID(), side, placement);
portal.moveTo(placement.center().x, placement.center().y, placement.center().z, placement.yaw(), 0.0F); portal.moveTo(placement.center().x, placement.center().y, placement.center().z, placement.yaw(), 0.0F);
if (!this.placePortalBlocks(level, player.getUUID(), side, portal, placement)) { if (!this.placePortalBlocks(level, player.getUUID(), side, portal, placement)) {
Antarchy.LOGGER.info("Portal gun block placement failed owner={} side={} portal={} center={} facing={} up={} master={} base={}", player.getUUID(), side, portal.getUUID(), placement.center(), placement.facing(), placement.upAxis(), placement.masterPos(), placement.basePos());
level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface", SoundEvents.DISPENSER_FAIL), SoundSource.PLAYERS, 0.55F, 1.0F); level.playSound(null, impactPos.x, impactPos.y, impactPos.z, PortalGunPortalEntity.sound("portal_gun_invalid_surface", SoundEvents.DISPENSER_FAIL), SoundSource.PLAYERS, 0.55F, 1.0F);
return; return;
} }
level.addFreshEntity(portal); level.addFreshEntity(portal);
PortalGunSavedData.setPortal(level.getServer(), player.getUUID(), side, portal.getUUID()); PortalGunSavedData.setPortal(level.getServer(), player.getUUID(), side, portal.getUUID());
Antarchy.LOGGER.info("Portal gun portal placed owner={} side={} portal={} center={} facing={} up={} width={} master={} base={}", player.getUUID(), side, portal.getUUID(), placement.center(), placement.facing(), placement.upAxis(), placement.widthAxis(), placement.masterPos(), placement.basePos());
PortalGunPortalEntity other = this.findCounterpart(level, player.getUUID(), side); PortalGunPortalEntity other = this.findCounterpart(level, player.getUUID(), side);
if (other != null) { if (other != null) {
portal.linkTo(other); portal.linkTo(other);
other.linkTo(portal); other.linkTo(portal);
this.syncPortalBlocks(level, portal); this.syncPortalBlocks(level, portal);
this.syncPortalBlocks(level, other); this.syncPortalBlocks(level, other);
Antarchy.LOGGER.info("Portal gun portals linked owner={} placedSide={} placedPortal={} otherPortal={} otherSide={}", player.getUUID(), side, portal.getUUID(), other.getUUID(), other.getPortalSide());
} else {
Antarchy.LOGGER.info("Portal gun portal waiting for counterpart owner={} side={} portal={}", player.getUUID(), side, portal.getUUID());
} }
String openPath = side == PortalGunPortalEntity.PortalSide.BLUE ? "portal_open_blue" : "portal_open_orange"; String openPath = side == PortalGunPortalEntity.PortalSide.BLUE ? "portal_open_blue" : "portal_open_orange";
level.playSound(null, portal.getX(), portal.getY(), portal.getZ(), PortalGunPortalEntity.sound(openPath, SoundEvents.END_PORTAL_SPAWN), SoundSource.PLAYERS, 0.45F, side == PortalGunPortalEntity.PortalSide.BLUE ? 1.05F : 0.92F); level.playSound(null, portal.getX(), portal.getY(), portal.getZ(), PortalGunPortalEntity.sound(openPath, SoundEvents.END_PORTAL_SPAWN), SoundSource.PLAYERS, 0.45F, side == PortalGunPortalEntity.PortalSide.BLUE ? 1.05F : 0.92F);
@@ -70,8 +70,8 @@ public final class PortalGunCollisionHelper {
Vec3 endCenter = endBox.getCenter(); Vec3 endCenter = endBox.getCenter();
PortalGunWorldPortalShape.PortalLocalCoords startCoords = shape.localCoords(startCenter); PortalGunWorldPortalShape.PortalLocalCoords startCoords = shape.localCoords(startCenter);
PortalGunWorldPortalShape.PortalLocalCoords endCoords = shape.localCoords(endCenter); PortalGunWorldPortalShape.PortalLocalCoords endCoords = shape.localCoords(endCenter);
return startCoords.depth() < 0.0D return startCoords.depth() > 0.0D
&& endCoords.depth() <= PLANE_TOLERANCE && endCoords.depth() >= -PLANE_TOLERANCE
&& Math.abs(endCoords.horizontal()) <= shape.halfWidth() + EDGE_PADDING && Math.abs(endCoords.horizontal()) <= shape.halfWidth() + EDGE_PADDING
&& Math.abs(endCoords.vertical()) <= shape.halfHeight() + EDGE_PADDING && Math.abs(endCoords.vertical()) <= shape.halfHeight() + EDGE_PADDING
&& projectedWindowOverlap(shape, startBox, endBox); && projectedWindowOverlap(shape, startBox, endBox);
@@ -82,8 +82,8 @@ public final class PortalGunCollisionHelper {
PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(corner); PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(corner);
if (Math.abs(coords.horizontal()) <= shape.halfWidth() + EDGE_PADDING if (Math.abs(coords.horizontal()) <= shape.halfWidth() + EDGE_PADDING
&& Math.abs(coords.vertical()) <= shape.halfHeight() + EDGE_PADDING && Math.abs(coords.vertical()) <= shape.halfHeight() + EDGE_PADDING
&& coords.depth() >= -DEPTH_PADDING && coords.depth() <= DEPTH_PADDING
&& coords.depth() <= PLANE_TOLERANCE) { && coords.depth() >= -PLANE_TOLERANCE) {
return true; return true;
} }
} }
@@ -9,6 +9,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -17,6 +18,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.network.syncher.SynchedEntityData;
@@ -25,6 +27,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
@@ -36,7 +39,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager; import software.bernie.geckolib.animation.AnimatableManager;
@@ -56,19 +58,26 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private static final EntityDataAccessor<Integer> FACING = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor<Integer> FACING = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> UP_AXIS = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor<Integer> UP_AXIS = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Boolean> CLOSING = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.BOOLEAN); private static final EntityDataAccessor<Boolean> CLOSING = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.BOOLEAN);
private static final EntityDataAccessor<Optional<UUID>> LINKED_PORTAL = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.OPTIONAL_UUID);
private static final EntityDataAccessor<Integer> CHANNEL_RED = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> CHANNEL_GREEN = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> CHANNEL_BLUE = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open"); private static final RawAnimation OPEN_ANIM = RawAnimation.begin().thenPlay("open");
private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle"); private static final RawAnimation IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation CLOSE_ANIM = RawAnimation.begin().thenPlay("close"); private static final RawAnimation CLOSE_ANIM = RawAnimation.begin().thenPlay("close");
private static final int OPEN_TICKS = 10; private static final int OPEN_TICKS = 10;
private static final int CLOSE_TICKS = 10; private static final int CLOSE_TICKS = 10;
private static final int MAX_LIFETIME_TICKS = 20 * 60 * 20; private static final int MAX_LIFETIME_TICKS = 20 * 60 * 20;
private static final int TELEPORT_COOLDOWN_TICKS = 15; private static final int TELEPORT_COOLDOWN_TICKS = 40;
private static final double PLAYER_PORTAL_INSIDE_SHIFT = 0.05D; private static final double PLAYER_PORTAL_INSIDE_SHIFT = 0.05D;
private static final double HALF_WIDTH = 0.5D; private static final double HALF_WIDTH = 0.5D;
private static final double HALF_HEIGHT = 1.0D; private static final double HALF_HEIGHT = 1.0D;
private static final double HALF_DEPTH = 0.35D; private static final double HALF_DEPTH = 0.35D;
private static final double MIN_EXIT_MOMENTUM = 0.42D;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private final Map<UUID, Integer> teleportCooldowns = new HashMap<>(); private final Map<UUID, Integer> teleportCooldowns = new HashMap<>();
private final Map<UUID, Integer> portalEntityDepths = new HashMap<>();
private Set<UUID> lastScanEntities = new HashSet<>();
private UUID ownerId; private UUID ownerId;
private UUID linkedPortalId; private UUID linkedPortalId;
private int ageTicks; private int ageTicks;
@@ -92,6 +101,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
builder.define(FACING, Direction.NORTH.get3DDataValue()); builder.define(FACING, Direction.NORTH.get3DDataValue());
builder.define(UP_AXIS, Direction.UP.get3DDataValue()); builder.define(UP_AXIS, Direction.UP.get3DDataValue());
builder.define(CLOSING, false); builder.define(CLOSING, false);
builder.define(LINKED_PORTAL, Optional.empty());
builder.define(CHANNEL_RED, 58);
builder.define(CHANNEL_GREEN, 166);
builder.define(CHANNEL_BLUE, 255);
} }
public void configure(UUID ownerId, PortalSide side, PortalGunPlacement placement) { public void configure(UUID ownerId, PortalSide side, PortalGunPlacement placement) {
@@ -99,6 +112,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.entityData.set(SIDE, side.ordinal()); this.entityData.set(SIDE, side.ordinal());
this.entityData.set(FACING, placement.facing().get3DDataValue()); this.entityData.set(FACING, placement.facing().get3DDataValue());
this.entityData.set(UP_AXIS, placement.upAxis().get3DDataValue()); this.entityData.set(UP_AXIS, placement.upAxis().get3DDataValue());
int[] channelColor = generateChannelColor(ownerId, side);
this.entityData.set(CHANNEL_RED, channelColor[0]);
this.entityData.set(CHANNEL_GREEN, channelColor[1]);
this.entityData.set(CHANNEL_BLUE, channelColor[2]);
this.supportOrigin = placement.supportOrigin().immutable(); this.supportOrigin = placement.supportOrigin().immutable();
this.masterPos = placement.masterPos().immutable(); this.masterPos = placement.masterPos().immutable();
this.basePos = placement.basePos().immutable(); this.basePos = placement.basePos().immutable();
@@ -108,11 +125,13 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
public void linkTo(PortalGunPortalEntity other) { public void linkTo(PortalGunPortalEntity other) {
this.linkedPortalId = other.getUUID(); this.linkedPortalId = other.getUUID();
this.entityData.set(LINKED_PORTAL, Optional.of(other.getUUID()));
this.pairTime = (int) this.level().getGameTime(); this.pairTime = (int) this.level().getGameTime();
} }
public void restorePair(UUID linkedPortalId, int pairTime) { public void restorePair(UUID linkedPortalId, int pairTime) {
this.linkedPortalId = linkedPortalId; this.linkedPortalId = linkedPortalId;
this.entityData.set(LINKED_PORTAL, Optional.ofNullable(linkedPortalId));
this.pairTime = pairTime; this.pairTime = pairTime;
} }
@@ -130,7 +149,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
public UUID getLinkedPortalId() { public UUID getLinkedPortalId() {
return this.linkedPortalId; return this.entityData.get(LINKED_PORTAL).orElse(this.linkedPortalId);
} }
public BlockPos getMasterPos() { public BlockPos getMasterPos() {
@@ -141,6 +160,18 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
return this.ownerId; return this.ownerId;
} }
public int getChannelRed() {
return this.entityData.get(CHANNEL_RED);
}
public int getChannelGreen() {
return this.entityData.get(CHANNEL_GREEN);
}
public int getChannelBlue() {
return this.entityData.get(CHANNEL_BLUE);
}
public BlockPos getBasePos() { public BlockPos getBasePos() {
return this.basePos; return this.basePos;
} }
@@ -158,10 +189,11 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
public PortalGunPortalEntity getLinkedPortal() { public PortalGunPortalEntity getLinkedPortal() {
if (this.linkedPortalId == null) { UUID linkedId = this.getLinkedPortalId();
if (linkedId == null) {
return null; return null;
} }
List<Entity> entities = this.level().getEntities(this, new AABB(-3.0E7D, -3.0E7D, -3.0E7D, 3.0E7D, 3.0E7D, 3.0E7D), entity -> this.linkedPortalId.equals(entity.getUUID())); List<Entity> entities = this.level().getEntities(this, new AABB(-3.0E7D, -3.0E7D, -3.0E7D, 3.0E7D, 3.0E7D, 3.0E7D), entity -> linkedId.equals(entity.getUUID()));
if (entities.isEmpty()) { if (entities.isEmpty()) {
return null; return null;
} }
@@ -216,7 +248,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
public AABB getCollisionRemovalAabbForEntity(Entity entity) { public AABB getCollisionRemovalAabbForEntity(Entity entity) {
double speed = entity.getDeltaMovement().length(); double speed = entity.getDeltaMovement().length();
double extent = Math.max(1.0D, Math.max(entity.getBbWidth(), entity.getBbHeight()) + speed); double extent = Math.max(1.0D, Math.max(entity.getBbWidth(), entity.getBbHeight()) + speed);
return this.getFlatPlane().expandTowards(this.getNormalVec().normalize().scale(-extent)); return this.getFlatPlane().expandTowards(this.getNormalVec().normalize().scale(extent));
} }
public Vec3 teleportProbePosition(Entity entity) { public Vec3 teleportProbePosition(Entity entity) {
@@ -253,7 +285,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
Vec3 previousProbe = this.previousTeleportProbePosition(entity); Vec3 previousProbe = this.previousTeleportProbePosition(entity);
Vec3 currentProbe = this.teleportProbePosition(entity); Vec3 currentProbe = this.teleportProbePosition(entity);
return this.crossesPortal(previousProbe, currentProbe) ? currentProbe : null; if (this.crossesPortal(previousProbe, currentProbe)) {
return currentProbe;
}
return this.overlapsPortalVolume(entity) ? this.portalVolumeProbe(entity) : null;
} }
public boolean containsPoint(Vec3 position) { public boolean containsPoint(Vec3 position) {
@@ -317,8 +352,14 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel); PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel);
if (linked == null || !linked.isAlive()) { if (linked == null || !linked.isAlive()) {
if (this.ageTicks % 100 == 0) {
Antarchy.LOGGER.info("Portal gun portal has no loaded linked portal portal={} owner={} side={} linked={}", this.getUUID(), this.ownerId, this.getPortalSide(), this.linkedPortalId);
}
return; return;
} }
if (this.ageTicks % 80 == 0) {
this.level().playSound(null, this.blockPosition(), sound("portal_ambient", SoundEvents.PORTAL_AMBIENT), SoundSource.BLOCKS, 0.18F, this.getPortalSide() == PortalSide.BLUE ? 1.05F : 0.92F);
}
this.tickTeleport(linked); this.tickTeleport(linked);
} }
@@ -351,15 +392,46 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private void tickTeleport(PortalGunPortalEntity linked) { private void tickTeleport(PortalGunPortalEntity linked) {
List<Entity> entities = this.level().getEntities(this, this.getScanRange(), this::canTeleportEntity); List<Entity> entities = this.level().getEntities(this, this.getScanRange(), this::canTeleportEntity);
this.updatePortalEntityScan(linked, entities);
if (!entities.isEmpty() && this.ageTicks % 20 == 0) {
Antarchy.LOGGER.info("Portal gun teleport scan portal={} side={} linked={} count={} scan={}", this.getUUID(), this.getPortalSide(), linked.getUUID(), entities.size(), this.getScanRange());
}
for (Entity entity : entities) { for (Entity entity : entities) {
Vec3 crossingProbe = this.resolveCrossingProbe(entity); Vec3 crossingProbe = this.resolveCrossingProbe(entity);
if (crossingProbe == null) { if (crossingProbe == null) {
if (this.ageTicks % 40 == 0) {
PortalGunWorldPortalShape.PortalLocalCoords coords = this.getWorldPortalShape().localCoords(this.teleportProbePosition(entity));
PortalBounds bounds = this.portalBounds(entity.getBoundingBox());
Antarchy.LOGGER.info("Portal gun entity in scan did not cross portal={} entity={} entityType={} depth={} horizontal={} vertical={} boxDepthMin={} boxDepthMax={} boxHorizontalMin={} boxHorizontalMax={} boxVerticalMin={} boxVerticalMax={} movement={}", this.getUUID(), entity.getUUID(), EntityType.getKey(entity.getType()), coords.depth(), coords.horizontal(), coords.vertical(), bounds.minDepth(), bounds.maxDepth(), bounds.minHorizontal(), bounds.maxHorizontal(), bounds.minVertical(), bounds.maxVertical(), entity.getDeltaMovement());
}
continue; continue;
} }
Antarchy.LOGGER.info("Portal gun teleport crossing portal={} side={} linked={} entity={} entityType={} probe={}", this.getUUID(), this.getPortalSide(), linked.getUUID(), entity.getUUID(), EntityType.getKey(entity.getType()), crossingProbe);
this.teleportEntity(entity, linked, crossingProbe); this.teleportEntity(entity, linked, crossingProbe);
} }
} }
private void updatePortalEntityScan(PortalGunPortalEntity linked, List<Entity> entities) {
Set<UUID> currentScan = new HashSet<>();
for (Entity entity : entities) {
UUID entityId = entity.getUUID();
currentScan.add(entityId);
PortalBounds bounds = this.portalBounds(entity.getBoundingBox());
int depthBucket = (int) Math.round(bounds.minDepth() * 1000.0D);
this.portalEntityDepths.put(entityId, depthBucket);
if (!this.lastScanEntities.contains(entityId)) {
Antarchy.LOGGER.info("Portal gun entity entered scan portal={} linked={} entity={} entityType={} minDepth={} maxDepth={} minHorizontal={} maxHorizontal={} minVertical={} maxVertical={} motion={}", this.getUUID(), linked.getUUID(), entityId, EntityType.getKey(entity.getType()), bounds.minDepth(), bounds.maxDepth(), bounds.minHorizontal(), bounds.maxHorizontal(), bounds.minVertical(), bounds.maxVertical(), entity.getDeltaMovement());
}
}
for (UUID previous : this.lastScanEntities) {
if (!currentScan.contains(previous)) {
Integer depth = this.portalEntityDepths.remove(previous);
Antarchy.LOGGER.info("Portal gun entity left scan portal={} linked={} entity={} lastDepth={}", this.getUUID(), linked.getUUID(), previous, depth);
}
}
this.lastScanEntities = currentScan;
}
private boolean canTeleportEntity(Entity entity) { private boolean canTeleportEntity(Entity entity) {
if (!entity.isAlive() || entity instanceof PortalGunPortalEntity || entity.isPassenger() || entity.isVehicle()) { if (!entity.isAlive() || entity instanceof PortalGunPortalEntity || entity.isPassenger() || entity.isVehicle()) {
return false; return false;
@@ -376,6 +448,72 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
return new PortalLocalCoords(coords.horizontal(), coords.vertical(), coords.depth()); return new PortalLocalCoords(coords.horizontal(), coords.vertical(), coords.depth());
} }
private boolean overlapsPortalVolume(Entity entity) {
PortalBounds bounds = this.portalBounds(entity.getBoundingBox());
double edgePadding = entity instanceof Player ? 0.22D : 0.14D;
double frontDepth = entity instanceof Player ? 0.5D : 0.36D;
double backDepth = entity instanceof Player ? 0.28D : 0.22D;
double normalVelocity = entity.getDeltaMovement().dot(this.getNormalVec().normalize());
boolean movingIntoPortal = normalVelocity < -0.01D;
boolean straddlingPlane = bounds.minDepth() <= 0.03D && bounds.maxDepth() >= -0.03D;
boolean inFrame = bounds.maxHorizontal() >= -HALF_WIDTH - edgePadding
&& bounds.minHorizontal() <= HALF_WIDTH + edgePadding
&& bounds.maxVertical() >= -HALF_HEIGHT - edgePadding
&& bounds.minVertical() <= HALF_HEIGHT + edgePadding
&& bounds.maxDepth() >= -backDepth
&& bounds.minDepth() <= frontDepth;
return inFrame && (movingIntoPortal || straddlingPlane);
}
private Vec3 portalVolumeProbe(Entity entity) {
Vec3 probe = this.teleportProbePosition(entity);
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(probe);
double horizontal = clamp(coords.horizontal(), -HALF_WIDTH + 0.05D, HALF_WIDTH - 0.05D);
double vertical = clamp(coords.vertical(), -HALF_HEIGHT + 0.05D, HALF_HEIGHT - 0.05D);
return shape.center()
.add(shape.right().scale(horizontal))
.add(shape.up().scale(vertical))
.subtract(shape.normal().scale(0.01D));
}
private PortalBounds portalBounds(AABB bounds) {
PortalGunWorldPortalShape shape = this.getWorldPortalShape();
double minHorizontal = Double.POSITIVE_INFINITY;
double maxHorizontal = Double.NEGATIVE_INFINITY;
double minVertical = Double.POSITIVE_INFINITY;
double maxVertical = Double.NEGATIVE_INFINITY;
double minDepth = Double.POSITIVE_INFINITY;
double maxDepth = Double.NEGATIVE_INFINITY;
for (Vec3 corner : boxCorners(bounds)) {
PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(corner);
minHorizontal = Math.min(minHorizontal, coords.horizontal());
maxHorizontal = Math.max(maxHorizontal, coords.horizontal());
minVertical = Math.min(minVertical, coords.vertical());
maxVertical = Math.max(maxVertical, coords.vertical());
minDepth = Math.min(minDepth, coords.depth());
maxDepth = Math.max(maxDepth, coords.depth());
}
return new PortalBounds(minHorizontal, maxHorizontal, minVertical, maxVertical, minDepth, maxDepth);
}
private static Vec3[] boxCorners(AABB bounds) {
return new Vec3[] {
new Vec3(bounds.minX, bounds.minY, bounds.minZ),
new Vec3(bounds.minX, bounds.minY, bounds.maxZ),
new Vec3(bounds.minX, bounds.maxY, bounds.minZ),
new Vec3(bounds.minX, bounds.maxY, bounds.maxZ),
new Vec3(bounds.maxX, bounds.minY, bounds.minZ),
new Vec3(bounds.maxX, bounds.minY, bounds.maxZ),
new Vec3(bounds.maxX, bounds.maxY, bounds.minZ),
new Vec3(bounds.maxX, bounds.maxY, bounds.maxZ)
};
}
private static double clamp(double value, double min, double max) {
return Math.max(min, Math.min(max, value));
}
private List<Vec3> portalSamples(Entity entity, AABB box, boolean previous) { private List<Vec3> portalSamples(Entity entity, AABB box, boolean previous) {
Vec3 center = new Vec3((box.minX + box.maxX) * 0.5D, (box.minY + box.maxY) * 0.5D, (box.minZ + box.maxZ) * 0.5D); Vec3 center = new Vec3((box.minX + box.maxX) * 0.5D, (box.minY + box.maxY) * 0.5D, (box.minZ + box.maxZ) * 0.5D);
Vec3 topCenter = new Vec3(center.x, box.maxY, center.z); Vec3 topCenter = new Vec3(center.x, box.maxY, center.z);
@@ -414,18 +552,21 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
private void teleportEntity(Entity entity, PortalGunPortalEntity destination, Vec3 currentProbe) { private void teleportEntity(Entity entity, PortalGunPortalEntity destination, Vec3 currentProbe) {
Quaternionf transform = PortalGunTransformUtil.createTransform(this, destination);
Vec3 relativeProbe = currentProbe.subtract(this.position()); Vec3 relativeProbe = currentProbe.subtract(this.position());
Vec3 transformedProbe = PortalGunTransformUtil.transform(relativeProbe, transform); Vec3 transformedProbe = PortalGunTransformUtil.transformPosition(this, destination, relativeProbe);
Vec3 entityOffsetFromProbe = entity.position().subtract(currentProbe); Vec3 entityOffsetFromProbe = entity.position().subtract(currentProbe);
Vec3 transformedEntityOffset = PortalGunTransformUtil.transform(entityOffsetFromProbe, transform); Vec3 transformedEntityOffset = PortalGunTransformUtil.transformVector(this, destination, entityOffsetFromProbe);
Vec3 transformedLook = PortalGunTransformUtil.transform(entity.getLookAngle(), transform).normalize(); Vec3 transformedLook = PortalGunTransformUtil.transformVector(this, destination, entity.getLookAngle()).normalize();
Vec3 transformedMotion = PortalGunTransformUtil.transform(entity.getDeltaMovement(), transform); Vec3 entryMotion = this.portalEntryMomentum(entity, currentProbe);
Vec3 exitProbe = destination.position().add(transformedProbe).add(destination.getNormalVec().normalize().scale(0.08D - transformedProbe.dot(destination.getNormalVec().normalize()))); Vec3 transformedMotion = this.exitMomentum(entity, destination, PortalGunTransformUtil.transformVector(this, destination, entryMotion));
Vec3 exitPos = exitProbe.add(transformedEntityOffset); double exitClearance = Math.max(0.35D, entity.getBbWidth() * 0.5D + 0.16D);
Vec3 exitProbe = destination.position().add(transformedProbe).add(destination.getNormalVec().normalize().scale(exitClearance - transformedProbe.dot(destination.getNormalVec().normalize())));
Vec3 requestedExitPos = exitProbe.add(transformedEntityOffset);
Vec3 exitPos = this.resolveSafeExitPosition(entity, destination, requestedExitPos);
float yaw = PortalGunTransformUtil.yawFromLook(transformedLook); float yaw = PortalGunTransformUtil.yawFromLook(transformedLook);
float pitch = PortalGunTransformUtil.pitchFromLook(transformedLook); float pitch = PortalGunTransformUtil.pitchFromLook(transformedLook);
this.applyTeleportCooldown(entity, destination); this.applyTeleportCooldown(entity, destination);
this.level().playSound(null, this.getX(), this.getY(), this.getZ(), sound("portal_enter", SoundEvents.PORTAL_TRAVEL), SoundSource.PLAYERS, 0.7F, 0.96F + this.random.nextFloat() * 0.08F);
if (entity instanceof ServerPlayer player && destination.level() instanceof ServerLevel destinationLevel) { if (entity instanceof ServerPlayer player && destination.level() instanceof ServerLevel destinationLevel) {
player.teleportTo(destinationLevel, exitPos.x, exitPos.y, exitPos.z, yaw, pitch); player.teleportTo(destinationLevel, exitPos.x, exitPos.y, exitPos.z, yaw, pitch);
} else { } else {
@@ -437,8 +578,62 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
entity.setDeltaMovement(transformedMotion); entity.setDeltaMovement(transformedMotion);
entity.hasImpulse = true; entity.hasImpulse = true;
entity.hurtMarked = true;
if (entity instanceof ServerPlayer player) {
player.connection.send(new ClientboundSetEntityMotionPacket(player));
}
entity.fallDistance = 0.0F; entity.fallDistance = 0.0F;
destination.level().playSound(null, exitPos.x, exitPos.y, exitPos.z, sound("portal_exit", SoundEvents.PORTAL_TRAVEL), SoundSource.PLAYERS, 0.7F, 0.96F + this.random.nextFloat() * 0.08F);
this.handleSpecialEntityPostTeleport(entity); this.handleSpecialEntityPostTeleport(entity);
Antarchy.LOGGER.info("Portal gun teleported entity source={} destination={} entity={} entityType={} requestedExit={} exit={} inputVelocity={} outputVelocity={} yaw={} pitch={} sourceFacing={} sourceUp={} destinationFacing={} destinationUp={}", this.getUUID(), destination.getUUID(), entity.getUUID(), EntityType.getKey(entity.getType()), requestedExitPos, exitPos, entryMotion, transformedMotion, yaw, pitch, this.getFacingDirection(), this.getUpAxis(), destination.getFacingDirection(), destination.getUpAxis());
}
private Vec3 portalEntryMomentum(Entity entity, Vec3 currentProbe) {
Vec3 velocity = entity.getDeltaMovement();
Vec3 probeVelocity = currentProbe.subtract(this.previousTeleportProbePosition(entity));
Vec3 positionVelocity = entity.position().subtract(entity.xo, entity.yo, entity.zo);
Vec3 selected = velocity;
if (probeVelocity.lengthSqr() > selected.lengthSqr()) {
selected = probeVelocity;
}
if (positionVelocity.lengthSqr() > selected.lengthSqr()) {
selected = positionVelocity;
}
return selected;
}
private Vec3 exitMomentum(Entity entity, PortalGunPortalEntity destination, Vec3 transformedMotion) {
Vec3 normal = destination.getNormalVec().normalize();
double outward = transformedMotion.dot(normal);
if (outward >= MIN_EXIT_MOMENTUM) {
return transformedMotion;
}
if (entity.getDeltaMovement().lengthSqr() <= 1.0E-5D && transformedMotion.lengthSqr() <= 1.0E-5D) {
return normal.scale(MIN_EXIT_MOMENTUM);
}
return transformedMotion.add(normal.scale(MIN_EXIT_MOMENTUM - outward));
}
private Vec3 resolveSafeExitPosition(Entity entity, PortalGunPortalEntity destination, Vec3 requestedExitPos) {
Vec3 normal = destination.getNormalVec().normalize();
if (this.canPlaceEntityAt(entity, requestedExitPos)) {
return requestedExitPos;
}
for (int i = 1; i <= 24; i++) {
Vec3 candidate = requestedExitPos.add(normal.scale(i * 0.125D));
if (this.canPlaceEntityAt(entity, candidate)) {
Antarchy.LOGGER.info("Portal gun adjusted blocked exit entity={} destination={} requested={} adjusted={} distance={}", entity.getUUID(), destination.getUUID(), requestedExitPos, candidate, i * 0.125D);
return candidate;
}
}
Vec3 fallback = destination.position().add(normal.scale(Math.max(1.0D, entity.getBbWidth() + 0.5D)));
Antarchy.LOGGER.info("Portal gun could not find clear exit entity={} destination={} requested={} fallback={}", entity.getUUID(), destination.getUUID(), requestedExitPos, fallback);
return fallback;
}
private boolean canPlaceEntityAt(Entity entity, Vec3 position) {
AABB movedBounds = entity.getBoundingBox().move(position.x - entity.getX(), position.y - entity.getY(), position.z - entity.getZ());
return this.level().noCollision(entity, movedBounds);
} }
private void tickTeleportCooldowns() { private void tickTeleportCooldowns() {
@@ -500,6 +695,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
tag.putInt("Side", this.getPortalSide().ordinal()); tag.putInt("Side", this.getPortalSide().ordinal());
tag.putInt("Facing", this.getFacingDirection().get3DDataValue()); tag.putInt("Facing", this.getFacingDirection().get3DDataValue());
tag.putInt("UpAxis", this.getUpAxis().get3DDataValue()); tag.putInt("UpAxis", this.getUpAxis().get3DDataValue());
tag.putInt("ChannelRed", this.getChannelRed());
tag.putInt("ChannelGreen", this.getChannelGreen());
tag.putInt("ChannelBlue", this.getChannelBlue());
tag.putInt("SupportX", this.supportOrigin.getX()); tag.putInt("SupportX", this.supportOrigin.getX());
tag.putInt("SupportY", this.supportOrigin.getY()); tag.putInt("SupportY", this.supportOrigin.getY());
tag.putInt("SupportZ", this.supportOrigin.getZ()); tag.putInt("SupportZ", this.supportOrigin.getZ());
@@ -536,12 +734,23 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
} }
if (tag.hasUUID("LinkedPortalId")) { if (tag.hasUUID("LinkedPortalId")) {
this.linkedPortalId = tag.getUUID("LinkedPortalId"); this.linkedPortalId = tag.getUUID("LinkedPortalId");
this.entityData.set(LINKED_PORTAL, Optional.of(this.linkedPortalId));
} }
this.ageTicks = tag.getInt("AgeTicks"); this.ageTicks = tag.getInt("AgeTicks");
this.pairTime = tag.getInt("PairTime"); this.pairTime = tag.getInt("PairTime");
this.entityData.set(SIDE, tag.getInt("Side")); this.entityData.set(SIDE, tag.getInt("Side"));
this.entityData.set(FACING, tag.getInt("Facing")); this.entityData.set(FACING, tag.getInt("Facing"));
this.entityData.set(UP_AXIS, tag.getInt("UpAxis")); this.entityData.set(UP_AXIS, tag.getInt("UpAxis"));
if (tag.contains("ChannelRed")) {
this.entityData.set(CHANNEL_RED, tag.getInt("ChannelRed"));
this.entityData.set(CHANNEL_GREEN, tag.getInt("ChannelGreen"));
this.entityData.set(CHANNEL_BLUE, tag.getInt("ChannelBlue"));
} else if (this.ownerId != null) {
int[] channelColor = generateChannelColor(this.ownerId, this.getPortalSide());
this.entityData.set(CHANNEL_RED, channelColor[0]);
this.entityData.set(CHANNEL_GREEN, channelColor[1]);
this.entityData.set(CHANNEL_BLUE, channelColor[2]);
}
this.supportOrigin = new BlockPos(tag.getInt("SupportX"), tag.getInt("SupportY"), tag.getInt("SupportZ")); this.supportOrigin = new BlockPos(tag.getInt("SupportX"), tag.getInt("SupportY"), tag.getInt("SupportZ"));
this.masterPos = new BlockPos(tag.getInt("MasterX"), tag.getInt("MasterY"), tag.getInt("MasterZ")); this.masterPos = new BlockPos(tag.getInt("MasterX"), tag.getInt("MasterY"), tag.getInt("MasterZ"));
this.basePos = new BlockPos(tag.getInt("BaseX"), tag.getInt("BaseY"), tag.getInt("BaseZ")); this.basePos = new BlockPos(tag.getInt("BaseX"), tag.getInt("BaseY"), tag.getInt("BaseZ"));
@@ -636,6 +845,20 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
return BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, path)).orElse(fallback); return BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, path)).orElse(fallback);
} }
private static int[] generateChannelColor(UUID ownerId, PortalSide side) {
int seed = ownerId == null ? side.ordinal() : ownerId.hashCode() ^ side.ordinal() * 0x45d9f3b;
int wobbleA = Math.floorMod(seed, 54);
int wobbleB = Math.floorMod(seed >> 8, 46);
int wobbleC = Math.floorMod(seed >> 16, 38);
if (side == PortalSide.BLUE) {
return new int[] {42 + wobbleC, 128 + wobbleB, 218 + wobbleA / 3};
}
return new int[] {230 + wobbleA / 5, 108 + wobbleB, 28 + wobbleC};
}
private record PortalLocalCoords(double horizontal, double vertical, double depth) { private record PortalLocalCoords(double horizontal, double vertical, double depth) {
} }
private record PortalBounds(double minHorizontal, double maxHorizontal, double minVertical, double maxVertical, double minDepth, double maxDepth) {
}
} }
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.content.portalgun;
import com.craisinlord.antarchy.content.item.PortalGunItem; import com.craisinlord.antarchy.content.item.PortalGunItem;
import java.util.UUID; import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -23,8 +24,19 @@ import net.minecraft.world.phys.Vec3;
public class PortalGunProjectileEntity extends ThrowableItemProjectile { public class PortalGunProjectileEntity extends ThrowableItemProjectile {
private static final EntityDataAccessor<Integer> SIDE = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT); private static final EntityDataAccessor<Integer> SIDE = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> SHOOTER_ID = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> DISTANCE = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> SPAWN_X = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> SPAWN_Y = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Integer> SPAWN_Z = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.INT);
private static final EntityDataAccessor<Float> VELOCITY_X = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.FLOAT);
private static final EntityDataAccessor<Float> VELOCITY_Y = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.FLOAT);
private static final EntityDataAccessor<Float> VELOCITY_Z = SynchedEntityData.defineId(PortalGunProjectileEntity.class, EntityDataSerializers.FLOAT);
private static final int MAX_FLIGHT_TICKS = 80; private static final int MAX_FLIGHT_TICKS = 80;
private UUID gunId; private UUID gunId;
private boolean spawnSynced;
public int portalWidth = 1;
public int portalHeight = 2;
public PortalGunProjectileEntity(EntityType<? extends PortalGunProjectileEntity> entityType, Level level) { public PortalGunProjectileEntity(EntityType<? extends PortalGunProjectileEntity> entityType, Level level) {
super(entityType, level); super(entityType, level);
@@ -45,18 +57,46 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
protected void defineSynchedData(SynchedEntityData.Builder builder) { protected void defineSynchedData(SynchedEntityData.Builder builder) {
super.defineSynchedData(builder); super.defineSynchedData(builder);
builder.define(SIDE, PortalGunPortalEntity.PortalSide.BLUE.ordinal()); builder.define(SIDE, PortalGunPortalEntity.PortalSide.BLUE.ordinal());
builder.define(SHOOTER_ID, -1);
builder.define(DISTANCE, 0);
builder.define(SPAWN_X, 0);
builder.define(SPAWN_Y, 0);
builder.define(SPAWN_Z, 0);
builder.define(VELOCITY_X, 0.0F);
builder.define(VELOCITY_Y, 0.0F);
builder.define(VELOCITY_Z, 0.0F);
} }
public void configure(PortalGunPortalEntity.PortalSide side, UUID gunId, ItemStack gunStack) { public void configure(PortalGunPortalEntity.PortalSide side, UUID gunId, ItemStack gunStack) {
this.entityData.set(SIDE, side.ordinal()); this.entityData.set(SIDE, side.ordinal());
this.gunId = gunId; this.gunId = gunId;
this.setItem(gunStack.copyWithCount(1)); this.setItem(gunStack.copyWithCount(1));
Entity owner = this.getOwner();
this.entityData.set(SHOOTER_ID, owner == null ? -1 : owner.getId());
this.syncSpawnPosition(this.blockPosition());
this.syncVelocity();
} }
public PortalGunPortalEntity.PortalSide getPortalSide() { public PortalGunPortalEntity.PortalSide getPortalSide() {
return this.entityData.get(SIDE) == PortalGunPortalEntity.PortalSide.ORANGE.ordinal() ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE; return this.entityData.get(SIDE) == PortalGunPortalEntity.PortalSide.ORANGE.ordinal() ? PortalGunPortalEntity.PortalSide.ORANGE : PortalGunPortalEntity.PortalSide.BLUE;
} }
public int getShooterId() {
return this.entityData.get(SHOOTER_ID);
}
public int getSyncedDistance() {
return this.entityData.get(DISTANCE);
}
public BlockPos getSyncedSpawnPos() {
return new BlockPos(this.entityData.get(SPAWN_X), this.entityData.get(SPAWN_Y), this.entityData.get(SPAWN_Z));
}
public Vec3 getSyncedVelocity() {
return new Vec3(this.entityData.get(VELOCITY_X), this.entityData.get(VELOCITY_Y), this.entityData.get(VELOCITY_Z));
}
@Override @Override
protected Item getDefaultItem() { protected Item getDefaultItem() {
return Items.AIR; return Items.AIR;
@@ -85,6 +125,11 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
if (!this.spawnSynced) {
this.syncSpawnPosition(this.blockPosition());
}
this.syncVelocity();
this.entityData.set(DISTANCE, this.tickCount);
if (this.tickCount > MAX_FLIGHT_TICKS) { if (this.tickCount > MAX_FLIGHT_TICKS) {
this.discard(); this.discard();
return; return;
@@ -133,6 +178,20 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
level.sendParticles(net.minecraft.core.particles.ParticleTypes.CRIT, impactPos.x, impactPos.y, impactPos.z, 6, 0.04D, 0.04D, 0.04D, 0.01D); level.sendParticles(net.minecraft.core.particles.ParticleTypes.CRIT, impactPos.x, impactPos.y, impactPos.z, 6, 0.04D, 0.04D, 0.04D, 0.01D);
} }
private void syncSpawnPosition(BlockPos pos) {
this.entityData.set(SPAWN_X, pos.getX());
this.entityData.set(SPAWN_Y, pos.getY());
this.entityData.set(SPAWN_Z, pos.getZ());
this.spawnSynced = true;
}
private void syncVelocity() {
Vec3 velocity = this.getDeltaMovement();
this.entityData.set(VELOCITY_X, (float) velocity.x);
this.entityData.set(VELOCITY_Y, (float) velocity.y);
this.entityData.set(VELOCITY_Z, (float) velocity.z);
}
private ItemStack resolveSourceStack() { private ItemStack resolveSourceStack() {
ItemStack projectileStack = this.getItem(); ItemStack projectileStack = this.getItem();
if (!(this.getOwner() instanceof Player player) || !(projectileStack.getItem() instanceof PortalGunItem portalGunItem) || this.gunId == null) { if (!(this.getOwner() instanceof Player player) || !(projectileStack.getItem() instanceof PortalGunItem portalGunItem) || this.gunId == null) {
@@ -146,6 +205,16 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
public void addAdditionalSaveData(CompoundTag tag) { public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag); super.addAdditionalSaveData(tag);
tag.putInt("Side", this.entityData.get(SIDE)); tag.putInt("Side", this.entityData.get(SIDE));
tag.putInt("ShooterId", this.entityData.get(SHOOTER_ID));
tag.putInt("Distance", this.entityData.get(DISTANCE));
tag.putInt("SpawnX", this.entityData.get(SPAWN_X));
tag.putInt("SpawnY", this.entityData.get(SPAWN_Y));
tag.putInt("SpawnZ", this.entityData.get(SPAWN_Z));
tag.putFloat("VelocityX", this.entityData.get(VELOCITY_X));
tag.putFloat("VelocityY", this.entityData.get(VELOCITY_Y));
tag.putFloat("VelocityZ", this.entityData.get(VELOCITY_Z));
tag.putInt("PortalWidth", this.portalWidth);
tag.putInt("PortalHeight", this.portalHeight);
if (this.gunId != null) { if (this.gunId != null) {
tag.putUUID("GunId", this.gunId); tag.putUUID("GunId", this.gunId);
} }
@@ -155,6 +224,17 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
public void readAdditionalSaveData(CompoundTag tag) { public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag); super.readAdditionalSaveData(tag);
this.entityData.set(SIDE, tag.getInt("Side")); this.entityData.set(SIDE, tag.getInt("Side"));
this.entityData.set(SHOOTER_ID, tag.getInt("ShooterId"));
this.entityData.set(DISTANCE, tag.getInt("Distance"));
this.entityData.set(SPAWN_X, tag.getInt("SpawnX"));
this.entityData.set(SPAWN_Y, tag.getInt("SpawnY"));
this.entityData.set(SPAWN_Z, tag.getInt("SpawnZ"));
this.entityData.set(VELOCITY_X, tag.getFloat("VelocityX"));
this.entityData.set(VELOCITY_Y, tag.getFloat("VelocityY"));
this.entityData.set(VELOCITY_Z, tag.getFloat("VelocityZ"));
this.portalWidth = Math.max(1, tag.getInt("PortalWidth"));
this.portalHeight = Math.max(2, tag.getInt("PortalHeight"));
this.spawnSynced = true;
if (tag.hasUUID("GunId")) { if (tag.hasUUID("GunId")) {
this.gunId = tag.getUUID("GunId"); this.gunId = tag.getUUID("GunId");
} }
@@ -38,7 +38,31 @@ public final class PortalGunTransformUtil {
} }
public static Vec3 transformRelativePosition(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 relativePosition) { public static Vec3 transformRelativePosition(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 relativePosition) {
return transform(relativePosition, createTransform(sourcePortal, destinationPortal)); return transformPosition(sourcePortal, destinationPortal, relativePosition);
}
public static Vec3 transformPosition(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 relativePosition) {
Vec3 sourceWidth = sourcePortal.getWidthVec().normalize();
Vec3 sourceUp = sourcePortal.getUpVec().normalize();
Vec3 sourceNormal = sourcePortal.getNormalVec().normalize();
Vec3 destinationWidth = destinationPortal.getWidthVec().normalize();
Vec3 destinationUp = destinationPortal.getUpVec().normalize();
Vec3 destinationNormal = destinationPortal.getNormalVec().normalize();
return destinationWidth.scale(relativePosition.dot(sourceWidth))
.add(destinationUp.scale(relativePosition.dot(sourceUp)))
.add(destinationNormal.scale(relativePosition.dot(sourceNormal)));
}
public static Vec3 transformVector(PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 vector) {
Vec3 sourceWidth = sourcePortal.getWidthVec().normalize();
Vec3 sourceUp = sourcePortal.getUpVec().normalize();
Vec3 sourceInto = sourcePortal.getNormalVec().normalize().scale(-1.0D);
Vec3 destinationWidth = destinationPortal.getWidthVec().normalize();
Vec3 destinationUp = destinationPortal.getUpVec().normalize();
Vec3 destinationOut = destinationPortal.getNormalVec().normalize();
return destinationWidth.scale(vector.dot(sourceWidth))
.add(destinationUp.scale(vector.dot(sourceUp)))
.add(destinationOut.scale(vector.dot(sourceInto)));
} }
public static float yawFromLook(Vec3 look) { public static float yawFromLook(Vec3 look) {
@@ -24,7 +24,7 @@ public record PortalGunWorldPortalShape(
} }
public AABB getScanRange() { public AABB getScanRange() {
return this.getFlatPlane().expandTowards(this.normal.scale(-DEFAULT_SCAN_DISTANCE)); return this.getFlatPlane().expandTowards(this.normal.scale(DEFAULT_SCAN_DISTANCE));
} }
public AABB getPortalInsides() { public AABB getPortalInsides() {
@@ -77,7 +77,7 @@ public record PortalGunWorldPortalShape(
public boolean shouldRenderFront(Vec3 cameraPos) { public boolean shouldRenderFront(Vec3 cameraPos) {
PortalLocalCoords coords = this.localCoords(cameraPos); PortalLocalCoords coords = this.localCoords(cameraPos);
if (coords.depth() <= 0.0D) { if (coords.depth() <= -0.25D) {
return false; return false;
} }
double depthScale = Math.min(DEFAULT_SCAN_DISTANCE, Math.max(0.0D, coords.depth())); double depthScale = Math.min(DEFAULT_SCAN_DISTANCE, Math.max(0.0D, coords.depth()));
@@ -96,6 +96,30 @@ public record PortalGunWorldPortalShape(
return false; return false;
} }
public boolean intersectsPortalColumn(AABB box, double horizontalPadding, double verticalPadding, double depthPadding) {
double minHorizontal = Double.POSITIVE_INFINITY;
double maxHorizontal = Double.NEGATIVE_INFINITY;
double minVertical = Double.POSITIVE_INFINITY;
double maxVertical = Double.NEGATIVE_INFINITY;
double minDepth = Double.POSITIVE_INFINITY;
double maxDepth = Double.NEGATIVE_INFINITY;
for (Vec3 corner : corners(box)) {
PortalLocalCoords coords = this.localCoords(corner);
minHorizontal = Math.min(minHorizontal, coords.horizontal());
maxHorizontal = Math.max(maxHorizontal, coords.horizontal());
minVertical = Math.min(minVertical, coords.vertical());
maxVertical = Math.max(maxVertical, coords.vertical());
minDepth = Math.min(minDepth, coords.depth());
maxDepth = Math.max(maxDepth, coords.depth());
}
return maxHorizontal >= -this.halfWidth - horizontalPadding
&& minHorizontal <= this.halfWidth + horizontalPadding
&& maxVertical >= -this.halfHeight - verticalPadding
&& minVertical <= this.halfHeight + verticalPadding
&& maxDepth >= -this.halfDepth - depthPadding
&& minDepth <= this.halfDepth + depthPadding;
}
public AABB getBoundsForCulling() { public AABB getBoundsForCulling() {
return this.createPlaneAround(0.0D, this.halfDepth).inflate(1.5D); return this.createPlaneAround(0.0D, this.halfDepth).inflate(1.5D);
} }
@@ -13,12 +13,15 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.level.Level;
public final class ThoraxisUndersideManager { public final class ThoraxisUndersideManager {
public static final int GRAVITY_FLIP_Y = 0; public static final int GRAVITY_FLIP_Y = 0;
private static final ResourceLocation THORAXIS_DIMENSION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis"); private static final ResourceLocation THORAXIS_DIMENSION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis");
private static final AntarchyGravityTransition TRANSITION = new AntarchyGravityTransition(12); private static final AntarchyGravityTransition TRANSITION = new AntarchyGravityTransition(12);
private static final int EFFECT_DURATION_TICKS = 40; private static final int EFFECT_DURATION_TICKS = 40;
private static final Set<UUID> UNDERSIDE_APPLIED_EFFECT = new HashSet<>();
private static final Set<UUID> UNDERSIDE_FORCED_GRAVITY = new HashSet<>(); private static final Set<UUID> UNDERSIDE_FORCED_GRAVITY = new HashSet<>();
private ThoraxisUndersideManager() { private ThoraxisUndersideManager() {
@@ -38,14 +41,28 @@ public final class ThoraxisUndersideManager {
boolean inUnderside = entity.getY() < GRAVITY_FLIP_Y; boolean inUnderside = entity.getY() < GRAVITY_FLIP_Y;
if (entity instanceof LivingEntity living) { if (entity instanceof LivingEntity living) {
UUID uuid = entity.getUUID();
if (inUnderside) { if (inUnderside) {
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false)); if (!living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
} else if (living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) { living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
living.removeEffect(AntarchyObjects.INVERTED_EFFECT.get()); UNDERSIDE_APPLIED_EFFECT.add(uuid);
}
} else if (UNDERSIDE_APPLIED_EFFECT.remove(uuid)) {
if (living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
living.removeEffect(AntarchyObjects.INVERTED_EFFECT.get());
}
if (AntarchyGravityApi.getGravityDirection(living) == AntarchyGravityDirection.UP
&& AntarchyGravityApi.isGravityForced(living)) {
AntarchyGravityApi.setGravityDirection(living, AntarchyGravityDirection.DOWN, false, TRANSITION);
}
} }
continue; continue;
} }
if (!(entity instanceof ItemEntity)) {
continue;
}
UUID uuid = entity.getUUID(); UUID uuid = entity.getUUID();
if (inUnderside) { if (inUnderside) {
activeThisTick.add(uuid); activeThisTick.add(uuid);
@@ -67,7 +84,7 @@ public final class ThoraxisUndersideManager {
UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick); UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick);
} }
public static boolean isThoraxis(ServerLevel level) { public static boolean isThoraxis(Level level) {
return level.dimension().location().equals(THORAXIS_DIMENSION); return level.dimension().location().equals(THORAXIS_DIMENSION);
} }
} }
@@ -1,7 +1,6 @@
package com.craisinlord.antarchy.mixins.client; package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState; import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
@@ -21,18 +20,9 @@ public abstract class BlockEntityRenderDispatcherPortalMixin {
if (PortalGunPortalRenderState.renderAll() || blockEntity == null || blockEntity.isRemoved()) { if (PortalGunPortalRenderState.renderAll() || blockEntity == null || blockEntity.isRemoved()) {
return; return;
} }
PortalGunWorldPortalShape destinationShape = PortalGunPortalRenderState.getDestinationShape();
PortalGunWorldPortalShape sourceShape = PortalGunPortalRenderState.getSourceShape();
if (destinationShape == null) {
return;
}
BlockPos pos = blockEntity.getBlockPos(); BlockPos pos = blockEntity.getBlockPos();
AABB bounds = new AABB(pos); AABB bounds = new AABB(pos);
if (!destinationShape.intersectsFront(bounds, 0.1D)) { if (!PortalGunPortalRenderState.shouldRenderBounds(bounds)) {
ci.cancel();
return;
}
if (sourceShape != null && sourceShape.intersectsFront(bounds, -0.02D)) {
ci.cancel(); ci.cancel();
} }
} }
@@ -2,7 +2,6 @@ package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState; import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity; import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@@ -18,16 +17,7 @@ public abstract class EntityRenderDispatcherPortalMixin {
if (PortalGunPortalRenderState.renderAll() || entity instanceof PortalGunPortalEntity) { if (PortalGunPortalRenderState.renderAll() || entity instanceof PortalGunPortalEntity) {
return; return;
} }
PortalGunWorldPortalShape destinationShape = PortalGunPortalRenderState.getDestinationShape(); if (!PortalGunPortalRenderState.shouldRenderBounds(entity.getBoundingBox())) {
PortalGunWorldPortalShape sourceShape = PortalGunPortalRenderState.getSourceShape();
if (destinationShape == null) {
return;
}
if (!destinationShape.intersectsFront(entity.getBoundingBox(), 0.1D)) {
cir.setReturnValue(false);
return;
}
if (sourceShape != null && sourceShape.intersectsFront(entity.getBoundingBox(), -0.02D)) {
cir.setReturnValue(false); cir.setReturnValue(false);
} }
} }
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.entity.HoverboardEntity; import com.craisinlord.antarchy.content.entity.HoverboardEntity;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@@ -45,4 +46,20 @@ public abstract class HoverboardRiderPoseMixin<T extends LivingEntity, M extends
this.getModel().riding = false; this.getModel().riding = false;
} }
} }
@Inject(
method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/model/EntityModel;setupAnim(Lnet/minecraft/world/entity/Entity;FFFFF)V",
shift = At.Shift.AFTER
)
)
private void antarchy$faceHoverboardRiderHeadForward(T entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, CallbackInfo ci) {
if (entity.getVehicle() instanceof HoverboardEntity && this.getModel() instanceof HumanoidModel<?> humanoidModel) {
float correction = (float) Math.toRadians(HOVERBOARD_RIDER_RENDER_YAW);
humanoidModel.head.yRot += correction;
humanoidModel.hat.yRot += correction;
}
}
} }
@@ -2,6 +2,7 @@ package com.craisinlord.antarchy.mixins.gravity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
@@ -33,7 +34,7 @@ public abstract class BehaviorUtilsGravityMixin {
@Local float yOffset, @Local float yOffset,
@Local LivingEntity entity @Local LivingEntity entity
) { ) {
if (!AntarchyGravityApi.isGravityInverted(entity)) { if (!antarchy$shouldInvertThrownItem(entity)) {
return original.call(level, x, y, z, stack); return original.call(level, x, y, z, stack);
} }
@@ -58,11 +59,17 @@ public abstract class BehaviorUtilsGravityMixin {
Operation<Void> original, Operation<Void> original,
@Local LivingEntity entity @Local LivingEntity entity
) { ) {
if (!AntarchyGravityApi.isGravityInverted(entity)) { if (!antarchy$shouldInvertThrownItem(entity)) {
original.call(itemEntity, deltaMovement); original.call(itemEntity, deltaMovement);
return; return;
} }
AntarchyGravityApi.setWorldVelocity(itemEntity, deltaMovement); AntarchyGravityApi.setWorldVelocity(itemEntity, deltaMovement);
} }
private static boolean antarchy$shouldInvertThrownItem(LivingEntity entity) {
return AntarchyGravityApi.isGravityInverted(entity)
&& ThoraxisUndersideManager.isThoraxis(entity.level())
&& entity.getY() < ThoraxisUndersideManager.GRAVITY_FLIP_Y;
}
} }
@@ -82,11 +82,9 @@
], ],
"client": [ "client": [
"client.AbstractMinecartRendererMixin", "client.AbstractMinecartRendererMixin",
"client.BlockEntityRenderDispatcherPortalMixin",
"client.EntityLightProbeMixin", "client.EntityLightProbeMixin",
"client.CustomBossBarMixin", "client.CustomBossBarMixin",
"client.DimensionMusicMixin", "client.DimensionMusicMixin",
"client.EntityRenderDispatcherPortalMixin",
"client.CavarynSkyMixin", "client.CavarynSkyMixin",
"client.CavarynHordeFogMixin", "client.CavarynHordeFogMixin",
"client.CavarynHordeLightTextureMixin", "client.CavarynHordeLightTextureMixin",
@@ -0,0 +1,45 @@
{
"format_version": "1.8.0",
"animations": {
"spinning_idle": {
"loop": true,
"animation_length": 1,
"bones": {
"top_ring": {
"rotation": {
"0.0": {
"vector": [0, 0, 0]
},
"1.0": {
"vector": [0, -360, 0]
}
}
},
"eye": {
"scale": {
"0.0": {
"vector": [1, 1, 1]
},
"0.5": {
"vector": [1.02, 1.02, 1.02],
"easing": "easeInOutQuad"
},
"1.0": {
"vector": [1, 1, 1]
}
}
},
"bottom_ring": {
"rotation": {
"0.0": {
"vector": [0, 0, 0]
},
"1.0": {
"vector": [0, 360, 0]
}
}
}
}
}
}
}
File diff suppressed because it is too large. Load diff
@@ -1,7 +1,16 @@
{ {
"variants": { "variants": {
"": { "axis=x": {
"model": "antarchy:block/stripped_truffalo_wood",
"x": 90,
"y": 90
},
"axis=y": {
"model": "antarchy:block/stripped_truffalo_wood" "model": "antarchy:block/stripped_truffalo_wood"
},
"axis=z": {
"model": "antarchy:block/stripped_truffalo_wood",
"x": 90
} }
} }
} }
@@ -0,0 +1,217 @@
{
"format_version": "1.21.110",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.eye_of_the_storm",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 2,
"visible_bounds_height": 4,
"visible_bounds_offset": [0, 1, 0]
},
"bones": [
{
"name": "eye_of_the_storm",
"pivot": [8, 0, -8]
},
{
"name": "staff",
"parent": "eye_of_the_storm",
"pivot": [1, -8, -1],
"cubes": [
{
"origin": [-0.5, -12, -0.5],
"size": [1, 36, 1],
"uv": {
"north": {"uv": [3, 0], "uv_size": [1, 36]},
"east": {"uv": [3, 0], "uv_size": [1, 36]},
"south": {"uv": [3, 0], "uv_size": [1, 36]},
"west": {"uv": [3, 0], "uv_size": [1, 36]},
"up": {"uv": [4, 36], "uv_size": [-1, -36]},
"down": {"uv": [4, 36], "uv_size": [-1, -36]}
}
},
{
"origin": [-1.5, -15, -1.5],
"size": [3, 3, 3],
"uv": {
"north": {"uv": [17, 20], "uv_size": [3, 3]},
"east": {"uv": [17, 20], "uv_size": [3, 3]},
"south": {"uv": [17, 20], "uv_size": [3, 3]},
"west": {"uv": [17, 20], "uv_size": [3, 3]},
"up": {"uv": [23, 23], "uv_size": [-3, -3]},
"down": {"uv": [23, 23], "uv_size": [-3, -3]}
}
},
{
"origin": [-2, 30, -2],
"size": [4, 2, 4],
"uv": {
"north": {"uv": [7, 21], "uv_size": [4, 2]},
"east": {"uv": [7, 21], "uv_size": [4, 2]},
"south": {"uv": [7, 21], "uv_size": [4, 2]},
"west": {"uv": [7, 21], "uv_size": [4, 2]},
"up": {"uv": [20, 4], "uv_size": [-4, -4]},
"down": {"uv": [12, 28], "uv_size": [-4, -4]}
}
},
{
"origin": [-2, 20, -2],
"size": [4, 2, 4],
"uv": {
"north": {"uv": [7, 21], "uv_size": [4, 2]},
"east": {"uv": [7, 21], "uv_size": [4, 2]},
"south": {"uv": [7, 21], "uv_size": [4, 2]},
"west": {"uv": [7, 21], "uv_size": [4, 2]},
"up": {"uv": [20, 4], "uv_size": [-4, -4]},
"down": {"uv": [12, 28], "uv_size": [-4, -4]}
}
},
{
"origin": [-0.5, 29, -0.5],
"size": [1, 1, 1],
"uv": {
"north": {"uv": [3, 15], "uv_size": [1, 1]},
"east": {"uv": [3, 15], "uv_size": [1, 1]},
"south": {"uv": [3, 15], "uv_size": [1, 1]},
"west": {"uv": [3, 15], "uv_size": [1, 1]},
"up": {"uv": [4, 16], "uv_size": [-1, -1]},
"down": {"uv": [4, 16], "uv_size": [-1, -1]}
}
}
]
},
{
"name": "top_ring",
"parent": "eye_of_the_storm",
"pivot": [0, 27, 0],
"cubes": [
{
"origin": [-5, 26.5, -5],
"size": [0, 1, 10],
"uv": {
"north": {"uv": [0, 0], "uv_size": [0, 1]},
"east": {"uv": [20, 0], "uv_size": [10, 1]},
"south": {"uv": [0, 0], "uv_size": [0, 1]},
"west": {"uv": [20, 0], "uv_size": [10, 1]},
"up": {"uv": [0, 0], "uv_size": [0, 10]},
"down": {"uv": [0, 10], "uv_size": [0, -10]}
}
},
{
"origin": [5, 26.5, -5],
"size": [0, 1, 10],
"uv": {
"north": {"uv": [0, 0], "uv_size": [0, 1]},
"east": {"uv": [20, 0], "uv_size": [10, 1]},
"south": {"uv": [0, 0], "uv_size": [0, 1]},
"west": {"uv": [20, 0], "uv_size": [10, 1]},
"up": {"uv": [0, 0], "uv_size": [0, 10]},
"down": {"uv": [0, 10], "uv_size": [0, -10]}
}
},
{
"origin": [-5, 26.5, -5],
"size": [10, 1, 0],
"uv": {
"north": {"uv": [20, 0], "uv_size": [10, 1]},
"east": {"uv": [0, 0], "uv_size": [0, 1]},
"south": {"uv": [20, 0], "uv_size": [10, 1]},
"west": {"uv": [0, 0], "uv_size": [0, 1]},
"up": {"uv": [0, 0], "uv_size": [10, 0]},
"down": {"uv": [0, 0], "uv_size": [10, 0]}
}
},
{
"origin": [-5, 26.5, 5],
"size": [10, 1, 0],
"uv": {
"north": {"uv": [20, 0], "uv_size": [10, 1]},
"east": {"uv": [0, 0], "uv_size": [0, 1]},
"south": {"uv": [20, 0], "uv_size": [10, 1]},
"west": {"uv": [0, 0], "uv_size": [0, 1]},
"up": {"uv": [0, 0], "uv_size": [10, 0]},
"down": {"uv": [0, 0], "uv_size": [10, 0]}
}
}
]
},
{
"name": "bottom_ring",
"parent": "eye_of_the_storm",
"pivot": [0, 25, 0],
"cubes": [
{
"origin": [-5, 24.5, -5],
"size": [10, 1, 0],
"uv": {
"north": {"uv": [20, 0], "uv_size": [10, 1]},
"east": {"uv": [0, 0], "uv_size": [0, 1]},
"south": {"uv": [20, 0], "uv_size": [10, 1]},
"west": {"uv": [0, 0], "uv_size": [0, 1]},
"up": {"uv": [0, 0], "uv_size": [10, 0]},
"down": {"uv": [0, 0], "uv_size": [10, 0]}
}
},
{
"origin": [5, 24.5, -5],
"size": [0, 1, 10],
"uv": {
"north": {"uv": [0, 0], "uv_size": [0, 1]},
"east": {"uv": [20, 0], "uv_size": [10, 1]},
"south": {"uv": [0, 0], "uv_size": [0, 1]},
"west": {"uv": [20, 0], "uv_size": [10, 1]},
"up": {"uv": [0, 0], "uv_size": [0, 10]},
"down": {"uv": [0, 10], "uv_size": [0, -10]}
}
},
{
"origin": [-5, 24.5, 5],
"size": [10, 1, 0],
"uv": {
"north": {"uv": [20, 0], "uv_size": [10, 1]},
"east": {"uv": [0, 0], "uv_size": [0, 1]},
"south": {"uv": [20, 0], "uv_size": [10, 1]},
"west": {"uv": [0, 0], "uv_size": [0, 1]},
"up": {"uv": [0, 0], "uv_size": [10, 0]},
"down": {"uv": [0, 0], "uv_size": [10, 0]}
}
},
{
"origin": [-5, 24.5, -5],
"size": [0, 1, 10],
"uv": {
"north": {"uv": [0, 0], "uv_size": [0, 1]},
"east": {"uv": [20, 0], "uv_size": [10, 1]},
"south": {"uv": [0, 0], "uv_size": [0, 1]},
"west": {"uv": [20, 0], "uv_size": [10, 1]},
"up": {"uv": [0, 0], "uv_size": [0, 10]},
"down": {"uv": [0, 10], "uv_size": [0, -10]}
}
}
]
},
{
"name": "eye",
"parent": "eye_of_the_storm",
"pivot": [0, 26, 0],
"cubes": [
{
"origin": [-3, 23, -3],
"size": [6, 6, 6],
"uv": {
"north": {"uv": [10, 0], "uv_size": [6, 6]},
"east": {"uv": [10, 0], "uv_size": [6, 6]},
"south": {"uv": [10, 0], "uv_size": [6, 6]},
"west": {"uv": [10, 0], "uv_size": [6, 6]},
"up": {"uv": [10, 12], "uv_size": [-6, -6]},
"down": {"uv": [10, 6], "uv_size": [-6, -6]}
}
}
]
}
]
}
]
}
@@ -0,0 +1,74 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.vortex",
"texture_width": 256,
"texture_height": 128,
"visible_bounds_width": 6,
"visible_bounds_height": 4.5,
"visible_bounds_offset": [0, 1.75, 0]
},
"bones": [
{
"name": "root",
"pivot": [0, 0, 0]
},
{
"name": "head",
"parent": "root",
"pivot": [0, 26.30769, 0.35392],
"cubes": [
{"origin": [0, 19, -11.975], "size": [16, 16, 16], "pivot": [0, 19, -11.975], "rotation": [0, -45, 0], "uv": [64, 0], "mirror": true},
{"origin": [-26, 22, -12], "size": [26, 16, 0], "pivot": [0, 20, -12], "rotation": [0, 45, 0], "uv": [2, 4]},
{"origin": [0, 22, -12], "size": [26, 16, 0], "pivot": [0, 20, -12], "rotation": [0, -45, 0], "uv": [2, 4], "mirror": true}
]
},
{
"name": "right_wing_bottom",
"parent": "head",
"pivot": [-12, 13, 3.025],
"cubes": [
{"origin": [-38, 2, 3.025], "size": [26, 22, 0], "uv": [0, 44]}
]
},
{
"name": "left_wing_bottom",
"parent": "head",
"pivot": [12, 13, 3.025],
"cubes": [
{"origin": [12, 2, 3.025], "size": [26, 22, 0], "uv": [0, 44], "mirror": true}
]
},
{
"name": "clouds",
"parent": "head",
"pivot": [0, 27, -0.31815],
"cubes": [
{"origin": [-8, 18, -13.975], "size": [24, 18, 0], "pivot": [0, 19, -5.975], "rotation": [0, -45, 0], "uv": [89, 57], "mirror": true},
{"origin": [-8, 18, -13.975], "size": [0, 18, 24], "pivot": [0, 19, -5.975], "rotation": [0, -45, 0], "uv": [89, 33], "mirror": true},
{"origin": [-8, 18, 10.025], "size": [24, 18, 0], "pivot": [0, 19, -5.975], "rotation": [0, -45, 0], "uv": [89, 57], "mirror": true},
{"origin": [16, 18, -13.975], "size": [0, 18, 24], "pivot": [0, 19, -5.975], "rotation": [0, -45, 0], "uv": [89, 33], "mirror": true}
]
},
{
"name": "right_wing",
"parent": "head",
"pivot": [-12, 40, 3.025],
"cubes": [
{"origin": [-38, 29, 3.025], "size": [26, 22, 0], "uv": [0, 22]}
]
},
{
"name": "left_wing",
"parent": "head",
"pivot": [12, 40, 3.025],
"cubes": [
{"origin": [12, 29, 3.025], "size": [26, 22, 0], "uv": [0, 22], "mirror": true}
]
}
]
}
]
}
@@ -344,7 +344,7 @@
"item.antarchy.seashell": "Seashell", "item.antarchy.seashell": "Seashell",
"item.antarchy.nightmare_scale": "Nightmare Scale", "item.antarchy.nightmare_scale": "Nightmare Scale",
"item.antarchy.music_disc_underside": "Music Disc", "item.antarchy.music_disc_underside": "Music Disc",
"jukebox_song.antarchy.underside": "docshrekbot - Underside", "jukebox_song.antarchy.underside": "docshrekbot - underside",
"item.antarchy.nightmare_helmet": "Nightmare Helmet", "item.antarchy.nightmare_helmet": "Nightmare Helmet",
"item.antarchy.nightmare_chestplate": "Nightmare Chestplate", "item.antarchy.nightmare_chestplate": "Nightmare Chestplate",
"item.antarchy.nightmare_leggings": "Nightmare Leggings", "item.antarchy.nightmare_leggings": "Nightmare Leggings",
@@ -10,10 +10,10 @@
"from": [0, 4, 4], "from": [0, 4, 4],
"to": [16, 12, 12], "to": [16, 12, 12],
"faces": { "faces": {
"north": {"uv": [0, 4, 16, 12], "texture": "#side"}, "north": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"south": {"uv": [0, 4, 16, 12], "texture": "#side"}, "south": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"up": {"uv": [0, 4, 16, 12], "texture": "#side"}, "up": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 4, 16, 12], "texture": "#side"}, "down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"east": {"uv": [4, 4, 12, 12], "texture": "#end"}, "east": {"uv": [4, 4, 12, 12], "texture": "#end"},
"west": {"uv": [4, 4, 12, 12], "texture": "#end"} "west": {"uv": [4, 4, 12, 12], "texture": "#end"}
} }
@@ -1,7 +1,7 @@
{ {
"parent": "minecraft:block/stripped_jungle_wood", "parent": "minecraft:block/stripped_jungle_wood",
"textures": { "textures": {
"end": "antarchy:block/truffalo/truffalo_log_stripped", "end": "antarchy:block/truffalo/truffalo_wood_stripped",
"side": "antarchy:block/truffalo/truffalo_log_stripped" "side": "antarchy:block/truffalo/truffalo_wood_stripped"
} }
} }
@@ -10,10 +10,10 @@
"from": [0, 4, 4], "from": [0, 4, 4],
"to": [16, 12, 12], "to": [16, 12, 12],
"faces": { "faces": {
"north": {"uv": [0, 4, 16, 12], "texture": "#side"}, "north": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"south": {"uv": [0, 4, 16, 12], "texture": "#side"}, "south": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"up": {"uv": [0, 4, 16, 12], "texture": "#side"}, "up": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"down": {"uv": [0, 4, 16, 12], "texture": "#side"}, "down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"east": {"uv": [4, 4, 12, 12], "texture": "#end"}, "east": {"uv": [4, 4, 12, 12], "texture": "#end"},
"west": {"uv": [4, 4, 12, 12], "texture": "#end"} "west": {"uv": [4, 4, 12, 12], "texture": "#end"}
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/black_truffalo_tuft" "0": "antarchy:block/truffalo/black_truffalo_tuft",
"1": "antarchy:block/truffalo/black_truffalo_tuft",
"2": "antarchy:block/truffalo/black_truffalo_tuft",
"particle": "antarchy:block/truffalo/black_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/blue_truffalo_tuft" "0": "antarchy:block/truffalo/blue_truffalo_tuft",
"1": "antarchy:block/truffalo/blue_truffalo_tuft",
"2": "antarchy:block/truffalo/blue_truffalo_tuft",
"particle": "antarchy:block/truffalo/blue_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/brown_truffalo_tuft" "0": "antarchy:block/truffalo/brown_truffalo_tuft",
"1": "antarchy:block/truffalo/brown_truffalo_tuft",
"2": "antarchy:block/truffalo/brown_truffalo_tuft",
"particle": "antarchy:block/truffalo/brown_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/cyan_truffalo_tuft" "0": "antarchy:block/truffalo/cyan_truffalo_tuft",
"1": "antarchy:block/truffalo/cyan_truffalo_tuft",
"2": "antarchy:block/truffalo/cyan_truffalo_tuft",
"particle": "antarchy:block/truffalo/cyan_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/gray_truffalo_tuft" "0": "antarchy:block/truffalo/gray_truffalo_tuft",
"1": "antarchy:block/truffalo/gray_truffalo_tuft",
"2": "antarchy:block/truffalo/gray_truffalo_tuft",
"particle": "antarchy:block/truffalo/gray_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/green_truffalo_tuft" "0": "antarchy:block/truffalo/green_truffalo_tuft",
"1": "antarchy:block/truffalo/green_truffalo_tuft",
"2": "antarchy:block/truffalo/green_truffalo_tuft",
"particle": "antarchy:block/truffalo/green_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/light_blue_truffalo_tuft" "0": "antarchy:block/truffalo/light_blue_truffalo_tuft",
"1": "antarchy:block/truffalo/light_blue_truffalo_tuft",
"2": "antarchy:block/truffalo/light_blue_truffalo_tuft",
"particle": "antarchy:block/truffalo/light_blue_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/light_gray_truffalo_tuft" "0": "antarchy:block/truffalo/light_gray_truffalo_tuft",
"1": "antarchy:block/truffalo/light_gray_truffalo_tuft",
"2": "antarchy:block/truffalo/light_gray_truffalo_tuft",
"particle": "antarchy:block/truffalo/light_gray_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/lime_truffalo_tuft" "0": "antarchy:block/truffalo/lime_truffalo_tuft",
"1": "antarchy:block/truffalo/lime_truffalo_tuft",
"2": "antarchy:block/truffalo/lime_truffalo_tuft",
"particle": "antarchy:block/truffalo/lime_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/magenta_truffalo_tuft" "0": "antarchy:block/truffalo/magenta_truffalo_tuft",
"1": "antarchy:block/truffalo/magenta_truffalo_tuft",
"2": "antarchy:block/truffalo/magenta_truffalo_tuft",
"particle": "antarchy:block/truffalo/magenta_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/orange_truffalo_tuft" "0": "antarchy:block/truffalo/orange_truffalo_tuft",
"1": "antarchy:block/truffalo/orange_truffalo_tuft",
"2": "antarchy:block/truffalo/orange_truffalo_tuft",
"particle": "antarchy:block/truffalo/orange_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/pink_truffalo_tuft" "0": "antarchy:block/truffalo/pink_truffalo_tuft",
"1": "antarchy:block/truffalo/pink_truffalo_tuft",
"2": "antarchy:block/truffalo/pink_truffalo_tuft",
"particle": "antarchy:block/truffalo/pink_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/purple_truffalo_tuft" "0": "antarchy:block/truffalo/purple_truffalo_tuft",
"1": "antarchy:block/truffalo/purple_truffalo_tuft",
"2": "antarchy:block/truffalo/purple_truffalo_tuft",
"particle": "antarchy:block/truffalo/purple_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/red_truffalo_tuft" "0": "antarchy:block/truffalo/red_truffalo_tuft",
"1": "antarchy:block/truffalo/red_truffalo_tuft",
"2": "antarchy:block/truffalo/red_truffalo_tuft",
"particle": "antarchy:block/truffalo/red_truffalo_tuft"
} }
} }
File diff suppressed because it is too large. Load diff
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/white_truffalo_tuft" "0": "antarchy:block/truffalo/white_truffalo_tuft",
"1": "antarchy:block/truffalo/white_truffalo_tuft",
"2": "antarchy:block/truffalo/white_truffalo_tuft",
"particle": "antarchy:block/truffalo/white_truffalo_tuft"
} }
} }
@@ -1,6 +1,9 @@
{ {
"parent": "antarchy:block/truffalo_tuft_template", "parent": "antarchy:block/truffalo_tuft_template",
"textures": { "textures": {
"all": "antarchy:block/truffalo/yellow_truffalo_tuft" "0": "antarchy:block/truffalo/yellow_truffalo_tuft",
"1": "antarchy:block/truffalo/yellow_truffalo_tuft",
"2": "antarchy:block/truffalo/yellow_truffalo_tuft",
"particle": "antarchy:block/truffalo/yellow_truffalo_tuft"
} }
} }
@@ -1,7 +1,7 @@
{ {
"parent": "minecraft:block/jungle_wood", "parent": "minecraft:block/jungle_wood",
"textures": { "textures": {
"end": "antarchy:block/truffalo/truffalo_log", "end": "antarchy:block/truffalo/truffalo_wood",
"side": "antarchy:block/truffalo/truffalo_log" "side": "antarchy:block/truffalo/truffalo_wood"
} }
} }
@@ -0,0 +1,111 @@
{
"format_version": "1.21.11",
"credit": "Made with Blockbench",
"texture_size": [64, 64],
"textures": {
"0": "vortex_lens_off",
"particle": "vortex_lens_off"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 11.5, 4, 12], "texture": "#0"},
"east": {"uv": [0, 11.5, 4, 12], "texture": "#0"},
"south": {"uv": [0, 11.5, 4, 12], "texture": "#0"},
"west": {"uv": [0, 11.5, 4, 12], "texture": "#0"},
"up": {"uv": [4, 4, 0, 0], "texture": "#0"},
"down": {"uv": [4, 4, 0, 8], "texture": "#0"}
}
},
{
"from": [4, 2, 4],
"to": [12, 10, 12],
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
"faces": {
"north": {"uv": [8, 7, 10, 9], "texture": "#0"},
"east": {"uv": [8, 7, 10, 9], "texture": "#0"},
"south": {"uv": [8, 7, 10, 9], "texture": "#0"},
"west": {"uv": [8, 7, 10, 9], "texture": "#0"},
"up": {"uv": [8, 7, 10, 9], "texture": "#0"},
"down": {"uv": [8, 7, 10, 9], "texture": "#0"}
}
},
{
"from": [0, 2, 0],
"to": [16, 16, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [0, 2, 0]},
"faces": {
"north": {"uv": [0, 8, 4, 11.5], "texture": "#0"},
"east": {"uv": [0, 8, 4, 11.5], "texture": "#0"},
"south": {"uv": [0, 8, 4, 11.5], "texture": "#0"},
"west": {"uv": [0, 8, 4, 11.5], "texture": "#0"},
"up": {"uv": [8, 4, 4, 0], "texture": "#0"},
"down": {"uv": [8, 4, 4, 8], "texture": "#0"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -135, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, -135, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
},
"groups": [
{
"name": "vortex_lens",
"origin": [0, 2, 0],
"scope": 0,
"color": 0,
"children": [
{
"name": "base",
"origin": [0, 0, 0],
"scope": 0,
"color": 0,
"children": [0]
},
{
"name": "eye",
"origin": [0, 2, 0],
"scope": 0,
"color": 0,
"children": [1]
},
{
"name": "glass",
"origin": [0, 2, 0],
"scope": 0,
"color": 0,
"children": [2]
}
]
}
]
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:item/generated",
"gui_light": "front",
"textures": {
"layer0": "antarchy:item/portal_gun/portal_gun_item"
}
}
@@ -1560,6 +1560,39 @@
} }
] ]
}, },
"portal_enter": {
"subtitle": "subtitles.antarchy.portal_enter",
"sounds": [
{
"name": "antarchy:portal/portal_enter_01"
},
{
"name": "antarchy:portal/portal_enter_02"
},
{
"name": "antarchy:portal/portal_enter_03"
}
]
},
"portal_exit": {
"subtitle": "subtitles.antarchy.portal_exit",
"sounds": [
{
"name": "antarchy:portal/portal_exit_01"
},
{
"name": "antarchy:portal/portal_exit_02"
}
]
},
"portal_ambient": {
"subtitle": "subtitles.antarchy.portal_ambient",
"sounds": [
{
"name": "antarchy:portal/wpn_portal_ambient_lp_01"
}
]
},
"bed_bug_ambient": { "bed_bug_ambient": {
"subtitle": "subtitles.antarchy.bed_bug_ambient", "subtitle": "subtitles.antarchy.bed_bug_ambient",
"sounds": [ "sounds": [
Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 B

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 B

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,6 @@
{
"animation": {
"frametime": 10,
"interpolate": true
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

@@ -12,7 +12,7 @@
"##" "##"
], ],
"result": { "result": {
"count": 3, "count": 2,
"id": "antarchy:stripped_truffalo_wood" "id": "antarchy:stripped_truffalo_wood"
} }
} }
@@ -4,7 +4,7 @@
"group": "planks", "group": "planks",
"ingredients": [ "ingredients": [
{ {
"tag": "antarchy:truffalo_logs" "item": "antarchy:truffalo_log"
} }
], ],
"result": { "result": {
@@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shapeless",
"category": "building",
"group": "planks",
"ingredients": [
{
"item": "antarchy:stripped_truffalo_log"
}
],
"result": {
"count": 2,
"id": "antarchy:truffalo_planks"
}
}
@@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shapeless",
"category": "building",
"group": "planks",
"ingredients": [
{
"item": "antarchy:stripped_truffalo_wood"
}
],
"result": {
"count": 4,
"id": "antarchy:truffalo_planks"
}
}
@@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shapeless",
"category": "building",
"group": "planks",
"ingredients": [
{
"item": "antarchy:truffalo_wood"
}
],
"result": {
"count": 4,
"id": "antarchy:truffalo_planks"
}
}
@@ -12,7 +12,7 @@
"##" "##"
], ],
"result": { "result": {
"count": 3, "count": 2,
"id": "antarchy:truffalo_wood" "id": "antarchy:truffalo_wood"
} }
} }
@@ -19,7 +19,6 @@
"antarchy:shellstone_brick_stairs", "antarchy:shellstone_brick_stairs",
"antarchy:shellstone_brick_slab", "antarchy:shellstone_brick_slab",
"antarchy:shellstone_brick_wall", "antarchy:shellstone_brick_wall",
"antarchy:myrmite_coal_ore",
"antarchy:chitin_block", "antarchy:chitin_block",
"antarchy:broodstone", "antarchy:broodstone",
"antarchy:polished_broodstone", "antarchy:polished_broodstone",
@@ -40,23 +39,6 @@
"antarchy:bluestone_block", "antarchy:bluestone_block",
"antarchy:shellstone_pillar", "antarchy:shellstone_pillar",
"antarchy:broodstone_pillar", "antarchy:broodstone_pillar",
"antarchy:myrmite_stairs",
"antarchy:myrmite_slab",
"antarchy:myrmite_wall",
"antarchy:polished_myrmite",
"antarchy:polished_myrmite_stairs",
"antarchy:polished_myrmite_slab",
"antarchy:polished_myrmite_wall",
"antarchy:chiseled_myrmite",
"antarchy:myrmite_bricks",
"antarchy:myrmite_brick_stairs",
"antarchy:myrmite_brick_slab",
"antarchy:myrmite_brick_wall",
"antarchy:mossy_myrmite_bricks",
"antarchy:mossy_myrmite_brick_stairs",
"antarchy:mossy_myrmite_brick_slab",
"antarchy:mossy_myrmite_brick_wall",
"antarchy:myrmite_pillar",
"antarchy:mossy_broodstone_bricks", "antarchy:mossy_broodstone_bricks",
"antarchy:mossy_broodstone_brick_stairs", "antarchy:mossy_broodstone_brick_stairs",
"antarchy:mossy_broodstone_brick_slab", "antarchy:mossy_broodstone_brick_slab",
@@ -546,7 +546,7 @@ public final class AntarchyFabricClientBootstrap {
BloodCrystalKatanaTrailHandler.render(context); BloodCrystalKatanaTrailHandler.render(context);
ScorpionWhipTetherRenderHandler.render(context); ScorpionWhipTetherRenderHandler.render(context);
WormHookTetherRenderHandler.render(context); WormHookTetherRenderHandler.render(context);
if (context.matrixStack() != null) { if (context.matrixStack() != null && com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.isEnabled()) {
com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.render(context.camera(), context.matrixStack().last().pose(), context.tickCounter()); com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer.render(context.camera(), context.matrixStack().last().pose(), context.tickCounter());
} }
}); });
@@ -9,7 +9,7 @@ import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
import net.neoforged.neoforge.client.settings.KeyConflictContext; import net.neoforged.neoforge.client.settings.KeyConflictContext;
@EventBusSubscriber(modid = Antarchy.MODID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class AntarchyKeyBindings { public final class AntarchyKeyBindings {
public static final String CATEGORY = "key.categories.antarchy"; public static final String CATEGORY = "key.categories.antarchy";
@@ -7,8 +7,6 @@ import com.craisinlord.antarchy.content.client.TigerEyeClientHooks;
import com.craisinlord.antarchy.content.client.hud.BloodglassHudRenderer; import com.craisinlord.antarchy.content.client.hud.BloodglassHudRenderer;
import com.craisinlord.antarchy.content.client.particle.*; import com.craisinlord.antarchy.content.client.particle.*;
import com.craisinlord.antarchy.content.client.renderer.*; import com.craisinlord.antarchy.content.client.renderer.*;
import com.craisinlord.antarchy.content.client.renderer.CreepingHorrorRenderer;
import com.craisinlord.antarchy.content.client.renderer.LurkingTerrorRenderer;
import com.craisinlord.antarchy.neoforge.AntarchyNeoForgeFluidTypes; import com.craisinlord.antarchy.neoforge.AntarchyNeoForgeFluidTypes;
import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeBlocks; import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeBlocks;
import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeEntites; import com.craisinlord.antarchy.neoforge.registry.AntarchyNeoforgeEntites;
@@ -37,7 +35,6 @@ import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.CampfireRenderer; import net.minecraft.client.renderer.blockentity.CampfireRenderer;
import net.minecraft.client.renderer.entity.ArmorStandRenderer;
import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@@ -65,6 +62,7 @@ import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent;
import net.neoforged.neoforge.client.model.DynamicFluidContainerModel; import net.neoforged.neoforge.client.model.DynamicFluidContainerModel;
import net.neoforged.neoforge.common.NeoForge;
import org.joml.Vector3f; import org.joml.Vector3f;
import software.bernie.geckolib.animatable.GeoAnimatable; import software.bernie.geckolib.animatable.GeoAnimatable;
import software.bernie.geckolib.animatable.client.GeoRenderProvider; import software.bernie.geckolib.animatable.client.GeoRenderProvider;
@@ -29,7 +29,7 @@ import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class BloodCrystalKatanaTrailHandler { public final class BloodCrystalKatanaTrailHandler {
private static final int MAX_TRAIL_POINTS = 16; private static final int MAX_TRAIL_POINTS = 16;
private static final int POINT_LIFETIME_TICKS = 10; private static final int POINT_LIFETIME_TICKS = 10;
@@ -14,7 +14,7 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.ClientTickEvent;
@EventBusSubscriber(modid = Antarchy.MODID, bus = EventBusSubscriber.Bus.GAME, value = Dist.CLIENT) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class MogglesClientRenderer { public final class MogglesClientRenderer {
private MogglesClientRenderer() {} private MogglesClientRenderer() {}
@@ -2,21 +2,26 @@ package com.craisinlord.antarchy.neoforge.client;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer; import com.craisinlord.antarchy.content.client.renderer.PortalGunPortalViewRenderer;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME)
public final class PortalGunPortalViewRenderHandler { public final class PortalGunPortalViewRenderHandler {
private static long lastStageLogNanos;
private PortalGunPortalViewRenderHandler() { private PortalGunPortalViewRenderHandler() {
} }
@SubscribeEvent
public static void onRenderLevelStage(RenderLevelStageEvent event) { public static void onRenderLevelStage(RenderLevelStageEvent event) {
if (!PortalGunPortalViewRenderer.isEnabled()) {
return;
}
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_PARTICLES) { if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_PARTICLES) {
return; return;
} }
long now = System.nanoTime();
if (now - lastStageLogNanos > 5_000_000_000L) {
lastStageLogNanos = now;
Antarchy.LOGGER.info("Portal gun NeoForge render stage fired stage={} partial={}", event.getStage(), event.getPartialTick().getGameTimeDeltaPartialTick(false));
}
PortalGunPortalViewRenderer.render(event.getCamera(), event.getPoseStack().last().pose(), event.getPartialTick()); PortalGunPortalViewRenderer.render(event.getCamera(), event.getPoseStack().last().pose(), event.getPartialTick());
} }
} }
@@ -8,7 +8,7 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.ClientTickEvent;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class PortalGunRollClientHandler { public final class PortalGunRollClientHandler {
private PortalGunRollClientHandler() { private PortalGunRollClientHandler() {
} }
@@ -30,7 +30,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class ReverieTrailHandler { public final class ReverieTrailHandler {
private static final int MAX_TRAIL_POINTS = 20; private static final int MAX_TRAIL_POINTS = 20;
@@ -26,7 +26,7 @@ import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class ScorpionWhipTetherRenderHandler { public final class ScorpionWhipTetherRenderHandler {
private ScorpionWhipTetherRenderHandler() { private ScorpionWhipTetherRenderHandler() {
} }
@@ -10,7 +10,7 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.ClientTickEvent;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class StinkySoundHandler { public final class StinkySoundHandler {
private static final int FIRST_SOUND_DELAY = 20; private static final int FIRST_SOUND_DELAY = 20;
private static final int MIN_INTERVAL = 60; private static final int MIN_INTERVAL = 60;
@@ -29,7 +29,7 @@ import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME) @EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT)
public final class WormHookTetherRenderHandler { public final class WormHookTetherRenderHandler {
private static final Map<Integer, WormHookRope> ROPES = new HashMap<>(); private static final Map<Integer, WormHookRope> ROPES = new HashMap<>();
@@ -6,13 +6,13 @@
}, },
"perspectives": { "perspectives": {
"gui": { "gui": {
"parent": "antarchy:item/portal_gun_display" "parent": "antarchy:item/portal_gun_gui"
}, },
"ground": { "ground": {
"parent": "antarchy:item/portal_gun_display" "parent": "antarchy:item/portal_gun_gui"
}, },
"fixed": { "fixed": {
"parent": "antarchy:item/portal_gun_display" "parent": "antarchy:item/portal_gun_gui"
} }
} }
} }