diff --git a/README.md b/README.md index 8b1bc0f21..b828b4cd7 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,40 @@ -![Paladin's Furniture Mod Banner](https://github.com/UnlikePaladin/paladin-furniture-mod/blob/main/docs/banner.png?raw=true) +![Paladin's Furniture Mod Banner](./docs/banner.png?raw=true) + +

+ fabric + forge + quilt +

+ ## Description -A Brand-New Furniture mod for Modern Minecraft where things are functional! It contains over 1,000 New Pieces of Furniture that you can use to furnish your build, while being functional and nice to look at. Everything is craftable and obtainable in Survival so it's friendly, and nice to look at, it has Compatibility with Sandwichable, REI, EMI and Patchouli. The mod has been in development for roughly 1 year but I don't plan on stopping with new updates, adding new furniture and mod compat with other mods! +A Brand-New Furniture mod for Modern Minecraft where things are functional! It contains over 1,000 New Pieces of Furniture that you can use to furnish your build, while being functional and nice to look at. Everything is craftable and obtainable in Survival so it's friendly, and nice to look at, it has compatibility with Sandwichable, REI, JEI, EMI, Patchouli, CookingForBlockHeads, Farmer's Delight and features modded wood type support. The mod has been in development for roughly 2 years but I don't plan on stopping with new updates, adding new furniture and mod compat with other mods! ![A Kitchen](https://cdn.discordapp.com/attachments/930656475741814804/1010808630683115611/2022-08-18_23.34.12.png) ## Installation -You will need Fabric Loader 0.14.6 or newer installed in your game in order to load this mod. If you haven't installed Fabric mods before, you can find a variety of community guides for doing so [here](https://fabricmc.net/wiki/install). +You will need Fabric Loader, Quilt Loader, NeoForge or MinecraftForge installed in your game in order to load this mod. If you haven't installed mods before, you can find a variety of community guides for doing so [here for Fabric](https://fabricmc.net/wiki/install) and [here for Forge](https://www.wikihow.com/Install-Minecraft-Forge). + +You will also need Fabric API installed if you're playing on Fabric to use the mod, you can get it [here](https://modrinth.com/mod/fabric-api). If you're playing with Sodium installed you will need [Indium](https://modrinth.com/mod/indium). + +The mod is available for versions 1.16.5 through 1.20.2 find the links further below. + +I have a [Discord](https://discord.gg/zbMDUPB) server that you can join if you need help or support with the mod, or if you would like to give me any feedback, I also provide compiled builds for testing new features before they make their way into public releases in it, so join if you'd like to keep up with the latest developments. -You will also need Fabric API and Cloth Config installed to use the mod, you can get that [here](https://modrinth.com/mod/fabric-api) and [here](https://modrinth.com/mod/cloth-config). +## Links +[discord]: https://discord.com/api/guilds/695034549045952592/widget.png +[modrinth]: https://img.shields.io/badge/Modrinth-1bd96a?logo=modrinth&logoColor=ffffff +[curseforge]: https://img.shields.io/badge/CurseForge-f16436?logo=curseforge&logoColor=ffffff +[github]: https://img.shields.io/badge/GitHub-181717?logo=github +[kofi]: https://img.shields.io/badge/Ko--fi-00b9fe?logo=kofi&logoColor=ffffff +[mcforum]: https://img.shields.io/badge/Minecraft-Forum-white?style=flat&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAAXNSR0IArs4c6QAAAUBJREFUOE9jZGBgYGRAA%2FFdKq4gIS5toe0g%2BtvVd54gemHZnd3oakGa4Qaga0RXjM0gsAGENOIzCGxA5lazP%2BiKiOFP9z7FQrYBT8%2B8YdpUf48JbIBfo9I%2FaRORf8TYClID0vzl%2BjeGfSteIAxA1ozLMJBGkDqQZhCAG9AY5%2FT3rPIDRpAEjyYXA7oBMBuRLdF4w%2Fdn2p5bbGAvgAyASR78dQ0crSCDkAHMVpBGmDhWA0CSnz9%2F%2Fg2iz7E%2FZgPRyJrACYyX%2F9%2B3zx%2BZ4AaUBJr%2B4OXlZYVphrFB%2FJfPnvyFaUDWDBLrWX%2BaA%2B4FkK3IGmHOBImDbMMWQ3AXgFKi0hW5HdgMgbkAZDiIDTPoq9s%2Fb1DegOcFWHKGGQRSiK4JJAbTCDMIJTOBBEEGiR4X3IzNAJCT8eZGZEmYQbDQxpVKAZ8ywSEpbPKhAAAAAElFTkSuQmCC&labelColor=52a435&color=52a435 +[pmc]: https://img.shields.io/badge/Planet-Minecraft-white?style=flat&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAATlBMVEX%2F%2F%2F8BV6kBV6kAAAAqVAEqVAFXsQ8nju1uwxBXqv89ov9LqP9EgAH%2F%2F%2F8vXAExmPcNdNMulfQBJkdYrgEBTpYTLi8BJkcTLi8Odcw8Kh1AKvelAAAAGnRSTlMA%2FwAAAP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwD%2F%2F%2F%2F%2F%2F%2F%2F%2FAAD%2FAHaBDEMAAADwSURBVHgBrNAHloQgEEVRlGhW0sz%2BVzp8quEYJ7%2BOWNfIdjW1lrNjIrcDAu2UzCmkEa3Zt0EeGdQZ0%2Ff9MGg9pqQUe4B56gZwAqgCiD1IswlVgAD4CZgb0Lbt7gimACTlLAQeHy5gdwpqWZY1HUN%2BC5hXZToM6Sud4t9BTw2IwLgH%2FRcAo68BRjTetu1yDY%2FAWts0zrm0oRydpuvqZQiBRQCtIQzaA28rSLlb8MYYi02TVmmbKmFKILJ78H4E1vrcWKO1tV%2BCCADhc%2Bt6AYy%2FBMpMIo8VHR%2BgCo8w93VOAAL5XAZYMgK8RoehYtn4MUkA1WIkb6ajLTUAAAAASUVORK5CYII%3D&labelColor=6fa1ce&color=6fa1ce +### Social: [ ![discord] ](https://discord.gg/zbMDUPB) +### Download: [ ![modrinth] ](https://modrinth.com/mod/paladins-furniture) [ ![curseforge] ](https://www.curseforge.com/minecraft/mc-mods/paladins-furniture) [![pmc]](https://www.planetminecraft.com/mod/paladin-s-furniture-mod/) [ ![mcforum] ](https://www.curseforge.com/minecraft/mc-mods/paladins-furniture) +### Donate: [ ![kofi] ](https://ko-fi.com/unlikepaladin) -The mod is avaialbe for versions 1.16.5 through 1.19.2 and can be downloaded off of [CurseForge](https://www.curseforge.com/minecraft/mc-mods/paladins-furniture), [Modrinth](https://modrinth.com/mod/paladins-furniture), [PlanetMC](https://www.planetminecraft.com/mod/paladin-s-furniture-mod/) and the [Minecraft Forum](https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/3159314-paladins-furniture-mod). -I've made a [Discord](https://discord.gg/zbMDUPB), you can join to ask for help or support, or to give any feedback, I'll also be providing compiled builds for testing new features before they make their way into public releases. ## License diff --git a/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java b/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java index ac54cab96..968ca3d80 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java +++ b/common/src/main/java/com/unlikepaladin/pfm/PaladinFurnitureMod.java @@ -54,7 +54,7 @@ public void commonInit() { if (getModList().contains("farmersdelight")) pfmModCompatibilities.add(PFMFarmersDelight.getInstance()); if (getModList().contains("imm_ptl_core") || getModList().contains("immersive_portals")) - pfmModCompatibilities.add(new PFMImmersivePortals()); + pfmModCompatibilities.add(PFMImmersivePortals.getInstance()); } diff --git a/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java b/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java index 43b3f927f..4ae1f3b5b 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java +++ b/common/src/main/java/com/unlikepaladin/pfm/blocks/models/ModelHelper.java @@ -347,6 +347,10 @@ public static Identifier getLogId(Block block, String postFix) { if (idExists(id, ResourceType.CLIENT_RESOURCES, IdLocation.TEXTURES)) { return id; } + id = new Identifier(namespace, "block/alpha_oak_log"); + if (idExists(id, ResourceType.CLIENT_RESOURCES, IdLocation.TEXTURES)) { + return id; + } } return new Identifier(namespace, "block/" + path); } diff --git a/common/src/main/java/com/unlikepaladin/pfm/client/PathPackRPWrapper.java b/common/src/main/java/com/unlikepaladin/pfm/client/PathPackRPWrapper.java new file mode 100644 index 000000000..6c8b81e01 --- /dev/null +++ b/common/src/main/java/com/unlikepaladin/pfm/client/PathPackRPWrapper.java @@ -0,0 +1,70 @@ +package com.unlikepaladin.pfm.client; + +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceType; +import net.minecraft.resource.metadata.PackResourceMetadata; +import net.minecraft.resource.metadata.ResourceMetadataReader; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.Set; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public class PathPackRPWrapper implements ResourcePack { + private final Supplier delegate; + private final PackResourceMetadata packResourceMetadata; + + public PathPackRPWrapper(Supplier delegate, PackResourceMetadata packResourceMetadata) { + this.delegate = delegate; + this.packResourceMetadata = packResourceMetadata; + } + + @Nullable + @Override + public InputStream openRoot(String fileName) throws IOException { + return null; + } + + @Override + public InputStream open(ResourceType type, Identifier id) throws IOException { + return delegate.get().open(type, id); + } + + @Override + public Collection findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate pathFilter) { + return delegate.get().findResources(type, namespace, prefix, maxDepth, pathFilter); + } + + @Override + public boolean contains(ResourceType type, Identifier id) { + return delegate.get().contains(type, id); + } + + @Override + public Set getNamespaces(ResourceType type) { + return delegate.get().getNamespaces(type); + } + + @Nullable + @Override + public T parseMetadata(ResourceMetadataReader metaReader) throws IOException { + if (metaReader.getKey().equals("pack")) { + return (T) packResourceMetadata; + } + return null; + } + + @Override + public String getName() { + return "PFM-Runtime-RP"; + } + + @Override + public void close() { + delegate.get().close(); + } +} diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java b/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java index 34de86fd2..5267b7a1e 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java +++ b/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMImmersivePortals.java @@ -1,46 +1,11 @@ package com.unlikepaladin.pfm.compat.imm_ptl; -import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; import com.unlikepaladin.pfm.compat.PFMModCompatibility; -import com.unlikepaladin.pfm.compat.imm_ptl.client.PFMImmersivePortalsClient; -//import com.unlikepaladin.pfm.compat.imm_ptl.entity.PFMMirrorEntity; -import com.unlikepaladin.pfm.compat.imm_ptl.entity.PFMMirrorEntity; -import com.unlikepaladin.pfm.registry.EntityRegistry; -import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; -import net.minecraft.block.AbstractBlock; -import net.minecraft.block.MapColor; -import net.minecraft.block.Material; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; +import dev.architectury.injectables.annotations.ExpectPlatform; -import java.util.Optional; - -public class PFMImmersivePortals implements PFMModCompatibility { - private PFMClientModCompatibility clientModCompatibility; - public PFMImmersivePortals(){ - } - public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); - - @Override - public void registerEntityTypes() { - EntityRegistry.registerEntityType("mirror_entity", MIRROR); - } - - @Override - public void createBlocks() { - PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.WHITE).nonOpaque()); - PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.GRAY).nonOpaque()); - } - - @Override - public String getModId() { - return "immersive_portals"; - } - - @Override - public Optional getClientModCompatiblity() { - if (clientModCompatibility == null) - clientModCompatibility = new PFMImmersivePortalsClient(this); - return Optional.of(clientModCompatibility); +public class PFMImmersivePortals { + @ExpectPlatform + public static PFMModCompatibility getInstance() { + throw new AssertionError(); } } diff --git a/common/src/main/java/com/unlikepaladin/pfm/config/PaladinFurnitureModConfig.java b/common/src/main/java/com/unlikepaladin/pfm/config/PaladinFurnitureModConfig.java index dd25b2c36..3c1dce6bd 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/config/PaladinFurnitureModConfig.java +++ b/common/src/main/java/com/unlikepaladin/pfm/config/PaladinFurnitureModConfig.java @@ -36,7 +36,9 @@ public PaladinFurnitureModConfig(Path propertiesPath) { tablesOfDifferentMaterialsConnect = new BooleanConfigOption(new TranslatableText("pfm.option.tablesOfDifferentMaterialsConnect"), new TranslatableText("pfm.option.tablesOfDifferentMaterialsConnect.tooltip"), GAMEPLAY_OPTIONS, false, Side.SERVER), differentMirrorsConnect = new BooleanConfigOption(new TranslatableText("pfm.option.differentMirrorsConnect"), new TranslatableText("pfm.option.differentMirrorsConnect.tooltip"), GAMEPLAY_OPTIONS, false, Side.SERVER), enableBook = new BooleanConfigOption(new TranslatableText("pfm.option.enableBook"), new TranslatableText("pfm.option.enableBook.tooltip"), GAMEPLAY_OPTIONS, true, Side.SERVER), - mobsSitOnChairs = new BooleanConfigOption(new TranslatableText("pfm.option.mobsSitOnChairs"), new TranslatableText("pfm.option.mobsSitOnChairs.tooltip"), GAMEPLAY_OPTIONS, true, Side.SERVER) + mobsSitOnChairs = new BooleanConfigOption(new TranslatableText("pfm.option.mobsSitOnChairs"), new TranslatableText("pfm.option.mobsSitOnChairs.tooltip"), GAMEPLAY_OPTIONS, true, Side.SERVER), + renderImmersivePortalsMirrors = new BooleanConfigOption(new TranslatableText("pfm.option.renderImmersivePortalsMirrors"), new TranslatableText("pfm.option.renderImmersivePortalsMirrors.tooltip"), GAMEPLAY_OPTIONS, true, Side.SERVER), + spawnImmersivePortalsMirror = new BooleanConfigOption(new TranslatableText("pfm.option.spawnImmersivePortalsMirror"), new TranslatableText("pfm.option.spawnImmersivePortalsMirror.tooltip"), GAMEPLAY_OPTIONS, true, Side.CLIENT) ); this.propertiesPath = propertiesPath; } @@ -96,6 +98,12 @@ public boolean doMobsSitOnChairs() { public boolean isShaderSolidFixOn() { return shaderSolidFix.getValue(); } + public boolean doImmersivePortalsMirrorsRender() { + return renderImmersivePortalsMirrors.getValue(); + } + public boolean doImmersivePortalsMirrorsSpawn() { + return spawnImmersivePortalsMirror.getValue(); + } private BooleanConfigOption checkForUpdates; @@ -113,6 +121,8 @@ public boolean isShaderSolidFixOn() { private BooleanConfigOption enableBook; private BooleanConfigOption mobsSitOnChairs; + private BooleanConfigOption renderImmersivePortalsMirrors; + private BooleanConfigOption spawnImmersivePortalsMirror; public Path getPath() { @@ -143,6 +153,8 @@ public void load() throws IOException { enableBook.setValue("true".equals(properties.getProperty("enableBook"))); differentMirrorsConnect.setValue(!"false".equals(properties.getProperty("differentMirrorsConnect"))); mobsSitOnChairs.setValue("true".equals(properties.getProperty("mobsSitOnChairs"))); + renderImmersivePortalsMirrors.setValue("true".equals(properties.getProperty("renderImmersivePortalsMirrors"))); + spawnImmersivePortalsMirror.setValue("true".equals(properties.getProperty("spawnImmersivePortalsMirror"))); for (String key : options.keySet()) { if (!properties.containsKey(key.replace("pfm.option.", ""))){ @@ -169,6 +181,8 @@ public void save() throws IOException { properties.setProperty("enableBook",enableBook.getValue() ? "true" : "false"); properties.setProperty("differentMirrorsConnect", differentMirrorsConnect.getValue() ? "true" : "false"); properties.setProperty("mobsSitOnChairs", mobsSitOnChairs.getValue() ? "true" : "false"); + properties.setProperty("renderImmersivePortalsMirrors", renderImmersivePortalsMirrors.getValue() ? "true" : "false"); + properties.setProperty("spawnImmersivePortalsMirror", spawnImmersivePortalsMirror.getValue() ? "true" : "false"); // NB: This uses ISO-8859-1 with unicode escapes as the encoding try (OutputStream os = Files.newOutputStream(propertiesPath)) { diff --git a/common/src/main/java/com/unlikepaladin/pfm/data/materials/DynamicBlockRegistry.java b/common/src/main/java/com/unlikepaladin/pfm/data/materials/DynamicBlockRegistry.java index ebd700575..6fff2ac43 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/data/materials/DynamicBlockRegistry.java +++ b/common/src/main/java/com/unlikepaladin/pfm/data/materials/DynamicBlockRegistry.java @@ -66,7 +66,14 @@ public static void compatInit() { embur.addChild("wood", "embur_pedu_top"); embur.addChild("stripped_wood", "stripped_embur_pedu_top"); addBlockTypeFinder(WoodVariant.class, embur); - + WoodVariant.Finder emburOld = WoodVariant.Finder.simple( + "byg", "embur", "embur_planks", "embur_pedu"); + emburOld.addChild("stripped_log", "stripped_embur_pedu"); + emburOld.addChild("wood", "embur_pedu_hyphae"); + emburOld.addChild("stripped_wood", "stripped_embur_pedu_hyphae"); + emburOld.addChild("fence", "embur_fence"); + emburOld.addChild("slab", "embur_slab"); + addBlockTypeFinder(WoodVariant.class, emburOld); //mcreator mod with typos... addBlockTypeFinder(WoodVariant.class, WoodVariant.Finder.simple( diff --git a/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java b/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java index f4c212c1c..9c042f89c 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java +++ b/common/src/main/java/com/unlikepaladin/pfm/data/materials/WoodVariantRegistry.java @@ -60,7 +60,7 @@ public Optional getVariantFromBlock(Block baseBlock, Identifier blo } String namespace = blockId.getNamespace(); if (name != null && !namespace.equals("securitycraft") && - !namespace.equals("absentbydesign") && !(namespace.equals("terrestria") && path.contains("sakura")) && !(namespace.equals("betternether") && path.contains("nether_mushroom")) && !namespace.equals("chipped")) { + !namespace.equals("absentbydesign") && !(namespace.equals("terrestria") && path.contains("sakura")) && !(namespace.equals("betternether") && path.contains("nether_mushroom")) && !namespace.equals("chipped") && !(namespace.equals("regions_unexplored") && path.contains("alpha"))) { BlockState state = baseBlock.getDefaultState(); //can't check if the block is a full one, so I do this. Adding some checks here diff --git a/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java b/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java index 25ee8bab8..2e4cfc040 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java +++ b/common/src/main/java/com/unlikepaladin/pfm/registry/dynamic/LateBlockRegistry.java @@ -335,6 +335,7 @@ public static void registerBlocks() throws InvocationTargetException, Instantiat PaladinFurnitureModBlocksItems.LIGHT_SWITCH_ITEM = new LightSwitchItem(PaladinFurnitureModBlocksItems.LIGHT_SWITCH, new Item.Settings().group(PaladinFurnitureMod.FURNITURE_GROUP)); PaladinFurnitureModBlocksItems.furnitureEntryMap.put(LightSwitchBlock.class, new FurnitureEntry() {{ this.addBlock( LateBlockRegistry.registerLateBlock( "light_switch",() -> PaladinFurnitureModBlocksItems.LIGHT_SWITCH, false, PaladinFurnitureMod.FURNITURE_GROUP)); + PaladinFurnitureModBlocksItems.BLOCKS.add(PaladinFurnitureModBlocksItems.LIGHT_SWITCH); LateBlockRegistry.registerLateItem("light_switch",() -> PaladinFurnitureModBlocksItems.LIGHT_SWITCH_ITEM); }}); PaladinFurnitureModBlocksItems.furnitureEntryMap.put(BasicToiletBlock.class, new FurnitureEntry() {{ diff --git a/common/src/main/java/com/unlikepaladin/pfm/runtime/PFMDataGen.java b/common/src/main/java/com/unlikepaladin/pfm/runtime/PFMDataGen.java index f97c953c7..5e1edf1cc 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/runtime/PFMDataGen.java +++ b/common/src/main/java/com/unlikepaladin/pfm/runtime/PFMDataGen.java @@ -15,6 +15,10 @@ import com.unlikepaladin.pfm.runtime.data.PFMTagProvider; import com.unlikepaladin.pfm.utilities.PFMFileUtil; import net.minecraft.data.DataCache; +import net.minecraft.data.DataProvider; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceType; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,12 +35,22 @@ public class PFMDataGen { public static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); private final Path output; private final boolean logOrDebug; + public static boolean running = false; public PFMDataGen(Path output, boolean logOrDebug) { this.output = output; this.logOrDebug = logOrDebug; } public void run() throws IOException { if (!frozen) { + log("Packs:"); + for (ResourcePack pack : PFMRuntimeResources.RESOURCE_PACK_LIST) { + log("\tPack {}", pack.getName()); + for (String namespace : pack.getNamespaces(ResourceType.CLIENT_RESOURCES)) { + log("\t\tNamespace {}", namespace); + } + } + running = true; + frozen = true; Path modListPath = PFMRuntimeResources.getPFMDirectory().resolve("modsList"); Path hashPath = PFMRuntimeResources.getPFMDirectory().resolve("dataHash"); if (!modListPath.toFile().isFile()) { @@ -113,11 +127,11 @@ public void run() throws IOException { Files.deleteIfExists(modListPath); Files.createFile(modListPath); Files.write(PFMRuntimeResources.createDirIfNeeded(modListPath), PaladinFurnitureMod.getVersionMap().toString().replace("[", "").replace("]", "").getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + running = false; } else { log("Data Hash and Mod list matched, skipping generation"); } } - frozen = true; } public void log(String s, Object p0) { diff --git a/common/src/main/resources/assets/pfm/icon.png b/common/src/main/resources/assets/pfm/icon.png index f99bda95a..ec3be490a 100644 Binary files a/common/src/main/resources/assets/pfm/icon.png and b/common/src/main/resources/assets/pfm/icon.png differ diff --git a/common/src/main/resources/assets/pfm/lang/en_us.json b/common/src/main/resources/assets/pfm/lang/en_us.json index 541e295e9..625fa170f 100644 --- a/common/src/main/resources/assets/pfm/lang/en_us.json +++ b/common/src/main/resources/assets/pfm/lang/en_us.json @@ -1191,6 +1191,10 @@ "pfm.option.mobsSitOnChairs.tooltip": "If true non-player mobs will sit on chairs on contact.", "pfm.option.shaderSolidFix": "Translucent Shader Fix", "pfm.option.shaderSolidFix.tooltip": "Makes furniture with translucent parts opaque to prevent rendering issues with shaders like Seus if shaders are on. Works both with Optifine and Iris/Oculus.", + "pfm.option.spawnImmersivePortalsMirror": "Spawn Immersive Portals Mirrors", + "pfm.option.spawnImmersivePortalsMirror.tooltip": "If true the mod's mirrors work if immersive portals is present, if the server sets this to false, it won't work for the players.", + "pfm.option.renderImmersivePortalsMirror": "Immersive Portals Mirror Rendering", + "pfm.option.renderImmersivePortalsMirror.tooltip": "If true mirrors will render if immersive portals is installed.", "pfm.config.title": "Paladin's Furniture Mod Config", "pfm.option.resetAll": "Reset All Options", diff --git a/common/src/main/resources/pfm-common.mixins.json b/common/src/main/resources/pfm-common.mixins.json index 2fdf40ab1..0eb8d10e1 100644 --- a/common/src/main/resources/pfm-common.mixins.json +++ b/common/src/main/resources/pfm-common.mixins.json @@ -9,7 +9,6 @@ "PFMMixinPointOfInterestType", "PFMMixinPointOfInterestTypeFactory", "PFMPlayerInventoryMixin", - "PFMReloadableResourceManagerImplMixin", "PFMTextureKeyFactory" ], "server": [ diff --git a/docs/banner.png b/docs/banner.png index a768fe3e6..a7cecd27c 100644 Binary files a/docs/banner.png and b/docs/banner.png differ diff --git a/fabric/build.gradle b/fabric/build.gradle index dd8e65cdc..18ea1e280 100755 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -111,7 +111,7 @@ else { if (rootProject.immersive_portals_compatibility_fabric == "true"){ dependencies { - modRuntimeOnly("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}") { + modImplementation("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}") { exclude group: "net.fabricmc.fabric-api" exclude group: "com.github.Virtuoel" } @@ -140,6 +140,13 @@ dependencies { modCompileOnly("maven.modrinth:farmers-delight-fabric:${rootProject.farmers_delight_version_fabric}") + //modImplementation "curse.maven:balm-fabric-500525:${rootProject.balm_version_fabric}" + //modImplementation "curse.maven:cooking-for-blockheads-fabric-634546:${rootProject.cookingforblockheads_version_fabric}" + + modCompileOnly("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version_fabric}") { + exclude group: "net.fabricmc.fabric-api" + exclude group: "com.github.Virtuoel" + } } dependencies { diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java new file mode 100644 index 000000000..e9e857e04 --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMImmersivePortalsImpl.java @@ -0,0 +1,46 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.fabric; + +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.client.PFMImmersivePortalsClient; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.registry.EntityRegistry; +import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.MapColor; +import net.minecraft.block.Material; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; + +import java.util.Optional; + +public class PFMImmersivePortalsImpl implements PFMModCompatibility { + private PFMClientModCompatibility clientModCompatibility; + public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); + + @Override + public void registerEntityTypes() { + EntityRegistry.registerEntityType("mirror_entity", MIRROR); + } + + @Override + public void createBlocks() { + PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.WHITE).nonOpaque()); + PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.GRAY).nonOpaque()); + } + + @Override + public String getModId() { + return "immersive_portals"; + } + + @Override + public Optional getClientModCompatiblity() { + if (clientModCompatibility == null) + clientModCompatibility = new PFMImmersivePortalsClient(this); + return Optional.of(clientModCompatibility); + } + public static PFMModCompatibility getInstance() { + return new PFMImmersivePortalsImpl(); + } +} diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java new file mode 100644 index 000000000..c4ba3bd2f --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/PFMMirrorBlockIP.java @@ -0,0 +1,69 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.fabric; + +import com.unlikepaladin.pfm.PaladinFurnitureMod; +import com.unlikepaladin.pfm.blocks.MirrorBlock; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity.PFMMirrorEntity; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class PFMMirrorBlockIP extends MirrorBlock { + protected PFMMirrorBlockIP(Settings settings) { + super(settings); + } + + @Override + public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { + super.onPlaced(world, pos, state, placer, itemStack); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { + if (!world.isClient && world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty()) { + PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + } + } + } + + @Override + public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { + super.onBreak(world, pos, state, player); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { + List mirrorBlockEntities; + if (!world.isClient && !(mirrorBlockEntities = world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))).isEmpty()) { + mirrorBlockEntities.forEach(pfmMirrorEntity -> { + ((PFMMirrorEntity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); + }); + world.updateNeighbors(pos, state.getBlock()); + } + } + } + + @Override + public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn() && !world.isClient()) { + List mirrorBlockEntities = new ArrayList<>(); + if (canConnect(neighborState, state)) { + mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(neighborPos))); + } + if (!(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty())) { + mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))); + mirrorBlockEntities.forEach(pfmMirrorEntity -> { + ((Entity)pfmMirrorEntity).remove(Entity.RemovalReason.KILLED); + }); + } + PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + world.updateNeighbors(pos, state.getBlock()); + } + return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos); + } +} diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java similarity index 60% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java index dfb858688..04c3cd088 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/client/PFMImmersivePortalsClient.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMImmersivePortalsClient.java @@ -1,14 +1,13 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.client; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.client; -import com.qouteall.immersive_portals.render.PortalEntityRenderer; import com.unlikepaladin.pfm.client.EntityRenderRegistry; import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; import com.unlikepaladin.pfm.compat.PFMModCompatibility; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMImmersivePortals; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMImmersivePortalsImpl; public class PFMImmersivePortalsClient implements PFMClientModCompatibility { - private final PFMImmersivePortals parent; - public PFMImmersivePortalsClient(PFMImmersivePortals parent) { + private final PFMImmersivePortalsImpl parent; + public PFMImmersivePortalsClient(PFMImmersivePortalsImpl parent) { this.parent = parent; } @Override @@ -18,6 +17,6 @@ public PFMModCompatibility getCompatiblity() { @Override public void registerEntityRenderer() { - EntityRenderRegistry.registerEntityRender(PFMImmersivePortals.MIRROR, PortalEntityRenderer::new); + EntityRenderRegistry.registerEntityRender(PFMImmersivePortalsImpl.MIRROR, PFMMirrorEntityRenderer::new); } } diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java new file mode 100644 index 000000000..a92ae3024 --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/client/PFMMirrorEntityRenderer.java @@ -0,0 +1,20 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.client; + +import com.unlikepaladin.pfm.PaladinFurnitureMod; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.util.math.MatrixStack; +import qouteall.imm_ptl.core.portal.Portal; +import qouteall.imm_ptl.core.render.PortalEntityRenderer; + +public class PFMMirrorEntityRenderer extends PortalEntityRenderer { + public PFMMirrorEntityRenderer(EntityRendererFactory.Context context) { + super(context); + } + + @Override + public void render(Portal portal, float yaw, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsRender()) + super.render(portal, yaw, tickDelta, matrixStack, vertexConsumerProvider, light); + } +} diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java similarity index 89% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java rename to fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java index 514a9f801..35651613d 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/entity/PFMMirrorEntity.java +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/entity/PFMMirrorEntity.java @@ -1,12 +1,13 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.entity; +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.entity; import com.qouteall.immersive_portals.my_util.IntBox; import com.qouteall.immersive_portals.portal.Mirror; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMImmersivePortals; -import com.unlikepaladin.pfm.compat.imm_ptl.PFMMirrorBlockIP; -import com.unlikepaladin.pfm.compat.imm_ptl.shape.BlockPortalShape; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMImmersivePortalsImpl; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.PFMMirrorBlockIP; +import com.unlikepaladin.pfm.compat.imm_ptl.fabric.shape.BlockPortalShape; import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.nbt.NbtCompound; import net.minecraft.server.world.ServerWorld; @@ -19,11 +20,14 @@ import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import com.qouteall.immersive_portals.Helper; +import qouteall.imm_ptl.core.portal.Mirror; +import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; import java.util.stream.Stream; public class PFMMirrorEntity extends Mirror { - public static EntityType entityType = PFMImmersivePortals.MIRROR; + public static EntityType entityType = PFMImmersivePortalsImpl.MIRROR; @Nullable public IntBox wallArea; @Nullable @@ -123,7 +127,7 @@ else if (blockPortalShape != null) { wallValid = false; } if (!wallValid) { - remove(); + ((Entity)this).remove(); } } @@ -135,13 +139,9 @@ public static boolean isMirrorBlock(World world, BlockPos blockPos, Direction fa return false; } - public static PFMMirrorEntity createMirror( - ServerWorld world, - BlockPos glassPos, - Direction facing - ) { + public static void createMirror(ServerWorld world, BlockPos glassPos, Direction facing) { if (!isMirrorBlock(world, glassPos, facing.getOpposite())) { - return null; + return; } BlockPortalShape shape = BlockPortalShape.findArea( @@ -151,7 +151,7 @@ public static PFMMirrorEntity createMirror( ); if (shape == null) { - return null; + return; } PFMMirrorEntity pfmMirrorEntity = PFMMirrorEntity.entityType.create(world); @@ -159,7 +159,7 @@ public static PFMMirrorEntity createMirror( Box wallBox = getWallBox(world, shape.area.stream()); if (wallBox == null) { - return null; + return; } pfmMirrorEntity.facing = facing; Vec3d pos = Helper.getBoxSurfaceInversed(wallBox, facing.getOpposite()).getCenter(); @@ -172,7 +172,7 @@ public static PFMMirrorEntity createMirror( facing.getAxis() ) ); - pfmMirrorEntity.setPosition(pos.x, pos.y, pos.z); + ((Entity)pfmMirrorEntity).setPos(pos.x, pos.y, pos.z); pfmMirrorEntity.setDestination(pos); pfmMirrorEntity.dimensionTo = world.getRegistryKey(); @@ -181,7 +181,6 @@ public static PFMMirrorEntity createMirror( pfmMirrorEntity.blockPortalShape = shape; world.spawnEntity(pfmMirrorEntity); - return pfmMirrorEntity; } @Nullable diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java new file mode 100644 index 000000000..74f4b24b8 --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/fabric/shape/BlockPortalShape.java @@ -0,0 +1,534 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.fabric.shape; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtInt; +import net.minecraft.nbt.NbtList; +import net.minecraft.util.Pair; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; +import org.apache.commons.lang3.Validate; +import org.jetbrains.annotations.Nullable; +import qouteall.imm_ptl.core.portal.GeometryPortalShape; +import qouteall.imm_ptl.core.portal.Portal; +import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; + +import java.util.ArrayDeque; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +/** + * Backported to 1.17 from ... + * */ +public class BlockPortalShape { + public BlockPos anchor; + public Set area; + public IntBox innerAreaBox; + public IntBox totalAreaBox; + public Direction.Axis axis; + public Set frameAreaWithoutCorner; + public Set frameAreaWithCorner; + + public BlockPos firstFramePos; + + public BlockPortalShape( + Set area, Direction.Axis axis + ) { + this.area = area; + this.axis = axis; + + calcAnchor(); + + calcFrameArea(); + + calcAreaBox(); + } + + public BlockPortalShape( + NbtCompound tag + ) { + this( + readArea(tag.getList("poses", 3)), + Direction.Axis.values()[tag.getInt("axis")] + ); + } + + private static Set readArea(NbtList list) { + int size = list.size(); + + Validate.isTrue(size % 3 == 0); + Set result = new HashSet<>(); + + for (int i = 0; i < size / 3; i++) { + result.add(new BlockPos( + list.getInt(i * 3 + 0), + list.getInt(i * 3 + 1), + list.getInt(i * 3 + 2) + )); + } + + return result; + } + + public static BlockPortalShape fromTag(NbtCompound tag) { + return new BlockPortalShape(tag); + } + + public NbtCompound toTag() { + NbtCompound data = new NbtCompound(); + NbtList list = new NbtList(); + + area.forEach(blockPos -> { + list.add(list.size(), NbtInt.of(blockPos.getX())); + list.add(list.size(), NbtInt.of(blockPos.getY())); + list.add(list.size(), NbtInt.of(blockPos.getZ())); + }); + + data.put("poses", list); + data.putInt("axis", axis.ordinal()); + + return data; + } + + public void calcAnchor() { + anchor = area.stream() + .min( + Comparator.comparingInt( + Vec3i::getX + ).thenComparingInt( + Vec3i::getY + ).thenComparingInt( + Vec3i::getZ + ) + ).get(); + + Validate.notNull(anchor); + } + + public void calcAreaBox() { + innerAreaBox = Helper.reduce( + new IntBox(anchor, anchor), + area.stream(), + IntBox::getExpanded + ); + totalAreaBox = Helper.reduce( + new IntBox(anchor, anchor), + frameAreaWithoutCorner.stream(), + IntBox::getExpanded + ); + } + + public void calcFrameArea() { + Direction[] directions = Helper.getAnotherFourDirections(axis); + frameAreaWithoutCorner = area.stream().flatMap( + blockPos -> Stream.of( + blockPos.add(directions[0].getVector()), + blockPos.add(directions[1].getVector()), + blockPos.add(directions[2].getVector()), + blockPos.add(directions[3].getVector()) + ) + ).filter( + blockPos -> !area.contains(blockPos) + ).collect(Collectors.toSet()); + + BlockPos[] cornerOffsets = { + new BlockPos(directions[0].getVector()).add(directions[1].getVector()), + new BlockPos(directions[1].getVector()).add(directions[2].getVector()), + new BlockPos(directions[2].getVector()).add(directions[3].getVector()), + new BlockPos(directions[3].getVector()).add(directions[0].getVector()) + }; + + frameAreaWithCorner = area.stream().flatMap( + blockPos -> Stream.of( + blockPos.add(cornerOffsets[0]), + blockPos.add(cornerOffsets[1]), + blockPos.add(cornerOffsets[2]), + blockPos.add(cornerOffsets[3]) + ) + ).filter( + blockPos -> !area.contains(blockPos) + ).collect(Collectors.toSet()); + frameAreaWithCorner.addAll(frameAreaWithoutCorner); + + firstFramePos = frameAreaWithoutCorner.iterator().next(); + } + + //null for not found + @Nullable + public static BlockPortalShape findArea( + BlockPos startingPos, + Direction.Axis axis, + Predicate isAir, + Predicate isObsidian + ) { + if (!isAir.test(startingPos)) { + return null; + } + + return findShapeWithoutRegardingStartingPos(startingPos, axis, isAir, isObsidian); + } + + @Nullable + public static BlockPortalShape findShapeWithoutRegardingStartingPos( + BlockPos startingPos, Direction.Axis axis, Predicate isAir, Predicate isObsidian + ) { + startingPos = startingPos.toImmutable(); + + Set area = new HashSet<>(); + area.add(startingPos); + + Direction[] directions = Helper.getAnotherFourDirections(axis); + boolean isNormalFrame = findAreaBreadthFirst( + startingPos, + isAir, + isObsidian, + directions, + area, + startingPos + ); + + if (!isNormalFrame) { + return null; + } + + return new BlockPortalShape(area, axis); + } + + private static boolean findAreaBreadthFirst( + BlockPos startingPos, + Predicate isAir, + Predicate isObsidian, + Direction[] directions, + Set foundArea, + BlockPos initialPos + ) { + + ArrayDeque newlyAdded = new ArrayDeque<>(); + newlyAdded.addLast(startingPos); + + while (!newlyAdded.isEmpty()) { + if (foundArea.size() > 400) { + return false; + } + + BlockPos last = newlyAdded.pollFirst(); + for (Direction direction : directions) { + BlockPos curr = last.offset(direction).toImmutable(); + if (!foundArea.contains(curr)) { + if (isAir.test(curr)) { + newlyAdded.addLast(curr); + foundArea.add(curr); + } + else if (isObsidian.test(curr)) { + //nothing happens + } + else { + return false; + } + } + } + + BlockPos delta = initialPos.subtract(startingPos); + if (Math.abs(delta.getX()) > 20 || Math.abs(delta.getY()) > 20 || Math.abs(delta.getZ()) > 20) { + return false; + } + } + + return true; + } + + @Deprecated + private static boolean findAreaRecursively( + BlockPos currPos, + Predicate isAir, + Predicate isObsidian, + Direction[] directions, + Set foundArea, + BlockPos initialPos + ) { + if (foundArea.size() > 400) { + return false; + } + BlockPos delta = initialPos.subtract(currPos); + if (Math.abs(delta.getX()) > 20 || Math.abs(delta.getY()) > 20 || Math.abs(delta.getZ()) > 20) { + return false; + } + for (Direction direction : directions) { + BlockPos newPos = currPos.add(direction.getVector()); + if (!foundArea.contains(newPos)) { + if (isAir.test(newPos)) { + foundArea.add(newPos.toImmutable()); + boolean shouldContinue = findAreaRecursively( + newPos, + isAir, + isObsidian, + directions, + foundArea, + initialPos + ); + if (!shouldContinue) { + return false; + } + } + else { + if (!isObsidian.test(newPos)) { + //abort + return false; + } + } + } + } + return true; + } + + //return null for not match + public BlockPortalShape matchShape( + Predicate isAir, + Predicate isObsidian, + BlockPos newAnchor, + BlockPos.Mutable temp + ) { + if (!isAir.test(newAnchor)) { + return null; + } + + boolean testFrame = testFrameWithoutCorner(isObsidian, newAnchor, temp); + + if (!testFrame) { + return null; + } + + boolean testAir = area.stream().map( + blockPos -> temp.set( + blockPos.getX() - anchor.getX() + newAnchor.getX(), + blockPos.getY() - anchor.getY() + newAnchor.getY(), + blockPos.getZ() - anchor.getZ() + newAnchor.getZ() + ) + //blockPos.subtract(anchor).add(newAnchor) + ).allMatch( + isAir + ); + + if (!testAir) { + return null; + } + + return getShapeWithMovedAnchor(newAnchor); + } + + private boolean testFrameWithoutCorner( + Predicate isObsidian, + BlockPos newAnchor, + BlockPos.Mutable temp + ) { + Function mapper = blockPos -> temp.set( + blockPos.getX() - anchor.getX() + newAnchor.getX(), + blockPos.getY() - anchor.getY() + newAnchor.getY(), + blockPos.getZ() - anchor.getZ() + newAnchor.getZ() + ); + + //does this have optimization effect? + if (!isObsidian.test(mapper.apply(firstFramePos))) { + return false; + } + + return frameAreaWithoutCorner.stream().map(mapper).allMatch(isObsidian); + } + + public BlockPortalShape getShapeWithMovedAnchor( + BlockPos newAnchor + ) { + BlockPos offset = newAnchor.subtract(anchor); + return new BlockPortalShape( + area.stream().map( + blockPos -> blockPos.add(offset) + ).collect(Collectors.toSet()), + axis + ); + } + + public boolean isFrameIntact( + Predicate isObsidian + ) { + return frameAreaWithoutCorner.stream().allMatch(isObsidian::test); + } + + public boolean isPortalIntact( + Predicate isPortalBlock, + Predicate isObsidian + ) { + return isFrameIntact(isObsidian) && + area.stream().allMatch(isPortalBlock); + } + + public void initPortalPosAxisShape(Portal portal, Direction.AxisDirection axisDirection) { + Vec3d center = innerAreaBox.getCenterVec(); + portal.setPos(center.x, center.y, center.z); + + initPortalAxisShape(portal, center, Direction.from(axis, axisDirection)); + } + + public void initPortalAxisShape(Portal portal, Vec3d center, Direction facing) { + Validate.isTrue(facing.getAxis() == axis); + + Pair perpendicularDirections = Helper.getPerpendicularDirections(facing); + Direction wDirection = perpendicularDirections.getLeft(); + Direction hDirection = perpendicularDirections.getRight(); + + portal.axisW = Vec3d.of(wDirection.getVector()); + portal.axisH = Vec3d.of(hDirection.getVector()); + portal.width = Helper.getCoordinate(innerAreaBox.getSize(), wDirection.getAxis()); + portal.height = Helper.getCoordinate(innerAreaBox.getSize(), hDirection.getAxis()); + + Vec3d offset = Vec3d.of( + Direction.get(Direction.AxisDirection.POSITIVE, axis) + .getVector() + ).multiply(0.5); + + if (isRectangle()) { + portal.specialShape = null; + } + else { + GeometryPortalShape shape = new GeometryPortalShape(); + + IntBox rectanglePart = Helper.expandRectangle( + anchor, + blockPos -> area.contains(blockPos), + axis + ); + + Stream.concat( + area.stream() + .filter(blockPos -> !rectanglePart.contains(blockPos)) + .map(blockPos -> new IntBox(blockPos, blockPos)), + Stream.of(rectanglePart) + ).forEach(part -> { + Vec3d p1 = Vec3d.of(part.l).add(offset); + Vec3d p2 = Vec3d.of(part.h).add(1, 1, 1).add(offset); + double p1LocalX = p1.subtract(center).dotProduct(portal.axisW); + double p1LocalY = p1.subtract(center).dotProduct(portal.axisH); + double p2LocalX = p2.subtract(center).dotProduct(portal.axisW); + double p2LocalY = p2.subtract(center).dotProduct(portal.axisH); + shape.addTriangleForRectangle( + p1LocalX, p1LocalY, + p2LocalX, p2LocalY + ); + }); + + portal.specialShape = shape; + + Vec3d p1 = Vec3d.of(rectanglePart.l).add(offset); + Vec3d p2 = Vec3d.of(rectanglePart.h).add(1, 1, 1).add(offset); + double p1LocalX = p1.subtract(center).dotProduct(portal.axisW); + double p1LocalY = p1.subtract(center).dotProduct(portal.axisH); + double p2LocalX = p2.subtract(center).dotProduct(portal.axisW); + double p2LocalY = p2.subtract(center).dotProduct(portal.axisH); + portal.initCullableRange( + p1LocalX, p2LocalX, + p1LocalY, p2LocalY + ); + } + } + + public BlockPortalShape matchShapeWithMovedFirstFramePos( + Predicate isAir, + Predicate isObsidian, + BlockPos newFirstObsidianPos, + BlockPos.Mutable temp + ) { + boolean testFrame = frameAreaWithoutCorner.stream().map(blockPos1 -> temp.set( + blockPos1.getX() - firstFramePos.getX() + newFirstObsidianPos.getX(), + blockPos1.getY() - firstFramePos.getY() + newFirstObsidianPos.getY(), + blockPos1.getZ() - firstFramePos.getZ() + newFirstObsidianPos.getZ() + )).allMatch(isObsidian); + + if (!testFrame) { + return null; + } + + boolean testAir = area.stream().map(blockPos -> temp.set( + blockPos.getX() - firstFramePos.getX() + newFirstObsidianPos.getX(), + blockPos.getY() - firstFramePos.getY() + newFirstObsidianPos.getY(), + blockPos.getZ() - firstFramePos.getZ() + newFirstObsidianPos.getZ() + )).allMatch(isAir); + + if (!testAir) { + return null; + } + + BlockPos offset = newFirstObsidianPos.subtract(firstFramePos); + return new BlockPortalShape( + area.stream().map( + blockPos -> blockPos.add(offset) + ).collect(Collectors.toSet()), + axis + ); + } + + public static boolean isSquareShape(BlockPortalShape shape, int length) { + BlockPos areaSize = shape.innerAreaBox.getSize(); + + Pair xs = Helper.getAnotherTwoAxis(shape.axis); + + return Helper.getCoordinate(areaSize, xs.getLeft()) == length && + Helper.getCoordinate(areaSize, xs.getRight()) == length && + shape.area.size() == (length * length); + } + + public static BlockPortalShape getSquareShapeTemplate( + Direction.Axis axis, + int length + ) { + Pair perpendicularDirections = Helper.getPerpendicularDirections( + Direction.from(axis, Direction.AxisDirection.POSITIVE) + ); + + Set area = new HashSet<>(); + + for (int i = 0; i < length; i++) { + for (int j = 0; j < length; j++) { + area.add( + BlockPos.ORIGIN.offset(perpendicularDirections.getLeft(), i) + .offset(perpendicularDirections.getRight(), j) + ); + } + } + + return new BlockPortalShape(area, axis); + } + + public BlockPortalShape getShapeWithMovedTotalAreaBox(IntBox newTotalAreaBox) { + Validate.isTrue(totalAreaBox.getSize().equals(newTotalAreaBox.getSize())); + + return getShapeWithMovedAnchor( + newTotalAreaBox.l.subtract(totalAreaBox.l) + .add(anchor) + ); + } + + public boolean isRectangle() { + BlockPos size = innerAreaBox.getSize(); + return size.getX() * size.getY() * size.getZ() == area.size(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BlockPortalShape that = (BlockPortalShape) o; + return area.equals(that.area) && + axis == that.axis; + } + + @Override + public int hashCode() { + return Objects.hash(area, axis); + } +} diff --git a/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java new file mode 100644 index 000000000..6ca6036ba --- /dev/null +++ b/fabric/src/main/java/com/unlikepaladin/pfm/mixin/fabric/PFMReloadableResourceManagerImplMixin.java @@ -0,0 +1,31 @@ +package com.unlikepaladin.pfm.mixin.fabric; + +import com.google.common.base.Suppliers; +import com.mojang.bridge.game.PackType; +import com.unlikepaladin.pfm.client.PathPackRPWrapper; +import com.unlikepaladin.pfm.runtime.PFMRuntimeResources; +import net.minecraft.SharedConstants; +import net.minecraft.resource.ReloadableResourceManagerImpl; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.metadata.PackResourceMetadata; +import net.minecraft.text.LiteralText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.util.ArrayList; +import java.util.List; + +@Mixin(value = ReloadableResourceManagerImpl.class) +public class PFMReloadableResourceManagerImplMixin { + + @ModifyVariable(at = @At(value = "HEAD"), method = "reload", argsOnly = true) + private List createReload(List packs) { + PFMRuntimeResources.RESOURCE_PACK_LIST = packs; + List resourcePacks = new ArrayList<>(packs); + PackResourceMetadata packResourceMetadata = new PackResourceMetadata(new LiteralText("pfm-runtime-resources"), SharedConstants.getGameVersion().getPackVersion(PackType.RESOURCE)); + resourcePacks.add(new PathPackRPWrapper(Suppliers.memoize(() -> { + PFMRuntimeResources.prepareAndRunResourceGen(false); return PFMRuntimeResources.ASSETS_PACK;}), packResourceMetadata)); + return resourcePacks; + } +} \ No newline at end of file diff --git a/fabric/src/main/resources/pfm.mixins.json b/fabric/src/main/resources/pfm.mixins.json index 59a94a439..9e9ab79fd 100755 --- a/fabric/src/main/resources/pfm.mixins.json +++ b/fabric/src/main/resources/pfm.mixins.json @@ -6,7 +6,8 @@ "PFMTitleScreenMixin" ], "mixins": [ - "PFMCookingPotBlockEntityMixin" + "PFMCookingPotBlockEntityMixin", + "PFMReloadableResourceManagerImplMixin" ], "injectors": { "defaultRequire": 1 diff --git a/forge/build.gradle b/forge/build.gradle index 93d598022..bb8e8cce4 100755 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -73,6 +73,7 @@ dependencies { modCompileOnly "curse.maven:cooking-for-blockheads-forge-231484:${rootProject.cookingforblockheads_version_forge}" modCompileOnly "curse.maven:farmers-delight-forge-398521:${rootProject.farmers_delight_version_forge}" + modCompileOnly ("curse.maven:imm_ptl-355440:${rootProject.immersive_portals_version_forge}") } if(rootProject.jei_compatibility == "true") { @@ -82,9 +83,7 @@ if(rootProject.jei_compatibility == "true") { } if (rootProject.immersive_portals_compatibility_forge == "true"){ dependencies { - modRuntimeOnly("curse.maven:imm_ptl-355440:${rootProject.immersive_portals_version_forge}"){ - transitive(false) - } + modImplementation("curse.maven:imm_ptl-355440:${rootProject.immersive_portals_version_forge}") } } diff --git a/forge/src/main/java/com/unlikepaladin/pfm/client/forge/PaladinFurnitureModClientForge.java b/forge/src/main/java/com/unlikepaladin/pfm/client/forge/PaladinFurnitureModClientForge.java index 9e715d367..82aa3fb3b 100644 --- a/forge/src/main/java/com/unlikepaladin/pfm/client/forge/PaladinFurnitureModClientForge.java +++ b/forge/src/main/java/com/unlikepaladin/pfm/client/forge/PaladinFurnitureModClientForge.java @@ -21,7 +21,6 @@ import com.unlikepaladin.pfm.client.PaladinFurnitureModClient; import com.unlikepaladin.pfm.client.ScreenRegistry; import com.unlikepaladin.pfm.client.screens.*; -import com.unlikepaladin.pfm.registry.forge.NetworkRegistryForge; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraftforge.api.distmarker.Dist; diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java new file mode 100644 index 000000000..e682d3433 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMImmersivePortalsImpl.java @@ -0,0 +1,46 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge; + +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.client.PFMImmersivePortalsClient; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.registry.EntityRegistry; +import com.unlikepaladin.pfm.registry.PaladinFurnitureModBlocksItems; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.MapColor; +import net.minecraft.block.Material; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; + +import java.util.Optional; + +public class PFMImmersivePortalsImpl implements PFMModCompatibility { + private PFMClientModCompatibility clientModCompatibility; + public static final EntityType MIRROR = EntityType.Builder.create(PFMMirrorEntity::new, SpawnGroup.MISC).setDimensions(0.0F, 0.0F).makeFireImmune().disableSummon().build("mirror_entity"); + + @Override + public void registerEntityTypes() { + EntityRegistry.registerEntityType("mirror_entity", MIRROR); + } + + @Override + public void createBlocks() { + PaladinFurnitureModBlocksItems.WHITE_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.WHITE).nonOpaque()); + PaladinFurnitureModBlocksItems.GRAY_MIRROR = new PFMMirrorBlockIP(AbstractBlock.Settings.of(Material.STONE, MapColor.GRAY).nonOpaque()); + } + + @Override + public String getModId() { + return "immersive_portals"; + } + + @Override + public Optional getClientModCompatiblity() { + if (clientModCompatibility == null) + clientModCompatibility = new PFMImmersivePortalsClient(this); + return Optional.of(clientModCompatibility); + } + public static PFMModCompatibility getInstance() { + return new PFMImmersivePortalsImpl(); + } +} diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java similarity index 78% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java rename to forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java index 9aa2ea78d..3d7465ecd 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/PFMMirrorBlockIP.java +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/PFMMirrorBlockIP.java @@ -1,8 +1,9 @@ -package com.unlikepaladin.pfm.compat.imm_ptl; +package com.unlikepaladin.pfm.compat.imm_ptl.forge; +import com.unlikepaladin.pfm.PaladinFurnitureMod; import com.qouteall.immersive_portals.portal.Portal; import com.unlikepaladin.pfm.blocks.MirrorBlock; -import com.unlikepaladin.pfm.compat.imm_ptl.entity.PFMMirrorEntity; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.entity.PFMMirrorEntity; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; @@ -27,14 +28,17 @@ protected PFMMirrorBlockIP(Settings settings) { @Override public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) { super.onPlaced(world, pos, state, placer, itemStack); - if (!world.isClient && world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty()) { - PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { + if (!world.isClient && world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos)).isEmpty()) { + PFMMirrorEntity.createMirror((ServerWorld) world, pos, state.get(FACING).getOpposite()); + } } } @Override public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { super.onBreak(world, pos, state, player); + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn()) { List mirrorBlockEntities; if (!world.isClient && !(mirrorBlockEntities = world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(pos))).isEmpty()) { mirrorBlockEntities.forEach(Portal::remove); @@ -44,7 +48,7 @@ public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity pl @Override public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { - if (!world.isClient()) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsSpawn() && !world.isClient()) { List mirrorBlockEntities = new ArrayList<>(); if (canConnect(neighborState, state)) { mirrorBlockEntities.addAll(world.getNonSpectatingEntities(PFMMirrorEntity.class, new Box(neighborPos))); diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java new file mode 100644 index 000000000..b466dc2b7 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMImmersivePortalsClient.java @@ -0,0 +1,22 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.client; + +import com.unlikepaladin.pfm.client.EntityRenderRegistry; +import com.unlikepaladin.pfm.compat.PFMClientModCompatibility; +import com.unlikepaladin.pfm.compat.PFMModCompatibility; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMImmersivePortalsImpl; + +public class PFMImmersivePortalsClient implements PFMClientModCompatibility { + private final PFMImmersivePortalsImpl parent; + public PFMImmersivePortalsClient(PFMImmersivePortalsImpl parent) { + this.parent = parent; + } + @Override + public PFMModCompatibility getCompatiblity() { + return parent; + } + + @Override + public void registerEntityRenderer() { + EntityRenderRegistry.registerEntityRender(PFMImmersivePortalsImpl.MIRROR, PFMMirrorEntityRenderer::new); + } +} diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java new file mode 100644 index 000000000..572bb378f --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/client/PFMMirrorEntityRenderer.java @@ -0,0 +1,20 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.client; + +import com.unlikepaladin.pfm.PaladinFurnitureMod; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.util.math.MatrixStack; +import qouteall.imm_ptl.core.portal.Portal; +import qouteall.imm_ptl.core.render.PortalEntityRenderer; + +public class PFMMirrorEntityRenderer extends PortalEntityRenderer { + public PFMMirrorEntityRenderer(EntityRendererFactory.Context context) { + super(context); + } + + @Override + public void render(Portal portal, float yaw, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light) { + if (PaladinFurnitureMod.getPFMConfig().doImmersivePortalsMirrorsRender()) + super.render(portal, yaw, tickDelta, matrixStack, vertexConsumerProvider, light); + } +} diff --git a/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java new file mode 100644 index 000000000..5bfadffa6 --- /dev/null +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/entity/PFMMirrorEntity.java @@ -0,0 +1,195 @@ +package com.unlikepaladin.pfm.compat.imm_ptl.forge.entity; + + +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMImmersivePortalsImpl; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.PFMMirrorBlockIP; +import com.unlikepaladin.pfm.compat.imm_ptl.forge.shape.BlockPortalShape; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import qouteall.imm_ptl.core.portal.Mirror; +import qouteall.q_misc_util.Helper; +import qouteall.q_misc_util.my_util.IntBox; + +import java.util.stream.Stream; + +public class PFMMirrorEntity extends Mirror { + public static EntityType entityType = PFMImmersivePortalsImpl.MIRROR; + @Nullable + public IntBox wallArea; + @Nullable + public BlockPortalShape blockPortalShape; + public boolean unbreakable = false; + private Direction facing; + + public PFMMirrorEntity(EntityType entityType, World world) { + super(entityType, world); + PFMMirrorEntity.entityType = entityType; + } + + @Override + protected void readCustomDataFromNbt(NbtCompound tag) { + super.readCustomDataFromNbt(tag); + if (tag.contains("boxXL")) { + wallArea = new IntBox( + new BlockPos( + tag.getInt("boxXL"), + tag.getInt("boxYL"), + tag.getInt("boxZL") + ), + new BlockPos( + tag.getInt("boxXH"), + tag.getInt("boxYH"), + tag.getInt("boxZH") + ) + ); + } + else { + wallArea = null; + } + if (tag.contains("blockPortalShape")) { + blockPortalShape = BlockPortalShape.fromTag(tag.getCompound("blockPortalShape")); + } + else { + blockPortalShape = null; + } + if (tag.contains("unbreakable")) { + unbreakable = tag.getBoolean("unbreakable"); + } + } + + @Override + protected void writeCustomDataToNbt(NbtCompound tag) { + super.writeCustomDataToNbt(tag); + if (wallArea != null) { + tag.putInt("boxXL", wallArea.l.getX()); + tag.putInt("boxYL", wallArea.l.getY()); + tag.putInt("boxZL", wallArea.l.getZ()); + tag.putInt("boxXH", wallArea.h.getX()); + tag.putInt("boxYH", wallArea.h.getY()); + tag.putInt("boxZH", wallArea.h.getZ()); + } + + if (blockPortalShape != null) { + tag.put("blockPortalShape", blockPortalShape.toTag()); + } + tag.putBoolean("unbreakable", unbreakable); + } + + @Override + public void tick() { + super.tick(); + if (!world.isClient) { + if (!unbreakable) { + if (world.getTime() % 10 == getId() % 10) { + checkWallIntegrity(); + } + } + } + } + + @Override + public boolean isPortalValid() { + return super.isPortalValid() && (wallArea != null || blockPortalShape != null); + } + + private void checkWallIntegrity() { + boolean wallValid; + if (this.facing == null && this.world.getBlockState(getBlockPos()).contains(Properties.HORIZONTAL_FACING)) + this.facing = this.world.getBlockState(getBlockPos()).get(Properties.HORIZONTAL_FACING).getOpposite(); + else if (this.facing == null){ + this.facing = Direction.NORTH; + } + if (wallArea != null) { + wallValid = wallArea.fastStream().allMatch( + blockPos -> isMirrorBlock(world, blockPos, this.facing.getOpposite()) + ); + } + else if (blockPortalShape != null) { + wallValid = blockPortalShape.area.stream().allMatch( + blockPos -> isMirrorBlock(world, blockPos, this.facing.getOpposite()) + ); + } + else { + wallValid = false; + } + if (!wallValid) { + ((Entity)this).remove(RemovalReason.DISCARDED); + } + } + + public static boolean isMirrorBlock(World world, BlockPos blockPos, Direction facing) { + BlockState blockState = world.getBlockState(blockPos); + if (blockState.contains(Properties.HORIZONTAL_FACING)) { + return blockState.getBlock() instanceof PFMMirrorBlockIP && blockState.get(Properties.HORIZONTAL_FACING).equals(facing); + } + return false; + } + + public static void createMirror(ServerWorld world, BlockPos glassPos, Direction facing) { + if (!isMirrorBlock(world, glassPos, facing.getOpposite())) { + return; + } + + BlockPortalShape shape = BlockPortalShape.findArea( + glassPos, facing.getAxis(), + blockPos -> isMirrorBlock(world, blockPos, facing.getOpposite()), + blockPos -> !(isMirrorBlock(world, blockPos, facing.getOpposite())) + ); + + if (shape == null) { + return; + } + + PFMMirrorEntity pfmMirrorEntity = PFMMirrorEntity.entityType.create(world); + double distanceToCenter = -0.452; + + Box wallBox = getWallBox(world, shape.area.stream()); + if (wallBox == null) { + return; + } + pfmMirrorEntity.facing = facing; + Vec3d pos = Helper.getBoxSurfaceInversed(wallBox, facing.getOpposite()).getCenter(); + pos = Helper.putCoordinate( + pos, facing.getAxis(), + Helper.getCoordinate( + shape.innerAreaBox.getCenterVec().add( + Vec3d.of(facing.getVector()).multiply(distanceToCenter) + ), + facing.getAxis() + ) + ); + ((Entity)pfmMirrorEntity).setPos(pos.x, pos.y, pos.z); + pfmMirrorEntity.setDestination(pos); + pfmMirrorEntity.dimensionTo = world.getRegistryKey(); + + shape.initPortalAxisShape(pfmMirrorEntity, pos, facing); + + pfmMirrorEntity.blockPortalShape = shape; + world.spawnEntity(pfmMirrorEntity); + + } + + @Nullable + public static Box getWallBox(World world, Stream blockPosStream) { + return blockPosStream.map(blockPos -> { + VoxelShape collisionShape = world.getBlockState(blockPos).getCollisionShape(world, blockPos); + + if (collisionShape.isEmpty()) { + return null; + } + + return collisionShape.getBoundingBox().offset(Vec3d.of(blockPos)); + }).filter(b -> b != null).reduce(Box::union).orElse(null); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java similarity index 99% rename from common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java rename to forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java index c83ed3b0e..0c4970f0a 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/shape/BlockPortalShape.java +++ b/forge/src/main/java/com/unlikepaladin/pfm/compat/imm_ptl/forge/shape/BlockPortalShape.java @@ -1,4 +1,4 @@ -package com.unlikepaladin.pfm.compat.imm_ptl.shape; +package com.unlikepaladin.pfm.compat.imm_ptl.forge.shape; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtInt; diff --git a/forge/src/main/java/com/unlikepaladin/pfm/forge/PaladinFurnitureModForge.java b/forge/src/main/java/com/unlikepaladin/pfm/forge/PaladinFurnitureModForge.java index ca2e19904..7dceeb393 100644 --- a/forge/src/main/java/com/unlikepaladin/pfm/forge/PaladinFurnitureModForge.java +++ b/forge/src/main/java/com/unlikepaladin/pfm/forge/PaladinFurnitureModForge.java @@ -1,16 +1,24 @@ package com.unlikepaladin.pfm.forge; +import com.google.common.base.Suppliers; +import com.mojang.bridge.game.PackType; import com.unlikepaladin.pfm.PaladinFurnitureMod; +import com.unlikepaladin.pfm.client.PathPackRPWrapper; import com.unlikepaladin.pfm.config.PaladinFurnitureModConfig; -import com.unlikepaladin.pfm.data.forge.PFMTagsImpl; import com.unlikepaladin.pfm.registry.dynamic.forge.LateBlockRegistryForge; import com.unlikepaladin.pfm.registry.forge.*; import net.minecraft.block.Block; import net.minecraft.item.Item; -import net.minecraft.tag.BlockTags; -import net.minecraft.util.Identifier; +import com.unlikepaladin.pfm.runtime.PFMRuntimeResources; +import net.minecraft.SharedConstants; +import net.minecraft.resource.ResourcePackProfile; +import net.minecraft.resource.ResourcePackSource; +import net.minecraft.resource.metadata.PackResourceMetadata; +import net.minecraft.text.LiteralText; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.AddPackFindersEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ExtensionPoint; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoadingContext; @@ -48,4 +56,13 @@ public PaladinFurnitureModForge() { LateBlockRegistryForge.addDynamicBlockRegistration(Item.class); PaladinFurnitureMod.isClient = FMLEnvironment.dist == Dist.CLIENT; } + + @SubscribeEvent + public static void generateResources(AddPackFindersEvent event) { + PackResourceMetadata packResourceMetadata = new PackResourceMetadata(new LiteralText("pfm-runtime-resources"), SharedConstants.getGameVersion().getPackVersion(PackType.RESOURCE)); + event.addRepositorySource((profileAdder, factory) -> profileAdder.accept(factory.create("pfm-resources", new LiteralText("PFM Resources"), true, + () -> new PathPackRPWrapper(Suppliers.memoize(() -> { + PFMRuntimeResources.prepareAndRunResourceGen(false); return PFMRuntimeResources.ASSETS_PACK;}), packResourceMetadata) + , packResourceMetadata, ResourcePackProfile.InsertionPosition.BOTTOM, ResourcePackSource.PACK_SOURCE_NONE, true))); + } } diff --git a/common/src/main/java/com/unlikepaladin/pfm/mixin/PFMReloadableResourceManagerImplMixin.java b/forge/src/main/java/com/unlikepaladin/pfm/mixin/forge/PFMReloadableResourceManagerImplMixin.java similarity index 60% rename from common/src/main/java/com/unlikepaladin/pfm/mixin/PFMReloadableResourceManagerImplMixin.java rename to forge/src/main/java/com/unlikepaladin/pfm/mixin/forge/PFMReloadableResourceManagerImplMixin.java index b5244bc95..445201b18 100644 --- a/common/src/main/java/com/unlikepaladin/pfm/mixin/PFMReloadableResourceManagerImplMixin.java +++ b/forge/src/main/java/com/unlikepaladin/pfm/mixin/forge/PFMReloadableResourceManagerImplMixin.java @@ -1,5 +1,6 @@ -package com.unlikepaladin.pfm.mixin; +package com.unlikepaladin.pfm.mixin.forge; +import com.unlikepaladin.pfm.client.PathPackRPWrapper; import com.unlikepaladin.pfm.runtime.PFMRuntimeResources; import net.minecraft.resource.ReloadableResourceManagerImpl; import net.minecraft.resource.ResourcePack; @@ -12,16 +13,12 @@ @Mixin(value = ReloadableResourceManagerImpl.class) public class PFMReloadableResourceManagerImplMixin { - private static int count = 0; + @ModifyVariable(at = @At(value = "HEAD"), method = "reload", argsOnly = true) private List createReload(List packs) { List resourcePacks = new ArrayList<>(packs); - if (PFMRuntimeResources.ready) { - PFMRuntimeResources.RESOURCE_PACK_LIST = resourcePacks; - //PFMRuntimeResources.runAsyncResourceGen(); No async for anyone, too bad forge won't behave - PFMRuntimeResources.prepareAndRunResourceGen(false); - resourcePacks.add(PFMRuntimeResources.ASSETS_PACK); - } - return resourcePacks; + resourcePacks.removeIf(pack -> pack instanceof PathPackRPWrapper); + PFMRuntimeResources.RESOURCE_PACK_LIST = resourcePacks; + return packs; } } \ No newline at end of file diff --git a/forge/src/main/resources/pfm.mixins.json b/forge/src/main/resources/pfm.mixins.json index 9f5458915..df42a19bc 100755 --- a/forge/src/main/resources/pfm.mixins.json +++ b/forge/src/main/resources/pfm.mixins.json @@ -8,7 +8,8 @@ "PFMRenderLayersForgeMixin" ], "mixins": [ - "PFMCookingPotBlockEntityMixin" + "PFMCookingPotBlockEntityMixin", + "PFMReloadableResourceManagerImplMixin" ], "injectors": { "defaultRequire": 1 diff --git a/gradle.properties b/gradle.properties index 533259768..6b6ede306 100755 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.16.5 enabled_platforms=fabric,forge archives_base_name=paladin-furniture-mod -mod_version=1.2.0-rc5 +mod_version=1.2.0-rc6 maven_group=com.unlikepaladin architectury_version=1.32.66