diff --git a/README.md b/README.md index 7596229..9601697 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Colourful Portals Reimagined -A Fabric Minecraft mod adding colourful portals, based on Immersive Portals \ No newline at end of file +A Fabric Minecraft mod adding colourful portalRepresentations, based on Immersive Portals \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8243add..b4898cf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "com.modrinth.minotaur" version "2.+" - id 'fabric-loom' version '1.5-SNAPSHOT' + id 'fabric-loom' version '1.6-SNAPSHOT' id 'maven-publish' } @@ -54,22 +54,29 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - modImplementation ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}") - - include(modApi("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}")) + modCompileOnly ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}") // Replace modImplementation with modApi if you expose components in your own API - include(modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}")) + modImplementation "org.ladysnake.cardinal-components-api:cardinal-components-base:${project.cca_version}" + // Includes Cardinal Components API as a Jar-in-Jar dependency (optional but recommended) + include "org.ladysnake.cardinal-components-api:cardinal-components-base:${project.cca_version}" - include(modApi(platform("de.siphalor.tweed4:tweed4-bom-$project.minecraft_version_major:$project.tweed_version"))) + // Replace modImplementation with modApi if you expose components in your own API + modImplementation "org.ladysnake.cardinal-components-api:cardinal-components-level:${project.cca_version}" + // Includes Cardinal Components API as a Jar-in-Jar dependency (optional but recommended) + include "org.ladysnake.cardinal-components-api:cardinal-components-level:${project.cca_version}" + + //include(modApi(platform("de.siphalor.tweed4:tweed4-bom-$project.minecraft_version_major:$project.tweed_version"))) // Pick any modules you want to use, e.g.: - include(modApi("de.siphalor.tweed4:tweed4-base-$project.minecraft_version_major")) - include(modApi("de.siphalor.tweed4:tweed4-annotated-$project.minecraft_version_major")) - include(modApi("de.siphalor.tweed4:tweed4-data-$project.minecraft_version_major")) - include(modApi("de.siphalor.tweed4:tweed4-data-hjson-$project.minecraft_version_major")) + //include(modApi("de.siphalor.tweed4:tweed4-base-$project.minecraft_version_major")) + //include(modApi("de.siphalor.tweed4:tweed4-annotated-$project.minecraft_version_major")) + //include(modApi("de.siphalor.tweed4:tweed4-data-$project.minecraft_version_major")) + //include(modApi("de.siphalor.tweed4:tweed4-data-hjson-$project.minecraft_version_major")) //include(modApi("de.siphalor.tweed4:tweed4-tailor-cloth-$project.minecraft_version_major")) - include(modApi("de.siphalor.tweed4:tweed4-tailor-screen-$project.minecraft_version_major")) + //include(modApi("de.siphalor.tweed4:tweed4-tailor-screen-$project.minecraft_version_major")) + modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}" + include "maven.modrinth:midnightlib:${project.midnightlib_version}" modImplementation("me.shedaniel.cloth:cloth-config-fabric:$project.cloth_config_version") @@ -95,7 +102,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } java { @@ -104,8 +111,8 @@ java { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } jar { @@ -119,10 +126,10 @@ import com.modrinth.minotaur.dependencies.ModDependency modrinth { projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work. uploadFile = remapJar // Tells Minotaur to use the remapped jar - versionType = "beta" + versionType = "alpha" dependencies = [ new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API - new ModDependency('zJpHMkdD', 'required') //required dependency on Immersive Portals + new ModDependency('dNHeFokL', 'optional'), //compatible with Sodium ] } // configure the maven publication diff --git a/gradle.properties b/gradle.properties index 992c60d..777295c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,21 +4,22 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20.4 -minecraft_version_major=1.20 -yarn_mappings=1.20.4+build.3 -loader_version=0.15.7 +minecraft_version=1.21 +minecraft_version_major=1.21 +yarn_mappings=1.21+build.2 +loader_version=0.15.11 # Mod Properties -mod_version=0.9.3.1 -maven_group=quimufu.colourful-portals -archives_base_name=colourful-portals +mod_version=0.9.4 +maven_group=quimufu.colourful-portalRepresentations +archives_base_name=colourful-portalRepresentations # Dependencies -fabric_version=0.96.11+1.20.4 -cardinal_components_version=5.4.0 +fabric_version=0.100.1+1.21 +cca_version = 6.1.0 immersive_portals_version_short=5.1.7 immersive_portals_version=v5.1.7-mc1.20.4 tweed_version=1.3.0+mc1.20.2 -sodium_version=mc1.20.4-0.5.8 -cloth_config_version=13.0.121 \ No newline at end of file +sodium_version=mc1.21-0.5.9 +cloth_config_version=15.0.127 +midnightlib_version=1.5.7-fabric \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 20db9ad..129d130 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ +#Sun Jun 16 00:12:45 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip -networkTimeout=10000 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/quimufu/colourful_portals/ColourfulPortalsMod.java b/src/main/java/quimufu/colourful_portals/ColourfulPortalsMod.java index 1ec8d4c..c25f3ec 100644 --- a/src/main/java/quimufu/colourful_portals/ColourfulPortalsMod.java +++ b/src/main/java/quimufu/colourful_portals/ColourfulPortalsMod.java @@ -1,16 +1,19 @@ package quimufu.colourful_portals; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.item.v1.FabricItemSettings; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroupEntries; import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.minecraft.block.AbstractBlock; import net.minecraft.block.BlockState; -import net.minecraft.block.enums.Instrument; +import net.minecraft.block.enums.NoteBlockInstrument; import net.minecraft.entity.EntityType; import net.minecraft.item.*; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.util.Identifier; import net.minecraft.util.Rarity; @@ -19,25 +22,34 @@ import net.minecraft.world.BlockView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import quimufu.colourful_portals.config.ColourfulPortalConfig; +import quimufu.colourful_portals.portal.*; import quimufu.colourful_portals.portal_fluid.PortalFluid; import quimufu.colourful_portals.portal_fluid.PortalFluidBlock; import quimufu.colourful_portals.portal_fluid.PortalFluidBucketItem; +import java.util.Comparator; import java.util.HashSet; +import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST; +import static quimufu.colourful_portals.Components.PORTAL_LIST; + public class ColourfulPortalsMod implements ModInitializer { public static final String MOD_ID = "colourful_portals"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final HashSet PORTAL_BLOCKS = new HashSet<>(); - public static final PortalBlock PORTAL_BLOCK = new PortalBlock(FabricBlockSettings.create().instrument(Instrument.HAT).sounds(BlockSoundGroup.GLASS).strength(-1.0f, 3600000.8f).dropsNothing().nonOpaque().luminance(15).allowsSpawning(ColourfulPortalsMod::never).solidBlock(ColourfulPortalsMod::never).suffocates(ColourfulPortalsMod::never).blockVision(ColourfulPortalsMod::never).ticksRandomly()); - public static final BlockItem PORTAL_BLOCK_ITEM = new BlockItem(PORTAL_BLOCK, new FabricItemSettings().rarity(Rarity.EPIC)); - public static final Item BLOB_DARK = new Item(new FabricItemSettings()); - public static final Item BLOB_BRIGHT = new Item(new FabricItemSettings()); + public static final PortalBlock PORTAL_BLOCK = new PortalBlock(AbstractBlock.Settings.create().instrument(NoteBlockInstrument.HAT).sounds(BlockSoundGroup.GLASS).strength(-1.0f, 3600000.8f).dropsNothing().nonOpaque().luminance((bs) -> 15).allowsSpawning(ColourfulPortalsMod::never).solidBlock(ColourfulPortalsMod::never).suffocates(ColourfulPortalsMod::never).blockVision(ColourfulPortalsMod::never).ticksRandomly()); + public static final BlockItem PORTAL_BLOCK_ITEM = new BlockItem(PORTAL_BLOCK, new Item.Settings().rarity(Rarity.EPIC)); + public static final Item BLOB_DARK = new Item(new Item.Settings()); + public static final Item BLOB_BRIGHT = new Item(new Item.Settings()); public static final PortalFluid PORTAL_FLUID = new PortalFluid(); - public static final PortalFluidBlock PORTAL_FLUID_BLOCk = new PortalFluidBlock(PORTAL_FLUID, FabricBlockSettings.create().sounds(BlockSoundGroup.INTENTIONALLY_EMPTY).luminance(15).noCollision().strength(100.0f).dropsNothing()); - public static final BucketItem PORTAL_FLUID_BUCKET_ITEM = new PortalFluidBucketItem(PORTAL_FLUID, new FabricItemSettings().recipeRemainder(Items.BUCKET).maxCount(1).rarity(Rarity.RARE)); + public static final PortalFluidBlock PORTAL_FLUID_BLOCk = new PortalFluidBlock(PORTAL_FLUID, AbstractBlock.Settings.create().sounds(BlockSoundGroup.INTENTIONALLY_EMPTY).luminance((bs) -> 15).noCollision().strength(100.0f).dropsNothing()); + public static final BucketItem PORTAL_FLUID_BUCKET_ITEM = new PortalFluidBucketItem(PORTAL_FLUID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1).rarity(Rarity.RARE)); + public static PortalManager PORTAL_MANAGER; + + public static final RegistryKey> PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY_KEY = RegistryKey.ofRegistry(Identifier.of(MOD_ID, "portal_linking_system")); + public static final Registry PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY = FabricRegistryBuilder.createSimple(PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY_KEY).buildAndRegister(); private static boolean never(BlockState blockState, BlockView blockView, BlockPos blockPos, EntityType entityType) { return false; @@ -50,23 +62,28 @@ public class ColourfulPortalsMod implements ModInitializer { @Override public void onInitialize() { - LOGGER.info("Colourizing Portals..."); + LOGGER.info("Colouring Portals..."); - for (String id : ColourfulPortalConfig.portalBlocks.keySet()) { + for (String id : ColourfulPortalConfig.getAllPortalBlocks()) { + LOGGER.info(id); PORTAL_BLOCKS.add(Identifier.tryParse(id)); } + if (!ColourfulPortalConfig.disableImmersivePortals && hasImmPtl()) { + Registry.register(PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY, ImmersivePortalsLinkingSystem.IMMERSIVE_PORTALS_LINKING_SYSTEM, new PrioritizedPortalLinkingSystemBuilder(ImmersivePortalsLinkingSystem::new, 100)); + } + Registry.register(PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY, DefaultLinkingSystem.DEFAULT_LINKING_SYSTEM, new PrioritizedPortalLinkingSystemBuilder(DefaultLinkingSystem::new, 90)); - Identifier identifier = new Identifier(MOD_ID, "portal_block"); + Identifier identifier = Identifier.of(MOD_ID, "portal_block"); Registry.register(Registries.BLOCK, identifier, PORTAL_BLOCK); Registry.register(Registries.ITEM, identifier, PORTAL_BLOCK_ITEM); - Registry.register(Registries.ITEM, new Identifier(MOD_ID, "portal_fluid_bucket"), PORTAL_FLUID_BUCKET_ITEM); - Registry.register(Registries.FLUID, new Identifier(MOD_ID, "portal_fluid"), PORTAL_FLUID); - Registry.register(Registries.BLOCK, new Identifier(MOD_ID, "portal_fluid_block"), PORTAL_FLUID_BLOCk); + Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "portal_fluid_bucket"), PORTAL_FLUID_BUCKET_ITEM); + Registry.register(Registries.FLUID, Identifier.of(MOD_ID, "portal_fluid"), PORTAL_FLUID); + Registry.register(Registries.BLOCK, Identifier.of(MOD_ID, "portal_fluid_block"), PORTAL_FLUID_BLOCk); - Registry.register(Registries.ITEM, new Identifier(MOD_ID, "colour_blob_bright"), BLOB_BRIGHT); - Registry.register(Registries.ITEM, new Identifier(MOD_ID, "colour_blob_dark"), BLOB_DARK); + Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "colour_blob_bright"), BLOB_BRIGHT); + Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "colour_blob_dark"), BLOB_DARK); ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS) .register(ColourfulPortalsMod::addToIngredients); @@ -74,9 +91,51 @@ public class ColourfulPortalsMod implements ModInitializer { ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS) .register(ColourfulPortalsMod::addTtTools); + ServerLifecycleEvents.SERVER_STARTED.register(this::onServerStarted); LOGGER.info("Portals Colourful!"); } + private boolean hasImmPtl() { + try { + Class.forName("qouteall.imm_ptl.core.IPModMain", false, this.getClass().getClassLoader()); + } catch (ClassNotFoundException e) { + return false; + } + return true; + } + + private void onServerStarted(MinecraftServer minecraftServer) { + + PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(minecraftServer.getSaveProperties().getMainWorldProperties()); + PortalListComponent portalList = PORTAL_LIST.get(minecraftServer.getSaveProperties().getMainWorldProperties()); + + PortalLinkingSystem currentLinkingSystem = getCurrentlyConfiguredLinkingSystem(minecraftServer); + if (currentLinkingSystem.getLinkingSystemId() != portalList.lastPortalLinkingSystemId() || currentLinkingSystem.needsReInit()) { + PrioritizedPortalLinkingSystemBuilder prevSystem; + if ((prevSystem = PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY.get(portalList.lastPortalLinkingSystemId())) != null) { + PortalLinkingSystem prevLS = prevSystem.portalLinkingSystemBuilder().build(minecraftServer); + for (Identifier blockId : portalList.getBlockIds()) { + for (PortalRepresentation portal : portalList.getPortals(blockId)) { + prevLS.unLinkPortal(portal); + } + } + } + for (Identifier blockId : portalList.getBlockIds()) { + currentLinkingSystem.linkPortals(portalList.getPortals(blockId)); + } + } + PORTAL_MANAGER = new PortalManager(currentLinkingSystem, portalCandidateList, portalList); + } + + private PortalLinkingSystem getCurrentlyConfiguredLinkingSystem(MinecraftServer minecraftServer) { + return PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY + .stream() + .min(Comparator.comparing(PrioritizedPortalLinkingSystemBuilder::priority)) + .map(PrioritizedPortalLinkingSystemBuilder::portalLinkingSystemBuilder) + .orElse(DefaultLinkingSystem::new) + .build(minecraftServer); + } + private static void addTtTools(FabricItemGroupEntries entries) { entries.add(PORTAL_FLUID_BUCKET_ITEM); } diff --git a/src/main/java/quimufu/colourful_portals/Components.java b/src/main/java/quimufu/colourful_portals/Components.java index 9b51e2f..389926e 100644 --- a/src/main/java/quimufu/colourful_portals/Components.java +++ b/src/main/java/quimufu/colourful_portals/Components.java @@ -1,17 +1,17 @@ package quimufu.colourful_portals; -import dev.onyxstudios.cca.api.v3.component.ComponentKey; -import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; -import dev.onyxstudios.cca.api.v3.level.LevelComponentFactoryRegistry; -import dev.onyxstudios.cca.api.v3.level.LevelComponentInitializer; +import org.ladysnake.cca.api.v3.component.ComponentKey; +import org.ladysnake.cca.api.v3.component.ComponentRegistry; +import org.ladysnake.cca.api.v3.level.LevelComponentFactoryRegistry; +import org.ladysnake.cca.api.v3.level.LevelComponentInitializer; import net.minecraft.util.Identifier; import quimufu.colourful_portals.portal.PortalListComponent; public class Components implements LevelComponentInitializer { public static final ComponentKey PORTAL_LIST = - ComponentRegistry.getOrCreate(new Identifier(ColourfulPortalsMod.MOD_ID, "portal_list"), PortalListComponent.class); + ComponentRegistry.getOrCreate(Identifier.of(ColourfulPortalsMod.MOD_ID, "portal_list"), PortalListComponent.class); public static final ComponentKey PORTAL_CANDIDATE_LIST = - ComponentRegistry.getOrCreate(new Identifier(ColourfulPortalsMod.MOD_ID, "portal_candidate_list"), PortalListComponent.class); + ComponentRegistry.getOrCreate(Identifier.of(ColourfulPortalsMod.MOD_ID, "portal_candidate_list"), PortalListComponent.class); @Override public void registerLevelComponentFactories(LevelComponentFactoryRegistry registry) { diff --git a/src/main/java/quimufu/colourful_portals/PortalBlock.java b/src/main/java/quimufu/colourful_portals/PortalBlock.java index 58eba4b..ba512dc 100644 --- a/src/main/java/quimufu/colourful_portals/PortalBlock.java +++ b/src/main/java/quimufu/colourful_portals/PortalBlock.java @@ -4,6 +4,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.FluidFillable; import net.minecraft.block.ShapeContext; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.FluidState; @@ -15,15 +16,16 @@ import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; import net.minecraft.util.BlockRotation; import net.minecraft.util.DyeColor; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; +import net.minecraft.util.math.*; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; import org.jetbrains.annotations.Nullable; -import quimufu.colourful_portals.portal.PortalManager; +import quimufu.colourful_portals.util.CollisionAwareShapeContext; + +import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_MANAGER; public class PortalBlock extends Block implements FluidFillable { @@ -63,8 +65,8 @@ public class PortalBlock extends Block implements FluidFillable { @Override public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos blockPos, ShapeContext shapeContext) { if (shapeContext.isHolding(Items.DEBUG_STICK) - || shapeContext.isHolding(ColourfulPortalsMod.PORTAL_BLOCK_ITEM) - || shapeContext.isHolding(ColourfulPortalsMod.PORTAL_FLUID_BUCKET_ITEM)) { + || shapeContext.isHolding(ColourfulPortalsMod.PORTAL_BLOCK_ITEM) + || shapeContext.isHolding(ColourfulPortalsMod.PORTAL_FLUID_BUCKET_ITEM)) { return switch (state.get(AXIS)) { case Z -> Z_AABB; case Y -> Y_AABB; @@ -74,8 +76,58 @@ public class PortalBlock extends Block implements FluidFillable { return VoxelShapes.empty(); } + @Override + protected void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { + if (entity.getBoundingBox() + .intersects(getShape(state, world, pos).getBoundingBox())) { + Vec3d vec3d = new Vec3d(0.5, 0.5f, 0.5); + entity.slowMovement(state, vec3d); + } + Vec3d entityPos = entity.getPos(); + Vec3d prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ); + Vec3d movement = entityPos.subtract(prevEntityPos); + if (world instanceof ServerWorld) { + Direction.Axis axis = state.get(AXIS); + double centerPosAlongAxis = pos.toCenterPos().getComponentAlongAxis(axis); + double entityPosAlongAxis = entityPos.getComponentAlongAxis(axis); + double prevEntityPosAlongAxis = prevEntityPos.getComponentAlongAxis(axis); + double movementAlongAxis = entityPosAlongAxis - prevEntityPosAlongAxis; + if (prevEntityPosAlongAxis > entityPosAlongAxis) { + if (entityPosAlongAxis < centerPosAlongAxis + && prevEntityPosAlongAxis >= centerPosAlongAxis) { + double plainHitAfter = (centerPosAlongAxis - entityPosAlongAxis) / movementAlongAxis; + Vec3d planeHitPoint = entityPos.add(movement.multiply(plainHitAfter)); + if (Box.from(new BlockBox(pos)).contains(planeHitPoint)) { + PORTAL_MANAGER.onPortalPassed(entity, pos, (ServerWorld) world, axis); + } + } + } else if (prevEntityPosAlongAxis < entityPosAlongAxis) { + if (entityPosAlongAxis > centerPosAlongAxis + && prevEntityPosAlongAxis <= centerPosAlongAxis) { + double plainHitAfter = (centerPosAlongAxis - entityPosAlongAxis) / movementAlongAxis; + Vec3d planeHitPoint = entityPos.add(movement.multiply(plainHitAfter)); + if (Box.from(new BlockBox(pos)).contains(planeHitPoint)) { + PORTAL_MANAGER.onPortalPassed(entity, pos, (ServerWorld) world, axis); + } + } + } + } + + } + + public VoxelShape getShape(BlockState state, BlockView world, BlockPos pos) { + return switch (state.get(AXIS)) { + case Z -> Z_AABB; + case Y -> Y_AABB; + default -> X_AABB; + }; + } + @Override public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + if (context instanceof CollisionAwareShapeContext) { + return getShape(state, world, pos); + } return VoxelShapes.empty(); } @@ -126,8 +178,8 @@ public class PortalBlock extends Block implements FluidFillable { return true; } return fluid == ColourfulPortalsMod.PORTAL_FLUID - && (world instanceof ServerWorld) - && PortalManager.canExtend((ServerWorld) world, pos); + && (world instanceof ServerWorld) + && PORTAL_MANAGER.canExtend((ServerWorld) world, pos); } @@ -137,7 +189,7 @@ public class PortalBlock extends Block implements FluidFillable { return true; } return fluidState.isOf(ColourfulPortalsMod.PORTAL_FLUID) - && (world instanceof ServerWorld) - && PortalManager.extend((ServerWorld) world, pos); + && (world instanceof ServerWorld) + && PORTAL_MANAGER.extend((ServerWorld) world, pos); } } diff --git a/src/main/java/quimufu/colourful_portals/client/PortalFluidRenderHandler.java b/src/main/java/quimufu/colourful_portals/client/PortalFluidRenderHandler.java index fe7bcad..6c62d09 100644 --- a/src/main/java/quimufu/colourful_portals/client/PortalFluidRenderHandler.java +++ b/src/main/java/quimufu/colourful_portals/client/PortalFluidRenderHandler.java @@ -17,7 +17,7 @@ import quimufu.colourful_portals.ColourfulPortalsMod; @Environment(value = EnvType.CLIENT) public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPortalFluidRenderer.VertexEater { - Identifier PORTAL_FLUID_STILL = new Identifier(ColourfulPortalsMod.MOD_ID, "block/portal_still"); + Identifier PORTAL_FLUID_STILL = Identifier.of(ColourfulPortalsMod.MOD_ID, "block/portal_still"); private final CommonPortalFluidRenderer commonPortalFluidRenderer = new CommonPortalFluidRenderer(); private Sprite sprite = null; @@ -82,8 +82,7 @@ public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPorta .color(1f, 1f, 1f, 1.0f) .texture(v[3], v[4]) .light(16) - .normal(0.0f, 1.0f, 0.0f) - .next(); + .normal(0.0f, 1.0f, 0.0f); } diff --git a/src/main/java/quimufu/colourful_portals/client/SodiumPortalFluidRenderHandler.java b/src/main/java/quimufu/colourful_portals/client/SodiumPortalFluidRenderHandler.java index ab15e5c..e466595 100644 --- a/src/main/java/quimufu/colourful_portals/client/SodiumPortalFluidRenderHandler.java +++ b/src/main/java/quimufu/colourful_portals/client/SodiumPortalFluidRenderHandler.java @@ -9,7 +9,9 @@ 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.terrain.material.DefaultMaterials; import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material; +import me.jellysquid.mods.sodium.client.render.chunk.vertex.builder.ChunkMeshBufferBuilder; import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; +import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder.Vertex; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.texture.Sprite; diff --git a/src/main/java/quimufu/colourful_portals/config/ColourfulPortalConfig.java b/src/main/java/quimufu/colourful_portals/config/ColourfulPortalConfig.java index 8de123d..9e73c60 100644 --- a/src/main/java/quimufu/colourful_portals/config/ColourfulPortalConfig.java +++ b/src/main/java/quimufu/colourful_portals/config/ColourfulPortalConfig.java @@ -1,44 +1,131 @@ package quimufu.colourful_portals.config; -import com.google.common.base.CaseFormat; -import com.google.common.collect.ImmutableMap; -import de.siphalor.tweed4.annotated.AConfigEntry; -import de.siphalor.tweed4.annotated.ATweedConfig; -import de.siphalor.tweed4.config.ConfigEnvironment; -import de.siphalor.tweed4.config.ConfigScope; -//import de.siphalor.tweed4.tailor.cloth.ClothData; +import com.google.common.collect.Lists; +import eu.midnightdust.lib.config.MidnightConfig; import net.minecraft.util.DyeColor; -//import quimufu.colourful_portals.ColourfulPortalsMod; -import java.util.Map; +import java.util.HashSet; +import java.util.List; +import java.util.Set; -@ATweedConfig(serializer = "tweed4:hjson", scope = ConfigScope.GAME, environment = ConfigEnvironment.SERVER, tailors = {"tweed4:lang_json_descriptions", "tweed4:coat", "tweed4:json_schema"}, casing = CaseFormat.LOWER_HYPHEN) -//@ClothData(modid = ColourfulPortalsMod.MOD_ID) -public class ColourfulPortalConfig { +public class ColourfulPortalConfig extends MidnightConfig { - @AConfigEntry(comment = - """ - Allows you to add additional blocks as portalBlocks, - assigning them the color of the portal plane. - null causes the portals out of that block to have *no* plane. - Changes in the plane color will only apply to new portals, - or on portal update. - """) - public static Map portalBlocks = ImmutableMap.ofEntries( - Map.entry("minecraft:white_wool", DyeColor.WHITE), - Map.entry("minecraft:orange_wool", DyeColor.ORANGE), - Map.entry("minecraft:magenta_wool", DyeColor.MAGENTA), - Map.entry("minecraft:light_blue_wool", DyeColor.LIGHT_BLUE), - Map.entry("minecraft:yellow_wool", DyeColor.YELLOW), - Map.entry("minecraft:lime_wool", DyeColor.LIME), - Map.entry("minecraft:pink_wool", DyeColor.PINK), - Map.entry("minecraft:gray_wool", DyeColor.GRAY), - Map.entry("minecraft:light_gray_wool", DyeColor.LIGHT_GRAY), - Map.entry("minecraft:cyan_wool", DyeColor.CYAN), - Map.entry("minecraft:purple_wool", DyeColor.PURPLE), - Map.entry("minecraft:blue_wool", DyeColor.BLUE), - Map.entry("minecraft:brown_wool", DyeColor.BROWN), - Map.entry("minecraft:green_wool", DyeColor.GREEN), - Map.entry("minecraft:red_wool", DyeColor.RED), - Map.entry("minecraft:black_wool", DyeColor.BLACK)); + @Comment(category = "text") + public static Comment explanation; + + @Entry(category = "text", name = "Disable Immersive Portals integration") + public static boolean disableImmersivePortals = false; + + @Entry(category = "text", name = "Blocks that create white portals") + public static List white = Lists.newArrayList("minecraft:white_wool"); + + @Entry(category = "text", name = "Blocks that create orange portals") + public static List orange = Lists.newArrayList("minecraft:orange_wool"); + + @Entry(category = "text", name = "Blocks that create magenta portals") + public static List magenta = Lists.newArrayList("minecraft:magenta_wool"); + + @Entry(category = "text", name = "Blocks that create light blue portals") + public static List light_blue = Lists.newArrayList("minecraft:light_blue_wool"); + + @Entry(category = "text", name = "Blocks that create yellow portals") + public static List yellow = Lists.newArrayList("minecraft:yellow_wool"); + + @Entry(category = "text", name = "Blocks that create lime portals") + public static List lime = Lists.newArrayList("minecraft:lime_wool"); + + @Entry(category = "text", name = "Blocks that create pink portals") + public static List pink = Lists.newArrayList("minecraft:pink_wool"); + + @Entry(category = "text", name = "Blocks that create gray portals") + public static List gray = Lists.newArrayList("minecraft:gray_wool"); + + @Entry(category = "text", name = "Blocks that create light gray portals") + public static List light_gray = Lists.newArrayList("minecraft:light_gray_wool"); + + @Entry(category = "text", name = "Blocks that create cyan portals") + public static List cyan = Lists.newArrayList("minecraft:cyan_wool"); + + @Entry(category = "text", name = "Blocks that create purple portals") + public static List purple = Lists.newArrayList("minecraft:purple_wool"); + + @Entry(category = "text", name = "Blocks that create blue portals") + public static List blue = Lists.newArrayList("minecraft:blue_wool"); + + @Entry(category = "text", name = "Blocks that create brown portals") + public static List brown = Lists.newArrayList("minecraft:brown_wool"); + + @Entry(category = "text", name = "Blocks that create green portals") + public static List green = Lists.newArrayList("minecraft:green_wool"); + + @Entry(category = "text", name = "Blocks that create red portals") + public static List red = Lists.newArrayList("minecraft:red_wool"); + + @Entry(category = "text", name = "Blocks that create black portals") + public static List black = Lists.newArrayList("minecraft:black_wool"); + + @Entry(category = "text", name = "Blocks that create fully transparent portals") + public static List none = Lists.newArrayList(); + + public static Set getAllPortalBlocks() { + Set allBlocks = new HashSet<>(); + allBlocks.addAll(white); + allBlocks.addAll(orange); + allBlocks.addAll(magenta); + allBlocks.addAll(light_blue); + allBlocks.addAll(yellow); + allBlocks.addAll(lime); + allBlocks.addAll(pink); + allBlocks.addAll(gray); + allBlocks.addAll(light_gray); + allBlocks.addAll(cyan); + allBlocks.addAll(purple); + allBlocks.addAll(blue); + allBlocks.addAll(brown); + allBlocks.addAll(green); + allBlocks.addAll(red); + allBlocks.addAll(black); + allBlocks.addAll(none); + return allBlocks; + } + + public static DyeColor colorOf(String block) { + if (white.contains(block)) { + return DyeColor.WHITE; + } else if (orange.contains(block)) { + return DyeColor.ORANGE; + } else if (magenta.contains(block)) { + return DyeColor.MAGENTA; + } else if (light_blue.contains(block)) { + return DyeColor.LIGHT_BLUE; + } else if (yellow.contains(block)) { + return DyeColor.YELLOW; + } else if (lime.contains(block)) { + return DyeColor.LIME; + } else if (pink.contains(block)) { + return DyeColor.PINK; + } else if (gray.contains(block)) { + return DyeColor.GRAY; + } else if (light_gray.contains(block)) { + return DyeColor.LIGHT_GRAY; + } else if (cyan.contains(block)) { + return DyeColor.CYAN; + } else if (purple.contains(block)) { + return DyeColor.PURPLE; + } else if (blue.contains(block)) { + return DyeColor.BLUE; + } else if (brown.contains(block)) { + return DyeColor.BROWN; + } else if (green.contains(block)) { + return DyeColor.GREEN; + } else if (red.contains(block)) { + return DyeColor.RED; + } else if (black.contains(block)) { + return DyeColor.BLACK; + } else if (none.contains(block)) { + return null; // Fully transparent portal + } else { + throw new IllegalArgumentException("Invalid portal block: " + block); + } + } } diff --git a/src/main/java/quimufu/colourful_portals/general_util/LinkedList.java b/src/main/java/quimufu/colourful_portals/general_util/LinkedList.java new file mode 100644 index 0000000..dc5901b --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/general_util/LinkedList.java @@ -0,0 +1,458 @@ +package quimufu.colourful_portals.general_util; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; + +public class LinkedList implements List { + + Node headNode = null; + + + @Override + public boolean contains(Object o) { + return indexOf(o) != -1; + } + + + @Override + public int size() { + Node node = headNode; + int size = 0; + while (node != null) { + size++; + node = node.getNext(); + } + LOGGER.info("" + size); + return size; + } + + @Override + public boolean isEmpty() { + return headNode == null; + } + + @NotNull + @Override + public Iterator iterator() { + return new LLIterator<>(this); + } + + @NotNull + @Override + public Object[] toArray() { + Object[] objects = new Object[size()]; + Node node = headNode; + int index = 0; + while (node != null) { + objects[index] = node.getValue(); + node = node.getNext(); + index++; + } + + return objects; + } + + @NotNull + @Override + public T @NotNull [] toArray(T[] a) { + int size = this.size(); + if (size > a.length) { + a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); + } + Object[] result = a; + Node node = headNode; + int index = 0; + while (node != null) { + result[index] = node.getValue(); + node = node.getNext(); + index++; + } + if (size != a.length) { + a[index] = null; + } + return a; + } + + @Override + public boolean add(E e) { + if (headNode == null) { + headNode = new Node<>(e, this); + return true; + } + Node node = getLastNode(headNode); + node.insertAfter(e); + return true; + } + + private @NotNull Node getLastNode(@NotNull Node start) { + Node node = start; + while (node.getNext() != null) { + node = node.getNext(); + } + return node; + } + + @Override + public boolean containsAll(@NotNull Collection c) { + for (Object o : c) { + if (!contains(o)) { + return false; + } + } + return true; + } + + @Override + public boolean addAll(@NotNull Collection c) { + if (headNode == null) { + headNode = new Node<>(null, this); + Node startNode = new Node<>(null, this); + Node currNode = startNode; + for (E o : c) { + currNode.insertAfter(o); + currNode = currNode.getNext(); + } + startNode.remove(); + return true; + } + Node currNode = getLastNode(headNode); + for (E o : c) { + currNode.insertAfter(o); + currNode = currNode.getNext(); + } + return true; + } + + @Override + public boolean addAll(int index, @NotNull Collection c) { + if (c.isEmpty()) { + return false; + } + Node node = getNode(index); + for (E e : c) { + node.insertBefore(e); + } + return true; + } + + @Override + public boolean removeAll(@NotNull Collection c) { + if (headNode == null) { + return false; + } + boolean ret = false; + Node currNode = headNode; + while (currNode != null) { + if (c.contains(currNode.getValue())) { + currNode.remove(); + ret = true; + } + currNode = currNode.getNext(); + } + return ret; + } + + @Override + public boolean retainAll(@NotNull Collection c) { + if (headNode == null) { + return false; + } + boolean ret = false; + Node currNode = headNode; + while (currNode != null) { + if (!c.contains(currNode.getValue())) { + currNode.remove(); + ret = true; + } + currNode = currNode.getNext(); + } + return ret; + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + Node node = headNode; + while (node != null) { + if (Objects.equals(node.getValue(), o)) { + node.remove(); + return true; + } + node = node.getNext(); + } + return false; + } + + + public E get(int index) { + return getNode(index).getValue(); + } + + public Node getNode(int index) { + Node node = headNode; + for (int i = 0; i < index; i++) { + if (node == null) + throw new IndexOutOfBoundsException(index); + node = node.getNext(); + + } + return node; + } + + public E set(int index, E element) { + getNode(index).setValue(element); + return element; + } + + public void add(int index, E element) { + getNode(index).insertBefore(element); + } + + public E remove(int index) { + Node node = getNode(index); + node.remove(); + return node.getValue(); + } + + public int indexOf(Object o) { + int index = 0; + Node node = headNode; + while (node != null) { + if (Objects.equals(node.getValue(), o)) { + return index; + } + node = node.getNext(); + index++; + } + + return -1; + } + + public int lastIndexOf(Object o) { + int ret = -1; + int index = 0; + Node node = headNode; + while (node != null) { + if (Objects.equals(node.getValue(), o)) { + ret = index; + } + node = node.getNext(); + index++; + } + + return ret; + } + + @NotNull + @Override + public ListIterator listIterator() { + + return new LLLIterator<>(this); + } + + @NotNull + @Override + public ListIterator listIterator(int index) { + LLLIterator iterator = new LLLIterator<>(this); + iterator.nextNode = getNode(index); + iterator.previousNode = iterator.nextNode.getPrevious(); + return iterator; + } + + @NotNull + @Override + public List subList(int fromIndex, int toIndex) { + throw new UnsupportedOperationException(); + } + + @Nullable + public Node getNodeOf(E content) { + Node node = headNode; + while (node != null) { + if (Objects.equals(node.getValue(), content)) { + return node; + } + node = node.getNext(); + } + + return null; + } + + private static class LLIterator implements Iterator { + + private Node nextNode; + + public LLIterator(LinkedList linkedList) { + nextNode = linkedList.headNode; + } + + @Override + public boolean hasNext() { + return nextNode != null; + } + + @Override + public E next() { + if (nextNode == null) + throw new IndexOutOfBoundsException(); + + E value = nextNode.getValue(); + nextNode = nextNode.getNext(); + return value; + } + } + + private static class LLLIterator implements ListIterator { + + @Nullable + private Node nextNode; + @Nullable + private Node previousNode; + private boolean lastNext = true; + + private final LinkedList linkedList; + + public LLLIterator(LinkedList linkedList) { + nextNode = linkedList.headNode; + previousNode = null; + this.linkedList = linkedList; + } + + @Override + public boolean hasNext() { + return nextNode != null; + } + + @Override + public E next() { + tryFixOrphans(); + if (nextNode == null) + throw new IndexOutOfBoundsException(); + + E value = nextNode.getValue(); + previousNode = nextNode; + nextNode = nextNode.getNext(); + lastNext = true; + return value; + } + + @Override + public boolean hasPrevious() { + return previousNode != null; + } + + @Override + public E previous() { + tryFixOrphans(); + if (previousNode == null) + throw new IndexOutOfBoundsException(); + E value = previousNode.getValue(); + nextNode = previousNode; + previousNode = previousNode.getPrevious(); + lastNext = false; + return value; + } + + @Override + public int nextIndex() { + tryFixOrphans(); + if(nextNode == null) + return linkedList.size(); + return linkedList.indexOfNode(nextNode); + } + + @Override + public int previousIndex() { + tryFixOrphans(); + if(previousNode == null) { + return -1; + } + return linkedList.indexOfNode(previousNode); + } + + @Override + public void remove() { + tryFixOrphans(); + if(lastNext) { + if(previousNode == null) + throw new IllegalStateException(); + previousNode.remove(); + previousNode = previousNode.getPrevious(); + } else { + if(nextNode == null) + throw new IllegalStateException(); + nextNode.remove(); + nextNode = nextNode.getNext(); + + } + } + + @Override + public void set(E e) { + tryFixOrphans(); + if(lastNext) { + if(previousNode == null) + throw new IllegalStateException(); + previousNode.setValue(e); + } else { + if(nextNode == null) + throw new IllegalStateException(); + nextNode.setValue(e); + } + } + + @Override + public void add(E e) { + tryFixOrphans(); + if(nextNode != null) { + nextNode.insertBefore(e); + } else if(previousNode != null) { + previousNode.insertAfter(e); + } else { + // empty! + linkedList.add(e); + nextNode = linkedList.headNode; + } + + } + + private void tryFixOrphans() { + if (previousNode != null && previousNode.orphaned()){ + if(nextNode != null && !nextNode.orphaned()){ + previousNode = nextNode.getPrevious(); + } else { + throw new ConcurrentModificationException("Node was concurrently deleted!"); + } + } + if (nextNode != null && nextNode.orphaned()){ + if(previousNode != null && !previousNode.orphaned()){ + nextNode = previousNode.getNext(); + } else { + throw new ConcurrentModificationException("Node was concurrently deleted!"); + } + } + } + } + + private int indexOfNode(Node needle) { + int index = 0; + Node node = headNode; + while (node != null) { + if (node == needle) { + return index; + } + node = node.getNext(); + index++; + } + + return -1; + } +} diff --git a/src/main/java/quimufu/colourful_portals/general_util/Node.java b/src/main/java/quimufu/colourful_portals/general_util/Node.java new file mode 100644 index 0000000..03defe3 --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/general_util/Node.java @@ -0,0 +1,89 @@ +package quimufu.colourful_portals.general_util; + +import org.jetbrains.annotations.Nullable; + +public class Node { + + private Node next = null; + private Node previous = null; + private E value; + + public LinkedList getPartOf() { + return partOf; + } + + private final LinkedList partOf; + private boolean orphaned = false; + + protected Node(E value, LinkedList partOf) { + this.value = value; + this.partOf = partOf; + } + + public Node getNext() { + return next; + } + + public void setNext(@Nullable Node next) { + if (next != null) { + next.previous = this; + } + if(next == this){ + throw new IllegalArgumentException("cycles are not allowed"); + } + this.next = next; + } + + public E getValue() { + return value; + } + + public void setValue(E value) { + this.value = value; + } + + public Node getPrevious() { + return previous; + } + + public void setPrevious(@Nullable Node previous) { + if (previous != null) { + previous.next = this; + } + this.previous = previous; + } + + public void remove() { + if (partOf.headNode == this) { + if (next != null) { + partOf.headNode = next; + } else { + partOf.headNode = previous; + } + + } + if (previous != null) { + previous.setNext(next); + } + if (next != null) { + next.setPrevious(previous); + } + orphaned = true; + } + + public void insertBefore(E element) { + Node newNode = new Node<>(element, partOf); + newNode.setPrevious(this.previous); + newNode.setNext(this); + } + + public void insertAfter(E element) { + Node newNode = new Node<>(element, partOf); + newNode.setNext(this.next); + newNode.setPrevious(this); + } + + public boolean orphaned() { + return orphaned; + } +} diff --git a/src/main/java/quimufu/colourful_portals/mixin/AnimationMixin.java b/src/main/java/quimufu/colourful_portals/mixin/AnimationMixin.java index 3991e81..8ea9d54 100644 --- a/src/main/java/quimufu/colourful_portals/mixin/AnimationMixin.java +++ b/src/main/java/quimufu/colourful_portals/mixin/AnimationMixin.java @@ -15,7 +15,7 @@ import quimufu.colourful_portals.client.AlphaInterpolationHolder; import java.util.List; -@Mixin(targets = "net.minecraft.client.texture.SpriteContents$Animation") +@Mixin(SpriteContents.Animation.class) public class AnimationMixin implements AlphaInterpolationHolder { @Shadow @Final diff --git a/src/main/java/quimufu/colourful_portals/mixin/BlockChangeMixin.java b/src/main/java/quimufu/colourful_portals/mixin/BlockChangeMixin.java index 32b809c..bdbf80e 100644 --- a/src/main/java/quimufu/colourful_portals/mixin/BlockChangeMixin.java +++ b/src/main/java/quimufu/colourful_portals/mixin/BlockChangeMixin.java @@ -9,31 +9,29 @@ 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 quimufu.colourful_portals.portal.PortalManager; -import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; -import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_BLOCKS; +import static quimufu.colourful_portals.ColourfulPortalsMod.*; @Mixin(ServerWorld.class) public class BlockChangeMixin { @Inject(at = @At("RETURN"), method = "onBlockChanged") - private void init(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo info) { + 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.debug("onBlockNew {} -> {}", oldBlock, newBlock); + LOGGER.info("onBlockNew {} -> {}", oldBlock, newBlock); Identifier blockId = Registries.BLOCK.getId(newBlock.getBlock()); - PortalManager.onPortalBlockPlaced(world, pos, blockId); + PORTAL_MANAGER.onPortalBlockPlaced(world, pos, blockId); } if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(oldBlock.getBlock()))) { - LOGGER.debug("onBlockOld {} -> {}", oldBlock, newBlock); + LOGGER.info("onBlockOld {} -> {}", oldBlock, newBlock); Identifier blockId = Registries.BLOCK.getId(oldBlock.getBlock()); - PortalManager.onPortalBlockBroken(world, pos, blockId); + PORTAL_MANAGER.onPortalBlockBroken(world, pos, blockId); } } diff --git a/src/main/java/quimufu/colourful_portals/mixin/EntityMixin.java b/src/main/java/quimufu/colourful_portals/mixin/EntityMixin.java new file mode 100644 index 0000000..9f5dd3a --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/mixin/EntityMixin.java @@ -0,0 +1,65 @@ +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> 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(); + } + + } +} diff --git a/src/main/java/quimufu/colourful_portals/portal/DefaultLinkingSystem.java b/src/main/java/quimufu/colourful_portals/portal/DefaultLinkingSystem.java new file mode 100644 index 0000000..ebb4e0f --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/DefaultLinkingSystem.java @@ -0,0 +1,115 @@ +package quimufu.colourful_portals.portal; + +import net.minecraft.entity.Entity; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.TeleportTarget; +import quimufu.colourful_portals.general_util.LinkedList; +import quimufu.colourful_portals.general_util.Node; + +import java.util.*; + +import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; +import static quimufu.colourful_portals.ColourfulPortalsMod.MOD_ID; +import static quimufu.colourful_portals.portal.PortalHelper.getAxisW; +import static quimufu.colourful_portals.portal.PortalHelper.insideOf; +import static quimufu.colourful_portals.portal.PortalManager.getDimId; + +public class DefaultLinkingSystem implements PortalLinkingSystem { + + public static final Identifier DEFAULT_LINKING_SYSTEM = Identifier.of(MOD_ID, "default_linking_system"); + + private final Map>> positionalLookup = new HashMap<>(); + private final MinecraftServer server; + + public DefaultLinkingSystem(MinecraftServer minecraftServer) { + this.server = minecraftServer; + } + + @Override + public Identifier getLinkingSystemId() { + return DEFAULT_LINKING_SYSTEM; + } + + @Override + public void linkPortals(LinkedList portalRepresentations) { + LOGGER.info("start linkPortals"); + for (Node node = portalRepresentations.getNode(0); node != null; node = node.getNext()) { + PortalRepresentation portalRepresentation = node.getValue(); + + Node finalNode = node; + insideOf(portalRepresentation.location()) + .forEachRemaining(blockPos -> { + Set> portalsAtPosition = positionalLookup.computeIfAbsent(blockPos, (k) -> new HashSet<>(1)); + portalsAtPosition.add(finalNode); + }); + } + LOGGER.info("end linkPortals"); + } + + @Override + public void unLinkPortal(PortalRepresentation portalRepresentation) { + //no-op + } + + @Override + public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) { + Set> portalRepresentationCandidated = positionalLookup.get(pos); + Optional> portalOpt = portalRepresentationCandidated.stream() + .filter(n -> !n.orphaned()) + .filter(n -> n.getValue() != null) + .filter(n -> getAxisW(n.getValue().location()).rotateYClockwise().getAxis() == a) + .filter(n -> Objects.equals(n.getValue().dimensionId(), getDimId(world))) + .findAny(); + if (portalOpt.isPresent()) { + Node fromNode = portalOpt.get(); + Node toNode = fromNode.getNext() != null ? fromNode.getNext() : fromNode.getPartOf().getNode(0); + if (toNode == null || toNode.getValue() == null) { + return; + } + + PortalRepresentation fromPortal = fromNode.getValue(); + PortalRepresentation toPortal = toNode.getValue(); + BlockBox fromBox = fromPortal.location(); + 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(); + Vec3d toCenter = new Vec3d((toBox.getMaxX()+1 + toBox.getMinX())/2D,(toBox.getMaxY()+1 + toBox.getMinY())/2D,(toBox.getMaxZ()+1 + toBox.getMinZ())/2D); + if (getAxisW(fromPortal.location()) == getAxisW(toPortal.location())) { + Vec3d relPos = entity.getPos().subtract(fromCenter); + Vec3d targetPos = toCenter.add(relPos); + //todo: maybe fancy continoous movement math! + ServerWorld toWorld = getPortalWorld(toPortal); + TeleportTarget teleportTarget = new TeleportTarget(toWorld, targetPos, entity.getVelocity(), entity.getYaw(), entity.getPitch(), TeleportTarget.ADD_PORTAL_CHUNK_TICKET); + entity.teleportTo(teleportTarget); + } else { + Vec3d relPos = entity.getPos().subtract(fromCenter); + Vec3d targetPos = toCenter.add(new Vec3d(-relPos.z, relPos.y, relPos.x)); + //todo: maybe fancy continoous movement math! + ServerWorld toWorld = getPortalWorld(toPortal); + TeleportTarget teleportTarget = new TeleportTarget(toWorld, targetPos, entity.getVelocity(), (entity.getYaw() + 90.F) % 360.F, entity.getPitch(), TeleportTarget.ADD_PORTAL_CHUNK_TICKET); + entity.teleportTo(teleportTarget); + } + } + } + + @Override + public boolean needsReInit() { + return true; + } + + private ServerWorld getPortalWorld(PortalRepresentation fromPortalRepresentation) { + ServerWorld serverWorld = server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortalRepresentation.dimensionId())); + if (serverWorld == null) { + LOGGER.warn("couldn't get portal dimensionId for portal {}. Don't sue me!", fromPortalRepresentation); + throw new RuntimeException(); + } + return serverWorld; + } +} diff --git a/src/main/java/quimufu/colourful_portals/portal/ImmersivePortalsLinkingSystem.java b/src/main/java/quimufu/colourful_portals/portal/ImmersivePortalsLinkingSystem.java new file mode 100644 index 0000000..4f040bf --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/ImmersivePortalsLinkingSystem.java @@ -0,0 +1,141 @@ +package quimufu.colourful_portals.portal; + +import net.minecraft.entity.Entity; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.TypeFilter; +import net.minecraft.util.math.*; +import net.minecraft.world.World; +import qouteall.imm_ptl.core.api.PortalAPI; +import qouteall.q_misc_util.my_util.DQuaternion; +import quimufu.colourful_portals.general_util.LinkedList; + +import java.util.ArrayList; +import java.util.List; + +import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; +import static quimufu.colourful_portals.ColourfulPortalsMod.MOD_ID; + +public class ImmersivePortalsLinkingSystem implements PortalLinkingSystem { + + public static final Identifier IMMERSIVE_PORTALS_LINKING_SYSTEM = Identifier.of(MOD_ID, "immersive_portals_linking_system"); + + private final MinecraftServer server; + + public ImmersivePortalsLinkingSystem(MinecraftServer server) { + this.server = server; + } + + @Override + public Identifier getLinkingSystemId() { + return IMMERSIVE_PORTALS_LINKING_SYSTEM; + } + + public void assureLinked(PortalRepresentation fromPortalRepresentation, PortalRepresentation linkedToPortalRepresentation) { + + ServerWorld fromPortalWorld = getPortalWorld(fromPortalRepresentation); + RegistryKey linkedToPortalWorldRegKey = RegistryKey.of(RegistryKeys.WORLD, linkedToPortalRepresentation.dimensionId()); + + BlockBox fromPortalBlockBox = fromPortalRepresentation.location(); + Box fromPortalBox = Box.from(fromPortalBlockBox); + BlockBox linkedToPortalBlockBox = linkedToPortalRepresentation.location(); + Box linkedToPortalBox = Box.from(linkedToPortalBlockBox); + + List outgoingPortals = new ArrayList<>(getPortalList(fromPortalRepresentation)); + + if (outgoingPortals.size() > 2) { + LOGGER.warn("Found more then 2 portals in {}, cleaning up", fromPortalBox); + for (int i = 2; i < outgoingPortals.size(); i++) { + qouteall.imm_ptl.core.portal.Portal outgoingPortal = outgoingPortals.get(i); + outgoingPortal.kill(); + } + } + if (outgoingPortals.isEmpty()) { + qouteall.imm_ptl.core.portal.Portal portal = qouteall.imm_ptl.core.portal.Portal.ENTITY_TYPE.create(fromPortalWorld); + if (portal == null) { + LOGGER.error("could not create PortalRepresentation entity for {}", fromPortalRepresentation); + return; + } + + portal.setOriginPos(fromPortalBox.getCenter()); + portal.setDestinationDimension(linkedToPortalWorldRegKey); + portal.setDestination(linkedToPortalBox.getCenter()); + Vec3d axisW = Vec3d.of(PortalHelper.getAxisW(fromPortalBlockBox).getVector()); + portal.setOrientationAndSize( + axisW, // axisW + new Vec3d(0, 1, 0), // axisH + 2, // width + 3 // height + ); + portal.setRotationTransformation(DQuaternion.getRotationBetween(axisW, Vec3d.of(PortalHelper.getAxisW(linkedToPortalBlockBox).getVector()))); + outgoingPortals.add(portal); + if (!fromPortalWorld.spawnEntity(portal)) { + LOGGER.error("could not spawn PortalRepresentation entity for {}", fromPortalRepresentation); + return; + } + } + if (outgoingPortals.size() == 1) { + qouteall.imm_ptl.core.portal.Portal portal = PortalAPI.createFlippedPortal(outgoingPortals.getFirst()); + outgoingPortals.add(portal); + if (!fromPortalWorld.spawnEntity(portal)) { + LOGGER.error("could not spawn second PortalRepresentation entity for {}", fromPortalRepresentation); + return; + } + } + for (qouteall.imm_ptl.core.portal.Portal outgoingPortal : outgoingPortals) { + outgoingPortal.setDestinationDimension(linkedToPortalWorldRegKey); + outgoingPortal.setDestination(linkedToPortalBox.getCenter()); + Vec3d axisW = Vec3d.of(PortalHelper.getAxisW(fromPortalBlockBox).getVector()); + outgoingPortal.setRotationTransformation(DQuaternion.getRotationBetween(axisW, Vec3d.of(PortalHelper.getAxisW(linkedToPortalBlockBox).getVector()))); + outgoingPortal.reloadAndSyncToClient(); + } + } + + @Override + public void linkPortals(LinkedList portalRepresentations) { + for (int i = 0; i < portalRepresentations.size(); i++) { + PortalRepresentation portalRepresentation = portalRepresentations.get(i); + PortalRepresentation linkedToPortalRepresentation = i + 1 < portalRepresentations.size() ? portalRepresentations.get(i + 1) : portalRepresentations.getFirst(); + + assureLinked(portalRepresentation, linkedToPortalRepresentation); + } + } + + @Override + public void unLinkPortal(PortalRepresentation portalRepresentation) { + List portals = getPortalList(portalRepresentation); + portals.forEach(portalEntity -> PortalAPI.removeGlobalPortal(getPortalWorld(portalRepresentation), portalEntity)); + } + + @Override + public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) { + //no-op, handled by immptl + } + + @Override + public boolean needsReInit() { + return false; + } + + private List getPortalList(PortalRepresentation portalRepresentation) { + Box portalBox = Box.from(portalRepresentation.location()); + return getPortalWorld(portalRepresentation) + .getEntitiesByType(TypeFilter.instanceOf(qouteall.imm_ptl.core.portal.Portal.class), portalBox, e -> e.isAlive() && contains(portalBox, e.getBoundingBox())); + } + + private boolean contains(Box outside, Box inside) { + return outside.contains(inside.getMaxPos()) && outside.contains(inside.getMinPos()); + } + + private ServerWorld getPortalWorld(PortalRepresentation fromPortalRepresentation) { + ServerWorld serverWorld = server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortalRepresentation.dimensionId())); + if (serverWorld == null) { + LOGGER.warn("couldn't get portal dimensionId for portal {}. Don't sue me!", fromPortalRepresentation); + throw new RuntimeException(); + } + return serverWorld; + } +} diff --git a/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystem.java b/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystem.java new file mode 100644 index 0000000..a55643e --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystem.java @@ -0,0 +1,22 @@ +package quimufu.colourful_portals.portal; + +import net.minecraft.entity.Entity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import quimufu.colourful_portals.general_util.LinkedList; + +import java.util.List; + +public interface PortalLinkingSystem { + Identifier getLinkingSystemId(); + + void linkPortals(LinkedList portalRepresentations); + + void unLinkPortal(PortalRepresentation portalRepresentation); + + void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a); + + boolean needsReInit(); +} diff --git a/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystemBuilder.java b/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystemBuilder.java new file mode 100644 index 0000000..2fc0fb9 --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/PortalLinkingSystemBuilder.java @@ -0,0 +1,8 @@ +package quimufu.colourful_portals.portal; + +import net.minecraft.server.MinecraftServer; +@FunctionalInterface +public interface PortalLinkingSystemBuilder { + + PortalLinkingSystem build(MinecraftServer minecraftServer); +} diff --git a/src/main/java/quimufu/colourful_portals/portal/PortalListComponent.java b/src/main/java/quimufu/colourful_portals/portal/PortalListComponent.java index 66828f3..c92fdf2 100644 --- a/src/main/java/quimufu/colourful_portals/portal/PortalListComponent.java +++ b/src/main/java/quimufu/colourful_portals/portal/PortalListComponent.java @@ -1,67 +1,113 @@ package quimufu.colourful_portals.portal; -import dev.onyxstudios.cca.api.v3.component.Component; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtHelper; import net.minecraft.nbt.NbtList; +import net.minecraft.registry.RegistryWrapper; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldProperties; -import quimufu.colourful_portals.util.Pair; +import org.ladysnake.cca.api.v3.component.Component; +import quimufu.colourful_portals.general_util.LinkedList; +import quimufu.colourful_portals.general_util.Node; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; -import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; +import static quimufu.colourful_portals.ColourfulPortalsMod.*; public class PortalListComponent implements Component { + public static final int CURRENT_VERSION = 1; private final WorldProperties worldProperties; - HashMap>> portalsPerPortalBlock = new HashMap<>(); + HashMap> portalsPerPortalBlock = new HashMap<>(); + + Identifier lastPortalLinkingSystem = Identifier.of(MOD_ID, "immersive_portals_linking_system"); public PortalListComponent(WorldProperties worldProperties) { this.worldProperties = worldProperties; } @Override - public void readFromNbt(NbtCompound tag) { + public void readFromNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { if (tag != null && !tag.isEmpty()) { - for (String block : tag.getKeys()) { - NbtList portalsWithDim = tag.getList(block, NbtElement.COMPOUND_TYPE); - ArrayList> portals = new ArrayList<>(); + if (!tag.contains("version")) { + readFromOldNbt(tag); + } + if (tag.getInt("version") > CURRENT_VERSION) { + LOGGER.warn("portals component comes from a newer version! Hopefully backwards compatible. Proceeding"); + } + if (tag.contains("linking_system")) { + lastPortalLinkingSystem = Identifier.tryParse(tag.getString("version")); + } + NbtCompound blocks = tag.getCompound("blocks"); + for (String block : blocks.getKeys()) { + NbtList portalsWithDim = blocks.getList(block, NbtElement.COMPOUND_TYPE); + LinkedList portalRepresentations = new LinkedList<>(); for (int i = 0; i < portalsWithDim.size(); i++) { NbtCompound portalWithDim = portalsWithDim.getCompound(i); NbtCompound portalCompound = portalWithDim.getCompound("portal"); - BlockBox portal = BlockBox.create(NbtHelper.toBlockPos(portalCompound.getCompound("from")), - NbtHelper.toBlockPos(portalCompound.getCompound("to"))); + BlockBox portal = BlockBox.create(NbtHelper.toBlockPos(portalCompound, "from").orElseThrow(), + NbtHelper.toBlockPos(portalCompound, "to").orElseThrow()); Identifier dimension = Identifier.tryParse(portalWithDim.getString("dim")); - portals.add(Pair.of(portal, dimension)); + portalRepresentations.add(new PortalRepresentation(portal, dimension)); } - portalsPerPortalBlock.put(Identifier.tryParse(block), portals); + portalsPerPortalBlock.put(Identifier.tryParse(block), portalRepresentations); + } } } + private void readFromOldNbt(NbtCompound tag) { + for (String block : tag.getKeys()) { + NbtList portalsWithDim = tag.getList(block, NbtElement.COMPOUND_TYPE); + LinkedList portalRepresentations = new LinkedList<>(); + for (int i = 0; i < portalsWithDim.size(); i++) { + NbtCompound portalWithDim = portalsWithDim.getCompound(i); + + NbtCompound portalCompound = portalWithDim.getCompound("portal"); + BlockBox portal = BlockBox.create(toBlockPosOld(portalCompound.getCompound("from")), + toBlockPosOld(portalCompound.getCompound("to"))); + + Identifier dimension = Identifier.tryParse(portalWithDim.getString("dim")); + + portalRepresentations.add(new PortalRepresentation(portal, dimension)); + } + portalsPerPortalBlock.put(Identifier.tryParse(block), portalRepresentations); + } + } + + public static BlockPos toBlockPosOld(NbtCompound nbt) { + return new BlockPos(nbt.getInt("X"), nbt.getInt("Y"), nbt.getInt("Z")); + } + @Override - public void writeToNbt(NbtCompound tag) { + public void writeToNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) { + LOGGER.debug("save"); + if(PORTAL_MANAGER == null) { + return; + } + tag.putInt("version", CURRENT_VERSION); + tag.putString("linking_system", PORTAL_MANAGER.getLinkingSystem().getLinkingSystemId().toString()); + NbtCompound blocks = new NbtCompound(); + tag.put("blocks", blocks); for (Identifier portalBlockId : portalsPerPortalBlock.keySet()) { NbtList portalsWithDimList = new NbtList(); - tag.put(portalBlockId.toString(), portalsWithDimList); - for (Pair portalWithDim : portalsPerPortalBlock.get(portalBlockId)) { + blocks.put(portalBlockId.toString(), portalsWithDimList); + for (PortalRepresentation portalRepresentationWithDim : portalsPerPortalBlock.get(portalBlockId)) { NbtCompound portalWithDimCompound = new NbtCompound(); portalsWithDimList.add(portalWithDimCompound); NbtCompound portalCompound = new NbtCompound(); portalWithDimCompound.put("portal", portalCompound); - portalWithDimCompound.putString("dim", portalWithDim.second.toString()); + portalWithDimCompound.putString("dim", portalRepresentationWithDim.dimensionId().toString()); - BlockBox portal = portalWithDim.first; + BlockBox portal = portalRepresentationWithDim.location(); BlockPos from = new BlockPos(portal.getMinX(), portal.getMinY(), portal.getMinZ()); BlockPos to = new BlockPos(portal.getMaxX(), portal.getMaxY(), portal.getMaxZ()); @@ -70,59 +116,58 @@ public class PortalListComponent implements Component { } } - LOGGER.debug("portals {}", tag.toString()); + LOGGER.info("portals {}", tag); } - public List getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) { - return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()).stream() - .filter((portalWithDim) -> (portalWithDim.second.equals(dim) - && portalWithDim.first.contains(pos))) - .map((p) -> p.first) + public List getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) { + return getPortals(blockId).stream() + .filter((portal) -> (portal.dimensionId().equals(dim) && portal.location().contains(pos))) .toList(); } - public void createPortal(Identifier blockId, Pair portalWithDim) { - List> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); - if (!portals.contains(portalWithDim)) { - portals.add(portalWithDim); + public void createPortal(Identifier blockId, PortalRepresentation portal) { + LinkedList portalRepresentations = getPortals(blockId); + if (!portalRepresentations.contains(portal)) { + portalRepresentations.add(portal); } } - public void removePortal(Identifier blockId, Pair portalWithDim) { - List> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); - portals.remove(portalWithDim); + public void removePortal(Identifier blockId, PortalRepresentation portal) { + getPortals(blockId).remove(portal); } - public List> getPortals(Identifier blockId) { - return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); + public LinkedList getPortals(Identifier blockId) { + return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new LinkedList<>()); } - public Set getBlockIds() { return portalsPerPortalBlock.keySet(); } - public Pair getNext(Identifier blockId, BlockBox portal, Identifier dim) { - List> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); - Pair portalWithDim = Pair.of(portal, dim); + public PortalRepresentation getNext(Identifier blockId, PortalRepresentation portalRepresentationWithDim) { + LOGGER.info("gn"); + LinkedList portals = getPortals(blockId); + Node node; + if ((node = portals.getNodeOf(portalRepresentationWithDim)) == null) { - int nextIndex = portals.indexOf(portalWithDim) + 1; - if (nextIndex >= portals.size()) { - return portals.get(0); + return portals.getFirst(); } - - return portals.get(nextIndex); + PortalRepresentation portalRepresentation = node.getNext() == null ? portals.getFirst() : node.getNext().getValue(); + LOGGER.info("gne"); + return portalRepresentation; } - public boolean containsPortal(Identifier blockId, Pair portal) { - List> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); - return portals.contains(portal); + public boolean containsPortal(Identifier blockId, PortalRepresentation portalRepresentation) { + return getPortals(blockId).contains(portalRepresentation); } - public Pair getLast(Identifier blockId) { - List> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()); - return portals.get(portals.size()-1); + public PortalRepresentation getLast(Identifier blockId) { + return getPortals(blockId).getLast(); + } + + public Identifier lastPortalLinkingSystemId() { + return lastPortalLinkingSystem; } } diff --git a/src/main/java/quimufu/colourful_portals/portal/PortalManager.java b/src/main/java/quimufu/colourful_portals/portal/PortalManager.java index 698b906..c42cfcd 100644 --- a/src/main/java/quimufu/colourful_portals/portal/PortalManager.java +++ b/src/main/java/quimufu/colourful_portals/portal/PortalManager.java @@ -9,41 +9,50 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.DyeColor; import net.minecraft.util.Identifier; -import net.minecraft.util.TypeFilter; -import net.minecraft.util.math.*; -import net.minecraft.world.World; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import org.jetbrains.annotations.Nullable; -import qouteall.imm_ptl.core.api.PortalAPI; -import qouteall.imm_ptl.core.portal.Portal; -import qouteall.q_misc_util.my_util.DQuaternion; import quimufu.colourful_portals.config.ColourfulPortalConfig; -import quimufu.colourful_portals.util.Pair; +import quimufu.colourful_portals.general_util.LinkedList; -import java.util.ArrayList; import java.util.List; import java.util.Set; import static quimufu.colourful_portals.ColourfulPortalsMod.*; import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST; -import static quimufu.colourful_portals.Components.PORTAL_LIST; public class PortalManager { - public static void onPortalBlockPlaced(ServerWorld world, BlockPos pos, Identifier blockId) { + private final PortalListComponent portalCandidateList; + private final PortalListComponent portalList; + + public PortalLinkingSystem getLinkingSystem() { + return linkingSystem; + } + + private final PortalLinkingSystem linkingSystem; + + public PortalManager(PortalLinkingSystem portalLinkingSystem, PortalListComponent portalCandidateList, PortalListComponent portalList) { + this.portalCandidateList = portalCandidateList; + this.portalList = portalList; + this.linkingSystem = portalLinkingSystem; + } + + public void onPortalBlockPlaced(ServerWorld world, BlockPos pos, Identifier blockId) { world.getProfiler().push("onPortalBlockPlaced"); LOGGER.debug("onPortalBlockPlaced, {}", blockId); - PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); - //delete portalCandidates obstructed by PortalBlocks for consistency - List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue()); - LOGGER.debug("got containing PortalCandidates , {}", portalCandidates); - for (BlockBox portalCandidate : portalCandidates) { - if (!PortalHelper.isValidCandidate(world, portalCandidate, blockId)) { - LOGGER.debug("invalid, {}", portalCandidate); - Pair portalWithDim = - Pair.of(portalCandidate, world.getDimensionKey().getValue()); + Identifier dimIdentifier = getDimId(world); - portalCandidateList.removePortal(blockId, portalWithDim); + //delete portalCandidates obstructed by PortalBlocks for consistency + List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dimIdentifier); + LOGGER.debug("got containing PortalCandidates , {}", portalCandidates); + for (PortalRepresentation portalCandidate : portalCandidates) { + if (!PortalHelper.isValidCandidate(world, portalCandidate.location(), blockId)) { + LOGGER.debug("invalid, {}", portalCandidate); + + portalCandidateList.removePortal(blockId, portalCandidate); } } //find new portalCandidates created by PortalBlock placement @@ -51,28 +60,26 @@ public class PortalManager { LOGGER.debug("new portalCandidates found, {}", portals); for (BlockBox portal : portals) { - Pair portalWithDim = Pair.of(portal, world.getDimensionKey().getValue()); - portalCandidateList.createPortal(blockId, portalWithDim); + PortalRepresentation portalRepresentationWithDim = new PortalRepresentation(portal, dimIdentifier); + portalCandidateList.createPortal(blockId, portalRepresentationWithDim); } world.getProfiler().pop(); } - public static void onPortalBlockBroken(ServerWorld world, BlockPos pos, Identifier blockId) { + public void onPortalBlockBroken(ServerWorld world, BlockPos pos, Identifier blockId) { world.getProfiler().push("onPortalBlockBroken"); LOGGER.debug("onPortalBlockBroken, {}", blockId); - PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties()); PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); //check portalCandidate validity - List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue()); + Identifier dimensionIdentifier = getDimId(world); + List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dimensionIdentifier); LOGGER.debug("getContainingPortals, {}", portalCandidates); - for (BlockBox portalCandidate : portalCandidates) { - if (!PortalHelper.isValidCandidate(world, portalCandidate, blockId)) { + for (PortalRepresentation portalCandidate : portalCandidates) { + if (!PortalHelper.isValidCandidate(world, portalCandidate.location(), blockId)) { LOGGER.debug("invalid, {}", portalCandidate); - Pair portalWithDim = - Pair.of(portalCandidate, world.getDimensionKey().getValue()); - portalCandidateList.removePortal(blockId, portalWithDim); + portalCandidateList.removePortal(blockId, portalCandidate); } } @@ -84,25 +91,23 @@ public class PortalManager { LOGGER.debug("potentially new candidate after deobstruction , {}", newPortal); PortalListComponent portalListComponent = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); - Pair portalWithDim = - Pair.of(newPortal, world.getDimensionKey().getValue()); - portalListComponent.createPortal(blockId, portalWithDim); + PortalRepresentation portalRepresentationWithDim = + new PortalRepresentation(newPortal, dimensionIdentifier); + portalListComponent.createPortal(blockId, portalRepresentationWithDim); } } //check portal validity - List portals = portalList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue()); + List portals = portalList.getContainingPortals(blockId, pos, dimensionIdentifier); boolean changed = false; - for (BlockBox portal : portals) { - if (!PortalHelper.isValidPortal(world, portal, blockId)) { - LOGGER.debug("portal became invalid ,{} {}", world.getDimensionKey().getValue(), portal); + for (PortalRepresentation portal : portals) { + if (!PortalHelper.isValidPortal(world, portal.location(), blockId)) { + LOGGER.debug("portal became invalid ,{} {}", dimensionIdentifier, portal); - Pair portalWithDim = - Pair.of(portal, world.getDimensionKey().getValue()); - portalList.removePortal(blockId, portalWithDim); - destroyPortalEntitiesInside(world, Box.from(portal)); - removePortalBlocks(world, portal); + portalList.removePortal(blockId, portal); + linkingSystem.unLinkPortal(portal); + removePortalBlocks(world, portal.location()); changed = true; } @@ -114,55 +119,53 @@ public class PortalManager { world.getProfiler().pop(); } - private static void removePortalBlocks(ServerWorld world, BlockBox portal) { + private void removePortalBlocks(ServerWorld world, BlockBox portal) { BlockPos.stream(portal) .filter(blockPos -> world.getBlockState(blockPos).isOf(PORTAL_BLOCK)) .forEach(blockPos -> world.setBlockState(blockPos, Blocks.AIR.getDefaultState())); } - private static void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) { - List> portalsWithDim = portalList.getPortals(blockId); + private void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) { + LinkedList portalsWithDim = portalList.getPortals(blockId); if (portalsWithDim.size() == 1) { - Pair portal = portalsWithDim.get(0); - ServerWorld world = getPortalWorld(portal, server); + PortalRepresentation portalRepresentation = portalsWithDim.getFirst(); + ServerWorld world = getPortalWorld(portalRepresentation, server); if (world == null) { - LOGGER.error("error fixing portalGroup, world {} was null", portal.second); + LOGGER.error("error fixing portalGroup, dimensionId {} was null", portalRepresentation.dimensionId()); return; } - Pair portalWithDim = Pair.of(portal.first, portal.second); - portalList.removePortal(blockId, portalWithDim); - destroyPortalEntitiesInside(world, Box.from(portal.first)); - removePortalBlocks(world, portal.first); + portalList.removePortal(blockId, portalRepresentation); + linkingSystem.unLinkPortal(portalRepresentation); + removePortalBlocks(world, portalRepresentation.location()); return; } - for (int i = 0; i < portalsWithDim.size(); i++) { - Pair portal = portalsWithDim.get(i); - Pair linkedToPortal = i + 1 < portalsWithDim.size() ? portalsWithDim.get(i + 1) : portalsWithDim.get(0); - assureLinkedTo(portal, linkedToPortal, server); - assurePortalBlocksPlaced(blockId, portal, server); + for (PortalRepresentation portalRepresentation : portalsWithDim) { + assurePortalBlocksPlaced(blockId, portalRepresentation, server); } + linkingSystem.linkPortals(portalsWithDim); + } - private static void assurePortalBlocksPlaced(Identifier blockId, Pair portal, MinecraftServer server) { - DyeColor color = ColourfulPortalConfig.portalBlocks.get(blockId.toString()); + private void assurePortalBlocksPlaced(Identifier blockId, PortalRepresentation portalRepresentation, MinecraftServer server) { + DyeColor color = ColourfulPortalConfig.colorOf(blockId.toString()); if (color != null) { - Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portal.first) + Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portalRepresentation.location()) .rotateClockwise(Direction.Axis.Y) .getAxis(); - ServerWorld portalWorld = getPortalWorld(portal, server); + ServerWorld portalWorld = getPortalWorld(portalRepresentation, server); if (portalWorld == null) { - LOGGER.error("error placing portal planes, world {} was null", portal.second); + LOGGER.error("error placing portalRepresentation planes, dimensionId {} was null", portalRepresentation.dimensionId()); return; } BlockState portalBlockState = PORTAL_BLOCK.getStateWith(color, portalPlaneAxis); - PortalHelper.insideOf(portal.first) + PortalHelper.insideOf(portalRepresentation.location()) .forEachRemaining(blockPos -> { BlockState blockState = portalWorld.getBlockState(blockPos); if (blockState.isAir() || blockState.getFluidState().isOf(PORTAL_FLUID)) { portalWorld.setBlockState(blockPos, portalBlockState); } else if (blockState.isReplaceable()) { - portalWorld.breakBlock(blockPos,true); + portalWorld.breakBlock(blockPos, true); portalWorld.setBlockState(blockPos, portalBlockState); } }); @@ -170,99 +173,27 @@ public class PortalManager { } - private static void assureLinkedTo(Pair fromPortal, Pair linkedToPortal, MinecraftServer server) { - - ServerWorld fromPortalWorld = getPortalWorld(fromPortal, server); - RegistryKey linkedToPortalWorldRegKey = RegistryKey.of(RegistryKeys.WORLD, linkedToPortal.second); - - BlockBox fromPortalBlockBox = fromPortal.first; - Box fromPortalBox = Box.from(fromPortalBlockBox); - BlockBox linkedToPortalBlockBox = linkedToPortal.first; - Box linkedToPortalBox = Box.from(linkedToPortalBlockBox); - if (fromPortalWorld == null) { - LOGGER.error("error linking portals, world {} was null", fromPortalBlockBox); - return; - } - - List portals = fromPortalWorld.getEntitiesByType(TypeFilter.instanceOf(Portal.class), fromPortalBox, Entity::isAlive); - List outgoingPortals = new ArrayList<>(); - for (Portal portal : portals) { - Box portalBoundingBox = portal.getBoundingBox(); - //is portal actually inside portalBox? - if (fromPortalBox.contains(portalBoundingBox.minX, portalBoundingBox.minY, portalBoundingBox.minZ) - && fromPortalBox.contains(portalBoundingBox.maxX, portalBoundingBox.maxY, portalBoundingBox.maxZ)) { - outgoingPortals.add(portal); - } - } - if (outgoingPortals.size() > 2) { - LOGGER.warn("Found more then 2 portals in {}, cleaning up", fromPortalBox); - for (int i = 2; i < outgoingPortals.size(); i++) { - Portal outgoingPortal = outgoingPortals.get(i); - outgoingPortal.kill(); - } - } - if (outgoingPortals.isEmpty()) { - Portal portal = Portal.ENTITY_TYPE.create(fromPortalWorld); - if (portal == null) { - LOGGER.error("could not create Portal entity for {}", fromPortal); - return; - } - - portal.setOriginPos(fromPortalBox.getCenter()); - portal.setDestinationDimension(linkedToPortalWorldRegKey); - portal.setDestination(linkedToPortalBox.getCenter()); - Vec3d axisW = Vec3d.of(PortalHelper.getAxisW(fromPortalBlockBox).getVector()); - portal.setOrientationAndSize( - axisW, // axisW - new Vec3d(0, 1, 0), // axisH - 2, // width - 3 // height - ); - portal.setRotationTransformation(DQuaternion.getRotationBetween(axisW, Vec3d.of(PortalHelper.getAxisW(linkedToPortalBlockBox).getVector()))); - outgoingPortals.add(portal); - PortalAPI.spawnServerEntity(portal); - } - if (outgoingPortals.size() == 1) { - Portal portal = PortalAPI.createFlippedPortal(outgoingPortals.get(0)); - outgoingPortals.add(portal); - PortalAPI.spawnServerEntity(portal); - } - for (Portal outgoingPortal : outgoingPortals) { - outgoingPortal.setDestinationDimension(linkedToPortalWorldRegKey); - outgoingPortal.setDestination(linkedToPortalBox.getCenter()); - Vec3d axisW = Vec3d.of(PortalHelper.getAxisW(fromPortalBlockBox).getVector()); - outgoingPortal.setRotationTransformation(DQuaternion.getRotationBetween(axisW, Vec3d.of(PortalHelper.getAxisW(linkedToPortalBlockBox).getVector()))); - outgoingPortal.reloadAndSyncToClient(); - } - } @Nullable - private static ServerWorld getPortalWorld(Pair fromPortal, MinecraftServer server) { - return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortal.second)); + private ServerWorld getPortalWorld(PortalRepresentation fromPortalRepresentation, MinecraftServer server) { + return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortalRepresentation.dimensionId())); } - private static void destroyPortalEntitiesInside(ServerWorld world, Box box) { - List portals = world.getEntitiesByType(TypeFilter.instanceOf(Portal.class), box, Entity::isAlive); - portals.forEach(portal -> PortalAPI.removeGlobalPortal(world, portal)); - } - - public static boolean tryIgnite(ServerWorld world, BlockPos pos) { + public boolean tryIgnite(ServerWorld world, BlockPos pos) { world.getProfiler().push("portal ignition"); - PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); - PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties()); + LOGGER.info("portal ignition"); Set blockIds = portalCandidateList.getBlockIds(); boolean ret = false; for (Identifier blockId : blockIds) { - Identifier dim = world.getDimensionKey().getValue(); - List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim); - for (BlockBox portalCandidate : portalCandidates) { - if (PortalHelper.isValidPortal(world, portalCandidate, blockId)) { - Pair current = Pair.of(portalCandidate, dim); - Pair next = portalCandidateList.getNext(blockId, portalCandidate, dim); - ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second)); + Identifier dim = getDimId(world); + List portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim); + for (PortalRepresentation current : portalCandidates) { + if (PortalHelper.isValidPortal(world, current.location(), blockId)) { + PortalRepresentation next = portalCandidateList.getNext(blockId, current); + ServerWorld nextWorld = getPortalWorld(next, world.getServer()); if (!next.equals(current) - && (!portalList.containsPortal(blockId, current) || !portalList.containsPortal(blockId, next)) - && PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)) { + && (!portalList.containsPortal(blockId, current) || !portalList.containsPortal(blockId, next)) + && PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) { portalList.createPortal(blockId, current); portalList.createPortal(blockId, next); ret = true; @@ -275,24 +206,21 @@ public class PortalManager { return ret; } - public static boolean canExtend(ServerWorld world, BlockPos pos) { + public boolean canExtend(ServerWorld world, BlockPos pos) { world.getProfiler().push("portal extension check"); - PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); - PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties()); Set blockIds = portalList.getBlockIds(); - Identifier dim = world.getDimensionKey().getValue(); + Identifier dim = getDimId(world); for (Identifier blockId : blockIds) { - List portals = portalList.getContainingPortals(blockId, pos, dim); - for (BlockBox portal : portals) { - if (PortalHelper.isValidPortal(world, portal, blockId)) { - Pair last = portalList.getLast(blockId); - Pair next = portalCandidateList.getNext(blockId, last.first, last.second); - ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second)); + List portals = portalList.getContainingPortals(blockId, pos, dim); + for (PortalRepresentation portal : portals) { + if (PortalHelper.isValidPortal(world, portal.location(), blockId)) { + PortalRepresentation last = portalList.getLast(blockId); + PortalRepresentation next = portalCandidateList.getNext(blockId, last); + ServerWorld nextWorld = getPortalWorld(next, world.getServer()); - if(!portalList.containsPortal(blockId, next) - && PortalHelper.isValidPortal(world, portal, blockId) - && PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){ + if (!portalList.containsPortal(blockId, next) + && PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) { world.getProfiler().pop(); return true; } @@ -305,25 +233,22 @@ public class PortalManager { return false; } - public static boolean extend(ServerWorld world, BlockPos pos) { + public boolean extend(ServerWorld world, BlockPos pos) { world.getProfiler().push("portal extension"); - PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties()); - PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties()); Set blockIds = portalList.getBlockIds(); - Identifier dim = world.getDimensionKey().getValue(); + Identifier dim = getDimId(world); boolean ret = false; for (Identifier blockId : blockIds) { - List portals = portalList.getContainingPortals(blockId, pos, dim); - for (BlockBox portal : portals) { - if (PortalHelper.isValidPortal(world, portal, blockId)) { - Pair last = portalList.getLast(blockId); - Pair next = portalCandidateList.getNext(blockId, last.first, last.second); - ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second)); + List portals = portalList.getContainingPortals(blockId, pos, dim); + for (PortalRepresentation portal : portals) { + if (PortalHelper.isValidPortal(world, portal.location(), blockId)) { + PortalRepresentation last = portalList.getLast(blockId); + PortalRepresentation next = portalCandidateList.getNext(blockId, last); + ServerWorld nextWorld = getPortalWorld(next, world.getServer()); - if(!portalList.containsPortal(blockId, next) - && PortalHelper.isValidPortal(world, portal, blockId) - && PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){ + if (!portalList.containsPortal(blockId, next) + && PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) { portalList.createPortal(blockId, next); ret = true; } @@ -336,4 +261,12 @@ public class PortalManager { world.getProfiler().pop(); return ret; } + + public static Identifier getDimId(ServerWorld world) { + return world.getDimensionEntry().getKey().orElseThrow().getValue(); + } + + public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) { + linkingSystem.onPortalPassed(entity, pos, world, a); + } } diff --git a/src/main/java/quimufu/colourful_portals/portal/PortalRepresentation.java b/src/main/java/quimufu/colourful_portals/portal/PortalRepresentation.java new file mode 100644 index 0000000..f42868d --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/PortalRepresentation.java @@ -0,0 +1,9 @@ +package quimufu.colourful_portals.portal; + +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockBox; + +public record PortalRepresentation(BlockBox location, Identifier dimensionId) { + + +} diff --git a/src/main/java/quimufu/colourful_portals/portal/PrioritizedPortalLinkingSystemBuilder.java b/src/main/java/quimufu/colourful_portals/portal/PrioritizedPortalLinkingSystemBuilder.java new file mode 100644 index 0000000..06a60bf --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/portal/PrioritizedPortalLinkingSystemBuilder.java @@ -0,0 +1,4 @@ +package quimufu.colourful_portals.portal; + +public record PrioritizedPortalLinkingSystemBuilder(PortalLinkingSystemBuilder portalLinkingSystemBuilder, + int priority) {} diff --git a/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluid.java b/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluid.java index 04b5bcc..179dad2 100644 --- a/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluid.java +++ b/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluid.java @@ -31,6 +31,7 @@ import quimufu.colourful_portals.portal.PortalManager; import java.util.*; import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER; +import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_MANAGER; public class PortalFluid extends Fluid { public static final EnumProperty AXIS = EnumProperty.of("axis", NullableAxis.class); @@ -138,7 +139,7 @@ public class PortalFluid extends Fluid { } if (amount <= 14) { - //*might* change my state in world, returned value is what new state should be + //*might* change my state in dimensionId, returned value is what new state should be newStateMe = steal(world, pos, newStateMe, currentAxis); } //my state might have changed. @@ -169,7 +170,7 @@ public class PortalFluid extends Fluid { } else if (!world.isClient) { for (Direction direction : Direction.values()) { if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(world.getBlockState(pos.offset(direction)).getBlock())) - && PortalManager.tryIgnite((ServerWorld) world, pos)) { + && PORTAL_MANAGER.tryIgnite((ServerWorld) world, pos)) { return; } } @@ -372,7 +373,7 @@ public class PortalFluid extends Fluid { BlockPos neighborOfInspectedLocation = inspectedLocation.offset(dir); BlockState neighbourOfInspected = world.getBlockState(neighborOfInspectedLocation); - //if adjacent to a Portal Block, 2 less + //if adjacent to a PortalRepresentation Block, 2 less if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(neighbourOfInspected.getBlock()))) { dirCost -= 2; discount = false; @@ -381,7 +382,7 @@ public class PortalFluid extends Fluid { //if adjacent to any solid Block, 1 less if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) { discount = true; - //maybe a Portal Block in another direction + //maybe a PortalRepresentation Block in another direction continue; } } diff --git a/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluidBlock.java b/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluidBlock.java index ad4997f..444f447 100644 --- a/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluidBlock.java +++ b/src/main/java/quimufu/colourful_portals/portal_fluid/PortalFluidBlock.java @@ -108,7 +108,7 @@ public class PortalFluidBlock } @Override - public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { + protected boolean canPathfindThrough(BlockState state, NavigationType type) { return true; } diff --git a/src/main/java/quimufu/colourful_portals/util/CollisionAwareShapeContext.java b/src/main/java/quimufu/colourful_portals/util/CollisionAwareShapeContext.java new file mode 100644 index 0000000..ee02a75 --- /dev/null +++ b/src/main/java/quimufu/colourful_portals/util/CollisionAwareShapeContext.java @@ -0,0 +1,32 @@ +package quimufu.colourful_portals.util; + +import net.minecraft.block.ShapeContext; +import net.minecraft.fluid.FluidState; +import net.minecraft.item.Item; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; + +public class CollisionAwareShapeContext implements ShapeContext { + public CollisionAwareShapeContext() { + } + + @Override + public boolean isDescending() { + return false; + } + + @Override + public boolean isAbove(VoxelShape shape, BlockPos pos, boolean defaultValue) { + return false; + } + + @Override + public boolean isHolding(Item item) { + return false; + } + + @Override + public boolean canWalkOnFluid(FluidState stateAbove, FluidState state) { + return false; + } +} diff --git a/src/main/java/quimufu/colourful_portals/util/Pair.java b/src/main/java/quimufu/colourful_portals/util/Pair.java deleted file mode 100644 index 40e3a6e..0000000 --- a/src/main/java/quimufu/colourful_portals/util/Pair.java +++ /dev/null @@ -1,31 +0,0 @@ -package quimufu.colourful_portals.util; - -import java.util.Objects; - -public class Pair { - - public final A first; - public final B second; - - public Pair(A first, B second) { - this.first = first; - this.second = second; - } - - public static Pair of(A first, B second) { - return new Pair<>(first, second); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Pair pair = (Pair) o; - return Objects.equals(first, pair.first) && Objects.equals(second, pair.second); - } - - @Override - public int hashCode() { - return Objects.hash(first, second); - } -} diff --git a/src/main/resources/assets/colourful_portals/lang/de_de.json b/src/main/resources/assets/colourful_portals/lang/de_de.json index d856975..1af092e 100644 --- a/src/main/resources/assets/colourful_portals/lang/de_de.json +++ b/src/main/resources/assets/colourful_portals/lang/de_de.json @@ -1,7 +1,26 @@ { - "item.colourful_portals.portal_fluid_bucket": "Farbeimer", "block.colourful_portals.portal_block": "Farbenfrohes Portal", + "block.colourful_portals.portal_fluid_block": "Farbenfrohe Flüssigkeit", + "colourful_portals.midnightconfig.black": "Blöcke, die schwarze Portale erzeugen", + "colourful_portals.midnightconfig.blue": "Blöcke, die blaue Portale erzeugen", + "colourful_portals.midnightconfig.brown": "Blöcke, die braune Portale erzeugen", + "colourful_portals.midnightconfig.cyan": "Blöcke, die cyanfarbene Portale erzeugen", + "colourful_portals.midnightconfig.disableImmersivePortals": "Immersive Portals integration deaktivieren", + "colourful_portals.midnightconfig.explanation": "Diese Konfiguration erlaubt es, zusätzliche/andere Portalblocke zu definieren.\nPortale aus diesen verbinden sich mit anderen aus dem selben Block.\nDie Liste, der der Block hinzugefügt wird, bestimmt dabei nur die Portalfarbe.\nÄnderungen treten für neue Portale oder bei Aktualisierung eines Portals in Kraft.", + "colourful_portals.midnightconfig.gray": "Blöcke, die graue Portale erzeugen", + "colourful_portals.midnightconfig.green": "Blöcke, die grüne Portale erstellen", + "colourful_portals.midnightconfig.light_blue": "Blöcke, die hellblaue Portale erzeugen", + "colourful_portals.midnightconfig.light_gray": "Blöcke, die hellgraue Portale erzeugen", + "colourful_portals.midnightconfig.lime": "Blöcke, die limonenfarbene Portale erzeugen", + "colourful_portals.midnightconfig.magenta": "Blöcke, die magentafarbene Portale erzeugen", + "colourful_portals.midnightconfig.none": "Blöcke, die vollständig transparente Portale erstellen", + "colourful_portals.midnightconfig.orange": "Blöcke, die orangefarbene Portale erzeugen", + "colourful_portals.midnightconfig.pink": "Blöcke, die rosa Portale erzeugen", + "colourful_portals.midnightconfig.purple": "Blöcke, die violette Portale erzeugen", + "colourful_portals.midnightconfig.red": "Blöcke, die rote Portale erzeugen", + "colourful_portals.midnightconfig.white": "Blöcke, die weiße Portale erzeugen", + "colourful_portals.midnightconfig.yellow": "Blöcke, die gelbe Portale erzeugen", "item.colourful_portals.colour_blob_bright": "Heller Farbmix", "item.colourful_portals.colour_blob_dark": "Dunkler Farbmix", - "block.colourful_portals.portal_fluid_block": "Farbenfrohe Flüssigkeit" + "item.colourful_portals.portal_fluid_bucket": "Farbeimer" } \ No newline at end of file diff --git a/src/main/resources/assets/colourful_portals/lang/en_us.json b/src/main/resources/assets/colourful_portals/lang/en_us.json index d6c8cc5..11fafb5 100644 --- a/src/main/resources/assets/colourful_portals/lang/en_us.json +++ b/src/main/resources/assets/colourful_portals/lang/en_us.json @@ -1,7 +1,26 @@ { - "item.colourful_portals.portal_fluid_bucket": "Colourful Bucket", + "block.colourful_portals.portal_block": "Colourful Portal", + "block.colourful_portals.portal_fluid_block": "Colourful Fluid", + "colourful_portals.midnightconfig.disableImmersivePortals": "Disable Immersive Portals integration", + "colourful_portals.midnightconfig.black": "Blocks that create black portals", + "colourful_portals.midnightconfig.blue": "Blocks that create blue portals", + "colourful_portals.midnightconfig.brown": "Blocks that create brown portals", + "colourful_portals.midnightconfig.cyan": "Blocks that create cyan portals", + "colourful_portals.midnightconfig.explanation": "This configuration allows you to define additional/other portal blocks.\nPortals from these connect to others from the same block.\nThe list to which the block is added only determines the portal color.\nChanges take effect for new portals or when a portal is updated.", + "colourful_portals.midnightconfig.gray": "Blocks that create gray portals", + "colourful_portals.midnightconfig.green": "Blocks that create green portals", + "colourful_portals.midnightconfig.light_blue": "Blocks that create light blue portals", + "colourful_portals.midnightconfig.light_gray": "Blocks that create light gray portals", + "colourful_portals.midnightconfig.lime": "Blocks that create lime portals", + "colourful_portals.midnightconfig.magenta": "Blocks that create magenta portals", + "colourful_portals.midnightconfig.none": "Blocks that create fully transparent portals", + "colourful_portals.midnightconfig.orange": "Blocks that create orange portals", + "colourful_portals.midnightconfig.pink": "Blocks that create pink portals", + "colourful_portals.midnightconfig.purple": "Blocks that create purple portals", + "colourful_portals.midnightconfig.red": "Blocks that create red portals", + "colourful_portals.midnightconfig.white": "Blocks that create white portals", + "colourful_portals.midnightconfig.yellow": "Blocks that create yellow portals", "item.colourful_portals.colour_blob_bright": "Bright Colour Mix", "item.colourful_portals.colour_blob_dark": "Dark Colour Mix", - "block.colourful_portals.portal_block": "Colourful Portal", - "block.colourful_portals.portal_fluid_block": "Colourful Fluid" + "item.colourful_portals.portal_fluid_bucket": "Colourful Bucket" } \ No newline at end of file diff --git a/src/main/resources/colourful_portals.mixins.json b/src/main/resources/colourful_portals.mixins.json index 29fa1d8..45c228d 100644 --- a/src/main/resources/colourful_portals.mixins.json +++ b/src/main/resources/colourful_portals.mixins.json @@ -3,17 +3,18 @@ "package": "quimufu.colourful_portals.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "BlockChangeMixin" + "BlockChangeMixin", + "EntityMixin" ], "injectors": { "defaultRequire": 1 }, "plugin": "quimufu.colourful_portals.MixinConfig", "client": [ - "AnimationResourceMetadataReaderMixin", "AnimationMixin", "AnimationResourceMetadataMixin", - "SpriteContentsMixin", - "SodiumFluidRendererMixin" + "AnimationResourceMetadataReaderMixin", + "SodiumFluidRendererMixin", + "SpriteContentsMixin" ] } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 73d1ba0..8f867d3 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -42,9 +42,8 @@ ], "depends": { "fabricloader": ">=${loader_version}", - "immersive_portals": ">=${immersive_portals_version_short}", "minecraft": "~${minecraft_version}", - "java": ">=17", + "java": ">=21", "fabric-api": "*" } } \ No newline at end of file