diff --git a/.gitignore b/.gitignore index ccb0c5626..75790c726 100755 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ out/ .gradle/ output/ bin/ -libs/ .classpath .project diff --git a/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java b/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java index 92e8ec405..20c110c13 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java +++ b/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java @@ -51,7 +51,7 @@ public void commonInit() { if (getModList().contains("farmersdelight")) pfmModCompatibilities.add(PFMFarmersDelight.getInstance()); if (getModList().contains("imm_ptl_core")) - pfmModCompatibilities.add(new PFMImmersivePortals()); + pfmModCompatibilities.add(PFMImmersivePortals.getInstance()); } @ExpectPlatform diff --git a/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java b/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java index 8f12f4a81..067cb4e54 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java +++ b/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java @@ -351,6 +351,10 @@ public static Identifier getLogId(Block block, String postFix) { if (idExists(id, ResourceType.CLIENT_RESOURCES, IdLocation.TEXTURES)) { return id; } + id = new Identifier(namespace, "block/alpha_oak_log"); + if (idExists(id, ResourceType.CLIENT_RESOURCES, IdLocation.TEXTURES)) { + return id; + } } return new Identifier(namespace, "block/" + path); } diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java b/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java index ca9c37caf..5267b7a1e 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java +++ b/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java @@ -1,44 +1,11 @@ package com.unlikepaladin.pfm.compat.imm_ptl; -import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; import com.unlikepaladin.pfm.compat.PFMModCompatibility; -import com.unlikepaladin.pfm.compat.imm_ptl.client.PFMImmersivePortalsClient; -import com.unlikepaladin.pfm.compat.imm_ptl.entity.PFMMirrorEntity; -import com.unlikepaladin.pfm.registry.EntityRegistry; -import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; -import net.minecraft.block.AbstractBlock; -import net.minecraft.block.MapColor; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; +import dev.architectury.injectables.annotations.ExpectPlatform; -import java.util.Optional; - -public class PFMImmersivePortals implements PFMModCompatibility { - private PFMClientModCompatibility clientModCompatibility; - public PFMImmersivePortals(){ - } - public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); - - @Override - public void registerEntityTypes() { - EntityRegistry.registerEntityType("mirror_entity", MIRROR); - } - - @Override - public void createBlocks() { - PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.WHITE).nonOpaque()); - PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.GRAY).nonOpaque()); - } - - @Override - public String getModId() { - return "immersive_portals"; - } - - @Override - public Optional getClientModCompatiblity() { - if (clientModCompatibility == null) - clientModCompatibility = new PFMImmersivePortalsClient(this); - return Optional.of(clientModCompatibility); +public class PFMImmersivePortals { + @ExpectPlatform + public static PFMModCompatibility getInstance() { + throw new AssertionError(); } } diff --git a/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java b/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java index d765b7c7e..acf594251 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java +++ b/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java @@ -63,7 +63,7 @@ public Optional getVariantFromBlock(Block baseBlock, Identifier blo } String namespace = blockId.getNamespace(); if (name != null && !namespace.equals("securitycraft") && - !namespace.equals("absentbydesign") && !(namespace.equals("terrestria") && path.contains("sakura")) && !(namespace.equals("betternether") && path.contains("nether_mushroom")) && !namespace.equals("chipped")) { + !namespace.equals("absentbydesign") && !(namespace.equals("terrestria") && path.contains("sakura")) && !(namespace.equals("betternether") && path.contains("nether_mushroom")) && !namespace.equals("chipped") && !(namespace.equals("regions_unexplored") && path.contains("alpha"))) { BlockState state = baseBlock.getDefaultState(); //can't check if the block is a full one, so I do this. Adding some checks here diff --git a/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java b/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java index a87f9cf20..6e4e1c76f 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java +++ b/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java @@ -369,7 +369,7 @@ public static void registerBlocks() throws InvocationTargetException, Instantiat this.addBlock(registerLateBlock(color.getName() + "_shower_towel", () -> new ShowerTowelBlock(color, AbstractBlock.Settings.create().burnable().strength(2.0f).resistance(2.0f).nonOpaque().sounds(BlockSoundGroup.WOOL).mapColor(color.getMapColor())), true, PaladinFurnitureMod.FURNITURE_GROUP)); } }}); - if (!BlockItemRegistry.isModLoaded("imm_ptl_core")) { + if (!BlockItemRegistry.isModLoaded("imm_ptl_core") && PaladinFurnitureMod.getLoader() == PaladinFurnitureMod.Loader.FABRIC_LIKE) { PaladinFurnitureModBlocksItems.WHITE_MIRROR = new MirrorBlock(AbstractBlock.Settings.create().mapColor(MapColor.WHITE).nonOpaque()); PaladinFurnitureModBlocksItems.GRAY_MIRROR = new MirrorBlock(AbstractBlock.Settings.create().mapColor(MapColor.GRAY).nonOpaque()); } diff --git a/fabric/build.gradle b/fabric/build.gradle index fec10dbda..c8e9453cd 100755 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -138,11 +138,11 @@ else { if (rootProject.immersive_portals_compatibility_fabric == "true"){ dependencies { - modRuntimeOnly ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}"){ + modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}"){ exclude(group: "net.fabricmc.fabric-api") transitive(false) } - modRuntimeOnly("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version_fabric}"){ + modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version_fabric}"){ exclude(group: "net.fabricmc.fabric-api") transitive(false) } @@ -183,6 +183,15 @@ dependencies { modCompileOnly "curse.maven:balm-fabric-500525:${rootProject.balm_version_fabric}" modCompileOnly "curse.maven:cooking-for-blockheads-fabric-634546:${rootProject.cookingforblockheads_version_fabric}" + + modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}"){ + exclude(group: "net.fabricmc.fabric-api") + transitive(false) + } + modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version_fabric}"){ + exclude(group: "net.fabricmc.fabric-api") + transitive(false) + } } dependencies { diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java new file mode 100644 index 000000000..34de05d38 --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java @@ -0,0 +1,45 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.fabric; + +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.client.PFMImmersivePortalsClient; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.registry.EntityRegistry; +import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.MapColor; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; + +import java.util.Optional; + +public class PFMImmersivePortalsImpl implements PFMModCompatibility { + private PFMClientModCompatibility clientModCompatibility; + public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); + + @Override + public void registerEntityTypes() { + EntityRegistry.registerEntityType("mirror_entity", MIRROR); + } + + @Override + public void createBlocks() { + PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.WHITE).nonOpaque()); + PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.GRAY).nonOpaque()); + } + + @Override + public String getModId() { + return "immersive_portals"; + } + + @Override + public Optional getClientModCompatiblity() { + if (clientModCompatibility == null) + clientModCompatibility = new PFMImmersivePortalsClient(this); + return Optional.of(clientModCompatibility); + } + public static PFMModCompatibility getInstance() { + return new PFMImmersivePortalsImpl(); + } +} diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java similarity index 91% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java index 277ab608a..c4ba3bd2f 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java @@ -1,8 +1,8 @@ -package com.unlikepaladin.pfm.compat.imm_ptl; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric; import com.unlikepaladin.pfm.PaladinFurnitureMod; import com.unlikepaladin.pfm.blocks.MirrorBlock; -import com.unlikepaladin.pfm.compat.imm_ptl.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity.PFMMirrorEntity; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; @@ -41,7 +41,7 @@ public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity pl List mirrorBlockEntities; if (!world.isClient && !(mirrorBlockEntities = world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))).isEmpty()) { mirrorBlockEntities.forEach(pfmMirrorEntity -> { - pfmMirrorEntity.remove(Entity.RemovalReason.KILLED); + ((PFMMirrorEntity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); }); world.updateNeighbors(pos, state.getBlock()); } @@ -58,7 +58,7 @@ public BlockState getStateForNeighborUpdate(BlockState state, Direction directio if (!(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty())) { mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))); mirrorBlockEntities.forEach(pfmMirrorEntity -> { - pfmMirrorEntity.remove(Entity.RemovalReason.KILLED); + ((Entity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); }); } PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java similarity index 60% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java index 3062b3540..04c3cd088 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java @@ -1,14 +1,13 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.client; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.client; import com.unlikepaladin.pfm.client.EntityRenderRegistry; import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; import com.unlikepaladin.pfm.compat.PFMModCompatibility; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMImmersivePortals; -import qouteall.imm_ptl.core.render.PortalEntityRenderer; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMImmersivePortalsImpl; public class PFMImmersivePortalsClient implements PFMClientModCompatibility { - private final PFMImmersivePortals parent; - public PFMImmersivePortalsClient(PFMImmersivePortals parent) { + private final PFMImmersivePortalsImpl parent; + public PFMImmersivePortalsClient(PFMImmersivePortalsImpl parent) { this.parent = parent; } @Override @@ -18,6 +17,6 @@ public PFMModCompatibility getCompatiblity() { @Override public void registerEntityRenderer() { - EntityRenderRegistry.registerEntityRender(PFMImmersivePortals.MIRROR, PFMMirrorEntityRenderer::new); + EntityRenderRegistry.registerEntityRender(PFMImmersivePortalsImpl.MIRROR, PFMMirrorEntityRenderer::new); } } diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMMirrorEntityRenderer.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java similarity index 93% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMMirrorEntityRenderer.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java index 18e988234..a92ae3024 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMMirrorEntityRenderer.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java @@ -1,4 +1,4 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.client; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.client; import com.unlikepaladin.pfm.PaladinFurnitureMod; import net.minecraft.client.render.VertexConsumerProvider; diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java similarity index 91% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java index 9efdbc9e2..6913e7f33 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java @@ -1,10 +1,11 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.entity; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMImmersivePortals; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMMirrorBlockIP; -import com.unlikepaladin.pfm.compat.imm_ptl.shape.BlockPortalShape; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMImmersivePortalsImpl; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMMirrorBlockIP; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.shape.BlockPortalShape; import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; @@ -15,15 +16,15 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; import qouteall.imm_ptl.core.portal.Mirror; -import qouteall.q_misc_util.my_util.IntBox; import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; -import org.jetbrains.annotations.Nullable; import java.util.stream.Stream; public class PFMMirrorEntity extends Mirror { - public static EntityType entityType = PFMImmersivePortals.MIRROR; + public static EntityType entityType = PFMImmersivePortalsImpl.MIRROR; @Nullable public IntBox wallArea; @Nullable @@ -123,7 +124,7 @@ else if (blockPortalShape != null) { wallValid = false; } if (!wallValid) { - remove(RemovalReason.DISCARDED); + ((Entity)this).remove(RemovalReason.DISCARDED); } } @@ -135,13 +136,9 @@ public static boolean isMirrorBlock(World world, BlockPos blockPos, Direction fa return false; } - public static PFMMirrorEntity createMirror( - ServerWorld world, - BlockPos glassPos, - Direction facing - ) { + public static void createMirror(ServerWorld world, BlockPos glassPos, Direction facing) { if (!isMirrorBlock(world, glassPos, facing.getOpposite())) { - return null; + return; } BlockPortalShape shape = BlockPortalShape.findArea( @@ -151,7 +148,7 @@ public static PFMMirrorEntity createMirror( ); if (shape == null) { - return null; + return; } PFMMirrorEntity pfmMirrorEntity = PFMMirrorEntity.entityType.create(world); @@ -159,7 +156,7 @@ public static PFMMirrorEntity createMirror( Box wallBox = getWallBox(world, shape.area.stream()); if (wallBox == null) { - return null; + return; } pfmMirrorEntity.facing = facing; Vec3d pos = Helper.getBoxSurfaceInversed(wallBox, facing.getOpposite()).getCenter(); @@ -172,7 +169,7 @@ public static PFMMirrorEntity createMirror( facing.getAxis() ) ); - pfmMirrorEntity.setPosition(pos); + ((Entity)pfmMirrorEntity).setPos(pos.x, pos.y, pos.z); pfmMirrorEntity.setDestination(pos); pfmMirrorEntity.dimensionTo = world.getRegistryKey(); @@ -181,7 +178,6 @@ public static PFMMirrorEntity createMirror( pfmMirrorEntity.blockPortalShape = shape; world.spawnEntity(pfmMirrorEntity); - return pfmMirrorEntity; } @Nullable diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java similarity index 97% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java index 1ca7ce875..7659ea134 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java @@ -1,4 +1,4 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.shape; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.shape; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtInt; @@ -9,12 +9,11 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; import org.apache.commons.lang3.Validate; +import org.jetbrains.annotations.Nullable; import qouteall.imm_ptl.core.portal.GeometryPortalShape; import qouteall.imm_ptl.core.portal.Portal; import qouteall.q_misc_util.Helper; import qouteall.q_misc_util.my_util.IntBox; - -import org.jetbrains.annotations.Nullable; import qouteall.q_misc_util.my_util.Mesh2D; import java.util.ArrayDeque; @@ -399,18 +398,18 @@ public void initPortalAxisShape(Portal portal, Vec3d center, Direction facing) { } else { GeometryPortalShape shape = new GeometryPortalShape(new Mesh2D()); - + IntBox rectanglePart = Helper.expandRectangle( - anchor, - blockPos -> area.contains(blockPos), - axis + anchor, + blockPos -> area.contains(blockPos), + axis ); - + Stream.concat( - area.stream() - .filter(blockPos -> !rectanglePart.contains(blockPos)) - .map(blockPos -> new IntBox(blockPos, blockPos)), - Stream.of(rectanglePart) + area.stream() + .filter(blockPos -> !rectanglePart.contains(blockPos)) + .map(blockPos -> new IntBox(blockPos, blockPos)), + Stream.of(rectanglePart) ).forEach(part -> { Vec3d p1 = Vec3d.of(part.l).add(offset); Vec3d p2 = Vec3d.of(part.h).add(1, 1, 1).add(offset); @@ -419,13 +418,13 @@ public void initPortalAxisShape(Portal portal, Vec3d center, Direction facing) { double p2LocalX = p2.subtract(center).dotProduct(portal.axisW); double p2LocalY = p2.subtract(center).dotProduct(portal.axisH); shape.addTriangleForRectangle( - p1LocalX, p1LocalY, - p2LocalX, p2LocalY + p1LocalX, p1LocalY, + p2LocalX, p2LocalY ); }); - + portal.specialShape = shape; - + Vec3d p1 = Vec3d.of(rectanglePart.l).add(offset); Vec3d p2 = Vec3d.of(rectanglePart.h).add(1, 1, 1).add(offset); double p1LocalX = p1.subtract(center).dotProduct(portal.axisW); diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java index 277d1648a..eccf49071 100644 --- a/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Mixin(value = ReloadableResourceManagerImpl.class) public class PFMReloadableResourceManagerImplMixin { @@ -23,7 +24,7 @@ public class PFMReloadableResourceManagerImplMixin { private List createReload(List packs) { PFMRuntimeResources.RESOURCE_PACK_LIST = packs; List resourcePacks = new ArrayList<>(packs); - PackResourceMetadata packResourceMetadata = new PackResourceMetadata(Text.literal("pfm-runtime-resources"), SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES)); + PackResourceMetadata packResourceMetadata = new PackResourceMetadata(Text.literal("pfm-runtime-resources"), SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES), Optional.empty()); resourcePacks.add(new PathPackRPWrapper(Suppliers.memoize(() -> { PFMRuntimeResources.prepareAndRunResourceGen(false); return PFMRuntimeResources.ASSETS_PACK;}), packResourceMetadata)); return resourcePacks; diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMSaveLoaderMixin.java b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMSaveLoaderMixin.java index ebbd80068..84405e9ca 100644 --- a/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMSaveLoaderMixin.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMSaveLoaderMixin.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Mixin(SaveLoading.DataPacks.class) public class PFMSaveLoaderMixin { @@ -25,11 +26,9 @@ public class PFMSaveLoaderMixin { private List createReload(List packs) { PFMRuntimeResources.RESOURCE_PACK_LIST = packs; List resourcePacks = new ArrayList<>(packs); - PackResourceMetadata packResourceMetadata = new PackResourceMetadata(Text.literal("pfm-runtime-resources"), SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES)); + PackResourceMetadata packResourceMetadata = new PackResourceMetadata(Text.literal("pfm-runtime-resources"), SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES), Optional.empty()); resourcePacks.add(new PathPackRPWrapper(Suppliers.memoize(() -> { - PFMRuntimeResources.prepareAndRunResourceGen(false); - return PFMRuntimeResources.ASSETS_PACK; - }), packResourceMetadata)); + PFMRuntimeResources.prepareAndRunResourceGen(false); return PFMRuntimeResources.ASSETS_PACK;}), packResourceMetadata)); return resourcePacks; } } \ No newline at end of file diff --git a/forge/build.gradle b/forge/build.gradle index 8a1ddef3f..31c09337f 100755 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -75,6 +75,7 @@ dependencies { modCompileOnly "curse.maven:balm-forge-531761:${rootProject.balm_version_forge}" modCompileOnly "curse.maven:cooking-for-blockheads-forge-231484:${rootProject.cookingforblockheads_version_forge}" modCompileOnly "curse.maven:farmers-delight-forge-398521:${rootProject.farmers_delight_version_forge}" + modCompileOnly(files("../libs/immersive-portals-2.5.4-mc1.19.3-forge.jar")) } if(rootProject.jei_compatibility == "true") { @@ -84,9 +85,7 @@ if(rootProject.jei_compatibility == "true") { } if (rootProject.immersive_portals_compatibility_forge == "true"){ dependencies { - modRuntimeOnly("curse.maven:imm_ptl-355440:${rootProject.immersive_portals_version_forge}"){ - transitive(false) - } + modImplementation("curse.maven:imm_ptl-355440:${rootProject.immersive_portals_version_forge}") } } diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java new file mode 100644 index 000000000..db8713fa0 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java @@ -0,0 +1,45 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge; + +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.client.PFMImmersivePortalsClient; +//import com.unlikepaladin.pfm.compat.imm_ptl.forge.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.registry.EntityRegistry; +import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.MapColor; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; + +import java.util.Optional; + +public class PFMImmersivePortalsImpl implements PFMModCompatibility { + private PFMClientModCompatibility clientModCompatibility; + //public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); + + @Override + public void registerEntityTypes() { + // EntityRegistry.registerEntityType("mirror_entity", MIRROR); + } + + @Override + public void createBlocks() { + // PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.WHITE).nonOpaque()); + // PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.create().mapColor(MapColor.GRAY).nonOpaque()); + } + + @Override + public String getModId() { + return "immersive_portals"; + } + + @Override + public Optional getClientModCompatiblity() { + if (clientModCompatibility == null) + clientModCompatibility = new PFMImmersivePortalsClient(this); + return Optional.of(clientModCompatibility); + } + public static PFMModCompatibility getInstance() { + return new PFMImmersivePortalsImpl(); + } +} diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java new file mode 100644 index 000000000..33ed50ff9 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java @@ -0,0 +1,70 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge; +/* +import com.unlikepaladin.pfm.PaladinFurnitureMod; +import com.unlikepaladin.pfm.blocks.MirrorBlock; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.entity.PFMMirrorEntity; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class PFMMirrorBlockIP extends MirrorBlock { + protected PFMMirrorBlockIP(Settings settings) { + super(settings); + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { + super.onPlaced(world, pos, state, placer, itemStack); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { + if (!world.isClient && world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty()) { + PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + } + } + } + + @Override + public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + super.onBreak(world, pos, state, player); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { + List mirrorBlockEntities; + if (!world.isClient && !(mirrorBlockEntities = world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))).isEmpty()) { + mirrorBlockEntities.forEach(pfmMirrorEntity -> { + ((PFMMirrorEntity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); + }); + world.updateNeighbors(pos, state.getBlock()); + } + } + } + + @Override + public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn() && !world.isClient()) { + List mirrorBlockEntities = new ArrayList<>(); + if (canConnect(neighborState, state)) { + mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(neighborPos))); + } + if (!(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty())) { + mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))); + mirrorBlockEntities.forEach(pfmMirrorEntity -> { + ((Entity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); + }); + } + PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + world.updateNeighbors(pos, state.getBlock()); + } + return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos); + } +} +*/ \ No newline at end of file diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java new file mode 100644 index 000000000..e81bad950 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java @@ -0,0 +1,22 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.client; + +import com.unlikepaladin.pfm.client.EntityRenderRegistry; +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMImmersivePortalsImpl; + +public class PFMImmersivePortalsClient implements PFMClientModCompatibility { + private final PFMImmersivePortalsImpl parent; + public PFMImmersivePortalsClient(PFMImmersivePortalsImpl parent) { + this.parent = parent; + } + @Override + public PFMModCompatibility getCompatiblity() { + return parent; + } + + @Override + public void registerEntityRenderer() { + //EntityRenderRegistry.registerEntityRender(PFMImmersivePortalsImpl.MIRROR, PFMMirrorEntityRenderer::new); + } +} diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java new file mode 100644 index 000000000..167e19b8e --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java @@ -0,0 +1,21 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.client; + +import com.unlikepaladin.pfm.PaladinFurnitureMod; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.util.math.MatrixStack; +import qouteall.imm_ptl.core.portal.Portal; +import qouteall.imm_ptl.core.render.PortalEntityRenderer; +/* +public class PFMMirrorEntityRenderer extends PortalEntityRenderer { + public PFMMirrorEntityRenderer(EntityRendererFactory.Context context) { + super(context); + } + + @Override + public void render(Portal portal, float yaw, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsRender()) + super.render(portal, yaw, tickDelta, matrixStack, vertexConsumerProvider, light); + } +} +*/ \ No newline at end of file diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java new file mode 100644 index 000000000..176656072 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java @@ -0,0 +1,196 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.entity; + +/* +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMImmersivePortalsImpl; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMMirrorBlockIP; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.shape.BlockPortalShape; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.World; +import qouteall.imm_ptl.core.portal.Mirror; +import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; + +import org.jetbrains.annotations.Nullable; +import java.util.stream.Stream; + +public class PFMMirrorEntity extends Mirror { + public static EntityType entityType = PFMImmersivePortalsImpl.MIRROR; + @Nullable + public IntBox wallArea; + @Nullable + public BlockPortalShape blockPortalShape; + public boolean unbreakable = false; + private Direction facing; + + public PFMMirrorEntity(EntityType entityType, World world) { + super(entityType, world); + PFMMirrorEntity.entityType = entityType; + } + + @Override + protected void readCustomDataFromNbt(NbtCompound tag) { + super.readCustomDataFromNbt(tag); + if (tag.contains("boxXL")) { + wallArea = new IntBox( + new BlockPos( + tag.getInt("boxXL"), + tag.getInt("boxYL"), + tag.getInt("boxZL") + ), + new BlockPos( + tag.getInt("boxXH"), + tag.getInt("boxYH"), + tag.getInt("boxZH") + ) + ); + } + else { + wallArea = null; + } + if (tag.contains("blockPortalShape")) { + blockPortalShape = BlockPortalShape.fromTag(tag.getCompound("blockPortalShape")); + } + else { + blockPortalShape = null; + } + if (tag.contains("unbreakable")) { + unbreakable = tag.getBoolean("unbreakable"); + } + } + + @Override + protected void writeCustomDataToNbt(NbtCompound tag) { + super.writeCustomDataToNbt(tag); + if (wallArea != null) { + tag.putInt("boxXL", wallArea.l.getX()); + tag.putInt("boxYL", wallArea.l.getY()); + tag.putInt("boxZL", wallArea.l.getZ()); + tag.putInt("boxXH", wallArea.h.getX()); + tag.putInt("boxYH", wallArea.h.getY()); + tag.putInt("boxZH", wallArea.h.getZ()); + } + + if (blockPortalShape != null) { + tag.put("blockPortalShape", blockPortalShape.toTag()); + } + tag.putBoolean("unbreakable", unbreakable); + } + + @Override + public void tick() { + super.tick(); + if (!getEntityWorld().isClient) { + if (!unbreakable) { + if (getEntityWorld().getTime() % 10 == getId() % 10) { + checkWallIntegrity(); + } + } + } + } + + @Override + public boolean isPortalValid() { + return super.isPortalValid() && (wallArea != null || blockPortalShape != null); + } + + private void checkWallIntegrity() { + boolean wallValid; + if (this.facing == null && this.getEntityWorld().getBlockState(getBlockPos()).contains(Properties.HORIZONTAL_FACING)) + this.facing = this.getEntityWorld().getBlockState(getBlockPos()).get(Properties.HORIZONTAL_FACING).getOpposite(); + else if (this.facing == null){ + this.facing = Direction.NORTH; + } + if (wallArea != null) { + wallValid = wallArea.fastStream().allMatch( + blockPos -> isMirrorBlock(getEntityWorld(), blockPos, this.facing.getOpposite()) + ); + } + else if (blockPortalShape != null) { + wallValid = blockPortalShape.area.stream().allMatch( + blockPos -> isMirrorBlock(getEntityWorld(), blockPos, this.facing.getOpposite()) + ); + } + else { + wallValid = false; + } + if (!wallValid) { + ((Entity)this).remove(RemovalReason.DISCARDED); + } + } + + public static boolean isMirrorBlock(World world, BlockPos blockPos, Direction facing) { + BlockState blockState = world.getBlockState(blockPos); + if (blockState.contains(Properties.HORIZONTAL_FACING)) { + return blockState.getBlock() instanceof PFMMirrorBlockIP && blockState.get(Properties.HORIZONTAL_FACING).equals(facing); + } + return false; + } + + public static void createMirror(ServerWorld world, BlockPos glassPos, Direction facing) { + if (!isMirrorBlock(world, glassPos, facing.getOpposite())) { + return; + } + + BlockPortalShape shape = BlockPortalShape.findArea( + glassPos, facing.getAxis(), + blockPos -> isMirrorBlock(world, blockPos, facing.getOpposite()), + blockPos -> !(isMirrorBlock(world, blockPos, facing.getOpposite())) + ); + + if (shape == null) { + return; + } + + PFMMirrorEntity pfmMirrorEntity = PFMMirrorEntity.entityType.create(world); + double distanceToCenter = -0.452; + + Box wallBox = getWallBox(world, shape.area.stream()); + if (wallBox == null) { + return; + } + pfmMirrorEntity.facing = facing; + Vec3d pos = Helper.getBoxSurfaceInversed(wallBox, facing.getOpposite()).getCenter(); + pos = Helper.putCoordinate( + pos, facing.getAxis(), + Helper.getCoordinate( + shape.innerAreaBox.getCenterVec().add( + Vec3d.of(facing.getVector()).multiply(distanceToCenter) + ), + facing.getAxis() + ) + ); + ((Entity)pfmMirrorEntity).setPos(pos.x, pos.y, pos.z); + pfmMirrorEntity.setDestination(pos); + pfmMirrorEntity.dimensionTo = world.getRegistryKey(); + + shape.initPortalAxisShape(pfmMirrorEntity, pos, facing); + + pfmMirrorEntity.blockPortalShape = shape; + world.spawnEntity(pfmMirrorEntity); + + } + + @Nullable + public static Box getWallBox(World world, Stream blockPosStream) { + return blockPosStream.map(blockPos -> { + VoxelShape collisionShape = world.getBlockState(blockPos).getCollisionShape(world, blockPos); + + if (collisionShape.isEmpty()) { + return null; + } + + return collisionShape.getBoundingBox().offset(Vec3d.of(blockPos)); + }).filter(b -> b != null).reduce(Box::union).orElse(null); + } +} + */ \ No newline at end of file diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java new file mode 100644 index 000000000..593a46db9 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java @@ -0,0 +1,537 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.shape; +/* +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtInt; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; +import org.apache.commons.lang3.Validate; +import qouteall.imm_ptl.core.portal.GeometryPortalShape; +import qouteall.imm_ptl.core.portal.Portal; +import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; + +import org.jetbrains.annotations.Nullable; +import qouteall.q_misc_util.my_util.Mesh2D; + +import java.util.ArrayDeque; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +/** + * Backported to 1.17 from ... + * */ +/* +public class BlockPortalShape { + public BlockPos anchor; + public Set area; + public IntBox innerAreaBox; + public IntBox totalAreaBox; + public Direction.Axis axis; + public Set frameAreaWithoutCorner; + public Set frameAreaWithCorner; + + public BlockPos firstFramePos; + + public BlockPortalShape( + Set area, Direction.Axis axis + ) { + this.area = area; + this.axis = axis; + + calcAnchor(); + + calcFrameArea(); + + calcAreaBox(); + } + + public BlockPortalShape( + NbtCompound tag + ) { + this( + readArea(tag.getList("poses", 3)), + Direction.Axis.values()[tag.getInt("axis")] + ); + } + + private static Set readArea(NbtList list) { + int size = list.size(); + + Validate.isTrue(size % 3 == 0); + Set result = new HashSet<>(); + + for (int i = 0; i < size / 3; i++) { + result.add(new BlockPos( + list.getInt(i * 3 + 0), + list.getInt(i * 3 + 1), + list.getInt(i * 3 + 2) + )); + } + + return result; + } + + public static BlockPortalShape fromTag(NbtCompound tag) { + return new BlockPortalShape(tag); + } + + public NbtCompound toTag() { + NbtCompound data = new NbtCompound(); + NbtList list = new NbtList(); + + area.forEach(blockPos -> { + list.add(list.size(), NbtInt.of(blockPos.getX())); + list.add(list.size(), NbtInt.of(blockPos.getY())); + list.add(list.size(), NbtInt.of(blockPos.getZ())); + }); + + data.put("poses", list); + data.putInt("axis", axis.ordinal()); + + return data; + } + + public void calcAnchor() { + anchor = area.stream() + .min( + Comparator.comparingInt( + Vec3i::getX + ).thenComparingInt( + Vec3i::getY + ).thenComparingInt( + Vec3i::getZ + ) + ).get(); + + Validate.notNull(anchor); + } + + public void calcAreaBox() { + innerAreaBox = Helper.reduce( + new IntBox(anchor, anchor), + area.stream(), + IntBox::getExpanded + ); + totalAreaBox = Helper.reduce( + new IntBox(anchor, anchor), + frameAreaWithoutCorner.stream(), + IntBox::getExpanded + ); + } + + public void calcFrameArea() { + Direction[] directions = Helper.getAnotherFourDirections(axis); + frameAreaWithoutCorner = area.stream().flatMap( + blockPos -> Stream.of( + blockPos.add(directions[0].getVector()), + blockPos.add(directions[1].getVector()), + blockPos.add(directions[2].getVector()), + blockPos.add(directions[3].getVector()) + ) + ).filter( + blockPos -> !area.contains(blockPos) + ).collect(Collectors.toSet()); + + BlockPos[] cornerOffsets = { + new BlockPos(directions[0].getVector()).add(directions[1].getVector()), + new BlockPos(directions[1].getVector()).add(directions[2].getVector()), + new BlockPos(directions[2].getVector()).add(directions[3].getVector()), + new BlockPos(directions[3].getVector()).add(directions[0].getVector()) + }; + + frameAreaWithCorner = area.stream().flatMap( + blockPos -> Stream.of( + blockPos.add(cornerOffsets[0]), + blockPos.add(cornerOffsets[1]), + blockPos.add(cornerOffsets[2]), + blockPos.add(cornerOffsets[3]) + ) + ).filter( + blockPos -> !area.contains(blockPos) + ).collect(Collectors.toSet()); + frameAreaWithCorner.addAll(frameAreaWithoutCorner); + + firstFramePos = frameAreaWithoutCorner.iterator().next(); + } + + //null for not found + @Nullable + public static BlockPortalShape findArea( + BlockPos startingPos, + Direction.Axis axis, + Predicate isAir, + Predicate isObsidian + ) { + if (!isAir.test(startingPos)) { + return null; + } + + return findShapeWithoutRegardingStartingPos(startingPos, axis, isAir, isObsidian); + } + + @Nullable + public static BlockPortalShape findShapeWithoutRegardingStartingPos( + BlockPos startingPos, Direction.Axis axis, Predicate isAir, Predicate isObsidian + ) { + startingPos = startingPos.toImmutable(); + + Set area = new HashSet<>(); + area.add(startingPos); + + Direction[] directions = Helper.getAnotherFourDirections(axis); + boolean isNormalFrame = findAreaBreadthFirst( + startingPos, + isAir, + isObsidian, + directions, + area, + startingPos + ); + + if (!isNormalFrame) { + return null; + } + + return new BlockPortalShape(area, axis); + } + + private static boolean findAreaBreadthFirst( + BlockPos startingPos, + Predicate isAir, + Predicate isObsidian, + Direction[] directions, + Set foundArea, + BlockPos initialPos + ) { + + ArrayDeque newlyAdded = new ArrayDeque<>(); + newlyAdded.addLast(startingPos); + + while (!newlyAdded.isEmpty()) { + if (foundArea.size() > 400) { + return false; + } + + BlockPos last = newlyAdded.pollFirst(); + for (Direction direction : directions) { + BlockPos curr = last.offset(direction).toImmutable(); + if (!foundArea.contains(curr)) { + if (isAir.test(curr)) { + newlyAdded.addLast(curr); + foundArea.add(curr); + } + else if (isObsidian.test(curr)) { + //nothing happens + } + else { + return false; + } + } + } + + BlockPos delta = initialPos.subtract(startingPos); + if (Math.abs(delta.getX()) > 20 || Math.abs(delta.getY()) > 20 || Math.abs(delta.getZ()) > 20) { + return false; + } + } + + return true; + } + + @Deprecated + private static boolean findAreaRecursively( + BlockPos currPos, + Predicate isAir, + Predicate isObsidian, + Direction[] directions, + Set foundArea, + BlockPos initialPos + ) { + if (foundArea.size() > 400) { + return false; + } + BlockPos delta = initialPos.subtract(currPos); + if (Math.abs(delta.getX()) > 20 || Math.abs(delta.getY()) > 20 || Math.abs(delta.getZ()) > 20) { + return false; + } + for (Direction direction : directions) { + BlockPos newPos = currPos.add(direction.getVector()); + if (!foundArea.contains(newPos)) { + if (isAir.test(newPos)) { + foundArea.add(newPos.toImmutable()); + boolean shouldContinue = findAreaRecursively( + newPos, + isAir, + isObsidian, + directions, + foundArea, + initialPos + ); + if (!shouldContinue) { + return false; + } + } + else { + if (!isObsidian.test(newPos)) { + //abort + return false; + } + } + } + } + return true; + } + + //return null for not match + public BlockPortalShape matchShape( + Predicate isAir, + Predicate isObsidian, + BlockPos newAnchor, + BlockPos.Mutable temp + ) { + if (!isAir.test(newAnchor)) { + return null; + } + + boolean testFrame = testFrameWithoutCorner(isObsidian, newAnchor, temp); + + if (!testFrame) { + return null; + } + + boolean testAir = area.stream().map( + blockPos -> temp.set( + blockPos.getX() - anchor.getX() + newAnchor.getX(), + blockPos.getY() - anchor.getY() + newAnchor.getY(), + blockPos.getZ() - anchor.getZ() + newAnchor.getZ() + ) + //blockPos.subtract(anchor).add(newAnchor) + ).allMatch( + isAir + ); + + if (!testAir) { + return null; + } + + return getShapeWithMovedAnchor(newAnchor); + } + + private boolean testFrameWithoutCorner( + Predicate isObsidian, + BlockPos newAnchor, + BlockPos.Mutable temp + ) { + Function mapper = blockPos -> temp.set( + blockPos.getX() - anchor.getX() + newAnchor.getX(), + blockPos.getY() - anchor.getY() + newAnchor.getY(), + blockPos.getZ() - anchor.getZ() + newAnchor.getZ() + ); + + //does this have optimization effect? + if (!isObsidian.test(mapper.apply(firstFramePos))) { + return false; + } + + return frameAreaWithoutCorner.stream().map(mapper).allMatch(isObsidian); + } + + public BlockPortalShape getShapeWithMovedAnchor( + BlockPos newAnchor + ) { + BlockPos offset = newAnchor.subtract(anchor); + return new BlockPortalShape( + area.stream().map( + blockPos -> blockPos.add(offset) + ).collect(Collectors.toSet()), + axis + ); + } + + public boolean isFrameIntact( + Predicate isObsidian + ) { + return frameAreaWithoutCorner.stream().allMatch(isObsidian::test); + } + + public boolean isPortalIntact( + Predicate isPortalBlock, + Predicate isObsidian + ) { + return isFrameIntact(isObsidian) && + area.stream().allMatch(isPortalBlock); + } + + public void initPortalPosAxisShape(Portal portal, Direction.AxisDirection axisDirection) { + Vec3d center = innerAreaBox.getCenterVec(); + portal.setPos(center.x, center.y, center.z); + + initPortalAxisShape(portal, center, Direction.from(axis, axisDirection)); + } + + public void initPortalAxisShape(Portal portal, Vec3d center, Direction facing) { + Validate.isTrue(facing.getAxis() == axis); + + Pair perpendicularDirections = Helper.getPerpendicularDirections(facing); + Direction wDirection = perpendicularDirections.getLeft(); + Direction hDirection = perpendicularDirections.getRight(); + + portal.axisW = Vec3d.of(wDirection.getVector()); + portal.axisH = Vec3d.of(hDirection.getVector()); + portal.width = Helper.getCoordinate(innerAreaBox.getSize(), wDirection.getAxis()); + portal.height = Helper.getCoordinate(innerAreaBox.getSize(), hDirection.getAxis()); + + Vec3d offset = Vec3d.of( + Direction.get(Direction.AxisDirection.POSITIVE, axis) + .getVector() + ).multiply(0.5); + + if (isRectangle()) { + portal.specialShape = null; + } + else { + GeometryPortalShape shape = new GeometryPortalShape(new Mesh2D()); + + IntBox rectanglePart = Helper.expandRectangle( + anchor, + blockPos -> area.contains(blockPos), + axis + ); + + Stream.concat( + area.stream() + .filter(blockPos -> !rectanglePart.contains(blockPos)) + .map(blockPos -> new IntBox(blockPos, blockPos)), + Stream.of(rectanglePart) + ).forEach(part -> { + Vec3d p1 = Vec3d.of(part.l).add(offset); + Vec3d p2 = Vec3d.of(part.h).add(1, 1, 1).add(offset); + double p1LocalX = p1.subtract(center).dotProduct(portal.axisW); + double p1LocalY = p1.subtract(center).dotProduct(portal.axisH); + double p2LocalX = p2.subtract(center).dotProduct(portal.axisW); + double p2LocalY = p2.subtract(center).dotProduct(portal.axisH); + shape.addTriangleForRectangle( + p1LocalX, p1LocalY, + p2LocalX, p2LocalY + ); + }); + + portal.specialShape = shape; + + Vec3d p1 = Vec3d.of(rectanglePart.l).add(offset); + Vec3d p2 = Vec3d.of(rectanglePart.h).add(1, 1, 1).add(offset); + double p1LocalX = p1.subtract(center).dotProduct(portal.axisW); + double p1LocalY = p1.subtract(center).dotProduct(portal.axisH); + double p2LocalX = p2.subtract(center).dotProduct(portal.axisW); + double p2LocalY = p2.subtract(center).dotProduct(portal.axisH); + shape.addTriangleForRectangle( + p1LocalX, p1LocalY, + p2LocalX, p2LocalY + ); + } + } + + public BlockPortalShape matchShapeWithMovedFirstFramePos( + Predicate isAir, + Predicate isObsidian, + BlockPos newFirstObsidianPos, + BlockPos.Mutable temp + ) { + boolean testFrame = frameAreaWithoutCorner.stream().map(blockPos1 -> temp.set( + blockPos1.getX() - firstFramePos.getX() + newFirstObsidianPos.getX(), + blockPos1.getY() - firstFramePos.getY() + newFirstObsidianPos.getY(), + blockPos1.getZ() - firstFramePos.getZ() + newFirstObsidianPos.getZ() + )).allMatch(isObsidian); + + if (!testFrame) { + return null; + } + + boolean testAir = area.stream().map(blockPos -> temp.set( + blockPos.getX() - firstFramePos.getX() + newFirstObsidianPos.getX(), + blockPos.getY() - firstFramePos.getY() + newFirstObsidianPos.getY(), + blockPos.getZ() - firstFramePos.getZ() + newFirstObsidianPos.getZ() + )).allMatch(isAir); + + if (!testAir) { + return null; + } + + BlockPos offset = newFirstObsidianPos.subtract(firstFramePos); + return new BlockPortalShape( + area.stream().map( + blockPos -> blockPos.add(offset) + ).collect(Collectors.toSet()), + axis + ); + } + + public static boolean isSquareShape(BlockPortalShape shape, int length) { + BlockPos areaSize = shape.innerAreaBox.getSize(); + + Pair xs = Helper.getAnotherTwoAxis(shape.axis); + + return Helper.getCoordinate(areaSize, xs.getLeft()) == length && + Helper.getCoordinate(areaSize, xs.getRight()) == length && + shape.area.size() == (length * length); + } + + public static BlockPortalShape getSquareShapeTemplate( + Direction.Axis axis, + int length + ) { + Pair perpendicularDirections = Helper.getPerpendicularDirections( + Direction.from(axis, Direction.AxisDirection.POSITIVE) + ); + + Set area = new HashSet<>(); + + for (int i = 0; i < length; i++) { + for (int j = 0; j < length; j++) { + area.add( + BlockPos.ORIGIN.offset(perpendicularDirections.getLeft(), i) + .offset(perpendicularDirections.getRight(), j) + ); + } + } + + return new BlockPortalShape(area, axis); + } + + public BlockPortalShape getShapeWithMovedTotalAreaBox(IntBox newTotalAreaBox) { + Validate.isTrue(totalAreaBox.getSize().equals(newTotalAreaBox.getSize())); + + return getShapeWithMovedAnchor( + newTotalAreaBox.l.subtract(totalAreaBox.l) + .add(anchor) + ); + } + + public boolean isRectangle() { + BlockPos size = innerAreaBox.getSize(); + return size.getX() * size.getY() * size.getZ() == area.size(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BlockPortalShape that = (BlockPortalShape) o; + return area.equals(that.area) && + axis == that.axis; + } + + @Override + public int hashCode() { + return Objects.hash(area, axis); + } +}*/ \ No newline at end of file diff --git a/libs/immersive-portals-2.5.4-mc1.19.3-forge.jar b/libs/immersive-portals-2.5.4-mc1.19.3-forge.jar new file mode 100644 index 000000000..4df338a64 Binary files /dev/null and b/libs/immersive-portals-2.5.4-mc1.19.3-forge.jar differ