Compare commits
2 Commits
b1cd170c60
...
0d1e607206
Author | SHA1 | Date | |
---|---|---|---|
0d1e607206 | |||
4aa2643a76 |
|
@ -1,3 +1,3 @@
|
||||||
# Colourful Portals Reimagined
|
# Colourful Portals Reimagined
|
||||||
|
|
||||||
A Fabric Minecraft mod adding colourful portals, based on Immersive Portals
|
A Fabric Minecraft mod adding colourful portalRepresentations, based on Immersive Portals
|
39
build.gradle
39
build.gradle
|
@ -1,6 +1,6 @@
|
||||||
plugins {
|
plugins {
|
||||||
id "com.modrinth.minotaur" version "2.+"
|
id "com.modrinth.minotaur" version "2.+"
|
||||||
id 'fabric-loom' version '1.5-SNAPSHOT'
|
id 'fabric-loom' version '1.6-SNAPSHOT'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,22 +54,29 @@ dependencies {
|
||||||
|
|
||||||
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
|
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
|
||||||
|
|
||||||
modImplementation ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}")
|
modCompileOnly ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}")
|
||||||
|
|
||||||
include(modApi("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}"))
|
|
||||||
|
|
||||||
// Replace modImplementation with modApi if you expose components in your own API
|
// 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.:
|
// 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-base-$project.minecraft_version_major"))
|
||||||
include(modApi("de.siphalor.tweed4:tweed4-annotated-$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-$project.minecraft_version_major"))
|
||||||
include(modApi("de.siphalor.tweed4:tweed4-data-hjson-$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-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")
|
modImplementation("me.shedaniel.cloth:cloth-config-fabric:$project.cloth_config_version")
|
||||||
|
|
||||||
|
@ -95,7 +102,7 @@ processResources {
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
it.options.release = 17
|
it.options.release = 21
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
@ -104,8 +111,8 @@ java {
|
||||||
// If you remove this line, sources will not be generated.
|
// If you remove this line, sources will not be generated.
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_21
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_21
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
@ -119,10 +126,10 @@ import com.modrinth.minotaur.dependencies.ModDependency
|
||||||
modrinth {
|
modrinth {
|
||||||
projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work.
|
projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work.
|
||||||
uploadFile = remapJar // Tells Minotaur to use the remapped jar
|
uploadFile = remapJar // Tells Minotaur to use the remapped jar
|
||||||
versionType = "beta"
|
versionType = "alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API
|
new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API
|
||||||
new ModDependency('zJpHMkdD', 'required') //required dependency on Immersive Portals
|
new ModDependency('AANobbMI', 'optional'), //compatible with Sodium
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
|
|
|
@ -4,21 +4,22 @@ org.gradle.parallel=true
|
||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.20.4
|
minecraft_version=1.21
|
||||||
minecraft_version_major=1.20
|
minecraft_version_major=1.21
|
||||||
yarn_mappings=1.20.4+build.3
|
yarn_mappings=1.21+build.2
|
||||||
loader_version=0.15.7
|
loader_version=0.15.11
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=0.9.3.1
|
mod_version=0.9.4
|
||||||
maven_group=quimufu.colourful-portals
|
maven_group=quimufu.colourful-portalRepresentations
|
||||||
archives_base_name=colourful-portals
|
archives_base_name=colourful-portalRepresentations
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.96.11+1.20.4
|
fabric_version=0.100.1+1.21
|
||||||
cardinal_components_version=5.4.0
|
cca_version = 6.1.0
|
||||||
immersive_portals_version_short=5.1.7
|
immersive_portals_version_short=5.1.7
|
||||||
immersive_portals_version=v5.1.7-mc1.20.4
|
immersive_portals_version=v5.1.7-mc1.20.4
|
||||||
tweed_version=1.3.0+mc1.20.2
|
tweed_version=1.3.0+mc1.20.2
|
||||||
sodium_version=mc1.20.4-0.5.8
|
sodium_version=mc1.21-0.5.9
|
||||||
cloth_config_version=13.0.121
|
cloth_config_version=15.0.127
|
||||||
|
midnightlib_version=1.5.7-fabric
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
|
#Sun Jun 16 00:12:45 CEST 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||||
networkTimeout=10000
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
package quimufu.colourful_portals;
|
package quimufu.colourful_portals;
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
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.FabricItemGroupEntries;
|
||||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
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.BlockState;
|
||||||
import net.minecraft.block.enums.Instrument;
|
import net.minecraft.block.enums.NoteBlockInstrument;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.item.*;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.sound.BlockSoundGroup;
|
import net.minecraft.sound.BlockSoundGroup;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.Rarity;
|
import net.minecraft.util.Rarity;
|
||||||
|
@ -19,25 +22,34 @@ import net.minecraft.world.BlockView;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import quimufu.colourful_portals.config.ColourfulPortalConfig;
|
import quimufu.colourful_portals.config.ColourfulPortalConfig;
|
||||||
|
import quimufu.colourful_portals.portal.*;
|
||||||
import quimufu.colourful_portals.portal_fluid.PortalFluid;
|
import quimufu.colourful_portals.portal_fluid.PortalFluid;
|
||||||
import quimufu.colourful_portals.portal_fluid.PortalFluidBlock;
|
import quimufu.colourful_portals.portal_fluid.PortalFluidBlock;
|
||||||
import quimufu.colourful_portals.portal_fluid.PortalFluidBucketItem;
|
import quimufu.colourful_portals.portal_fluid.PortalFluidBucketItem;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
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 class ColourfulPortalsMod implements ModInitializer {
|
||||||
|
|
||||||
public static final String MOD_ID = "colourful_portals";
|
public static final String MOD_ID = "colourful_portals";
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||||
public static final HashSet<Identifier> PORTAL_BLOCKS = new HashSet<>();
|
public static final HashSet<Identifier> 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 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 FabricItemSettings().rarity(Rarity.EPIC));
|
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 FabricItemSettings());
|
public static final Item BLOB_DARK = new Item(new Item.Settings());
|
||||||
public static final Item BLOB_BRIGHT = new Item(new FabricItemSettings());
|
public static final Item BLOB_BRIGHT = new Item(new Item.Settings());
|
||||||
public static final PortalFluid PORTAL_FLUID = new PortalFluid();
|
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 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 FabricItemSettings().recipeRemainder(Items.BUCKET).maxCount(1).rarity(Rarity.RARE));
|
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<Registry<PrioritizedPortalLinkingSystemBuilder>> PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY_KEY = RegistryKey.ofRegistry(Identifier.of(MOD_ID, "portal_linking_system"));
|
||||||
|
public static final Registry<PrioritizedPortalLinkingSystemBuilder> 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) {
|
private static boolean never(BlockState blockState, BlockView blockView, BlockPos blockPos, EntityType<?> entityType) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,23 +62,28 @@ public class ColourfulPortalsMod implements ModInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
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));
|
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.BLOCK, identifier, PORTAL_BLOCK);
|
||||||
Registry.register(Registries.ITEM, identifier, PORTAL_BLOCK_ITEM);
|
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.ITEM, Identifier.of(MOD_ID, "portal_fluid_bucket"), PORTAL_FLUID_BUCKET_ITEM);
|
||||||
Registry.register(Registries.FLUID, new Identifier(MOD_ID, "portal_fluid"), PORTAL_FLUID);
|
Registry.register(Registries.FLUID, Identifier.of(MOD_ID, "portal_fluid"), PORTAL_FLUID);
|
||||||
Registry.register(Registries.BLOCK, new Identifier(MOD_ID, "portal_fluid_block"), PORTAL_FLUID_BLOCk);
|
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, Identifier.of(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_dark"), BLOB_DARK);
|
||||||
|
|
||||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS)
|
ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS)
|
||||||
.register(ColourfulPortalsMod::addToIngredients);
|
.register(ColourfulPortalsMod::addToIngredients);
|
||||||
|
@ -74,9 +91,51 @@ public class ColourfulPortalsMod implements ModInitializer {
|
||||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS)
|
ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS)
|
||||||
.register(ColourfulPortalsMod::addTtTools);
|
.register(ColourfulPortalsMod::addTtTools);
|
||||||
|
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register(this::onServerStarted);
|
||||||
LOGGER.info("Portals Colourful!");
|
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) {
|
private static void addTtTools(FabricItemGroupEntries entries) {
|
||||||
entries.add(PORTAL_FLUID_BUCKET_ITEM);
|
entries.add(PORTAL_FLUID_BUCKET_ITEM);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package quimufu.colourful_portals;
|
package quimufu.colourful_portals;
|
||||||
|
|
||||||
import dev.onyxstudios.cca.api.v3.component.ComponentKey;
|
import org.ladysnake.cca.api.v3.component.ComponentKey;
|
||||||
import dev.onyxstudios.cca.api.v3.component.ComponentRegistry;
|
import org.ladysnake.cca.api.v3.component.ComponentRegistry;
|
||||||
import dev.onyxstudios.cca.api.v3.level.LevelComponentFactoryRegistry;
|
import org.ladysnake.cca.api.v3.level.LevelComponentFactoryRegistry;
|
||||||
import dev.onyxstudios.cca.api.v3.level.LevelComponentInitializer;
|
import org.ladysnake.cca.api.v3.level.LevelComponentInitializer;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import quimufu.colourful_portals.portal.PortalListComponent;
|
import quimufu.colourful_portals.portal.PortalListComponent;
|
||||||
|
|
||||||
public class Components implements LevelComponentInitializer {
|
public class Components implements LevelComponentInitializer {
|
||||||
public static final ComponentKey<PortalListComponent> PORTAL_LIST =
|
public static final ComponentKey<PortalListComponent> 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<PortalListComponent> PORTAL_CANDIDATE_LIST =
|
public static final ComponentKey<PortalListComponent> 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
|
@Override
|
||||||
public void registerLevelComponentFactories(LevelComponentFactoryRegistry registry) {
|
public void registerLevelComponentFactories(LevelComponentFactoryRegistry registry) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.FluidFillable;
|
import net.minecraft.block.FluidFillable;
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.fluid.Fluid;
|
import net.minecraft.fluid.Fluid;
|
||||||
import net.minecraft.fluid.FluidState;
|
import net.minecraft.fluid.FluidState;
|
||||||
|
@ -15,15 +16,16 @@ import net.minecraft.state.property.EnumProperty;
|
||||||
import net.minecraft.state.property.Properties;
|
import net.minecraft.state.property.Properties;
|
||||||
import net.minecraft.util.BlockRotation;
|
import net.minecraft.util.BlockRotation;
|
||||||
import net.minecraft.util.DyeColor;
|
import net.minecraft.util.DyeColor;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.*;
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
import net.minecraft.util.shape.VoxelShape;
|
||||||
import net.minecraft.util.shape.VoxelShapes;
|
import net.minecraft.util.shape.VoxelShapes;
|
||||||
import net.minecraft.world.BlockView;
|
import net.minecraft.world.BlockView;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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 {
|
public class PortalBlock extends Block implements FluidFillable {
|
||||||
|
@ -74,8 +76,58 @@ public class PortalBlock extends Block implements FluidFillable {
|
||||||
return VoxelShapes.empty();
|
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
|
@Override
|
||||||
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||||
|
if (context instanceof CollisionAwareShapeContext) {
|
||||||
|
return getShape(state, world, pos);
|
||||||
|
}
|
||||||
return VoxelShapes.empty();
|
return VoxelShapes.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +179,7 @@ public class PortalBlock extends Block implements FluidFillable {
|
||||||
}
|
}
|
||||||
return fluid == ColourfulPortalsMod.PORTAL_FLUID
|
return fluid == ColourfulPortalsMod.PORTAL_FLUID
|
||||||
&& (world instanceof ServerWorld)
|
&& (world instanceof ServerWorld)
|
||||||
&& PortalManager.canExtend((ServerWorld) world, pos);
|
&& PORTAL_MANAGER.canExtend((ServerWorld) world, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,6 +190,6 @@ public class PortalBlock extends Block implements FluidFillable {
|
||||||
}
|
}
|
||||||
return fluidState.isOf(ColourfulPortalsMod.PORTAL_FLUID)
|
return fluidState.isOf(ColourfulPortalsMod.PORTAL_FLUID)
|
||||||
&& (world instanceof ServerWorld)
|
&& (world instanceof ServerWorld)
|
||||||
&& PortalManager.extend((ServerWorld) world, pos);
|
&& PORTAL_MANAGER.extend((ServerWorld) world, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import quimufu.colourful_portals.ColourfulPortalsMod;
|
||||||
|
|
||||||
@Environment(value = EnvType.CLIENT)
|
@Environment(value = EnvType.CLIENT)
|
||||||
public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPortalFluidRenderer.VertexEater {
|
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 final CommonPortalFluidRenderer commonPortalFluidRenderer = new CommonPortalFluidRenderer();
|
||||||
private Sprite sprite = null;
|
private Sprite sprite = null;
|
||||||
|
@ -82,8 +82,7 @@ public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPorta
|
||||||
.color(1f, 1f, 1f, 1.0f)
|
.color(1f, 1f, 1f, 1.0f)
|
||||||
.texture(v[3], v[4])
|
.texture(v[3], v[4])
|
||||||
.light(16)
|
.light(16)
|
||||||
.normal(0.0f, 1.0f, 0.0f)
|
.normal(0.0f, 1.0f, 0.0f);
|
||||||
.next();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.compile.buffers.ChunkModelBuilder;
|
||||||
import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
|
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.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;
|
||||||
|
import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder.Vertex;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.texture.Sprite;
|
import net.minecraft.client.texture.Sprite;
|
||||||
|
|
|
@ -1,44 +1,131 @@
|
||||||
package quimufu.colourful_portals.config;
|
package quimufu.colourful_portals.config;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import eu.midnightdust.lib.config.MidnightConfig;
|
||||||
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 net.minecraft.util.DyeColor;
|
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)
|
public class ColourfulPortalConfig extends MidnightConfig {
|
||||||
//@ClothData(modid = ColourfulPortalsMod.MOD_ID)
|
|
||||||
public class ColourfulPortalConfig {
|
|
||||||
|
|
||||||
@AConfigEntry(comment =
|
@Comment(category = "text")
|
||||||
"""
|
public static Comment explanation;
|
||||||
Allows you to add additional blocks as portalBlocks,
|
|
||||||
assigning them the color of the portal plane.
|
@Entry(category = "text", name = "Disable Immersive Portals integration")
|
||||||
null causes the portals out of that block to have *no* plane.
|
public static boolean disableImmersivePortals = false;
|
||||||
Changes in the plane color will only apply to new portals,
|
|
||||||
or on portal update.
|
@Entry(category = "text", name = "Blocks that create white portals")
|
||||||
""")
|
public static List<String> white = Lists.newArrayList("minecraft:white_wool");
|
||||||
public static Map<String, DyeColor> portalBlocks = ImmutableMap.ofEntries(
|
|
||||||
Map.entry("minecraft:white_wool", DyeColor.WHITE),
|
@Entry(category = "text", name = "Blocks that create orange portals")
|
||||||
Map.entry("minecraft:orange_wool", DyeColor.ORANGE),
|
public static List<String> orange = Lists.newArrayList("minecraft:orange_wool");
|
||||||
Map.entry("minecraft:magenta_wool", DyeColor.MAGENTA),
|
|
||||||
Map.entry("minecraft:light_blue_wool", DyeColor.LIGHT_BLUE),
|
@Entry(category = "text", name = "Blocks that create magenta portals")
|
||||||
Map.entry("minecraft:yellow_wool", DyeColor.YELLOW),
|
public static List<String> magenta = Lists.newArrayList("minecraft:magenta_wool");
|
||||||
Map.entry("minecraft:lime_wool", DyeColor.LIME),
|
|
||||||
Map.entry("minecraft:pink_wool", DyeColor.PINK),
|
@Entry(category = "text", name = "Blocks that create light blue portals")
|
||||||
Map.entry("minecraft:gray_wool", DyeColor.GRAY),
|
public static List<String> light_blue = Lists.newArrayList("minecraft:light_blue_wool");
|
||||||
Map.entry("minecraft:light_gray_wool", DyeColor.LIGHT_GRAY),
|
|
||||||
Map.entry("minecraft:cyan_wool", DyeColor.CYAN),
|
@Entry(category = "text", name = "Blocks that create yellow portals")
|
||||||
Map.entry("minecraft:purple_wool", DyeColor.PURPLE),
|
public static List<String> yellow = Lists.newArrayList("minecraft:yellow_wool");
|
||||||
Map.entry("minecraft:blue_wool", DyeColor.BLUE),
|
|
||||||
Map.entry("minecraft:brown_wool", DyeColor.BROWN),
|
@Entry(category = "text", name = "Blocks that create lime portals")
|
||||||
Map.entry("minecraft:green_wool", DyeColor.GREEN),
|
public static List<String> lime = Lists.newArrayList("minecraft:lime_wool");
|
||||||
Map.entry("minecraft:red_wool", DyeColor.RED),
|
|
||||||
Map.entry("minecraft:black_wool", DyeColor.BLACK));
|
@Entry(category = "text", name = "Blocks that create pink portals")
|
||||||
|
public static List<String> pink = Lists.newArrayList("minecraft:pink_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create gray portals")
|
||||||
|
public static List<String> gray = Lists.newArrayList("minecraft:gray_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create light gray portals")
|
||||||
|
public static List<String> light_gray = Lists.newArrayList("minecraft:light_gray_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create cyan portals")
|
||||||
|
public static List<String> cyan = Lists.newArrayList("minecraft:cyan_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create purple portals")
|
||||||
|
public static List<String> purple = Lists.newArrayList("minecraft:purple_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create blue portals")
|
||||||
|
public static List<String> blue = Lists.newArrayList("minecraft:blue_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create brown portals")
|
||||||
|
public static List<String> brown = Lists.newArrayList("minecraft:brown_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create green portals")
|
||||||
|
public static List<String> green = Lists.newArrayList("minecraft:green_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create red portals")
|
||||||
|
public static List<String> red = Lists.newArrayList("minecraft:red_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create black portals")
|
||||||
|
public static List<String> black = Lists.newArrayList("minecraft:black_wool");
|
||||||
|
|
||||||
|
@Entry(category = "text", name = "Blocks that create fully transparent portals")
|
||||||
|
public static List<String> none = Lists.newArrayList();
|
||||||
|
|
||||||
|
public static Set<String> getAllPortalBlocks() {
|
||||||
|
Set<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<E> implements List<E> {
|
||||||
|
|
||||||
|
Node<E> headNode = null;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return indexOf(o) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
Node<E> 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<E> iterator() {
|
||||||
|
return new LLIterator<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Object[] toArray() {
|
||||||
|
Object[] objects = new Object[size()];
|
||||||
|
Node<E> node = headNode;
|
||||||
|
int index = 0;
|
||||||
|
while (node != null) {
|
||||||
|
objects[index] = node.getValue();
|
||||||
|
node = node.getNext();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> 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<E> 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<E> node = getLastNode(headNode);
|
||||||
|
node.insertAfter(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull Node<E> getLastNode(@NotNull Node<E> start) {
|
||||||
|
Node<E> 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<? extends E> c) {
|
||||||
|
if (headNode == null) {
|
||||||
|
headNode = new Node<>(null, this);
|
||||||
|
Node<E> startNode = new Node<>(null, this);
|
||||||
|
Node<E> currNode = startNode;
|
||||||
|
for (E o : c) {
|
||||||
|
currNode.insertAfter(o);
|
||||||
|
currNode = currNode.getNext();
|
||||||
|
}
|
||||||
|
startNode.remove();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Node<E> currNode = getLastNode(headNode);
|
||||||
|
for (E o : c) {
|
||||||
|
currNode.insertAfter(o);
|
||||||
|
currNode = currNode.getNext();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(int index, @NotNull Collection<? extends E> c) {
|
||||||
|
if (c.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Node<E> 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<E> 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<E> 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<E> 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<E> getNode(int index) {
|
||||||
|
Node<E> 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<E> node = getNode(index);
|
||||||
|
node.remove();
|
||||||
|
return node.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int indexOf(Object o) {
|
||||||
|
int index = 0;
|
||||||
|
Node<E> 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<E> node = headNode;
|
||||||
|
while (node != null) {
|
||||||
|
if (Objects.equals(node.getValue(), o)) {
|
||||||
|
ret = index;
|
||||||
|
}
|
||||||
|
node = node.getNext();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ListIterator<E> listIterator() {
|
||||||
|
|
||||||
|
return new LLLIterator<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ListIterator<E> listIterator(int index) {
|
||||||
|
LLLIterator<E> iterator = new LLLIterator<>(this);
|
||||||
|
iterator.nextNode = getNode(index);
|
||||||
|
iterator.previousNode = iterator.nextNode.getPrevious();
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<E> subList(int fromIndex, int toIndex) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Node<E> getNodeOf(E content) {
|
||||||
|
Node<E> node = headNode;
|
||||||
|
while (node != null) {
|
||||||
|
if (Objects.equals(node.getValue(), content)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
node = node.getNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LLIterator<E> implements Iterator<E> {
|
||||||
|
|
||||||
|
private Node<E> nextNode;
|
||||||
|
|
||||||
|
public LLIterator(LinkedList<E> 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<E> implements ListIterator<E> {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Node<E> nextNode;
|
||||||
|
@Nullable
|
||||||
|
private Node<E> previousNode;
|
||||||
|
private boolean lastNext = true;
|
||||||
|
|
||||||
|
private final LinkedList<E> linkedList;
|
||||||
|
|
||||||
|
public LLLIterator(LinkedList<E> 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<E> needle) {
|
||||||
|
int index = 0;
|
||||||
|
Node<E> node = headNode;
|
||||||
|
while (node != null) {
|
||||||
|
if (node == needle) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
node = node.getNext();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package quimufu.colourful_portals.general_util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class Node<E> {
|
||||||
|
|
||||||
|
private Node<E> next = null;
|
||||||
|
private Node<E> previous = null;
|
||||||
|
private E value;
|
||||||
|
|
||||||
|
public LinkedList<E> getPartOf() {
|
||||||
|
return partOf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LinkedList<E> partOf;
|
||||||
|
private boolean orphaned = false;
|
||||||
|
|
||||||
|
protected Node(E value, LinkedList<E> partOf) {
|
||||||
|
this.value = value;
|
||||||
|
this.partOf = partOf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node<E> getNext() {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNext(@Nullable Node<E> 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<E> getPrevious() {
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrevious(@Nullable Node<E> 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<E> newNode = new Node<>(element, partOf);
|
||||||
|
newNode.setPrevious(this.previous);
|
||||||
|
newNode.setNext(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertAfter(E element) {
|
||||||
|
Node<E> newNode = new Node<>(element, partOf);
|
||||||
|
newNode.setNext(this.next);
|
||||||
|
newNode.setPrevious(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean orphaned() {
|
||||||
|
return orphaned;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ import quimufu.colourful_portals.client.AlphaInterpolationHolder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mixin(targets = "net.minecraft.client.texture.SpriteContents$Animation")
|
@Mixin(SpriteContents.Animation.class)
|
||||||
public class AnimationMixin implements AlphaInterpolationHolder {
|
public class AnimationMixin implements AlphaInterpolationHolder {
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
|
|
|
@ -9,31 +9,29 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import quimufu.colourful_portals.portal.PortalManager;
|
|
||||||
|
|
||||||
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||||
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_BLOCKS;
|
|
||||||
|
|
||||||
@Mixin(ServerWorld.class)
|
@Mixin(ServerWorld.class)
|
||||||
public class BlockChangeMixin {
|
public class BlockChangeMixin {
|
||||||
|
|
||||||
@Inject(at = @At("RETURN"), method = "onBlockChanged")
|
@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;
|
ServerWorld world = (ServerWorld) (Object) this;
|
||||||
if(world.isDebugWorld()|| !world.isChunkLoaded(pos))
|
if(world.isDebugWorld()|| !world.isChunkLoaded(pos))
|
||||||
return;
|
return;
|
||||||
// This code is injected into the end of ServerWorld.onBlockChanged()V
|
// This code is injected into the end of ServerWorld.onBlockChanged()V
|
||||||
if (oldBlock.getBlock() != newBlock.getBlock()) {
|
if (oldBlock.getBlock() != newBlock.getBlock()) {
|
||||||
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(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());
|
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()))) {
|
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());
|
Identifier blockId = Registries.BLOCK.getId(oldBlock.getBlock());
|
||||||
PortalManager.onPortalBlockBroken(world, pos, blockId);
|
PORTAL_MANAGER.onPortalBlockBroken(world, pos, blockId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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<HashSet<BlockPos>> calledAlready = ThreadLocal.withInitial(HashSet::new);
|
||||||
|
|
||||||
|
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onEntityCollision(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;)V"), method = "checkBlockCollision")
|
||||||
|
public void cpm_dontCallTwice(CallbackInfo ci, @Local BlockPos.Mutable mutable) {
|
||||||
|
calledAlready.get().add(mutable.toImmutable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "checkBlockCollision")
|
||||||
|
public void cpm_afterCheckBlockCollision(CallbackInfo ci) {
|
||||||
|
if (!world.isClient()) {
|
||||||
|
BlockHitResult hitResult = world.raycast(new RaycastContext(new Vec3d(prevX, prevY, prevZ), pos, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, new CollisionAwareShapeContext()));
|
||||||
|
|
||||||
|
BlockPos hitResultBlockPos = hitResult.getBlockPos();
|
||||||
|
if (!calledAlready.get().contains(hitResultBlockPos)) {
|
||||||
|
BlockState state = world.getBlockState(hitResultBlockPos);
|
||||||
|
if (state.getBlock() == PORTAL_BLOCK) {
|
||||||
|
state.onEntityCollision(world, hitResultBlockPos, (Entity) ((Object) this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
calledAlready.get().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<BlockPos, Set<Node<PortalRepresentation>>> 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<PortalRepresentation> portalRepresentations) {
|
||||||
|
LOGGER.info("start linkPortals");
|
||||||
|
for (Node<PortalRepresentation> node = portalRepresentations.getNode(0); node != null; node = node.getNext()) {
|
||||||
|
PortalRepresentation portalRepresentation = node.getValue();
|
||||||
|
|
||||||
|
Node<PortalRepresentation> finalNode = node;
|
||||||
|
insideOf(portalRepresentation.location())
|
||||||
|
.forEachRemaining(blockPos -> {
|
||||||
|
Set<Node<PortalRepresentation>> 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<Node<PortalRepresentation>> portalRepresentationCandidated = positionalLookup.get(pos);
|
||||||
|
Optional<Node<PortalRepresentation>> 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<PortalRepresentation> fromNode = portalOpt.get();
|
||||||
|
Node<PortalRepresentation> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<World> 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<qouteall.imm_ptl.core.portal.Portal> 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<PortalRepresentation> 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<qouteall.imm_ptl.core.portal.Portal> 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<qouteall.imm_ptl.core.portal.Portal> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<PortalRepresentation> portalRepresentations);
|
||||||
|
|
||||||
|
void unLinkPortal(PortalRepresentation portalRepresentation);
|
||||||
|
|
||||||
|
void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a);
|
||||||
|
|
||||||
|
boolean needsReInit();
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package quimufu.colourful_portals.portal;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PortalLinkingSystemBuilder {
|
||||||
|
|
||||||
|
PortalLinkingSystem build(MinecraftServer minecraftServer);
|
||||||
|
}
|
|
@ -1,67 +1,113 @@
|
||||||
package quimufu.colourful_portals.portal;
|
package quimufu.colourful_portals.portal;
|
||||||
|
|
||||||
import dev.onyxstudios.cca.api.v3.component.Component;
|
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.NbtElement;
|
import net.minecraft.nbt.NbtElement;
|
||||||
import net.minecraft.nbt.NbtHelper;
|
import net.minecraft.nbt.NbtHelper;
|
||||||
import net.minecraft.nbt.NbtList;
|
import net.minecraft.nbt.NbtList;
|
||||||
|
import net.minecraft.registry.RegistryWrapper;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.BlockBox;
|
import net.minecraft.util.math.BlockBox;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.WorldProperties;
|
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.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||||
|
|
||||||
public class PortalListComponent implements Component {
|
public class PortalListComponent implements Component {
|
||||||
|
public static final int CURRENT_VERSION = 1;
|
||||||
private final WorldProperties worldProperties;
|
private final WorldProperties worldProperties;
|
||||||
HashMap<Identifier, List<Pair<BlockBox, Identifier>>> portalsPerPortalBlock = new HashMap<>();
|
HashMap<Identifier, LinkedList<PortalRepresentation>> portalsPerPortalBlock = new HashMap<>();
|
||||||
|
|
||||||
|
Identifier lastPortalLinkingSystem = Identifier.of(MOD_ID, "immersive_portals_linking_system");
|
||||||
|
|
||||||
public PortalListComponent(WorldProperties worldProperties) {
|
public PortalListComponent(WorldProperties worldProperties) {
|
||||||
this.worldProperties = worldProperties;
|
this.worldProperties = worldProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readFromNbt(NbtCompound tag) {
|
public void readFromNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) {
|
||||||
if (tag != null && !tag.isEmpty()) {
|
if (tag != null && !tag.isEmpty()) {
|
||||||
for (String block : tag.getKeys()) {
|
if (!tag.contains("version")) {
|
||||||
NbtList portalsWithDim = tag.getList(block, NbtElement.COMPOUND_TYPE);
|
readFromOldNbt(tag);
|
||||||
ArrayList<Pair<BlockBox, Identifier>> portals = new ArrayList<>();
|
}
|
||||||
|
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<PortalRepresentation> portalRepresentations = new LinkedList<>();
|
||||||
for (int i = 0; i < portalsWithDim.size(); i++) {
|
for (int i = 0; i < portalsWithDim.size(); i++) {
|
||||||
NbtCompound portalWithDim = portalsWithDim.getCompound(i);
|
NbtCompound portalWithDim = portalsWithDim.getCompound(i);
|
||||||
|
|
||||||
NbtCompound portalCompound = portalWithDim.getCompound("portal");
|
NbtCompound portalCompound = portalWithDim.getCompound("portal");
|
||||||
BlockBox portal = BlockBox.create(NbtHelper.toBlockPos(portalCompound.getCompound("from")),
|
BlockBox portal = BlockBox.create(NbtHelper.toBlockPos(portalCompound, "from").orElseThrow(),
|
||||||
NbtHelper.toBlockPos(portalCompound.getCompound("to")));
|
NbtHelper.toBlockPos(portalCompound, "to").orElseThrow());
|
||||||
|
|
||||||
Identifier dimension = Identifier.tryParse(portalWithDim.getString("dim"));
|
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<PortalRepresentation> 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
|
@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()) {
|
for (Identifier portalBlockId : portalsPerPortalBlock.keySet()) {
|
||||||
NbtList portalsWithDimList = new NbtList();
|
NbtList portalsWithDimList = new NbtList();
|
||||||
tag.put(portalBlockId.toString(), portalsWithDimList);
|
blocks.put(portalBlockId.toString(), portalsWithDimList);
|
||||||
for (Pair<BlockBox, Identifier> portalWithDim : portalsPerPortalBlock.get(portalBlockId)) {
|
for (PortalRepresentation portalRepresentationWithDim : portalsPerPortalBlock.get(portalBlockId)) {
|
||||||
NbtCompound portalWithDimCompound = new NbtCompound();
|
NbtCompound portalWithDimCompound = new NbtCompound();
|
||||||
portalsWithDimList.add(portalWithDimCompound);
|
portalsWithDimList.add(portalWithDimCompound);
|
||||||
|
|
||||||
NbtCompound portalCompound = new NbtCompound();
|
NbtCompound portalCompound = new NbtCompound();
|
||||||
portalWithDimCompound.put("portal", portalCompound);
|
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 from = new BlockPos(portal.getMinX(), portal.getMinY(), portal.getMinZ());
|
||||||
BlockPos to = new BlockPos(portal.getMaxX(), portal.getMaxY(), portal.getMaxZ());
|
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<BlockBox> getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) {
|
public List<PortalRepresentation> getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) {
|
||||||
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()).stream()
|
return getPortals(blockId).stream()
|
||||||
.filter((portalWithDim) -> (portalWithDim.second.equals(dim)
|
.filter((portal) -> (portal.dimensionId().equals(dim) && portal.location().contains(pos)))
|
||||||
&& portalWithDim.first.contains(pos)))
|
|
||||||
.map((p) -> p.first)
|
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createPortal(Identifier blockId, Pair<BlockBox, Identifier> portalWithDim) {
|
public void createPortal(Identifier blockId, PortalRepresentation portal) {
|
||||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
LinkedList<PortalRepresentation> portalRepresentations = getPortals(blockId);
|
||||||
if (!portals.contains(portalWithDim)) {
|
if (!portalRepresentations.contains(portal)) {
|
||||||
portals.add(portalWithDim);
|
portalRepresentations.add(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePortal(Identifier blockId, Pair<BlockBox, Identifier> portalWithDim) {
|
public void removePortal(Identifier blockId, PortalRepresentation portal) {
|
||||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
getPortals(blockId).remove(portal);
|
||||||
portals.remove(portalWithDim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pair<BlockBox, Identifier>> getPortals(Identifier blockId) {
|
public LinkedList<PortalRepresentation> getPortals(Identifier blockId) {
|
||||||
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new LinkedList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set<Identifier> getBlockIds() {
|
public Set<Identifier> getBlockIds() {
|
||||||
return portalsPerPortalBlock.keySet();
|
return portalsPerPortalBlock.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<BlockBox, Identifier> getNext(Identifier blockId, BlockBox portal, Identifier dim) {
|
public PortalRepresentation getNext(Identifier blockId, PortalRepresentation portalRepresentationWithDim) {
|
||||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
LOGGER.info("gn");
|
||||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal, dim);
|
LinkedList<PortalRepresentation> portals = getPortals(blockId);
|
||||||
|
Node<PortalRepresentation> node;
|
||||||
|
if ((node = portals.getNodeOf(portalRepresentationWithDim)) == null) {
|
||||||
|
|
||||||
int nextIndex = portals.indexOf(portalWithDim) + 1;
|
return portals.getFirst();
|
||||||
if (nextIndex >= portals.size()) {
|
}
|
||||||
return portals.get(0);
|
PortalRepresentation portalRepresentation = node.getNext() == null ? portals.getFirst() : node.getNext().getValue();
|
||||||
|
LOGGER.info("gne");
|
||||||
|
return portalRepresentation;
|
||||||
}
|
}
|
||||||
|
|
||||||
return portals.get(nextIndex);
|
public boolean containsPortal(Identifier blockId, PortalRepresentation portalRepresentation) {
|
||||||
|
return getPortals(blockId).contains(portalRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsPortal(Identifier blockId, Pair<BlockBox,Identifier> portal) {
|
public PortalRepresentation getLast(Identifier blockId) {
|
||||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
return getPortals(blockId).getLast();
|
||||||
return portals.contains(portal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<BlockBox, Identifier> getLast(Identifier blockId) {
|
public Identifier lastPortalLinkingSystemId() {
|
||||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
return lastPortalLinkingSystem;
|
||||||
return portals.get(portals.size()-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,41 +9,50 @@ import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.DyeColor;
|
import net.minecraft.util.DyeColor;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.TypeFilter;
|
import net.minecraft.util.math.BlockBox;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.util.math.Direction;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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.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.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||||
import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST;
|
import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST;
|
||||||
import static quimufu.colourful_portals.Components.PORTAL_LIST;
|
|
||||||
|
|
||||||
public class PortalManager {
|
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");
|
world.getProfiler().push("onPortalBlockPlaced");
|
||||||
LOGGER.debug("onPortalBlockPlaced, {}", blockId);
|
LOGGER.debug("onPortalBlockPlaced, {}", blockId);
|
||||||
|
|
||||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
Identifier dimIdentifier = getDimId(world);
|
||||||
//delete portalCandidates obstructed by PortalBlocks for consistency
|
|
||||||
List<BlockBox> 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<BlockBox, Identifier> portalWithDim =
|
|
||||||
Pair.of(portalCandidate, world.getDimensionKey().getValue());
|
|
||||||
|
|
||||||
portalCandidateList.removePortal(blockId, portalWithDim);
|
//delete portalCandidates obstructed by PortalBlocks for consistency
|
||||||
|
List<PortalRepresentation> 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
|
//find new portalCandidates created by PortalBlock placement
|
||||||
|
@ -51,28 +60,26 @@ public class PortalManager {
|
||||||
LOGGER.debug("new portalCandidates found, {}", portals);
|
LOGGER.debug("new portalCandidates found, {}", portals);
|
||||||
|
|
||||||
for (BlockBox portal : portals) {
|
for (BlockBox portal : portals) {
|
||||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal, world.getDimensionKey().getValue());
|
PortalRepresentation portalRepresentationWithDim = new PortalRepresentation(portal, dimIdentifier);
|
||||||
portalCandidateList.createPortal(blockId, portalWithDim);
|
portalCandidateList.createPortal(blockId, portalRepresentationWithDim);
|
||||||
}
|
}
|
||||||
world.getProfiler().pop();
|
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");
|
world.getProfiler().push("onPortalBlockBroken");
|
||||||
LOGGER.debug("onPortalBlockBroken, {}", blockId);
|
LOGGER.debug("onPortalBlockBroken, {}", blockId);
|
||||||
|
|
||||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
|
||||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||||
|
|
||||||
//check portalCandidate validity
|
//check portalCandidate validity
|
||||||
List<BlockBox> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue());
|
Identifier dimensionIdentifier = getDimId(world);
|
||||||
|
List<PortalRepresentation> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dimensionIdentifier);
|
||||||
LOGGER.debug("getContainingPortals, {}", portalCandidates);
|
LOGGER.debug("getContainingPortals, {}", portalCandidates);
|
||||||
for (BlockBox portalCandidate : portalCandidates) {
|
for (PortalRepresentation portalCandidate : portalCandidates) {
|
||||||
if (!PortalHelper.isValidCandidate(world, portalCandidate, blockId)) {
|
if (!PortalHelper.isValidCandidate(world, portalCandidate.location(), blockId)) {
|
||||||
LOGGER.debug("invalid, {}", portalCandidate);
|
LOGGER.debug("invalid, {}", portalCandidate);
|
||||||
Pair<BlockBox, Identifier> portalWithDim =
|
portalCandidateList.removePortal(blockId, portalCandidate);
|
||||||
Pair.of(portalCandidate, world.getDimensionKey().getValue());
|
|
||||||
portalCandidateList.removePortal(blockId, portalWithDim);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,25 +91,23 @@ public class PortalManager {
|
||||||
LOGGER.debug("potentially new candidate after deobstruction , {}", newPortal);
|
LOGGER.debug("potentially new candidate after deobstruction , {}", newPortal);
|
||||||
|
|
||||||
PortalListComponent portalListComponent = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
PortalListComponent portalListComponent = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||||
Pair<BlockBox, Identifier> portalWithDim =
|
PortalRepresentation portalRepresentationWithDim =
|
||||||
Pair.of(newPortal, world.getDimensionKey().getValue());
|
new PortalRepresentation(newPortal, dimensionIdentifier);
|
||||||
portalListComponent.createPortal(blockId, portalWithDim);
|
portalListComponent.createPortal(blockId, portalRepresentationWithDim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//check portal validity
|
//check portal validity
|
||||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue());
|
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dimensionIdentifier);
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (BlockBox portal : portals) {
|
for (PortalRepresentation portal : portals) {
|
||||||
if (!PortalHelper.isValidPortal(world, portal, blockId)) {
|
if (!PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||||
LOGGER.debug("portal became invalid ,{} {}", world.getDimensionKey().getValue(), portal);
|
LOGGER.debug("portal became invalid ,{} {}", dimensionIdentifier, portal);
|
||||||
|
|
||||||
Pair<BlockBox, Identifier> portalWithDim =
|
portalList.removePortal(blockId, portal);
|
||||||
Pair.of(portal, world.getDimensionKey().getValue());
|
linkingSystem.unLinkPortal(portal);
|
||||||
portalList.removePortal(blockId, portalWithDim);
|
removePortalBlocks(world, portal.location());
|
||||||
destroyPortalEntitiesInside(world, Box.from(portal));
|
|
||||||
removePortalBlocks(world, portal);
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,49 +119,47 @@ public class PortalManager {
|
||||||
world.getProfiler().pop();
|
world.getProfiler().pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removePortalBlocks(ServerWorld world, BlockBox portal) {
|
private void removePortalBlocks(ServerWorld world, BlockBox portal) {
|
||||||
BlockPos.stream(portal)
|
BlockPos.stream(portal)
|
||||||
.filter(blockPos -> world.getBlockState(blockPos).isOf(PORTAL_BLOCK))
|
.filter(blockPos -> world.getBlockState(blockPos).isOf(PORTAL_BLOCK))
|
||||||
.forEach(blockPos -> world.setBlockState(blockPos, Blocks.AIR.getDefaultState()));
|
.forEach(blockPos -> world.setBlockState(blockPos, Blocks.AIR.getDefaultState()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) {
|
private void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) {
|
||||||
List<Pair<BlockBox, Identifier>> portalsWithDim = portalList.getPortals(blockId);
|
LinkedList<PortalRepresentation> portalsWithDim = portalList.getPortals(blockId);
|
||||||
if (portalsWithDim.size() == 1) {
|
if (portalsWithDim.size() == 1) {
|
||||||
Pair<BlockBox, Identifier> portal = portalsWithDim.get(0);
|
PortalRepresentation portalRepresentation = portalsWithDim.getFirst();
|
||||||
ServerWorld world = getPortalWorld(portal, server);
|
ServerWorld world = getPortalWorld(portalRepresentation, server);
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
LOGGER.error("error fixing portalGroup, world {} was null", portal.second);
|
LOGGER.error("error fixing portalGroup, dimensionId {} was null", portalRepresentation.dimensionId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal.first, portal.second);
|
portalList.removePortal(blockId, portalRepresentation);
|
||||||
portalList.removePortal(blockId, portalWithDim);
|
linkingSystem.unLinkPortal(portalRepresentation);
|
||||||
destroyPortalEntitiesInside(world, Box.from(portal.first));
|
removePortalBlocks(world, portalRepresentation.location());
|
||||||
removePortalBlocks(world, portal.first);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < portalsWithDim.size(); i++) {
|
for (PortalRepresentation portalRepresentation : portalsWithDim) {
|
||||||
Pair<BlockBox, Identifier> portal = portalsWithDim.get(i);
|
assurePortalBlocksPlaced(blockId, portalRepresentation, server);
|
||||||
Pair<BlockBox, Identifier> linkedToPortal = i + 1 < portalsWithDim.size() ? portalsWithDim.get(i + 1) : portalsWithDim.get(0);
|
|
||||||
assureLinkedTo(portal, linkedToPortal, server);
|
|
||||||
assurePortalBlocksPlaced(blockId, portal, server);
|
|
||||||
}
|
}
|
||||||
|
linkingSystem.linkPortals(portalsWithDim);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assurePortalBlocksPlaced(Identifier blockId, Pair<BlockBox, Identifier> portal, MinecraftServer server) {
|
private void assurePortalBlocksPlaced(Identifier blockId, PortalRepresentation portalRepresentation, MinecraftServer server) {
|
||||||
DyeColor color = ColourfulPortalConfig.portalBlocks.get(blockId.toString());
|
DyeColor color = ColourfulPortalConfig.colorOf(blockId.toString());
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portal.first)
|
Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portalRepresentation.location())
|
||||||
.rotateClockwise(Direction.Axis.Y)
|
.rotateClockwise(Direction.Axis.Y)
|
||||||
.getAxis();
|
.getAxis();
|
||||||
ServerWorld portalWorld = getPortalWorld(portal, server);
|
ServerWorld portalWorld = getPortalWorld(portalRepresentation, server);
|
||||||
if (portalWorld == null) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
BlockState portalBlockState = PORTAL_BLOCK.getStateWith(color, portalPlaneAxis);
|
BlockState portalBlockState = PORTAL_BLOCK.getStateWith(color, portalPlaneAxis);
|
||||||
|
|
||||||
PortalHelper.insideOf(portal.first)
|
PortalHelper.insideOf(portalRepresentation.location())
|
||||||
.forEachRemaining(blockPos -> {
|
.forEachRemaining(blockPos -> {
|
||||||
BlockState blockState = portalWorld.getBlockState(blockPos);
|
BlockState blockState = portalWorld.getBlockState(blockPos);
|
||||||
if (blockState.isAir() || blockState.getFluidState().isOf(PORTAL_FLUID)) {
|
if (blockState.isAir() || blockState.getFluidState().isOf(PORTAL_FLUID)) {
|
||||||
|
@ -170,99 +173,27 @@ public class PortalManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assureLinkedTo(Pair<BlockBox, Identifier> fromPortal, Pair<BlockBox, Identifier> linkedToPortal, MinecraftServer server) {
|
|
||||||
|
|
||||||
ServerWorld fromPortalWorld = getPortalWorld(fromPortal, server);
|
|
||||||
RegistryKey<World> 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<Portal> portals = fromPortalWorld.getEntitiesByType(TypeFilter.instanceOf(Portal.class), fromPortalBox, Entity::isAlive);
|
|
||||||
List<Portal> 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
|
@Nullable
|
||||||
private static ServerWorld getPortalWorld(Pair<BlockBox, Identifier> fromPortal, MinecraftServer server) {
|
private ServerWorld getPortalWorld(PortalRepresentation fromPortalRepresentation, MinecraftServer server) {
|
||||||
return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortal.second));
|
return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortalRepresentation.dimensionId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void destroyPortalEntitiesInside(ServerWorld world, Box box) {
|
public boolean tryIgnite(ServerWorld world, BlockPos pos) {
|
||||||
List<Portal> 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) {
|
|
||||||
world.getProfiler().push("portal ignition");
|
world.getProfiler().push("portal ignition");
|
||||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
LOGGER.info("portal ignition");
|
||||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
|
||||||
Set<Identifier> blockIds = portalCandidateList.getBlockIds();
|
Set<Identifier> blockIds = portalCandidateList.getBlockIds();
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
for (Identifier blockId : blockIds) {
|
for (Identifier blockId : blockIds) {
|
||||||
Identifier dim = world.getDimensionKey().getValue();
|
Identifier dim = getDimId(world);
|
||||||
List<BlockBox> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim);
|
List<PortalRepresentation> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim);
|
||||||
for (BlockBox portalCandidate : portalCandidates) {
|
for (PortalRepresentation current : portalCandidates) {
|
||||||
if (PortalHelper.isValidPortal(world, portalCandidate, blockId)) {
|
if (PortalHelper.isValidPortal(world, current.location(), blockId)) {
|
||||||
Pair<BlockBox, Identifier> current = Pair.of(portalCandidate, dim);
|
PortalRepresentation next = portalCandidateList.getNext(blockId, current);
|
||||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, portalCandidate, dim);
|
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
|
||||||
if (!next.equals(current)
|
if (!next.equals(current)
|
||||||
&& (!portalList.containsPortal(blockId, current) || !portalList.containsPortal(blockId, next))
|
&& (!portalList.containsPortal(blockId, current) || !portalList.containsPortal(blockId, next))
|
||||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)) {
|
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||||
portalList.createPortal(blockId, current);
|
portalList.createPortal(blockId, current);
|
||||||
portalList.createPortal(blockId, next);
|
portalList.createPortal(blockId, next);
|
||||||
ret = true;
|
ret = true;
|
||||||
|
@ -275,24 +206,21 @@ public class PortalManager {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canExtend(ServerWorld world, BlockPos pos) {
|
public boolean canExtend(ServerWorld world, BlockPos pos) {
|
||||||
world.getProfiler().push("portal extension check");
|
world.getProfiler().push("portal extension check");
|
||||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
|
||||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
|
||||||
Set<Identifier> blockIds = portalList.getBlockIds();
|
Set<Identifier> blockIds = portalList.getBlockIds();
|
||||||
Identifier dim = world.getDimensionKey().getValue();
|
Identifier dim = getDimId(world);
|
||||||
|
|
||||||
for (Identifier blockId : blockIds) {
|
for (Identifier blockId : blockIds) {
|
||||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, dim);
|
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||||
for (BlockBox portal : portals) {
|
for (PortalRepresentation portal : portals) {
|
||||||
if (PortalHelper.isValidPortal(world, portal, blockId)) {
|
if (PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||||
Pair<BlockBox, Identifier> last = portalList.getLast(blockId);
|
PortalRepresentation last = portalList.getLast(blockId);
|
||||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, last.first, last.second);
|
PortalRepresentation next = portalCandidateList.getNext(blockId, last);
|
||||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||||
|
|
||||||
if (!portalList.containsPortal(blockId, next)
|
if (!portalList.containsPortal(blockId, next)
|
||||||
&& PortalHelper.isValidPortal(world, portal, blockId)
|
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){
|
|
||||||
world.getProfiler().pop();
|
world.getProfiler().pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -305,25 +233,22 @@ public class PortalManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean extend(ServerWorld world, BlockPos pos) {
|
public boolean extend(ServerWorld world, BlockPos pos) {
|
||||||
world.getProfiler().push("portal extension");
|
world.getProfiler().push("portal extension");
|
||||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
|
||||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
|
||||||
Set<Identifier> blockIds = portalList.getBlockIds();
|
Set<Identifier> blockIds = portalList.getBlockIds();
|
||||||
Identifier dim = world.getDimensionKey().getValue();
|
Identifier dim = getDimId(world);
|
||||||
|
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
for (Identifier blockId : blockIds) {
|
for (Identifier blockId : blockIds) {
|
||||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, dim);
|
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||||
for (BlockBox portal : portals) {
|
for (PortalRepresentation portal : portals) {
|
||||||
if (PortalHelper.isValidPortal(world, portal, blockId)) {
|
if (PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||||
Pair<BlockBox, Identifier> last = portalList.getLast(blockId);
|
PortalRepresentation last = portalList.getLast(blockId);
|
||||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, last.first, last.second);
|
PortalRepresentation next = portalCandidateList.getNext(blockId, last);
|
||||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||||
|
|
||||||
if (!portalList.containsPortal(blockId, next)
|
if (!portalList.containsPortal(blockId, next)
|
||||||
&& PortalHelper.isValidPortal(world, portal, blockId)
|
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){
|
|
||||||
portalList.createPortal(blockId, next);
|
portalList.createPortal(blockId, next);
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -336,4 +261,12 @@ public class PortalManager {
|
||||||
world.getProfiler().pop();
|
world.getProfiler().pop();
|
||||||
return ret;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package quimufu.colourful_portals.portal;
|
||||||
|
|
||||||
|
public record PrioritizedPortalLinkingSystemBuilder(PortalLinkingSystemBuilder portalLinkingSystemBuilder,
|
||||||
|
int priority) {}
|
|
@ -31,6 +31,7 @@ import quimufu.colourful_portals.portal.PortalManager;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
||||||
|
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_MANAGER;
|
||||||
|
|
||||||
public class PortalFluid extends Fluid {
|
public class PortalFluid extends Fluid {
|
||||||
public static final EnumProperty<NullableAxis> AXIS = EnumProperty.of("axis", NullableAxis.class);
|
public static final EnumProperty<NullableAxis> AXIS = EnumProperty.of("axis", NullableAxis.class);
|
||||||
|
@ -138,7 +139,7 @@ public class PortalFluid extends Fluid {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount <= 14) {
|
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);
|
newStateMe = steal(world, pos, newStateMe, currentAxis);
|
||||||
}
|
}
|
||||||
//my state might have changed.
|
//my state might have changed.
|
||||||
|
@ -169,7 +170,7 @@ public class PortalFluid extends Fluid {
|
||||||
} else if (!world.isClient) {
|
} else if (!world.isClient) {
|
||||||
for (Direction direction : Direction.values()) {
|
for (Direction direction : Direction.values()) {
|
||||||
if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(world.getBlockState(pos.offset(direction)).getBlock()))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,7 +373,7 @@ public class PortalFluid extends Fluid {
|
||||||
BlockPos neighborOfInspectedLocation = inspectedLocation.offset(dir);
|
BlockPos neighborOfInspectedLocation = inspectedLocation.offset(dir);
|
||||||
BlockState neighbourOfInspected = world.getBlockState(neighborOfInspectedLocation);
|
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()))) {
|
if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(neighbourOfInspected.getBlock()))) {
|
||||||
dirCost -= 2;
|
dirCost -= 2;
|
||||||
discount = false;
|
discount = false;
|
||||||
|
@ -381,7 +382,7 @@ public class PortalFluid extends Fluid {
|
||||||
//if adjacent to any solid Block, 1 less
|
//if adjacent to any solid Block, 1 less
|
||||||
if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) {
|
if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) {
|
||||||
discount = true;
|
discount = true;
|
||||||
//maybe a Portal Block in another direction
|
//maybe a PortalRepresentation Block in another direction
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class PortalFluidBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
protected boolean canPathfindThrough(BlockState state, NavigationType type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
package quimufu.colourful_portals.util;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class Pair<A, B> {
|
|
||||||
|
|
||||||
public final A first;
|
|
||||||
public final B second;
|
|
||||||
|
|
||||||
public Pair(A first, B second) {
|
|
||||||
this.first = first;
|
|
||||||
this.second = second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <A, B> Pair<A, B> 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,26 @@
|
||||||
{
|
{
|
||||||
"item.colourful_portals.portal_fluid_bucket": "Farbeimer",
|
|
||||||
"block.colourful_portals.portal_block": "Farbenfrohes Portal",
|
"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_bright": "Heller Farbmix",
|
||||||
"item.colourful_portals.colour_blob_dark": "Dunkler 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"
|
||||||
}
|
}
|
|
@ -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_bright": "Bright Colour Mix",
|
||||||
"item.colourful_portals.colour_blob_dark": "Dark Colour Mix",
|
"item.colourful_portals.colour_blob_dark": "Dark Colour Mix",
|
||||||
"block.colourful_portals.portal_block": "Colourful Portal",
|
"item.colourful_portals.portal_fluid_bucket": "Colourful Bucket"
|
||||||
"block.colourful_portals.portal_fluid_block": "Colourful Fluid"
|
|
||||||
}
|
}
|
|
@ -3,17 +3,18 @@
|
||||||
"package": "quimufu.colourful_portals.mixin",
|
"package": "quimufu.colourful_portals.mixin",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"BlockChangeMixin"
|
"BlockChangeMixin",
|
||||||
|
"EntityMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"plugin": "quimufu.colourful_portals.MixinConfig",
|
"plugin": "quimufu.colourful_portals.MixinConfig",
|
||||||
"client": [
|
"client": [
|
||||||
"AnimationResourceMetadataReaderMixin",
|
|
||||||
"AnimationMixin",
|
"AnimationMixin",
|
||||||
"AnimationResourceMetadataMixin",
|
"AnimationResourceMetadataMixin",
|
||||||
"SpriteContentsMixin",
|
"AnimationResourceMetadataReaderMixin",
|
||||||
"SodiumFluidRendererMixin"
|
"SodiumFluidRendererMixin",
|
||||||
|
"SpriteContentsMixin"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -42,9 +42,8 @@
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=${loader_version}",
|
"fabricloader": ">=${loader_version}",
|
||||||
"immersive_portals": ">=${immersive_portals_version_short}",
|
|
||||||
"minecraft": "~${minecraft_version}",
|
"minecraft": "~${minecraft_version}",
|
||||||
"java": ">=17",
|
"java": ">=21",
|
||||||
"fabric-api": "*"
|
"fabric-api": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user