Compare commits
2 Commits
b1cd170c60
...
0d1e607206
Author | SHA1 | Date | |
---|---|---|---|
0d1e607206 | |||
4aa2643a76 |
|
@ -1,3 +1,3 @@
|
|||
# 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 {
|
||||
id "com.modrinth.minotaur" version "2.+"
|
||||
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||
id 'fabric-loom' version '1.6-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
|
@ -54,22 +54,29 @@ dependencies {
|
|||
|
||||
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
|
||||
|
||||
modImplementation ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}")
|
||||
|
||||
include(modApi("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}"))
|
||||
modCompileOnly ("com.github.iPortalTeam:ImmersivePortalsMod:${project.immersive_portals_version}")
|
||||
|
||||
// Replace modImplementation with modApi if you expose components in your own API
|
||||
include(modImplementation("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}"))
|
||||
modImplementation "org.ladysnake.cardinal-components-api:cardinal-components-base:${project.cca_version}"
|
||||
// Includes Cardinal Components API as a Jar-in-Jar dependency (optional but recommended)
|
||||
include "org.ladysnake.cardinal-components-api:cardinal-components-base:${project.cca_version}"
|
||||
|
||||
include(modApi(platform("de.siphalor.tweed4:tweed4-bom-$project.minecraft_version_major:$project.tweed_version")))
|
||||
// Replace modImplementation with modApi if you expose components in your own API
|
||||
modImplementation "org.ladysnake.cardinal-components-api:cardinal-components-level:${project.cca_version}"
|
||||
// Includes Cardinal Components API as a Jar-in-Jar dependency (optional but recommended)
|
||||
include "org.ladysnake.cardinal-components-api:cardinal-components-level:${project.cca_version}"
|
||||
|
||||
//include(modApi(platform("de.siphalor.tweed4:tweed4-bom-$project.minecraft_version_major:$project.tweed_version")))
|
||||
// Pick any modules you want to use, e.g.:
|
||||
include(modApi("de.siphalor.tweed4:tweed4-base-$project.minecraft_version_major"))
|
||||
include(modApi("de.siphalor.tweed4:tweed4-annotated-$project.minecraft_version_major"))
|
||||
include(modApi("de.siphalor.tweed4:tweed4-data-$project.minecraft_version_major"))
|
||||
include(modApi("de.siphalor.tweed4:tweed4-data-hjson-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-base-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-annotated-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-data-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-data-hjson-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-tailor-cloth-$project.minecraft_version_major"))
|
||||
include(modApi("de.siphalor.tweed4:tweed4-tailor-screen-$project.minecraft_version_major"))
|
||||
//include(modApi("de.siphalor.tweed4:tweed4-tailor-screen-$project.minecraft_version_major"))
|
||||
|
||||
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||
|
||||
modImplementation("me.shedaniel.cloth:cloth-config-fabric:$project.cloth_config_version")
|
||||
|
||||
|
@ -95,7 +102,7 @@ processResources {
|
|||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.release = 17
|
||||
it.options.release = 21
|
||||
}
|
||||
|
||||
java {
|
||||
|
@ -104,8 +111,8 @@ java {
|
|||
// If you remove this line, sources will not be generated.
|
||||
withSourcesJar()
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
jar {
|
||||
|
@ -119,10 +126,10 @@ import com.modrinth.minotaur.dependencies.ModDependency
|
|||
modrinth {
|
||||
projectId = 'QXA901PE' // The ID of your Modrinth project. Slugs will not work.
|
||||
uploadFile = remapJar // Tells Minotaur to use the remapped jar
|
||||
versionType = "beta"
|
||||
versionType = "alpha"
|
||||
dependencies = [
|
||||
new ModDependency('P7dR8mSH', 'required'), //required dependency on Fabric API
|
||||
new ModDependency('zJpHMkdD', 'required') //required dependency on Immersive Portals
|
||||
new ModDependency('AANobbMI', 'optional'), //compatible with Sodium
|
||||
]
|
||||
}
|
||||
// configure the maven publication
|
||||
|
|
|
@ -4,21 +4,22 @@ org.gradle.parallel=true
|
|||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.20.4
|
||||
minecraft_version_major=1.20
|
||||
yarn_mappings=1.20.4+build.3
|
||||
loader_version=0.15.7
|
||||
minecraft_version=1.21
|
||||
minecraft_version_major=1.21
|
||||
yarn_mappings=1.21+build.2
|
||||
loader_version=0.15.11
|
||||
|
||||
# Mod Properties
|
||||
mod_version=0.9.3.1
|
||||
maven_group=quimufu.colourful-portals
|
||||
archives_base_name=colourful-portals
|
||||
mod_version=0.9.4
|
||||
maven_group=quimufu.colourful-portalRepresentations
|
||||
archives_base_name=colourful-portalRepresentations
|
||||
|
||||
# Dependencies
|
||||
fabric_version=0.96.11+1.20.4
|
||||
cardinal_components_version=5.4.0
|
||||
fabric_version=0.100.1+1.21
|
||||
cca_version = 6.1.0
|
||||
immersive_portals_version_short=5.1.7
|
||||
immersive_portals_version=v5.1.7-mc1.20.4
|
||||
tweed_version=1.3.0+mc1.20.2
|
||||
sodium_version=mc1.20.4-0.5.8
|
||||
cloth_config_version=13.0.121
|
||||
sodium_version=mc1.21-0.5.9
|
||||
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
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
package quimufu.colourful_portals;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroupEntries;
|
||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.enums.Instrument;
|
||||
import net.minecraft.block.enums.NoteBlockInstrument;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.sound.BlockSoundGroup;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Rarity;
|
||||
|
@ -19,25 +22,34 @@ import net.minecraft.world.BlockView;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import quimufu.colourful_portals.config.ColourfulPortalConfig;
|
||||
import quimufu.colourful_portals.portal.*;
|
||||
import quimufu.colourful_portals.portal_fluid.PortalFluid;
|
||||
import quimufu.colourful_portals.portal_fluid.PortalFluidBlock;
|
||||
import quimufu.colourful_portals.portal_fluid.PortalFluidBucketItem;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST;
|
||||
import static quimufu.colourful_portals.Components.PORTAL_LIST;
|
||||
|
||||
public class ColourfulPortalsMod implements ModInitializer {
|
||||
|
||||
public static final String MOD_ID = "colourful_portals";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
public static final HashSet<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 BlockItem PORTAL_BLOCK_ITEM = new BlockItem(PORTAL_BLOCK, new FabricItemSettings().rarity(Rarity.EPIC));
|
||||
public static final Item BLOB_DARK = new Item(new FabricItemSettings());
|
||||
public static final Item BLOB_BRIGHT = new Item(new FabricItemSettings());
|
||||
public static final PortalBlock PORTAL_BLOCK = new PortalBlock(AbstractBlock.Settings.create().instrument(NoteBlockInstrument.HAT).sounds(BlockSoundGroup.GLASS).strength(-1.0f, 3600000.8f).dropsNothing().nonOpaque().luminance((bs) -> 15).allowsSpawning(ColourfulPortalsMod::never).solidBlock(ColourfulPortalsMod::never).suffocates(ColourfulPortalsMod::never).blockVision(ColourfulPortalsMod::never).ticksRandomly());
|
||||
public static final BlockItem PORTAL_BLOCK_ITEM = new BlockItem(PORTAL_BLOCK, new Item.Settings().rarity(Rarity.EPIC));
|
||||
public static final Item BLOB_DARK = new Item(new Item.Settings());
|
||||
public static final Item BLOB_BRIGHT = new Item(new Item.Settings());
|
||||
public static final PortalFluid PORTAL_FLUID = new PortalFluid();
|
||||
public static final PortalFluidBlock PORTAL_FLUID_BLOCk = new PortalFluidBlock(PORTAL_FLUID, FabricBlockSettings.create().sounds(BlockSoundGroup.INTENTIONALLY_EMPTY).luminance(15).noCollision().strength(100.0f).dropsNothing());
|
||||
public static final BucketItem PORTAL_FLUID_BUCKET_ITEM = new PortalFluidBucketItem(PORTAL_FLUID, new FabricItemSettings().recipeRemainder(Items.BUCKET).maxCount(1).rarity(Rarity.RARE));
|
||||
public static final PortalFluidBlock PORTAL_FLUID_BLOCk = new PortalFluidBlock(PORTAL_FLUID, AbstractBlock.Settings.create().sounds(BlockSoundGroup.INTENTIONALLY_EMPTY).luminance((bs) -> 15).noCollision().strength(100.0f).dropsNothing());
|
||||
public static final BucketItem PORTAL_FLUID_BUCKET_ITEM = new PortalFluidBucketItem(PORTAL_FLUID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1).rarity(Rarity.RARE));
|
||||
public static PortalManager PORTAL_MANAGER;
|
||||
|
||||
public static final RegistryKey<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) {
|
||||
return false;
|
||||
|
@ -50,23 +62,28 @@ public class ColourfulPortalsMod implements ModInitializer {
|
|||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
LOGGER.info("Colourizing Portals...");
|
||||
LOGGER.info("Colouring Portals...");
|
||||
|
||||
for (String id : ColourfulPortalConfig.portalBlocks.keySet()) {
|
||||
for (String id : ColourfulPortalConfig.getAllPortalBlocks()) {
|
||||
LOGGER.info(id);
|
||||
PORTAL_BLOCKS.add(Identifier.tryParse(id));
|
||||
}
|
||||
if (!ColourfulPortalConfig.disableImmersivePortals && hasImmPtl()) {
|
||||
Registry.register(PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY, ImmersivePortalsLinkingSystem.IMMERSIVE_PORTALS_LINKING_SYSTEM, new PrioritizedPortalLinkingSystemBuilder(ImmersivePortalsLinkingSystem::new, 100));
|
||||
}
|
||||
Registry.register(PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY, DefaultLinkingSystem.DEFAULT_LINKING_SYSTEM, new PrioritizedPortalLinkingSystemBuilder(DefaultLinkingSystem::new, 90));
|
||||
|
||||
Identifier identifier = new Identifier(MOD_ID, "portal_block");
|
||||
Identifier identifier = Identifier.of(MOD_ID, "portal_block");
|
||||
|
||||
Registry.register(Registries.BLOCK, identifier, PORTAL_BLOCK);
|
||||
Registry.register(Registries.ITEM, identifier, PORTAL_BLOCK_ITEM);
|
||||
|
||||
Registry.register(Registries.ITEM, new Identifier(MOD_ID, "portal_fluid_bucket"), PORTAL_FLUID_BUCKET_ITEM);
|
||||
Registry.register(Registries.FLUID, new Identifier(MOD_ID, "portal_fluid"), PORTAL_FLUID);
|
||||
Registry.register(Registries.BLOCK, new Identifier(MOD_ID, "portal_fluid_block"), PORTAL_FLUID_BLOCk);
|
||||
Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "portal_fluid_bucket"), PORTAL_FLUID_BUCKET_ITEM);
|
||||
Registry.register(Registries.FLUID, Identifier.of(MOD_ID, "portal_fluid"), PORTAL_FLUID);
|
||||
Registry.register(Registries.BLOCK, Identifier.of(MOD_ID, "portal_fluid_block"), PORTAL_FLUID_BLOCk);
|
||||
|
||||
Registry.register(Registries.ITEM, new Identifier(MOD_ID, "colour_blob_bright"), BLOB_BRIGHT);
|
||||
Registry.register(Registries.ITEM, new Identifier(MOD_ID, "colour_blob_dark"), BLOB_DARK);
|
||||
Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "colour_blob_bright"), BLOB_BRIGHT);
|
||||
Registry.register(Registries.ITEM, Identifier.of(MOD_ID, "colour_blob_dark"), BLOB_DARK);
|
||||
|
||||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS)
|
||||
.register(ColourfulPortalsMod::addToIngredients);
|
||||
|
@ -74,9 +91,51 @@ public class ColourfulPortalsMod implements ModInitializer {
|
|||
ItemGroupEvents.modifyEntriesEvent(ItemGroups.TOOLS)
|
||||
.register(ColourfulPortalsMod::addTtTools);
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTED.register(this::onServerStarted);
|
||||
LOGGER.info("Portals Colourful!");
|
||||
}
|
||||
|
||||
private boolean hasImmPtl() {
|
||||
try {
|
||||
Class.forName("qouteall.imm_ptl.core.IPModMain", false, this.getClass().getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onServerStarted(MinecraftServer minecraftServer) {
|
||||
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(minecraftServer.getSaveProperties().getMainWorldProperties());
|
||||
PortalListComponent portalList = PORTAL_LIST.get(minecraftServer.getSaveProperties().getMainWorldProperties());
|
||||
|
||||
PortalLinkingSystem currentLinkingSystem = getCurrentlyConfiguredLinkingSystem(minecraftServer);
|
||||
if (currentLinkingSystem.getLinkingSystemId() != portalList.lastPortalLinkingSystemId() || currentLinkingSystem.needsReInit()) {
|
||||
PrioritizedPortalLinkingSystemBuilder prevSystem;
|
||||
if ((prevSystem = PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY.get(portalList.lastPortalLinkingSystemId())) != null) {
|
||||
PortalLinkingSystem prevLS = prevSystem.portalLinkingSystemBuilder().build(minecraftServer);
|
||||
for (Identifier blockId : portalList.getBlockIds()) {
|
||||
for (PortalRepresentation portal : portalList.getPortals(blockId)) {
|
||||
prevLS.unLinkPortal(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Identifier blockId : portalList.getBlockIds()) {
|
||||
currentLinkingSystem.linkPortals(portalList.getPortals(blockId));
|
||||
}
|
||||
}
|
||||
PORTAL_MANAGER = new PortalManager(currentLinkingSystem, portalCandidateList, portalList);
|
||||
}
|
||||
|
||||
private PortalLinkingSystem getCurrentlyConfiguredLinkingSystem(MinecraftServer minecraftServer) {
|
||||
return PORTAL_LINKING_SYSTEM_BUILDER_REGISTRY
|
||||
.stream()
|
||||
.min(Comparator.comparing(PrioritizedPortalLinkingSystemBuilder::priority))
|
||||
.map(PrioritizedPortalLinkingSystemBuilder::portalLinkingSystemBuilder)
|
||||
.orElse(DefaultLinkingSystem::new)
|
||||
.build(minecraftServer);
|
||||
}
|
||||
|
||||
private static void addTtTools(FabricItemGroupEntries entries) {
|
||||
entries.add(PORTAL_FLUID_BUCKET_ITEM);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package quimufu.colourful_portals;
|
||||
|
||||
import dev.onyxstudios.cca.api.v3.component.ComponentKey;
|
||||
import dev.onyxstudios.cca.api.v3.component.ComponentRegistry;
|
||||
import dev.onyxstudios.cca.api.v3.level.LevelComponentFactoryRegistry;
|
||||
import dev.onyxstudios.cca.api.v3.level.LevelComponentInitializer;
|
||||
import org.ladysnake.cca.api.v3.component.ComponentKey;
|
||||
import org.ladysnake.cca.api.v3.component.ComponentRegistry;
|
||||
import org.ladysnake.cca.api.v3.level.LevelComponentFactoryRegistry;
|
||||
import org.ladysnake.cca.api.v3.level.LevelComponentInitializer;
|
||||
import net.minecraft.util.Identifier;
|
||||
import quimufu.colourful_portals.portal.PortalListComponent;
|
||||
|
||||
public class Components implements LevelComponentInitializer {
|
||||
public static final ComponentKey<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 =
|
||||
ComponentRegistry.getOrCreate(new Identifier(ColourfulPortalsMod.MOD_ID, "portal_candidate_list"), PortalListComponent.class);
|
||||
ComponentRegistry.getOrCreate(Identifier.of(ColourfulPortalsMod.MOD_ID, "portal_candidate_list"), PortalListComponent.class);
|
||||
|
||||
@Override
|
||||
public void registerLevelComponentFactories(LevelComponentFactoryRegistry registry) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import net.minecraft.block.Block;
|
|||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidFillable;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
|
@ -15,15 +16,16 @@ import net.minecraft.state.property.EnumProperty;
|
|||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.BlockRotation;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import quimufu.colourful_portals.portal.PortalManager;
|
||||
import quimufu.colourful_portals.util.CollisionAwareShapeContext;
|
||||
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_MANAGER;
|
||||
|
||||
|
||||
public class PortalBlock extends Block implements FluidFillable {
|
||||
|
@ -74,8 +76,58 @@ public class PortalBlock extends Block implements FluidFillable {
|
|||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {
|
||||
if (entity.getBoundingBox()
|
||||
.intersects(getShape(state, world, pos).getBoundingBox())) {
|
||||
Vec3d vec3d = new Vec3d(0.5, 0.5f, 0.5);
|
||||
entity.slowMovement(state, vec3d);
|
||||
}
|
||||
Vec3d entityPos = entity.getPos();
|
||||
Vec3d prevEntityPos = new Vec3d(entity.prevX, entity.prevY, entity.prevZ);
|
||||
Vec3d movement = entityPos.subtract(prevEntityPos);
|
||||
if (world instanceof ServerWorld) {
|
||||
Direction.Axis axis = state.get(AXIS);
|
||||
double centerPosAlongAxis = pos.toCenterPos().getComponentAlongAxis(axis);
|
||||
double entityPosAlongAxis = entityPos.getComponentAlongAxis(axis);
|
||||
double prevEntityPosAlongAxis = prevEntityPos.getComponentAlongAxis(axis);
|
||||
double movementAlongAxis = entityPosAlongAxis - prevEntityPosAlongAxis;
|
||||
if (prevEntityPosAlongAxis > entityPosAlongAxis) {
|
||||
if (entityPosAlongAxis < centerPosAlongAxis
|
||||
&& prevEntityPosAlongAxis >= centerPosAlongAxis) {
|
||||
double plainHitAfter = (centerPosAlongAxis - entityPosAlongAxis) / movementAlongAxis;
|
||||
Vec3d planeHitPoint = entityPos.add(movement.multiply(plainHitAfter));
|
||||
if (Box.from(new BlockBox(pos)).contains(planeHitPoint)) {
|
||||
PORTAL_MANAGER.onPortalPassed(entity, pos, (ServerWorld) world, axis);
|
||||
}
|
||||
}
|
||||
} else if (prevEntityPosAlongAxis < entityPosAlongAxis) {
|
||||
if (entityPosAlongAxis > centerPosAlongAxis
|
||||
&& prevEntityPosAlongAxis <= centerPosAlongAxis) {
|
||||
double plainHitAfter = (centerPosAlongAxis - entityPosAlongAxis) / movementAlongAxis;
|
||||
Vec3d planeHitPoint = entityPos.add(movement.multiply(plainHitAfter));
|
||||
if (Box.from(new BlockBox(pos)).contains(planeHitPoint)) {
|
||||
PORTAL_MANAGER.onPortalPassed(entity, pos, (ServerWorld) world, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public VoxelShape getShape(BlockState state, BlockView world, BlockPos pos) {
|
||||
return switch (state.get(AXIS)) {
|
||||
case Z -> Z_AABB;
|
||||
case Y -> Y_AABB;
|
||||
default -> X_AABB;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
||||
if (context instanceof CollisionAwareShapeContext) {
|
||||
return getShape(state, world, pos);
|
||||
}
|
||||
return VoxelShapes.empty();
|
||||
}
|
||||
|
||||
|
@ -127,7 +179,7 @@ public class PortalBlock extends Block implements FluidFillable {
|
|||
}
|
||||
return fluid == ColourfulPortalsMod.PORTAL_FLUID
|
||||
&& (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)
|
||||
&& (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)
|
||||
public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPortalFluidRenderer.VertexEater {
|
||||
Identifier PORTAL_FLUID_STILL = new Identifier(ColourfulPortalsMod.MOD_ID, "block/portal_still");
|
||||
Identifier PORTAL_FLUID_STILL = Identifier.of(ColourfulPortalsMod.MOD_ID, "block/portal_still");
|
||||
|
||||
private final CommonPortalFluidRenderer commonPortalFluidRenderer = new CommonPortalFluidRenderer();
|
||||
private Sprite sprite = null;
|
||||
|
@ -82,8 +82,7 @@ public class PortalFluidRenderHandler implements FluidRenderHandler, CommonPorta
|
|||
.color(1f, 1f, 1f, 1.0f)
|
||||
.texture(v[3], v[4])
|
||||
.light(16)
|
||||
.normal(0.0f, 1.0f, 0.0f)
|
||||
.next();
|
||||
.normal(0.0f, 1.0f, 0.0f);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers;
|
|||
import me.jellysquid.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.terrain.material.Material;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.vertex.builder.ChunkMeshBufferBuilder;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder;
|
||||
import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder.Vertex;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
|
|
|
@ -1,44 +1,131 @@
|
|||
package quimufu.colourful_portals.config;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import de.siphalor.tweed4.annotated.AConfigEntry;
|
||||
import de.siphalor.tweed4.annotated.ATweedConfig;
|
||||
import de.siphalor.tweed4.config.ConfigEnvironment;
|
||||
import de.siphalor.tweed4.config.ConfigScope;
|
||||
//import de.siphalor.tweed4.tailor.cloth.ClothData;
|
||||
import com.google.common.collect.Lists;
|
||||
import eu.midnightdust.lib.config.MidnightConfig;
|
||||
import net.minecraft.util.DyeColor;
|
||||
//import quimufu.colourful_portals.ColourfulPortalsMod;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ATweedConfig(serializer = "tweed4:hjson", scope = ConfigScope.GAME, environment = ConfigEnvironment.SERVER, tailors = {"tweed4:lang_json_descriptions", "tweed4:coat", "tweed4:json_schema"}, casing = CaseFormat.LOWER_HYPHEN)
|
||||
//@ClothData(modid = ColourfulPortalsMod.MOD_ID)
|
||||
public class ColourfulPortalConfig {
|
||||
public class ColourfulPortalConfig extends MidnightConfig {
|
||||
|
||||
@AConfigEntry(comment =
|
||||
"""
|
||||
Allows you to add additional blocks as portalBlocks,
|
||||
assigning them the color of the portal plane.
|
||||
null causes the portals out of that block to have *no* plane.
|
||||
Changes in the plane color will only apply to new portals,
|
||||
or on portal update.
|
||||
""")
|
||||
public static Map<String, DyeColor> portalBlocks = ImmutableMap.ofEntries(
|
||||
Map.entry("minecraft:white_wool", DyeColor.WHITE),
|
||||
Map.entry("minecraft:orange_wool", DyeColor.ORANGE),
|
||||
Map.entry("minecraft:magenta_wool", DyeColor.MAGENTA),
|
||||
Map.entry("minecraft:light_blue_wool", DyeColor.LIGHT_BLUE),
|
||||
Map.entry("minecraft:yellow_wool", DyeColor.YELLOW),
|
||||
Map.entry("minecraft:lime_wool", DyeColor.LIME),
|
||||
Map.entry("minecraft:pink_wool", DyeColor.PINK),
|
||||
Map.entry("minecraft:gray_wool", DyeColor.GRAY),
|
||||
Map.entry("minecraft:light_gray_wool", DyeColor.LIGHT_GRAY),
|
||||
Map.entry("minecraft:cyan_wool", DyeColor.CYAN),
|
||||
Map.entry("minecraft:purple_wool", DyeColor.PURPLE),
|
||||
Map.entry("minecraft:blue_wool", DyeColor.BLUE),
|
||||
Map.entry("minecraft:brown_wool", DyeColor.BROWN),
|
||||
Map.entry("minecraft:green_wool", DyeColor.GREEN),
|
||||
Map.entry("minecraft:red_wool", DyeColor.RED),
|
||||
Map.entry("minecraft:black_wool", DyeColor.BLACK));
|
||||
@Comment(category = "text")
|
||||
public static Comment explanation;
|
||||
|
||||
@Entry(category = "text", name = "Disable Immersive Portals integration")
|
||||
public static boolean disableImmersivePortals = false;
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create white portals")
|
||||
public static List<String> white = Lists.newArrayList("minecraft:white_wool");
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create orange portals")
|
||||
public static List<String> orange = Lists.newArrayList("minecraft:orange_wool");
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create magenta portals")
|
||||
public static List<String> magenta = Lists.newArrayList("minecraft:magenta_wool");
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create light blue portals")
|
||||
public static List<String> light_blue = Lists.newArrayList("minecraft:light_blue_wool");
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create yellow portals")
|
||||
public static List<String> yellow = Lists.newArrayList("minecraft:yellow_wool");
|
||||
|
||||
@Entry(category = "text", name = "Blocks that create lime portals")
|
||||
public static List<String> lime = Lists.newArrayList("minecraft:lime_wool");
|
||||
|
||||
@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;
|
||||
|
||||
@Mixin(targets = "net.minecraft.client.texture.SpriteContents$Animation")
|
||||
@Mixin(SpriteContents.Animation.class)
|
||||
public class AnimationMixin implements AlphaInterpolationHolder {
|
||||
@Shadow
|
||||
@Final
|
||||
|
|
|
@ -9,31 +9,29 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import quimufu.colourful_portals.portal.PortalManager;
|
||||
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_BLOCKS;
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||
|
||||
@Mixin(ServerWorld.class)
|
||||
public class BlockChangeMixin {
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "onBlockChanged")
|
||||
private void init(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo info) {
|
||||
private void cpm_afterOnBlockChanged(BlockPos pos, BlockState oldBlock, BlockState newBlock, CallbackInfo info) {
|
||||
ServerWorld world = (ServerWorld) (Object) this;
|
||||
if(world.isDebugWorld()|| !world.isChunkLoaded(pos))
|
||||
return;
|
||||
// This code is injected into the end of ServerWorld.onBlockChanged()V
|
||||
if (oldBlock.getBlock() != newBlock.getBlock()) {
|
||||
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(newBlock.getBlock()))) {
|
||||
LOGGER.debug("onBlockNew {} -> {}", oldBlock, newBlock);
|
||||
LOGGER.info("onBlockNew {} -> {}", oldBlock, newBlock);
|
||||
Identifier blockId = Registries.BLOCK.getId(newBlock.getBlock());
|
||||
PortalManager.onPortalBlockPlaced(world, pos, blockId);
|
||||
PORTAL_MANAGER.onPortalBlockPlaced(world, pos, blockId);
|
||||
|
||||
}
|
||||
if (PORTAL_BLOCKS.contains(Registries.BLOCK.getId(oldBlock.getBlock()))) {
|
||||
LOGGER.debug("onBlockOld {} -> {}", oldBlock, newBlock);
|
||||
LOGGER.info("onBlockOld {} -> {}", oldBlock, newBlock);
|
||||
Identifier blockId = Registries.BLOCK.getId(oldBlock.getBlock());
|
||||
PortalManager.onPortalBlockBroken(world, pos, blockId);
|
||||
PORTAL_MANAGER.onPortalBlockBroken(world, pos, blockId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
import dev.onyxstudios.cca.api.v3.component.Component;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.WorldProperties;
|
||||
import quimufu.colourful_portals.util.Pair;
|
||||
import org.ladysnake.cca.api.v3.component.Component;
|
||||
import quimufu.colourful_portals.general_util.LinkedList;
|
||||
import quimufu.colourful_portals.general_util.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||
|
||||
public class PortalListComponent implements Component {
|
||||
public static final int CURRENT_VERSION = 1;
|
||||
private final WorldProperties worldProperties;
|
||||
HashMap<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) {
|
||||
this.worldProperties = worldProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNbt(NbtCompound tag) {
|
||||
public void readFromNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) {
|
||||
if (tag != null && !tag.isEmpty()) {
|
||||
for (String block : tag.getKeys()) {
|
||||
NbtList portalsWithDim = tag.getList(block, NbtElement.COMPOUND_TYPE);
|
||||
ArrayList<Pair<BlockBox, Identifier>> portals = new ArrayList<>();
|
||||
if (!tag.contains("version")) {
|
||||
readFromOldNbt(tag);
|
||||
}
|
||||
if (tag.getInt("version") > CURRENT_VERSION) {
|
||||
LOGGER.warn("portals component comes from a newer version! Hopefully backwards compatible. Proceeding");
|
||||
}
|
||||
if (tag.contains("linking_system")) {
|
||||
lastPortalLinkingSystem = Identifier.tryParse(tag.getString("version"));
|
||||
}
|
||||
NbtCompound blocks = tag.getCompound("blocks");
|
||||
for (String block : blocks.getKeys()) {
|
||||
NbtList portalsWithDim = blocks.getList(block, NbtElement.COMPOUND_TYPE);
|
||||
LinkedList<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(NbtHelper.toBlockPos(portalCompound.getCompound("from")),
|
||||
NbtHelper.toBlockPos(portalCompound.getCompound("to")));
|
||||
BlockBox portal = BlockBox.create(NbtHelper.toBlockPos(portalCompound, "from").orElseThrow(),
|
||||
NbtHelper.toBlockPos(portalCompound, "to").orElseThrow());
|
||||
|
||||
Identifier dimension = Identifier.tryParse(portalWithDim.getString("dim"));
|
||||
|
||||
portals.add(Pair.of(portal, dimension));
|
||||
portalRepresentations.add(new PortalRepresentation(portal, dimension));
|
||||
}
|
||||
portalsPerPortalBlock.put(Identifier.tryParse(block), portals);
|
||||
portalsPerPortalBlock.put(Identifier.tryParse(block), portalRepresentations);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readFromOldNbt(NbtCompound tag) {
|
||||
for (String block : tag.getKeys()) {
|
||||
NbtList portalsWithDim = tag.getList(block, NbtElement.COMPOUND_TYPE);
|
||||
LinkedList<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
|
||||
public void writeToNbt(NbtCompound tag) {
|
||||
public void writeToNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLookup) {
|
||||
LOGGER.debug("save");
|
||||
if(PORTAL_MANAGER == null) {
|
||||
return;
|
||||
}
|
||||
tag.putInt("version", CURRENT_VERSION);
|
||||
tag.putString("linking_system", PORTAL_MANAGER.getLinkingSystem().getLinkingSystemId().toString());
|
||||
NbtCompound blocks = new NbtCompound();
|
||||
tag.put("blocks", blocks);
|
||||
for (Identifier portalBlockId : portalsPerPortalBlock.keySet()) {
|
||||
NbtList portalsWithDimList = new NbtList();
|
||||
tag.put(portalBlockId.toString(), portalsWithDimList);
|
||||
for (Pair<BlockBox, Identifier> portalWithDim : portalsPerPortalBlock.get(portalBlockId)) {
|
||||
blocks.put(portalBlockId.toString(), portalsWithDimList);
|
||||
for (PortalRepresentation portalRepresentationWithDim : portalsPerPortalBlock.get(portalBlockId)) {
|
||||
NbtCompound portalWithDimCompound = new NbtCompound();
|
||||
portalsWithDimList.add(portalWithDimCompound);
|
||||
|
||||
NbtCompound portalCompound = new NbtCompound();
|
||||
portalWithDimCompound.put("portal", portalCompound);
|
||||
portalWithDimCompound.putString("dim", portalWithDim.second.toString());
|
||||
portalWithDimCompound.putString("dim", portalRepresentationWithDim.dimensionId().toString());
|
||||
|
||||
BlockBox portal = portalWithDim.first;
|
||||
BlockBox portal = portalRepresentationWithDim.location();
|
||||
BlockPos from = new BlockPos(portal.getMinX(), portal.getMinY(), portal.getMinZ());
|
||||
BlockPos to = new BlockPos(portal.getMaxX(), portal.getMaxY(), portal.getMaxZ());
|
||||
|
||||
|
@ -70,59 +116,58 @@ public class PortalListComponent implements Component {
|
|||
}
|
||||
|
||||
}
|
||||
LOGGER.debug("portals {}", tag.toString());
|
||||
LOGGER.info("portals {}", tag);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public List<BlockBox> getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) {
|
||||
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>()).stream()
|
||||
.filter((portalWithDim) -> (portalWithDim.second.equals(dim)
|
||||
&& portalWithDim.first.contains(pos)))
|
||||
.map((p) -> p.first)
|
||||
public List<PortalRepresentation> getContainingPortals(Identifier blockId, BlockPos pos, Identifier dim) {
|
||||
return getPortals(blockId).stream()
|
||||
.filter((portal) -> (portal.dimensionId().equals(dim) && portal.location().contains(pos)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
public void createPortal(Identifier blockId, Pair<BlockBox, Identifier> portalWithDim) {
|
||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
if (!portals.contains(portalWithDim)) {
|
||||
portals.add(portalWithDim);
|
||||
public void createPortal(Identifier blockId, PortalRepresentation portal) {
|
||||
LinkedList<PortalRepresentation> portalRepresentations = getPortals(blockId);
|
||||
if (!portalRepresentations.contains(portal)) {
|
||||
portalRepresentations.add(portal);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePortal(Identifier blockId, Pair<BlockBox, Identifier> portalWithDim) {
|
||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
portals.remove(portalWithDim);
|
||||
public void removePortal(Identifier blockId, PortalRepresentation portal) {
|
||||
getPortals(blockId).remove(portal);
|
||||
}
|
||||
|
||||
public List<Pair<BlockBox, Identifier>> getPortals(Identifier blockId) {
|
||||
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
public LinkedList<PortalRepresentation> getPortals(Identifier blockId) {
|
||||
return portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new LinkedList<>());
|
||||
}
|
||||
|
||||
|
||||
public Set<Identifier> getBlockIds() {
|
||||
return portalsPerPortalBlock.keySet();
|
||||
}
|
||||
|
||||
public Pair<BlockBox, Identifier> getNext(Identifier blockId, BlockBox portal, Identifier dim) {
|
||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal, dim);
|
||||
public PortalRepresentation getNext(Identifier blockId, PortalRepresentation portalRepresentationWithDim) {
|
||||
LOGGER.info("gn");
|
||||
LinkedList<PortalRepresentation> portals = getPortals(blockId);
|
||||
Node<PortalRepresentation> node;
|
||||
if ((node = portals.getNodeOf(portalRepresentationWithDim)) == null) {
|
||||
|
||||
int nextIndex = portals.indexOf(portalWithDim) + 1;
|
||||
if (nextIndex >= portals.size()) {
|
||||
return portals.get(0);
|
||||
return portals.getFirst();
|
||||
}
|
||||
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) {
|
||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
return portals.contains(portal);
|
||||
public PortalRepresentation getLast(Identifier blockId) {
|
||||
return getPortals(blockId).getLast();
|
||||
}
|
||||
|
||||
public Pair<BlockBox, Identifier> getLast(Identifier blockId) {
|
||||
List<Pair<BlockBox, Identifier>> portals = portalsPerPortalBlock.computeIfAbsent(blockId, (i) -> new ArrayList<>());
|
||||
return portals.get(portals.size()-1);
|
||||
public Identifier lastPortalLinkingSystemId() {
|
||||
return lastPortalLinkingSystem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,41 +9,50 @@ import net.minecraft.server.MinecraftServer;
|
|||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.DyeColor;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.TypeFilter;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import qouteall.imm_ptl.core.api.PortalAPI;
|
||||
import qouteall.imm_ptl.core.portal.Portal;
|
||||
import qouteall.q_misc_util.my_util.DQuaternion;
|
||||
import quimufu.colourful_portals.config.ColourfulPortalConfig;
|
||||
import quimufu.colourful_portals.util.Pair;
|
||||
import quimufu.colourful_portals.general_util.LinkedList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.*;
|
||||
import static quimufu.colourful_portals.Components.PORTAL_CANDIDATE_LIST;
|
||||
import static quimufu.colourful_portals.Components.PORTAL_LIST;
|
||||
|
||||
public class PortalManager {
|
||||
|
||||
public static void onPortalBlockPlaced(ServerWorld world, BlockPos pos, Identifier blockId) {
|
||||
private final PortalListComponent portalCandidateList;
|
||||
private final PortalListComponent portalList;
|
||||
|
||||
public PortalLinkingSystem getLinkingSystem() {
|
||||
return linkingSystem;
|
||||
}
|
||||
|
||||
private final PortalLinkingSystem linkingSystem;
|
||||
|
||||
public PortalManager(PortalLinkingSystem portalLinkingSystem, PortalListComponent portalCandidateList, PortalListComponent portalList) {
|
||||
this.portalCandidateList = portalCandidateList;
|
||||
this.portalList = portalList;
|
||||
this.linkingSystem = portalLinkingSystem;
|
||||
}
|
||||
|
||||
public void onPortalBlockPlaced(ServerWorld world, BlockPos pos, Identifier blockId) {
|
||||
world.getProfiler().push("onPortalBlockPlaced");
|
||||
LOGGER.debug("onPortalBlockPlaced, {}", blockId);
|
||||
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
//delete portalCandidates obstructed by PortalBlocks for consistency
|
||||
List<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());
|
||||
Identifier dimIdentifier = getDimId(world);
|
||||
|
||||
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
|
||||
|
@ -51,28 +60,26 @@ public class PortalManager {
|
|||
LOGGER.debug("new portalCandidates found, {}", portals);
|
||||
|
||||
for (BlockBox portal : portals) {
|
||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal, world.getDimensionKey().getValue());
|
||||
portalCandidateList.createPortal(blockId, portalWithDim);
|
||||
PortalRepresentation portalRepresentationWithDim = new PortalRepresentation(portal, dimIdentifier);
|
||||
portalCandidateList.createPortal(blockId, portalRepresentationWithDim);
|
||||
}
|
||||
world.getProfiler().pop();
|
||||
}
|
||||
|
||||
public static void onPortalBlockBroken(ServerWorld world, BlockPos pos, Identifier blockId) {
|
||||
public void onPortalBlockBroken(ServerWorld world, BlockPos pos, Identifier blockId) {
|
||||
world.getProfiler().push("onPortalBlockBroken");
|
||||
LOGGER.debug("onPortalBlockBroken, {}", blockId);
|
||||
|
||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
|
||||
//check portalCandidate validity
|
||||
List<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);
|
||||
for (BlockBox portalCandidate : portalCandidates) {
|
||||
if (!PortalHelper.isValidCandidate(world, portalCandidate, blockId)) {
|
||||
for (PortalRepresentation portalCandidate : portalCandidates) {
|
||||
if (!PortalHelper.isValidCandidate(world, portalCandidate.location(), blockId)) {
|
||||
LOGGER.debug("invalid, {}", portalCandidate);
|
||||
Pair<BlockBox, Identifier> portalWithDim =
|
||||
Pair.of(portalCandidate, world.getDimensionKey().getValue());
|
||||
portalCandidateList.removePortal(blockId, portalWithDim);
|
||||
portalCandidateList.removePortal(blockId, portalCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,25 +91,23 @@ public class PortalManager {
|
|||
LOGGER.debug("potentially new candidate after deobstruction , {}", newPortal);
|
||||
|
||||
PortalListComponent portalListComponent = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
Pair<BlockBox, Identifier> portalWithDim =
|
||||
Pair.of(newPortal, world.getDimensionKey().getValue());
|
||||
portalListComponent.createPortal(blockId, portalWithDim);
|
||||
PortalRepresentation portalRepresentationWithDim =
|
||||
new PortalRepresentation(newPortal, dimensionIdentifier);
|
||||
portalListComponent.createPortal(blockId, portalRepresentationWithDim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//check portal validity
|
||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, world.getDimensionKey().getValue());
|
||||
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dimensionIdentifier);
|
||||
boolean changed = false;
|
||||
for (BlockBox portal : portals) {
|
||||
if (!PortalHelper.isValidPortal(world, portal, blockId)) {
|
||||
LOGGER.debug("portal became invalid ,{} {}", world.getDimensionKey().getValue(), portal);
|
||||
for (PortalRepresentation portal : portals) {
|
||||
if (!PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||
LOGGER.debug("portal became invalid ,{} {}", dimensionIdentifier, portal);
|
||||
|
||||
Pair<BlockBox, Identifier> portalWithDim =
|
||||
Pair.of(portal, world.getDimensionKey().getValue());
|
||||
portalList.removePortal(blockId, portalWithDim);
|
||||
destroyPortalEntitiesInside(world, Box.from(portal));
|
||||
removePortalBlocks(world, portal);
|
||||
portalList.removePortal(blockId, portal);
|
||||
linkingSystem.unLinkPortal(portal);
|
||||
removePortalBlocks(world, portal.location());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -114,49 +119,47 @@ public class PortalManager {
|
|||
world.getProfiler().pop();
|
||||
}
|
||||
|
||||
private static void removePortalBlocks(ServerWorld world, BlockBox portal) {
|
||||
private void removePortalBlocks(ServerWorld world, BlockBox portal) {
|
||||
BlockPos.stream(portal)
|
||||
.filter(blockPos -> world.getBlockState(blockPos).isOf(PORTAL_BLOCK))
|
||||
.forEach(blockPos -> world.setBlockState(blockPos, Blocks.AIR.getDefaultState()));
|
||||
}
|
||||
|
||||
private static void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) {
|
||||
List<Pair<BlockBox, Identifier>> portalsWithDim = portalList.getPortals(blockId);
|
||||
private void fixPortalGroup(Identifier blockId, PortalListComponent portalList, MinecraftServer server) {
|
||||
LinkedList<PortalRepresentation> portalsWithDim = portalList.getPortals(blockId);
|
||||
if (portalsWithDim.size() == 1) {
|
||||
Pair<BlockBox, Identifier> portal = portalsWithDim.get(0);
|
||||
ServerWorld world = getPortalWorld(portal, server);
|
||||
PortalRepresentation portalRepresentation = portalsWithDim.getFirst();
|
||||
ServerWorld world = getPortalWorld(portalRepresentation, server);
|
||||
if (world == null) {
|
||||
LOGGER.error("error fixing portalGroup, world {} was null", portal.second);
|
||||
LOGGER.error("error fixing portalGroup, dimensionId {} was null", portalRepresentation.dimensionId());
|
||||
return;
|
||||
}
|
||||
Pair<BlockBox, Identifier> portalWithDim = Pair.of(portal.first, portal.second);
|
||||
portalList.removePortal(blockId, portalWithDim);
|
||||
destroyPortalEntitiesInside(world, Box.from(portal.first));
|
||||
removePortalBlocks(world, portal.first);
|
||||
portalList.removePortal(blockId, portalRepresentation);
|
||||
linkingSystem.unLinkPortal(portalRepresentation);
|
||||
removePortalBlocks(world, portalRepresentation.location());
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < portalsWithDim.size(); i++) {
|
||||
Pair<BlockBox, Identifier> portal = portalsWithDim.get(i);
|
||||
Pair<BlockBox, Identifier> linkedToPortal = i + 1 < portalsWithDim.size() ? portalsWithDim.get(i + 1) : portalsWithDim.get(0);
|
||||
assureLinkedTo(portal, linkedToPortal, server);
|
||||
assurePortalBlocksPlaced(blockId, portal, server);
|
||||
for (PortalRepresentation portalRepresentation : portalsWithDim) {
|
||||
assurePortalBlocksPlaced(blockId, portalRepresentation, server);
|
||||
}
|
||||
linkingSystem.linkPortals(portalsWithDim);
|
||||
|
||||
}
|
||||
|
||||
private static void assurePortalBlocksPlaced(Identifier blockId, Pair<BlockBox, Identifier> portal, MinecraftServer server) {
|
||||
DyeColor color = ColourfulPortalConfig.portalBlocks.get(blockId.toString());
|
||||
private void assurePortalBlocksPlaced(Identifier blockId, PortalRepresentation portalRepresentation, MinecraftServer server) {
|
||||
DyeColor color = ColourfulPortalConfig.colorOf(blockId.toString());
|
||||
if (color != null) {
|
||||
Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portal.first)
|
||||
Direction.Axis portalPlaneAxis = PortalHelper.getAxisW(portalRepresentation.location())
|
||||
.rotateClockwise(Direction.Axis.Y)
|
||||
.getAxis();
|
||||
ServerWorld portalWorld = getPortalWorld(portal, server);
|
||||
ServerWorld portalWorld = getPortalWorld(portalRepresentation, server);
|
||||
if (portalWorld == null) {
|
||||
LOGGER.error("error placing portal planes, world {} was null", portal.second);
|
||||
LOGGER.error("error placing portalRepresentation planes, dimensionId {} was null", portalRepresentation.dimensionId());
|
||||
return;
|
||||
}
|
||||
BlockState portalBlockState = PORTAL_BLOCK.getStateWith(color, portalPlaneAxis);
|
||||
|
||||
PortalHelper.insideOf(portal.first)
|
||||
PortalHelper.insideOf(portalRepresentation.location())
|
||||
.forEachRemaining(blockPos -> {
|
||||
BlockState blockState = portalWorld.getBlockState(blockPos);
|
||||
if (blockState.isAir() || blockState.getFluidState().isOf(PORTAL_FLUID)) {
|
||||
|
@ -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
|
||||
private static ServerWorld getPortalWorld(Pair<BlockBox, Identifier> fromPortal, MinecraftServer server) {
|
||||
return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortal.second));
|
||||
private ServerWorld getPortalWorld(PortalRepresentation fromPortalRepresentation, MinecraftServer server) {
|
||||
return server.getWorld(RegistryKey.of(RegistryKeys.WORLD, fromPortalRepresentation.dimensionId()));
|
||||
}
|
||||
|
||||
private static void destroyPortalEntitiesInside(ServerWorld world, Box box) {
|
||||
List<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) {
|
||||
public boolean tryIgnite(ServerWorld world, BlockPos pos) {
|
||||
world.getProfiler().push("portal ignition");
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
||||
LOGGER.info("portal ignition");
|
||||
Set<Identifier> blockIds = portalCandidateList.getBlockIds();
|
||||
boolean ret = false;
|
||||
for (Identifier blockId : blockIds) {
|
||||
Identifier dim = world.getDimensionKey().getValue();
|
||||
List<BlockBox> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim);
|
||||
for (BlockBox portalCandidate : portalCandidates) {
|
||||
if (PortalHelper.isValidPortal(world, portalCandidate, blockId)) {
|
||||
Pair<BlockBox, Identifier> current = Pair.of(portalCandidate, dim);
|
||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, portalCandidate, dim);
|
||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
||||
Identifier dim = getDimId(world);
|
||||
List<PortalRepresentation> portalCandidates = portalCandidateList.getContainingPortals(blockId, pos, dim);
|
||||
for (PortalRepresentation current : portalCandidates) {
|
||||
if (PortalHelper.isValidPortal(world, current.location(), blockId)) {
|
||||
PortalRepresentation next = portalCandidateList.getNext(blockId, current);
|
||||
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||
if (!next.equals(current)
|
||||
&& (!portalList.containsPortal(blockId, current) || !portalList.containsPortal(blockId, next))
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)) {
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||
portalList.createPortal(blockId, current);
|
||||
portalList.createPortal(blockId, next);
|
||||
ret = true;
|
||||
|
@ -275,24 +206,21 @@ public class PortalManager {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static boolean canExtend(ServerWorld world, BlockPos pos) {
|
||||
public boolean canExtend(ServerWorld world, BlockPos pos) {
|
||||
world.getProfiler().push("portal extension check");
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
||||
Set<Identifier> blockIds = portalList.getBlockIds();
|
||||
Identifier dim = world.getDimensionKey().getValue();
|
||||
Identifier dim = getDimId(world);
|
||||
|
||||
for (Identifier blockId : blockIds) {
|
||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||
for (BlockBox portal : portals) {
|
||||
if (PortalHelper.isValidPortal(world, portal, blockId)) {
|
||||
Pair<BlockBox, Identifier> last = portalList.getLast(blockId);
|
||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, last.first, last.second);
|
||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
||||
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||
for (PortalRepresentation portal : portals) {
|
||||
if (PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||
PortalRepresentation last = portalList.getLast(blockId);
|
||||
PortalRepresentation next = portalCandidateList.getNext(blockId, last);
|
||||
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||
|
||||
if (!portalList.containsPortal(blockId, next)
|
||||
&& PortalHelper.isValidPortal(world, portal, blockId)
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||
world.getProfiler().pop();
|
||||
return true;
|
||||
}
|
||||
|
@ -305,25 +233,22 @@ public class PortalManager {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean extend(ServerWorld world, BlockPos pos) {
|
||||
public boolean extend(ServerWorld world, BlockPos pos) {
|
||||
world.getProfiler().push("portal extension");
|
||||
PortalListComponent portalCandidateList = PORTAL_CANDIDATE_LIST.get(world.getLevelProperties());
|
||||
PortalListComponent portalList = PORTAL_LIST.get(world.getLevelProperties());
|
||||
Set<Identifier> blockIds = portalList.getBlockIds();
|
||||
Identifier dim = world.getDimensionKey().getValue();
|
||||
Identifier dim = getDimId(world);
|
||||
|
||||
boolean ret = false;
|
||||
for (Identifier blockId : blockIds) {
|
||||
List<BlockBox> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||
for (BlockBox portal : portals) {
|
||||
if (PortalHelper.isValidPortal(world, portal, blockId)) {
|
||||
Pair<BlockBox, Identifier> last = portalList.getLast(blockId);
|
||||
Pair<BlockBox, Identifier> next = portalCandidateList.getNext(blockId, last.first, last.second);
|
||||
ServerWorld nextWorld = world.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, next.second));
|
||||
List<PortalRepresentation> portals = portalList.getContainingPortals(blockId, pos, dim);
|
||||
for (PortalRepresentation portal : portals) {
|
||||
if (PortalHelper.isValidPortal(world, portal.location(), blockId)) {
|
||||
PortalRepresentation last = portalList.getLast(blockId);
|
||||
PortalRepresentation next = portalCandidateList.getNext(blockId, last);
|
||||
ServerWorld nextWorld = getPortalWorld(next, world.getServer());
|
||||
|
||||
if (!portalList.containsPortal(blockId, next)
|
||||
&& PortalHelper.isValidPortal(world, portal, blockId)
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.first, blockId)){
|
||||
&& PortalHelper.isPortalPlaceable(nextWorld, next.location(), blockId)) {
|
||||
portalList.createPortal(blockId, next);
|
||||
ret = true;
|
||||
}
|
||||
|
@ -336,4 +261,12 @@ public class PortalManager {
|
|||
world.getProfiler().pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Identifier getDimId(ServerWorld world) {
|
||||
return world.getDimensionEntry().getKey().orElseThrow().getValue();
|
||||
}
|
||||
|
||||
public void onPortalPassed(Entity entity, BlockPos pos, ServerWorld world, Direction.Axis a) {
|
||||
linkingSystem.onPortalPassed(entity, pos, world, a);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 static quimufu.colourful_portals.ColourfulPortalsMod.LOGGER;
|
||||
import static quimufu.colourful_portals.ColourfulPortalsMod.PORTAL_MANAGER;
|
||||
|
||||
public class PortalFluid extends Fluid {
|
||||
public static final EnumProperty<NullableAxis> AXIS = EnumProperty.of("axis", NullableAxis.class);
|
||||
|
@ -138,7 +139,7 @@ public class PortalFluid extends Fluid {
|
|||
}
|
||||
|
||||
if (amount <= 14) {
|
||||
//*might* change my state in world, returned value is what new state should be
|
||||
//*might* change my state in dimensionId, returned value is what new state should be
|
||||
newStateMe = steal(world, pos, newStateMe, currentAxis);
|
||||
}
|
||||
//my state might have changed.
|
||||
|
@ -169,7 +170,7 @@ public class PortalFluid extends Fluid {
|
|||
} else if (!world.isClient) {
|
||||
for (Direction direction : Direction.values()) {
|
||||
if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(world.getBlockState(pos.offset(direction)).getBlock()))
|
||||
&& PortalManager.tryIgnite((ServerWorld) world, pos)) {
|
||||
&& PORTAL_MANAGER.tryIgnite((ServerWorld) world, pos)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +373,7 @@ public class PortalFluid extends Fluid {
|
|||
BlockPos neighborOfInspectedLocation = inspectedLocation.offset(dir);
|
||||
BlockState neighbourOfInspected = world.getBlockState(neighborOfInspectedLocation);
|
||||
|
||||
//if adjacent to a Portal Block, 2 less
|
||||
//if adjacent to a PortalRepresentation Block, 2 less
|
||||
if (ColourfulPortalsMod.PORTAL_BLOCKS.contains(Registries.BLOCK.getId(neighbourOfInspected.getBlock()))) {
|
||||
dirCost -= 2;
|
||||
discount = false;
|
||||
|
@ -381,7 +382,7 @@ public class PortalFluid extends Fluid {
|
|||
//if adjacent to any solid Block, 1 less
|
||||
if (neighbourOfInspected.isSideSolidFullSquare(world, neighborOfInspectedLocation, dir.getOpposite())) {
|
||||
discount = true;
|
||||
//maybe a Portal Block in another direction
|
||||
//maybe a PortalRepresentation Block in another direction
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public class PortalFluidBlock
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
||||
protected boolean canPathfindThrough(BlockState state, NavigationType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_fluid_block": "Farbenfrohe Flüssigkeit",
|
||||
"colourful_portals.midnightconfig.black": "Blöcke, die schwarze Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.blue": "Blöcke, die blaue Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.brown": "Blöcke, die braune Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.cyan": "Blöcke, die cyanfarbene Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.disableImmersivePortals": "Immersive Portals integration deaktivieren",
|
||||
"colourful_portals.midnightconfig.explanation": "Diese Konfiguration erlaubt es, zusätzliche/andere Portalblocke zu definieren.\nPortale aus diesen verbinden sich mit anderen aus dem selben Block.\nDie Liste, der der Block hinzugefügt wird, bestimmt dabei nur die Portalfarbe.\nÄnderungen treten für neue Portale oder bei Aktualisierung eines Portals in Kraft.",
|
||||
"colourful_portals.midnightconfig.gray": "Blöcke, die graue Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.green": "Blöcke, die grüne Portale erstellen",
|
||||
"colourful_portals.midnightconfig.light_blue": "Blöcke, die hellblaue Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.light_gray": "Blöcke, die hellgraue Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.lime": "Blöcke, die limonenfarbene Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.magenta": "Blöcke, die magentafarbene Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.none": "Blöcke, die vollständig transparente Portale erstellen",
|
||||
"colourful_portals.midnightconfig.orange": "Blöcke, die orangefarbene Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.pink": "Blöcke, die rosa Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.purple": "Blöcke, die violette Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.red": "Blöcke, die rote Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.white": "Blöcke, die weiße Portale erzeugen",
|
||||
"colourful_portals.midnightconfig.yellow": "Blöcke, die gelbe Portale erzeugen",
|
||||
"item.colourful_portals.colour_blob_bright": "Heller Farbmix",
|
||||
"item.colourful_portals.colour_blob_dark": "Dunkler Farbmix",
|
||||
"block.colourful_portals.portal_fluid_block": "Farbenfrohe Flüssigkeit"
|
||||
"item.colourful_portals.portal_fluid_bucket": "Farbeimer"
|
||||
}
|
|
@ -1,7 +1,26 @@
|
|||
{
|
||||
"item.colourful_portals.portal_fluid_bucket": "Colourful Bucket",
|
||||
"block.colourful_portals.portal_block": "Colourful Portal",
|
||||
"block.colourful_portals.portal_fluid_block": "Colourful Fluid",
|
||||
"colourful_portals.midnightconfig.disableImmersivePortals": "Disable Immersive Portals integration",
|
||||
"colourful_portals.midnightconfig.black": "Blocks that create black portals",
|
||||
"colourful_portals.midnightconfig.blue": "Blocks that create blue portals",
|
||||
"colourful_portals.midnightconfig.brown": "Blocks that create brown portals",
|
||||
"colourful_portals.midnightconfig.cyan": "Blocks that create cyan portals",
|
||||
"colourful_portals.midnightconfig.explanation": "This configuration allows you to define additional/other portal blocks.\nPortals from these connect to others from the same block.\nThe list to which the block is added only determines the portal color.\nChanges take effect for new portals or when a portal is updated.",
|
||||
"colourful_portals.midnightconfig.gray": "Blocks that create gray portals",
|
||||
"colourful_portals.midnightconfig.green": "Blocks that create green portals",
|
||||
"colourful_portals.midnightconfig.light_blue": "Blocks that create light blue portals",
|
||||
"colourful_portals.midnightconfig.light_gray": "Blocks that create light gray portals",
|
||||
"colourful_portals.midnightconfig.lime": "Blocks that create lime portals",
|
||||
"colourful_portals.midnightconfig.magenta": "Blocks that create magenta portals",
|
||||
"colourful_portals.midnightconfig.none": "Blocks that create fully transparent portals",
|
||||
"colourful_portals.midnightconfig.orange": "Blocks that create orange portals",
|
||||
"colourful_portals.midnightconfig.pink": "Blocks that create pink portals",
|
||||
"colourful_portals.midnightconfig.purple": "Blocks that create purple portals",
|
||||
"colourful_portals.midnightconfig.red": "Blocks that create red portals",
|
||||
"colourful_portals.midnightconfig.white": "Blocks that create white portals",
|
||||
"colourful_portals.midnightconfig.yellow": "Blocks that create yellow portals",
|
||||
"item.colourful_portals.colour_blob_bright": "Bright Colour Mix",
|
||||
"item.colourful_portals.colour_blob_dark": "Dark Colour Mix",
|
||||
"block.colourful_portals.portal_block": "Colourful Portal",
|
||||
"block.colourful_portals.portal_fluid_block": "Colourful Fluid"
|
||||
"item.colourful_portals.portal_fluid_bucket": "Colourful Bucket"
|
||||
}
|
|
@ -3,17 +3,18 @@
|
|||
"package": "quimufu.colourful_portals.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"BlockChangeMixin"
|
||||
"BlockChangeMixin",
|
||||
"EntityMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"plugin": "quimufu.colourful_portals.MixinConfig",
|
||||
"client": [
|
||||
"AnimationResourceMetadataReaderMixin",
|
||||
"AnimationMixin",
|
||||
"AnimationResourceMetadataMixin",
|
||||
"SpriteContentsMixin",
|
||||
"SodiumFluidRendererMixin"
|
||||
"AnimationResourceMetadataReaderMixin",
|
||||
"SodiumFluidRendererMixin",
|
||||
"SpriteContentsMixin"
|
||||
]
|
||||
}
|
|
@ -42,9 +42,8 @@
|
|||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=${loader_version}",
|
||||
"immersive_portals": ">=${immersive_portals_version_short}",
|
||||
"minecraft": "~${minecraft_version}",
|
||||
"java": ">=17",
|
||||
"java": ">=21",
|
||||
"fabric-api": "*"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user