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 java.util.ArrayDeque;
import java.util.Deque;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
public final class PortalGunPortalRenderState {
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<PortalRenderContext>> ACTIVE_CONTEXTS = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<Integer> RENDER_ALL_DEPTH = ThreadLocal.withInitial(() -> 0);
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) {
Deque<PortalGunWorldPortalShape> sourceShapes = ACTIVE_SOURCE_SHAPES.get();
if (!sourceShapes.isEmpty()) {
@@ -43,6 +52,13 @@ public final class PortalGunPortalRenderState {
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) {
@@ -69,7 +85,55 @@ public final class PortalGunPortalRenderState {
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() {
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.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
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_EPSILON = 0.05F;
private static final Map<UUID, Long> TELEPORT_COOLDOWNS = new HashMap<>();
@@ -82,10 +81,11 @@ public final class PortalGunRollClientState {
if (!canTeleport(cameraEntity, gameTime)) {
continue;
}
if (portal.resolveCrossingProbe(cameraEntity) == null) {
Vec3 crossingProbe = portal.resolveCrossingProbe(cameraEntity);
if (crossingProbe == null) {
continue;
}
applyPredictedTeleport(cameraEntity, portal, linkedPortal, gameTime);
applyPredictedTeleport(cameraEntity, portal, linkedPortal, crossingProbe, gameTime);
break;
}
}
@@ -98,11 +98,26 @@ public final class PortalGunRollClientState {
return cooldownUntil <= gameTime;
}
private static void applyPredictedTeleport(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, long gameTime) {
Quaternionf transform = PortalGunTransformUtil.createTransform(sourcePortal, destinationPortal);
Vec3 transformedLook = PortalGunTransformUtil.transform(entity.getLookAngle(), transform).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transform(PortalGunTransformUtil.upVectorFromLookAndRoll(entity.getLookAngle(), rollDegrees), transform).normalize();
private static void applyPredictedTeleport(Entity entity, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal, Vec3 currentProbe, long gameTime) {
Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, entity.getLookAngle()).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, PortalGunTransformUtil.upVectorFromLookAndRoll(entity.getLookAngle(), rollDegrees)).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);
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);
}
}
@@ -3,15 +3,16 @@ package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.model.PortalGunPortalModel;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderType;
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.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Matrix4f;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class PortalGunPortalRenderer extends GeoEntityRenderer<PortalGunPortalEntity> {
@@ -22,20 +23,39 @@ public class PortalGunPortalRenderer extends GeoEntityRenderer<PortalGunPortalEn
@Override
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
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
@@ -1,9 +1,11 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.client.PortalGunEntityTransformationStack;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
import com.craisinlord.antarchy.content.portalgun.PortalGunTransformUtil;
import com.craisinlord.antarchy.content.portalgun.PortalGunPortalEntity;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.pipeline.TextureTarget;
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.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.ArrayList;
@@ -18,6 +21,7 @@ import java.util.List;
import net.minecraft.client.Camera;
import net.minecraft.client.DeltaTracker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
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 TextureTarget[] PORTAL_TARGETS = new TextureTarget[MAX_RECURSION_DEPTH + 1];
private static boolean renderingPortalView;
private static long lastRenderLogTick = Long.MIN_VALUE;
private static long lastHookLogTick = Long.MIN_VALUE;
private PortalGunPortalViewRenderer() {
}
public static boolean isEnabled() {
return false;
}
public static void render(Camera camera, Matrix4f poseMatrix, DeltaTracker tickCounter) {
if (!isEnabled()) {
return;
}
if (renderingPortalView) {
return;
}
Minecraft minecraft = Minecraft.getInstance();
if (minecraft.level == null || minecraft.gameRenderer == null || camera == null || poseMatrix == null || tickCounter == null) {
logRenderUnavailable(minecraft, camera, poseMatrix, tickCounter);
return;
}
logRenderHook(minecraft, camera);
Entity cameraEntity = minecraft.getCameraEntity();
if (cameraEntity == null) {
return;
}
List<PortalGunPortalEntity> portals = collectVisiblePortals(minecraft, camera);
if (portals.isEmpty()) {
logRenderEmpty(minecraft, camera.getPosition());
return;
}
ensureTargets(minecraft);
@@ -67,18 +83,60 @@ public final class PortalGunPortalViewRenderer {
RenderContext rootContext = new RenderContext(cameraPos, rootLook, rootUp, rootViewMatrix);
renderingPortalView = true;
RenderSystem.backupProjectionMatrix();
for (PortalGunPortalEntity portal : portals) {
PortalGunPortalEntity linkedPortal = portal.getLinkedPortal();
if (linkedPortal == null || !linkedPortal.isAlive()) {
continue;
try {
logRenderCollection(minecraft, cameraPos, portals);
for (PortalGunPortalEntity portal : portals) {
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);
minecraft.getMainRenderTarget().bindWrite(true);
drawPortalQuad(cameraPos, poseMatrix, portal, textureId);
drawPortalOverlay(minecraft, cameraPos, poseMatrix, portal);
} catch (RuntimeException exception) {
Antarchy.LOGGER.error("Portal gun portal view render failed", exception);
} finally {
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) {
@@ -91,10 +149,7 @@ public final class PortalGunPortalViewRenderer {
if (!(entity instanceof PortalGunPortalEntity portal) || !portal.isAlive()) {
continue;
}
if (portal.getLinkedPortalId() == null) {
continue;
}
if (!portal.shouldRenderFront(cameraPos)) {
if (portal.distanceToSqr(cameraPos) > 16384.0D) {
continue;
}
portals.add(portal);
@@ -103,6 +158,61 @@ public final class PortalGunPortalViewRenderer {
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) {
int width = minecraft.getWindow().getWidth();
int height = minecraft.getWindow().getHeight();
@@ -148,10 +258,24 @@ public final class PortalGunPortalViewRenderer {
if (clipEnabled) {
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 {
minecraft.levelRenderer.prepareCullFrustum(portalCamera.getPosition(), 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) {
List<PortalGunPortalEntity> nestedPortals = collectVisiblePortals(minecraft, transformedContext.cameraPos());
Matrix4f nestedPose = new Matrix4f().identity();
@@ -164,6 +288,8 @@ public final class PortalGunPortalViewRenderer {
continue;
}
int nestedTextureId = renderPortalSurface(minecraft, cameraEntity, tickCounter, transformedContext, nestedPortal, nestedLinked, depth + 1);
RenderSystem.restoreProjectionMatrix();
RenderSystem.backupProjectionMatrix();
target.bindWrite(true);
drawPortalQuad(transformedContext.cameraPos(), nestedPose, nestedPortal, nestedTextureId);
drawPortalOverlay(minecraft, transformedContext.cameraPos(), nestedPose, nestedPortal);
@@ -179,7 +305,6 @@ public final class PortalGunPortalViewRenderer {
}
private static RenderContext transformContext(RenderContext currentContext, PortalGunPortalEntity sourcePortal, PortalGunPortalEntity destinationPortal) {
Quaternionf transform = PortalGunTransformUtil.createTransform(sourcePortal, destinationPortal);
Vec3 destinationNormal = destinationPortal.getNormalVec().normalize();
Vec3 relativeEye = currentContext.cameraPos().subtract(sourcePortal.position());
double depthOffset = Math.max(CAMERA_OFFSET, relativeEye.dot(sourcePortal.getNormalVec().normalize()));
@@ -187,8 +312,8 @@ public final class PortalGunPortalViewRenderer {
Vec3 destinationEye = destinationPortal.position()
.add(transformedEyeOffset)
.add(destinationNormal.scale(depthOffset + CAMERA_OFFSET - transformedEyeOffset.dot(destinationNormal)));
Vec3 transformedLook = PortalGunTransformUtil.transform(currentContext.look(), transform).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transform(currentContext.up(), transform).normalize();
Vec3 transformedLook = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, currentContext.look()).normalize();
Vec3 transformedUp = PortalGunTransformUtil.transformVector(sourcePortal, destinationPortal, currentContext.up()).normalize();
Matrix4f viewMatrix = new Matrix4f().rotation(PortalGunTransformUtil.orientationQuaternion(transformedLook, transformedUp).conjugate(new Quaternionf()));
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);
}
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) {
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 pulse = 0.72F + 0.18F * (float) Math.sin(time);
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) {
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;
}
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) {
@@ -324,6 +512,7 @@ public final class PortalGunPortalViewRenderer {
RenderSystem.defaultBlendFunc();
}
RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
RenderSystem.disableCull();
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, texture);
@@ -340,6 +529,7 @@ public final class PortalGunPortalViewRenderer {
}
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
RenderSystem.disableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
@@ -362,6 +552,7 @@ public final class PortalGunPortalViewRenderer {
RenderSystem.defaultBlendFunc();
}
RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
RenderSystem.disableCull();
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, textureId);
@@ -378,6 +569,7 @@ public final class PortalGunPortalViewRenderer {
}
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
RenderSystem.disableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
@@ -26,15 +26,17 @@ public class PortalGunProjectileRenderer extends EntityRenderer<PortalGunProject
poseStack.pushPose();
poseStack.mulPose(this.entityRenderDispatcher.cameraOrientation());
float age = entity.tickCount + partialTick;
float syncedDistance = entity.getSyncedDistance() + partialTick;
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;
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 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;
poseStack.scale(baseScale * trailStretch, baseScale, baseScale);
poseStack.scale(baseScale * trailStretch, baseScale * travelPulse, baseScale * travelPulse);
PoseStack.Pose pose = poseStack.last();
Matrix4f matrix = pose.pose();
VertexConsumer core = bufferSource.getBuffer(RenderType.entityTranslucent(texture));
@@ -50,7 +52,7 @@ public class PortalGunProjectileRenderer extends EntityRenderer<PortalGunProject
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);
poseStack.popPose();
}
}
@Override
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 MAX_SPEED = 1.8D;
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 RIDER_Y_OFFSET = 0.65D;
private static final float RIDER_FORWARD_HEAD_OFFSET = 90.0F;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@@ -153,15 +153,11 @@ public class HoverboardEntity extends PathfinderMob implements GeoEntity {
this.yBodyRot = this.getYRot();
this.yHeadRot = this.getYRot();
this.setXRot(0.0F);
rider.setYHeadRot(rider.getYRot() + RIDER_FORWARD_HEAD_OFFSET);
Vec3 look = Vec3.directionFromRotation(0.0F, this.getYRot());
float forward = rider.zza;
boolean holdingJump = ((LivingEntityJumpingAccessor) rider).antarchy$isJumping();
double ascend = holdingJump ? ASCEND_SPEED : (rider.isShiftKeyDown() ? -ASCEND_SPEED : 0.0D);
double groundHeight = this.findGroundHeight();
double maxY = groundHeight + MAX_HOVER_HEIGHT;
double verticalMotion = this.resolveVerticalMotion(holdingJump);
Vec3 currentHorizontal = new Vec3(this.getDeltaMovement().x, 0.0D, this.getDeltaMovement().z);
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);
}
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.move(MoverType.SELF, this.getDeltaMovement());
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());
}
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() {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ()));
int minY = this.level().getMinBuildHeight();
@@ -141,10 +141,12 @@ public class PortalGunItem extends Item implements GeoItem {
PortalGunPortalEntity existing = this.findPlacedPortal(level, player.getUUID(), side);
PortalGunPlacement placement = this.findPlacement(level, player, side, hitResult, existing);
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);
return;
}
if (existing != null) {
Antarchy.LOGGER.info("Portal gun replacing existing portal owner={} side={} oldPortal={}", player.getUUID(), side, existing.getUUID());
existing.discard();
}
if (this.isMoonSideArmed(stack, side)) {
@@ -158,17 +160,22 @@ public class PortalGunItem extends Item implements GeoItem {
portal.configure(player.getUUID(), side, placement);
portal.moveTo(placement.center().x, placement.center().y, placement.center().z, placement.yaw(), 0.0F);
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);
return;
}
level.addFreshEntity(portal);
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);
if (other != null) {
portal.linkTo(other);
other.linkTo(portal);
this.syncPortalBlocks(level, portal);
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";
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();
PortalGunWorldPortalShape.PortalLocalCoords startCoords = shape.localCoords(startCenter);
PortalGunWorldPortalShape.PortalLocalCoords endCoords = shape.localCoords(endCenter);
return startCoords.depth() < 0.0D
&& endCoords.depth() <= PLANE_TOLERANCE
return startCoords.depth() > 0.0D
&& endCoords.depth() >= -PLANE_TOLERANCE
&& Math.abs(endCoords.horizontal()) <= shape.halfWidth() + EDGE_PADDING
&& Math.abs(endCoords.vertical()) <= shape.halfHeight() + EDGE_PADDING
&& projectedWindowOverlap(shape, startBox, endBox);
@@ -82,8 +82,8 @@ public final class PortalGunCollisionHelper {
PortalGunWorldPortalShape.PortalLocalCoords coords = shape.localCoords(corner);
if (Math.abs(coords.horizontal()) <= shape.halfWidth() + EDGE_PADDING
&& Math.abs(coords.vertical()) <= shape.halfHeight() + EDGE_PADDING
&& coords.depth() >= -DEPTH_PADDING
&& coords.depth() <= PLANE_TOLERANCE) {
&& coords.depth() <= DEPTH_PADDING
&& coords.depth() >= -PLANE_TOLERANCE) {
return true;
}
}
@@ -9,6 +9,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import net.minecraft.core.BlockPos;
@@ -17,6 +18,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
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.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@@ -36,7 +39,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
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> UP_AXIS = SynchedEntityData.defineId(PortalGunPortalEntity.class, EntityDataSerializers.INT);
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 IDLE_ANIM = RawAnimation.begin().thenLoop("idle");
private static final RawAnimation CLOSE_ANIM = RawAnimation.begin().thenPlay("close");
private static final int OPEN_TICKS = 10;
private static final int CLOSE_TICKS = 10;
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 HALF_WIDTH = 0.5D;
private static final double HALF_HEIGHT = 1.0D;
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 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 linkedPortalId;
private int ageTicks;
@@ -92,6 +101,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
builder.define(FACING, Direction.NORTH.get3DDataValue());
builder.define(UP_AXIS, Direction.UP.get3DDataValue());
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) {
@@ -99,6 +112,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
this.entityData.set(SIDE, side.ordinal());
this.entityData.set(FACING, placement.facing().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.masterPos = placement.masterPos().immutable();
this.basePos = placement.basePos().immutable();
@@ -108,11 +125,13 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
public void linkTo(PortalGunPortalEntity other) {
this.linkedPortalId = other.getUUID();
this.entityData.set(LINKED_PORTAL, Optional.of(other.getUUID()));
this.pairTime = (int) this.level().getGameTime();
}
public void restorePair(UUID linkedPortalId, int pairTime) {
this.linkedPortalId = linkedPortalId;
this.entityData.set(LINKED_PORTAL, Optional.ofNullable(linkedPortalId));
this.pairTime = pairTime;
}
@@ -130,7 +149,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
public UUID getLinkedPortalId() {
return this.linkedPortalId;
return this.entityData.get(LINKED_PORTAL).orElse(this.linkedPortalId);
}
public BlockPos getMasterPos() {
@@ -141,6 +160,18 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
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() {
return this.basePos;
}
@@ -158,10 +189,11 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
public PortalGunPortalEntity getLinkedPortal() {
if (this.linkedPortalId == null) {
UUID linkedId = this.getLinkedPortalId();
if (linkedId == 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()) {
return null;
}
@@ -216,7 +248,7 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
public AABB getCollisionRemovalAabbForEntity(Entity entity) {
double speed = entity.getDeltaMovement().length();
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) {
@@ -253,7 +285,10 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
Vec3 previousProbe = this.previousTeleportProbePosition(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) {
@@ -317,8 +352,14 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
PortalGunPortalEntity linked = this.findLinkedPortal(serverLevel);
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;
}
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);
}
@@ -351,15 +392,46 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
private void tickTeleport(PortalGunPortalEntity linked) {
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) {
Vec3 crossingProbe = this.resolveCrossingProbe(entity);
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;
}
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);
}
}
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) {
if (!entity.isAlive() || entity instanceof PortalGunPortalEntity || entity.isPassenger() || entity.isVehicle()) {
return false;
@@ -376,6 +448,72 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
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) {
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);
@@ -414,18 +552,21 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
private void teleportEntity(Entity entity, PortalGunPortalEntity destination, Vec3 currentProbe) {
Quaternionf transform = PortalGunTransformUtil.createTransform(this, destination);
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 transformedEntityOffset = PortalGunTransformUtil.transform(entityOffsetFromProbe, transform);
Vec3 transformedLook = PortalGunTransformUtil.transform(entity.getLookAngle(), transform).normalize();
Vec3 transformedMotion = PortalGunTransformUtil.transform(entity.getDeltaMovement(), transform);
Vec3 exitProbe = destination.position().add(transformedProbe).add(destination.getNormalVec().normalize().scale(0.08D - transformedProbe.dot(destination.getNormalVec().normalize())));
Vec3 exitPos = exitProbe.add(transformedEntityOffset);
Vec3 transformedEntityOffset = PortalGunTransformUtil.transformVector(this, destination, entityOffsetFromProbe);
Vec3 transformedLook = PortalGunTransformUtil.transformVector(this, destination, entity.getLookAngle()).normalize();
Vec3 entryMotion = this.portalEntryMomentum(entity, currentProbe);
Vec3 transformedMotion = this.exitMomentum(entity, destination, PortalGunTransformUtil.transformVector(this, destination, entryMotion));
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 pitch = PortalGunTransformUtil.pitchFromLook(transformedLook);
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) {
player.teleportTo(destinationLevel, exitPos.x, exitPos.y, exitPos.z, yaw, pitch);
} else {
@@ -437,8 +578,62 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
entity.setDeltaMovement(transformedMotion);
entity.hasImpulse = true;
entity.hurtMarked = true;
if (entity instanceof ServerPlayer player) {
player.connection.send(new ClientboundSetEntityMotionPacket(player));
}
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);
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() {
@@ -500,6 +695,9 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
tag.putInt("Side", this.getPortalSide().ordinal());
tag.putInt("Facing", this.getFacingDirection().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("SupportY", this.supportOrigin.getY());
tag.putInt("SupportZ", this.supportOrigin.getZ());
@@ -536,12 +734,23 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
}
if (tag.hasUUID("LinkedPortalId")) {
this.linkedPortalId = tag.getUUID("LinkedPortalId");
this.entityData.set(LINKED_PORTAL, Optional.of(this.linkedPortalId));
}
this.ageTicks = tag.getInt("AgeTicks");
this.pairTime = tag.getInt("PairTime");
this.entityData.set(SIDE, tag.getInt("Side"));
this.entityData.set(FACING, tag.getInt("Facing"));
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.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"));
@@ -636,6 +845,20 @@ public class PortalGunPortalEntity extends Entity implements GeoEntity {
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 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 java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
@@ -23,8 +24,19 @@ import net.minecraft.world.phys.Vec3;
public class PortalGunProjectileEntity extends ThrowableItemProjectile {
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 UUID gunId;
private boolean spawnSynced;
public int portalWidth = 1;
public int portalHeight = 2;
public PortalGunProjectileEntity(EntityType<? extends PortalGunProjectileEntity> entityType, Level level) {
super(entityType, level);
@@ -45,18 +57,46 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
protected void defineSynchedData(SynchedEntityData.Builder builder) {
super.defineSynchedData(builder);
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) {
this.entityData.set(SIDE, side.ordinal());
this.gunId = gunId;
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() {
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
protected Item getDefaultItem() {
return Items.AIR;
@@ -85,6 +125,11 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
@Override
public void tick() {
super.tick();
if (!this.spawnSynced) {
this.syncSpawnPosition(this.blockPosition());
}
this.syncVelocity();
this.entityData.set(DISTANCE, this.tickCount);
if (this.tickCount > MAX_FLIGHT_TICKS) {
this.discard();
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);
}
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() {
ItemStack projectileStack = this.getItem();
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) {
super.addAdditionalSaveData(tag);
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) {
tag.putUUID("GunId", this.gunId);
}
@@ -155,6 +224,17 @@ public class PortalGunProjectileEntity extends ThrowableItemProjectile {
public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag);
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")) {
this.gunId = tag.getUUID("GunId");
}
@@ -38,7 +38,31 @@ public final class PortalGunTransformUtil {
}
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) {
@@ -24,7 +24,7 @@ public record PortalGunWorldPortalShape(
}
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() {
@@ -77,7 +77,7 @@ public record PortalGunWorldPortalShape(
public boolean shouldRenderFront(Vec3 cameraPos) {
PortalLocalCoords coords = this.localCoords(cameraPos);
if (coords.depth() <= 0.0D) {
if (coords.depth() <= -0.25D) {
return false;
}
double depthScale = Math.min(DEFAULT_SCAN_DISTANCE, Math.max(0.0D, coords.depth()));
@@ -96,6 +96,30 @@ public record PortalGunWorldPortalShape(
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() {
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.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.level.Level;
public final class ThoraxisUndersideManager {
public static final int GRAVITY_FLIP_Y = 0;
private static final ResourceLocation THORAXIS_DIMENSION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "thoraxis");
private static final AntarchyGravityTransition TRANSITION = new AntarchyGravityTransition(12);
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 ThoraxisUndersideManager() {
@@ -38,14 +41,28 @@ public final class ThoraxisUndersideManager {
boolean inUnderside = entity.getY() < GRAVITY_FLIP_Y;
if (entity instanceof LivingEntity living) {
UUID uuid = entity.getUUID();
if (inUnderside) {
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
} else if (living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
living.removeEffect(AntarchyObjects.INVERTED_EFFECT.get());
if (!living.hasEffect(AntarchyObjects.INVERTED_EFFECT.get())) {
living.addEffect(new MobEffectInstance(AntarchyObjects.INVERTED_EFFECT.get(), EFFECT_DURATION_TICKS, 0, true, false, false));
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;
}
if (!(entity instanceof ItemEntity)) {
continue;
}
UUID uuid = entity.getUUID();
if (inUnderside) {
activeThisTick.add(uuid);
@@ -67,7 +84,7 @@ public final class ThoraxisUndersideManager {
UNDERSIDE_FORCED_GRAVITY.retainAll(activeThisTick);
}
public static boolean isThoraxis(ServerLevel level) {
public static boolean isThoraxis(Level level) {
return level.dimension().location().equals(THORAXIS_DIMENSION);
}
}
@@ -1,7 +1,6 @@
package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
import com.craisinlord.antarchy.content.portalgun.PortalGunWorldPortalShape;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.MultiBufferSource;
@@ -21,18 +20,9 @@ public abstract class BlockEntityRenderDispatcherPortalMixin {
if (PortalGunPortalRenderState.renderAll() || blockEntity == null || blockEntity.isRemoved()) {
return;
}
PortalGunWorldPortalShape destinationShape = PortalGunPortalRenderState.getDestinationShape();
PortalGunWorldPortalShape sourceShape = PortalGunPortalRenderState.getSourceShape();
if (destinationShape == null) {
return;
}
BlockPos pos = blockEntity.getBlockPos();
AABB bounds = new AABB(pos);
if (!destinationShape.intersectsFront(bounds, 0.1D)) {
ci.cancel();
return;
}
if (sourceShape != null && sourceShape.intersectsFront(bounds, -0.02D)) {
if (!PortalGunPortalRenderState.shouldRenderBounds(bounds)) {
ci.cancel();
}
}
@@ -2,7 +2,6 @@ package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.client.PortalGunPortalRenderState;
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.entity.EntityRenderDispatcher;
import net.minecraft.world.entity.Entity;
@@ -18,16 +17,7 @@ public abstract class EntityRenderDispatcherPortalMixin {
if (PortalGunPortalRenderState.renderAll() || entity instanceof PortalGunPortalEntity) {
return;
}
PortalGunWorldPortalShape destinationShape = PortalGunPortalRenderState.getDestinationShape();
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)) {
if (!PortalGunPortalRenderState.shouldRenderBounds(entity.getBoundingBox())) {
cir.setReturnValue(false);
}
}
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.mixins.client;
import com.craisinlord.antarchy.content.entity.HoverboardEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.world.entity.LivingEntity;
@@ -45,4 +46,20 @@ public abstract class HoverboardRiderPoseMixin<T extends LivingEntity, M extends
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.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
@@ -33,7 +34,7 @@ public abstract class BehaviorUtilsGravityMixin {
@Local float yOffset,
@Local LivingEntity entity
) {
if (!AntarchyGravityApi.isGravityInverted(entity)) {
if (!antarchy$shouldInvertThrownItem(entity)) {
return original.call(level, x, y, z, stack);
}
@@ -58,11 +59,17 @@ public abstract class BehaviorUtilsGravityMixin {
Operation<Void> original,
@Local LivingEntity entity
) {
if (!AntarchyGravityApi.isGravityInverted(entity)) {
if (!antarchy$shouldInvertThrownItem(entity)) {
original.call(itemEntity, deltaMovement);
return;
}
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.AbstractMinecartRendererMixin",
"client.BlockEntityRenderDispatcherPortalMixin",
"client.EntityLightProbeMixin",
"client.CustomBossBarMixin",
"client.DimensionMusicMixin",
"client.EntityRenderDispatcherPortalMixin",
"client.CavarynSkyMixin",
"client.CavarynHordeFogMixin",
"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": {
"": {
"axis=x": {
"model": "antarchy:block/stripped_truffalo_wood",
"x": 90,
"y": 90
},
"axis=y": {
"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.nightmare_scale": "Nightmare Scale",
"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_chestplate": "Nightmare Chestplate",
"item.antarchy.nightmare_leggings": "Nightmare Leggings",
@@ -10,10 +10,10 @@
"from": [0, 4, 4],
"to": [16, 12, 12],
"faces": {
"north": {"uv": [0, 4, 16, 12], "texture": "#side"},
"south": {"uv": [0, 4, 16, 12], "texture": "#side"},
"up": {"uv": [0, 4, 16, 12], "texture": "#side"},
"down": {"uv": [0, 4, 16, 12], "texture": "#side"},
"north": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"south": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"up": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"east": {"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",
"textures": {
"end": "antarchy:block/truffalo/truffalo_log_stripped",
"side": "antarchy:block/truffalo/truffalo_log_stripped"
"end": "antarchy:block/truffalo/truffalo_wood_stripped",
"side": "antarchy:block/truffalo/truffalo_wood_stripped"
}
}
@@ -10,10 +10,10 @@
"from": [0, 4, 4],
"to": [16, 12, 12],
"faces": {
"north": {"uv": [0, 4, 16, 12], "texture": "#side"},
"south": {"uv": [0, 4, 16, 12], "texture": "#side"},
"up": {"uv": [0, 4, 16, 12], "texture": "#side"},
"down": {"uv": [0, 4, 16, 12], "texture": "#side"},
"north": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"south": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"up": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#side"},
"east": {"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"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",
"textures": {
"end": "antarchy:block/truffalo/truffalo_log",
"side": "antarchy:block/truffalo/truffalo_log"
"end": "antarchy:block/truffalo/truffalo_wood",
"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": {
"subtitle": "subtitles.antarchy.bed_bug_ambient",
"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": {
"count": 3,
"count": 2,
"id": "antarchy:stripped_truffalo_wood"
}
}
@@ -4,7 +4,7 @@
"group": "planks",
"ingredients": [
{
"tag": "antarchy:truffalo_logs"
"item": "antarchy:truffalo_log"
}
],
"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": {
"count": 3,
"count": 2,
"id": "antarchy:truffalo_wood"
}
}
@@ -19,7 +19,6 @@
"antarchy:shellstone_brick_stairs",
"antarchy:shellstone_brick_slab",
"antarchy:shellstone_brick_wall",
"antarchy:myrmite_coal_ore",
"antarchy:chitin_block",
"antarchy:broodstone",
"antarchy:polished_broodstone",
@@ -40,23 +39,6 @@
"antarchy:bluestone_block",
"antarchy:shellstone_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_brick_stairs",
"antarchy:mossy_broodstone_brick_slab",