fixes... lots of fixes

This commit is contained in:
QuImUfu 2024-07-23 22:42:47 +02:00
parent a654eec852
commit 8c877a5043
20 changed files with 346 additions and 151 deletions

View File

@ -126,7 +126,7 @@ import com.modrinth.minotaur.dependencies.ModDependency
modrinth { modrinth {
projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work. projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work.
uploadFile = remapJar // Tells Minotaur to use the remapped jar uploadFile = remapJar // Tells Minotaur to use the remapped jar
versionType = "alpha" versionType = "beta"
dependencies = [ dependencies = [
new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API
new ModDependency('AANobbMI', 'optional'), //compatible with Sodium new ModDependency('AANobbMI', 'optional'), //compatible with Sodium

View File

@ -14,7 +14,7 @@ public class MixinConfig implements IMixinConfigPlugin {
private static final Supplier<Boolean> TRUE = () -> true; private static final Supplier<Boolean> TRUE = () -> true;
private static final Map<String, Supplier<Boolean>> CONDITIONS = Map.of( private static final Map<String, Supplier<Boolean>> CONDITIONS = Map.of(
"quimufu.colourful_portals.mixin.SodiumFluidRendererMixin", () -> FabricLoader.getInstance().isModLoaded("sodium") "quimufu.colourful_portals.mixin.client.SodiumFluidRendererMixin", () -> FabricLoader.getInstance().isModLoaded("sodium")
); );
@Override @Override

View File

@ -76,8 +76,8 @@ public class PortalBlock extends Block implements FluidFillable {
return VoxelShapes.empty(); return VoxelShapes.empty();
} }
@Override protected void onEntityCollisionOld(BlockState state, World world, BlockPos pos, Entity entity) {
protected void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { ColourfulPortalsMod.LOGGER.info("detected collision {}", entity.getType());
if (entity.getBoundingBox() if (entity.getBoundingBox()
.intersects(getShape(state, world, pos).getBoundingBox())) { .intersects(getShape(state, world, pos).getBoundingBox())) {
Vec3d vec3d = new Vec3d(0.5, 0.5f, 0.5); Vec3d vec3d = new Vec3d(0.5, 0.5f, 0.5);
@ -85,6 +85,11 @@ public class PortalBlock extends Block implements FluidFillable {
} }
Vec3d entityPos = entity.getPos(); Vec3d entityPos = entity.getPos();
Vec3d prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ); Vec3d prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ);
if(entityPos.equals(prevEntityPos) && entity.getVelocity().squaredDistanceTo(Vec3d.ZERO) >= 0.01D){
//in this case, the collision logic was called prior to the movement logic,
// so we'll have to calculate our own next postion
entityPos = entityPos.add(entity.getVelocity());
}
Vec3d movement = entityPos.subtract(prevEntityPos); Vec3d movement = entityPos.subtract(prevEntityPos);
if (world instanceof ServerWorld) { if (world instanceof ServerWorld) {
Direction.Axis axis = state.get(AXIS); Direction.Axis axis = state.get(AXIS);

View File

@ -0,0 +1,89 @@
package quimufu.colourful_portals.mixin;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.registry.Registries;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import quimufu.colourful_portals.util.RaycastHelper;
import java.util.List;
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
@Mixin(ServerWorld.class)
public abstract class BlockChangeAndEntityMovementMixin {
@Unique
private static final List<Direction> HORIZONTAL = Direction.stream().filter(d -> d.getAxis().isHorizontal()).toList();
// @Unique
// private final ThreadLocal<Map<EntityType<?>, Entity>> entities =
// ThreadLocal.withInitial(() -> HashMap.newHashMap(Registries.ENTITY_TYPE.size()));
@Shadow
public abstract String toString();
// @Inject(at = @At(value = "HEAD"), method = "tickEntity")
// private void cpm_beforeEntityTick(Entity entity, CallbackInfo ci) {
// if(PORTAL_MANAGER.getLinkingSystem().needsMovementCallback()){
// Entity copy = entities.get().computeIfAbsent(entity.getType(), t -> t.create(null));
// copy.copyFrom(entity);
// }
// }
@Shadow
public abstract boolean isChunkLoaded(long chunkPos);
@Inject(at = @At("RETURN"), method = "tickEntity")
private void cpm_afterEntityTick(Entity entity, CallbackInfo ci) {
if (PORTAL_MANAGER.getLinkingSystem().needsMovementCallback()) {
Vec3d prevEntityPos;
if (entity instanceof ServerPlayerEntity serverPlayerEntity) {
ServerPlayNetworkHandlerAccessor spnha = (ServerPlayNetworkHandlerAccessor) serverPlayerEntity.networkHandler;
prevEntityPos = new Vec3d(spnha.getLastTickX(), spnha.getLastTickY(), spnha.getLastTickZ());
} else {
prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ);
}
Vec3d entityPos = entity.getPos();
ServerWorld world = (ServerWorld) (Object) this;
List<BlockPos> passedBlocks = RaycastHelper.passedBlocks(prevEntityPos, entityPos);
for (BlockPos passedBlock : passedBlocks) {
if (PORTAL_MANAGER.onMovementThroughBlock(entity, passedBlock, world)) {
return;
}
}
}
}
@Inject(at = @At("RETURN"), method = "onBlockChanged")
private void cpm_afterOnBlockChanged(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo info) {
ServerWorld world = (ServerWorld) (Object) this;
if (world.isDebugWorld())
return;
// This code is injected into the end of ServerWorld.onBlockChanged()V
if (oldBlock.getBlock() != newBlock.getBlock()) {
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(newBlock.getBlock()))) {
LOGGER.info("onBlockNew {} -> {}", oldBlock, newBlock);
Identifier blockId = Registries.BLOCK.getId(newBlock.getBlock());
world.getServer().execute(() -> PORTAL_MANAGER.onPortalBlockPlaced(world, pos, blockId));
}
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(oldBlock.getBlock()))) {
LOGGER.info("onBlockOld {} -> {}", oldBlock, newBlock);
Identifier blockId = Registries.BLOCK.getId(oldBlock.getBlock());
world.getServer().execute(() -> PORTAL_MANAGER.onPortalBlockBroken(world, pos, blockId));
}
}
}
}

View File

@ -1,39 +0,0 @@
package quimufu.colourful_portals.mixin;
import net.minecraft.block.BlockState;
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
@Mixin(ServerWorld.class)
public class BlockChangeMixin {
@Inject(at = @At("RETURN"), method = "onBlockChanged")
private void cpm_afterOnBlockChanged(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo info) {
ServerWorld world = (ServerWorld) (Object) this;
if(world.isDebugWorld()|| !world.isChunkLoaded(pos))
return;
// This code is injected into the end of ServerWorld.onBlockChanged()V
if (oldBlock.getBlock() != newBlock.getBlock()) {
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(newBlock.getBlock()))) {
LOGGER.info("onBlockNew {} -> {}", oldBlock, newBlock);
Identifier blockId = Registries.BLOCK.getId(newBlock.getBlock());
PORTAL_MANAGER.onPortalBlockPlaced(world, pos, blockId);
}
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(oldBlock.getBlock()))) {
LOGGER.info("onBlockOld {} -> {}", oldBlock, newBlock);
Identifier blockId = Registries.BLOCK.getId(oldBlock.getBlock());
PORTAL_MANAGER.onPortalBlockBroken(world, pos, blockId);
}
}
}
}

View File

@ -1,65 +0,0 @@
package quimufu.colourful_portals.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import quimufu.colourful_portals.util.CollisionAwareShapeContext;
import java.util.HashSet;
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_BLOCK;
@Mixin(Entity.class)
public class EntityMixin {
@Shadow
private World world;
@Shadow
public double prevX;
@Shadow
public double prevY;
@Shadow
public double prevZ;
@Shadow
private Vec3d pos;
@Unique
private final ThreadLocal<HashSet<BlockPos>> calledAlready = ThreadLocal.withInitial(HashSet::new);
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onEntityCollision(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;)V"), method = "checkBlockCollision")
public void cpm_dontCallTwice(CallbackInfo ci, @Local BlockPos.Mutable mutable) {
calledAlready.get().add(mutable.toImmutable());
}
@Inject(at = @At("RETURN"), method = "checkBlockCollision")
public void cpm_afterCheckBlockCollision(CallbackInfo ci) {
if (!world.isClient()) {
BlockHitResult hitResult = world.raycast(new RaycastContext(new Vec3d(prevX, prevY, prevZ), pos, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, new CollisionAwareShapeContext()));
BlockPos hitResultBlockPos = hitResult.getBlockPos();
if (!calledAlready.get().contains(hitResultBlockPos)) {
BlockState state = world.getBlockState(hitResultBlockPos);
if (state.getBlock() == PORTAL_BLOCK) {
state.onEntityCollision(world, hitResultBlockPos, (Entity) ((Object) this));
}
}
calledAlready.get().clear();
}
}
}

View File

@ -0,0 +1,26 @@
package quimufu.colourful_portals.mixin;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ServerPlayNetworkHandler.class)
public interface ServerPlayNetworkHandlerAccessor {
@Accessor
double getLastTickX();
@Accessor
double getLastTickY();
@Accessor
double getLastTickZ();
@Accessor
double getLastTickRiddenX();
@Accessor
double getLastTickRiddenY();
@Accessor
double getLastTickRiddenZ();
}

View File

@ -0,0 +1,12 @@
package quimufu.colourful_portals.mixin;
import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ServerPlayerEntity.class)
public interface ServerPlayerEntityAccessor {
@Accessor
void setInTeleportationState(boolean inTeleportationState);
}

View File

@ -1,4 +1,4 @@
package quimufu.colourful_portals.mixin; package quimufu.colourful_portals.mixin.client;
import net.minecraft.client.texture.Animator; import net.minecraft.client.texture.Animator;
import net.minecraft.client.texture.SpriteContents; import net.minecraft.client.texture.SpriteContents;

View File

@ -1,4 +1,4 @@
package quimufu.colourful_portals.mixin; package quimufu.colourful_portals.mixin.client;
import net.minecraft.client.resource.metadata.AnimationResourceMetadata; import net.minecraft.client.resource.metadata.AnimationResourceMetadata;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,4 +1,4 @@
package quimufu.colourful_portals.mixin; package quimufu.colourful_portals.mixin.client;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.client.resource.metadata.AnimationResourceMetadata; import net.minecraft.client.resource.metadata.AnimationResourceMetadata;

View File

@ -1,17 +1,14 @@
package quimufu.colourful_portals.mixin; package quimufu.colourful_portals.mixin.client;
import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers;
import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder;
import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; import me.jellysquid.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer;
import me.jellysquid.mods.sodium.client.world.WorldSlice; import me.jellysquid.mods.sodium.client.world.WorldSlice;
import net.minecraft.fluid.FluidState; import net.minecraft.fluid.FluidState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import quimufu.colourful_portals.client.SodiumPortalFluidRenderHandler; import quimufu.colourful_portals.client.SodiumPortalFluidRenderHandler;
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_FLUID; import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_FLUID;

View File

@ -1,9 +1,8 @@
package quimufu.colourful_portals.mixin; package quimufu.colourful_portals.mixin.client;
import net.minecraft.client.resource.metadata.AnimationResourceMetadata; import net.minecraft.client.resource.metadata.AnimationResourceMetadata;
import net.minecraft.client.texture.SpriteContents; import net.minecraft.client.texture.SpriteContents;
import net.minecraft.client.texture.SpriteDimensions; import net.minecraft.client.texture.SpriteDimensions;
import net.minecraft.resource.metadata.ResourceMetadata;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,7 +1,10 @@
package quimufu.colourful_portals.portal; package quimufu.colourful_portals.portal;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.ArrowEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockBox;
@ -11,14 +14,15 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.TeleportTarget; import net.minecraft.world.TeleportTarget;
import quimufu.colourful_portals.general_util.LinkedList; import quimufu.colourful_portals.general_util.LinkedList;
import quimufu.colourful_portals.general_util.Node; import quimufu.colourful_portals.general_util.Node;
import quimufu.colourful_portals.mixin.ServerPlayNetworkHandlerAccessor;
import quimufu.colourful_portals.mixin.ServerPlayerEntityAccessor;
import quimufu.colourful_portals.util.RaycastHelper;
import java.util.*; import java.util.*;
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
import static quimufu.colourful_portals.ColourfulPortalsMod.MOD_ID; import static quimufu.colourful_portals.ColourfulPortalsMod.MOD_ID;
import static quimufu.colourful_portals.portal.PortalHelper.getAxisW; import static quimufu.colourful_portals.portal.PortalHelper.*;
import static quimufu.colourful_portals.portal.PortalHelper.insideOf;
import static quimufu.colourful_portals.portal.PortalHelper.getDimId;
public class DefaultLinkingSystem implements PortalLinkingSystem { public class DefaultLinkingSystem implements PortalLinkingSystem {
@ -58,9 +62,32 @@ public class DefaultLinkingSystem implements PortalLinkingSystem {
} }
@Override @Override
public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) { public boolean movementCallback(Entity entity, BlockPos pos, ServerWorld world) {
Set<Node<PortalRepresentation>> portalRepresentationCandidated = positionalLookup.get(pos); for (Direction.Axis axis : Direction.Axis.values()) {
Optional<Node<PortalRepresentation>> portalOpt = portalRepresentationCandidated.stream() Vec3d prevEntityPos;
if (entity instanceof ServerPlayerEntity serverPlayerEntity) {
ServerPlayNetworkHandlerAccessor spnha = (ServerPlayNetworkHandlerAccessor) serverPlayerEntity.networkHandler;
prevEntityPos = new Vec3d(spnha.getLastTickX(), spnha.getLastTickY(), spnha.getLastTickZ());
} else {
prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ);
}
if (RaycastHelper.passedOnAxis(prevEntityPos, entity.getPos(), pos, axis)) {
//LOGGER.info("passed on Axis!");
if (onPortalPassed(entity, pos, world, axis)) {
return true;
}
}
}
return false;
}
@Override
public boolean onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) {
Set<Node<PortalRepresentation>> portalRepresentationCandidates = positionalLookup.get(pos);
if (portalRepresentationCandidates == null) {
return false;
}
Optional<Node<PortalRepresentation>> portalOpt = portalRepresentationCandidates.stream()
.filter(n -> !n.orphaned()) .filter(n -> !n.orphaned())
.filter(n -> n.getValue() != null) .filter(n -> n.getValue() != null)
.filter(n -> getAxisW(n.getValue()).rotateYClockwise().getAxis() == a) .filter(n -> getAxisW(n.getValue()).rotateYClockwise().getAxis() == a)
@ -70,7 +97,7 @@ public class DefaultLinkingSystem implements PortalLinkingSystem {
Node<PortalRepresentation> fromNode = portalOpt.get(); Node<PortalRepresentation> fromNode = portalOpt.get();
Node<PortalRepresentation> toNode = fromNode.getNext() != null ? fromNode.getNext() : fromNode.getPartOf().getNode(0); Node<PortalRepresentation> toNode = fromNode.getNext() != null ? fromNode.getNext() : fromNode.getPartOf().getNode(0);
if (toNode == null || toNode.getValue() == null) { if (toNode == null || toNode.getValue() == null) {
return; return false;
} }
PortalRepresentation fromPortal = fromNode.getValue(); PortalRepresentation fromPortal = fromNode.getValue();
@ -79,22 +106,57 @@ public class DefaultLinkingSystem implements PortalLinkingSystem {
Vec3d fromCenter = new Vec3d((fromBox.getMaxX() + 1 + fromBox.getMinX()) / 2D, (fromBox.getMaxY() + 1 + fromBox.getMinY()) / 2D, (fromBox.getMaxZ() + 1 + fromBox.getMinZ()) / 2D); Vec3d fromCenter = new Vec3d((fromBox.getMaxX() + 1 + fromBox.getMinX()) / 2D, (fromBox.getMaxY() + 1 + fromBox.getMinY()) / 2D, (fromBox.getMaxZ() + 1 + fromBox.getMinZ()) / 2D);
BlockBox toBox = toPortal.location(); BlockBox toBox = toPortal.location();
Vec3d toCenter = new Vec3d((toBox.getMaxX() + 1 + toBox.getMinX()) / 2D, (toBox.getMaxY() + 1 + toBox.getMinY()) / 2D, (toBox.getMaxZ() + 1 + toBox.getMinZ()) / 2D); Vec3d toCenter = new Vec3d((toBox.getMaxX() + 1 + toBox.getMinX()) / 2D, (toBox.getMaxY() + 1 + toBox.getMinY()) / 2D, (toBox.getMaxZ() + 1 + toBox.getMinZ()) / 2D);
Vec3d relPos = entity.getPos().subtract(fromCenter);
Vec3d targetPos;
float targetYaw;
Vec3d targetVelocity;
ServerWorld toWorld = getPortalWorld(server, toPortal);
if (getAxisW(fromPortal) == getAxisW(toPortal)) { if (getAxisW(fromPortal) == getAxisW(toPortal)) {
Vec3d relPos = entity.getPos().subtract(fromCenter); targetPos = toCenter.add(relPos);
Vec3d targetPos = toCenter.add(relPos); targetYaw = entity.getYaw();
//todo: maybe fancy continoous movement math! targetVelocity = entity.getVelocity();
ServerWorld toWorld = getPortalWorld(server, toPortal);
TeleportTarget teleportTarget = new TeleportTarget(toWorld, targetPos, entity.getVelocity(), entity.getYaw(), entity.getPitch(), TeleportTarget.ADD_PORTAL_CHUNK_TICKET);
entity.teleportTo(teleportTarget);
} else { } else {
Vec3d relPos = entity.getPos().subtract(fromCenter); targetPos = toCenter.add(new Vec3d(-relPos.z, relPos.y, relPos.x));
Vec3d targetPos = toCenter.add(new Vec3d(-relPos.z, relPos.y, relPos.x)); if (entity instanceof PersistentProjectileEntity) {
// //un-fuck up arrow Yaw
// //rotate by 90°
// targetYaw = (entity.getYaw() + 90.F) % 360.F;
// //mirror
// targetYaw = (-targetYaw) % 360.F;
// //rotate by 90°
// targetYaw = (targetYaw - 90.F) % 360.F;
//
// //now it's normal!
// //Let's rotate it!
// targetYaw = (targetYaw + 90.F) % 360.F;
//
// //fuck it up again
// //rotate by 90°
// targetYaw = (targetYaw + 90.F) % 360.F;
// //mirror
// targetYaw = (-targetYaw) % 360.F;
// //rotate by 90°
// targetYaw = (targetYaw - 90.F) % 360.F;
//short:
targetYaw = (entity.getYaw() - 90.F) % 360.F;
} else {
targetYaw = (entity.getYaw() + 90.F) % 360.F;
}
Vec3d currVelocity = entity.getVelocity();
targetVelocity = new Vec3d(-currVelocity.z, currVelocity.y, currVelocity.x);
}
//todo: maybe fancy continoous movement math! //todo: maybe fancy continoous movement math!
ServerWorld toWorld = getPortalWorld(server, toPortal); TeleportTarget teleportTarget = new TeleportTarget(toWorld, targetPos, targetVelocity, targetYaw, entity.getPitch(), TeleportTarget.ADD_PORTAL_CHUNK_TICKET);
TeleportTarget teleportTarget = new TeleportTarget(toWorld, targetPos, entity.getVelocity(), (entity.getYaw() + 90.F) % 360.F, entity.getPitch(), TeleportTarget.ADD_PORTAL_CHUNK_TICKET); if (entity instanceof ServerPlayerEntity) {
entity.teleportTo(teleportTarget); ((ServerPlayerEntityAccessor) entity).setInTeleportationState(true);
}
Entity target;
if ((target = entity.teleportTo(teleportTarget)) != null) {
target.velocityDirty = true;
return true;
} }
} }
return false;
} }
@Override @Override
@ -102,6 +164,11 @@ public class DefaultLinkingSystem implements PortalLinkingSystem {
return true; return true;
} }
@Override
public boolean needsMovementCallback() {
return true;
}
private static ServerWorld getPortalWorld(MinecraftServer server, PortalRepresentation fromPortalRepresentation) { private static ServerWorld getPortalWorld(MinecraftServer server, PortalRepresentation fromPortalRepresentation) {
ServerWorld serverWorld = PortalHelper.getPortalWorld(server, fromPortalRepresentation); ServerWorld serverWorld = PortalHelper.getPortalWorld(server, fromPortalRepresentation);
if (serverWorld == null) { if (serverWorld == null) {

View File

@ -111,8 +111,9 @@ public class ImmersivePortalsLinkingSystem implements PortalLinkingSystem {
} }
@Override @Override
public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) { public boolean onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) {
//no-op, handled by immptl //no-op, handled by immptl
return false;
} }
@Override @Override
@ -120,6 +121,16 @@ public class ImmersivePortalsLinkingSystem implements PortalLinkingSystem {
return false; return false;
} }
@Override
public boolean needsMovementCallback() {
return false;
}
@Override
public boolean movementCallback(Entity entity, BlockPos p, ServerWorld world) {
return false;
}
private List<qouteall.imm_ptl.core.portal.Portal> getPortalList(PortalRepresentation portalRepresentation) { private List<qouteall.imm_ptl.core.portal.Portal> getPortalList(PortalRepresentation portalRepresentation) {
Box portalBox = Box.from(portalRepresentation.location()); Box portalBox = Box.from(portalRepresentation.location());
return getPortalWorld(portalRepresentation) return getPortalWorld(portalRepresentation)

View File

@ -7,8 +7,6 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import quimufu.colourful_portals.general_util.LinkedList; import quimufu.colourful_portals.general_util.LinkedList;
import java.util.List;
public interface PortalLinkingSystem { public interface PortalLinkingSystem {
Identifier getLinkingSystemId(); Identifier getLinkingSystemId();
@ -16,7 +14,11 @@ public interface PortalLinkingSystem {
void unLinkPortal(PortalRepresentation portalRepresentation); void unLinkPortal(PortalRepresentation portalRepresentation);
void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a); boolean onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a);
boolean needsReInit(); boolean needsReInit();
boolean needsMovementCallback();
boolean movementCallback(Entity entity, BlockPos p, ServerWorld world);
} }

View File

@ -251,6 +251,10 @@ public class PortalManager {
linkingSystem.onPortalPassed(entity, pos, world, a); linkingSystem.onPortalPassed(entity, pos, world, a);
} }
public boolean onMovementThroughBlock(Entity entity, BlockPos pos, ServerWorld world) {
return linkingSystem.movementCallback(entity, pos, world);
}
public void onLoad(MinecraftServer minecraftServer) { public void onLoad(MinecraftServer minecraftServer) {
HashSet<Identifier> blockIdsToDelete = new HashSet<>(portalCandidateList.getBlockIds()); HashSet<Identifier> blockIdsToDelete = new HashSet<>(portalCandidateList.getBlockIds());
blockIdsToDelete.addAll(portalList.getBlockIds()); blockIdsToDelete.addAll(portalList.getBlockIds());

View File

@ -198,6 +198,8 @@ public class PortalFluid extends Fluid {
} }
} }
Direction candidate = null; Direction candidate = null;
BlockState candidateBlockState = null;
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
if (dir == targetDir.getOpposite() || dir == targetDir) { if (dir == targetDir.getOpposite() || dir == targetDir) {
continue; continue;
@ -212,12 +214,16 @@ public class PortalFluid extends Fluid {
//if adjacent to any solid Block, it's a candidate //if adjacent to any solid Block, it's a candidate
if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) { if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) {
candidate = dir; candidate = dir;
candidateBlockState = world.getBlockState(pos.offset(dir));
} }
if (candidate == null && !neighbourOfInspected.isReplaceable()) { if ((candidate == null || candidateBlockState.isReplaceable()) && !neighbourOfInspected.isReplaceable()) {
candidate = dir; candidate = dir;
candidateBlockState = world.getBlockState(pos.offset(dir));
} }
if (candidate == null && !neighbourOfInspected.isReplaceable()) { if (candidate == null) {
candidate = dir; candidate = dir;
candidateBlockState = world.getBlockState(pos.offset(dir));
} }
} }

View File

@ -0,0 +1,80 @@
package quimufu.colourful_portals.util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import quimufu.colourful_portals.ColourfulPortalsMod;
import java.util.LinkedList;
import java.util.List;
public class RaycastHelper {
public static List<BlockPos> passedBlocks(Vec3d from, Vec3d to) {
LinkedList<BlockPos> psitions = new LinkedList<>();
Vec3d difference = to.subtract(from);
if(to.equals(from)){
return List.of();
}
double[] diff = new double[]{difference.getX(), difference.getY(), difference.getZ()};
double[] start = new double[]{from.getX(), from.getY(), from.getZ()};
double[] pos = new double[]{from.getX(), from.getY(), from.getZ()};
BlockPos currentBlockPos = BlockPos.ofFloored(pos[0], pos[1], pos[2]);
double currDelta = 0;
while (currDelta < 1) {
psitions.add(currentBlockPos);
double minMissing = 1;
for (int i = 0; i < 3; i++) {
if (diff[i] == 0) {
continue;
}
double curr;
if ((curr = ((round(pos[i], Math.signum(diff[i])) - pos[i]) / diff[i])) < minMissing) {
minMissing = curr;
}
}
currDelta += minMissing;
for (int i = 0; i < 3; i++) {
pos[i] = start[i] + currDelta * diff[i];
}
currentBlockPos = BlockPos.ofFloored(pos[0], pos[1], pos[2]);
}
BlockPos last = BlockPos.ofFloored(to);
if(!psitions.getLast().equals(last)){
psitions.add(last);
}
return psitions;
}
private static double round(double val, double signum) {
if (signum > 0) {
return Math.floor(val + signum);
}
return Math.ceil(val + signum);
}
public static boolean passedOnAxis(Vec3d from, Vec3d to, BlockPos blockPos, Direction.Axis axis) {
double startAA = from.getComponentAlongAxis(axis);
double centerAA = blockPos.toCenterPos().getComponentAlongAxis(axis);
Vec3d diff = to.subtract(from);
double differenceAA = diff.getComponentAlongAxis(axis);
double hitAfter = (centerAA - startAA) / differenceAA;
if (differenceAA == 0 || hitAfter > 1 || hitAfter < 0) {
return false;
}
//ColourfulPortalsMod.LOGGER.info("{}, {}: {} -> {}", hitAfter,axis, from, to);
return BlockPos.ofFloored(from.add(diff.multiply(hitAfter)))
.equals(blockPos);
}
}

View File

@ -3,18 +3,19 @@
"package": "quimufu.colourful_portals.mixin", "package": "quimufu.colourful_portals.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"BlockChangeMixin", "BlockChangeAndEntityMovementMixin",
"EntityMixin" "ServerPlayerEntityAccessor",
"ServerPlayNetworkHandlerAccessor"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
}, },
"plugin": "quimufu.colourful_portals.MixinConfig", "plugin": "quimufu.colourful_portals.MixinConfig",
"client": [ "client": [
"AnimationMixin", "client.AnimationMixin",
"AnimationResourceMetadataMixin", "client.AnimationResourceMetadataMixin",
"AnimationResourceMetadataReaderMixin", "client.AnimationResourceMetadataReaderMixin",
"SodiumFluidRendererMixin", "client.SodiumFluidRendererMixin",
"SpriteContentsMixin" "client.SpriteContentsMixin"
] ]
} }