diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 4cd1fe88c..66d7109fd 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ -patreon: srendi +ko_fi: srendi +github: SirEndii \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index dde6f4283..425e8ab82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +For now, just a prototype changelog so I don't need to remember/search everything I did +### Added +- NBT Hashes for filters and item/fluid properties. Lightweight version of the fingerprints, cc also uses nbt hashes for everything nbt related + ## [1.19.2-0.7.37r] - 2024-10-06 ### Added diff --git a/README.md b/README.md index 74d5d8a3e..78c94213d 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ will close pull requests related to translations. [CurseForge]: https://www.curseforge.com/minecraft/mc-mods/advanced-peripherals [Actions]: https://github.com/Seniorendi/AdvancedPeripherals/actions [Crowdin]: https://crowdin.com/project/advanced-peripherals -[Discord]: https://discord.com/invite/QuF3hWDtWC +[Discord]: https://discord.intelligence-modding.de [Banner]: https://www.bisecthosting.com/images/CF/Advanced_Peripherals/BH_AP_Header.png 'Advanced Peripherals' [PeripheralsPlusOne]: https://github.com/rolandoislas/PeripheralsPlusOne diff --git a/build.gradle b/build.gradle index 4d6f7d61c..5cbf98fa4 100644 --- a/build.gradle +++ b/build.gradle @@ -3,17 +3,17 @@ import net.darkhax.curseforgegradle.TaskPublishCurseForge import java.text.SimpleDateFormat plugins { - id "maven-publish" + id 'checkstyle' + id 'com.github.breadmoirai.github-release' version '2.5.2' + id 'com.modrinth.minotaur' version '2.+' + id 'java' + id 'maven-publish' id 'net.darkhax.curseforgegradle' version '1.1.16' - id 'org.jetbrains.changelog' version '1.2.1' - id "com.modrinth.minotaur" version "2.+" - id "org.jetbrains.kotlin.jvm" version "1.6.10" id 'net.minecraftforge.gradle' version '[6.0.18,6.2)' + id 'org.jetbrains.changelog' version '1.2.1' + id 'org.jetbrains.kotlin.jvm' version '1.6.10' id 'org.parchmentmc.librarian.forgegradle' version '1.+' id 'org.spongepowered.mixin' version '0.7.+' - id "com.github.breadmoirai.github-release" version "2.5.2" - id 'checkstyle' - id 'java' } java { @@ -201,20 +201,18 @@ repositories { } } maven { - name = "Modmaven Jei" + name = "Modmaven" url = 'https://modmaven.dev/' content { - includeGroup("mezz.jei") includeGroup("appeng") includeGroup("mekanism") + includeGroup("mezz.jei") } } maven { name = "Create maven" url = "https://maven.tterrag.com/" content { - includeGroup("com.simibubi.create") - includeGroup("com.jozufozu.flywheel") includeGroup("com.tterrag.registrate") } } @@ -246,7 +244,17 @@ repositories { maven { url = "https://cursemaven.com" content { - includeGroup "curse.maven" + includeGroup("curse.maven") + } + } + maven { + url = "https://maven.valkyrienskies.org" + content { + includeGroup("org.valkyrienskies") + includeGroup("org.valkyrienskies.core") + includeGroup("com.github.LlamaLad7") + includeGroup("com.github.Rubydesic") + includeGroup("org.mapstruct") } } } @@ -313,23 +321,29 @@ dependencies { compileOnly fg.deobf("com.ldtteam:multipiston:${multipiston_version}") compileOnly fg.deobf("com.ldtteam:domum_ornamentum:${domumornamentum_version}:universal") compileOnly fg.deobf("com.ldtteam:blockui:${blockui_version}") - // IMPORTANT. This should be removed/uncommented when running `runData` - runtimeOnly fg.deobf("com.ldtteam:minecolonies:${minecolonies_version}") - runtimeOnly fg.deobf("com.ldtteam:structurize:${structurize_version}") - runtimeOnly fg.deobf("com.ldtteam:multipiston:${multipiston_version}") - runtimeOnly fg.deobf("com.ldtteam:domum_ornamentum:${domumornamentum_version}:universal") - runtimeOnly fg.deobf("com.ldtteam:blockui:${blockui_version}") - - //Patchouli + // IMPORTANT. This should be removed/commented when running `runData` + // Automated now, tho if you are not executing runData directly it's no help + if (!project.gradle.startParameter.taskNames.contains("runData")) { + runtimeOnly fg.deobf("com.ldtteam:minecolonies:${minecolonies_version}") + runtimeOnly fg.deobf("com.ldtteam:structurize:${structurize_version}") + runtimeOnly fg.deobf("com.ldtteam:multipiston:${multipiston_version}") + runtimeOnly fg.deobf("com.ldtteam:domum_ornamentum:${domumornamentum_version}:universal") + runtimeOnly fg.deobf("com.ldtteam:blockui:${blockui_version}") + } + + // Patchouli compileOnly fg.deobf("vazkii.patchouli:Patchouli:${patchouli_version}") runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:${patchouli_version}") // Create - compileOnly fg.deobf("com.simibubi.create:create-${minecraft_version}:${create_version}:all") - runtimeOnly fg.deobf("com.simibubi.create:create-${minecraft_version}:${create_version}:all") + compileOnly fg.deobf("curse.maven:create-328085:${create_version}") + runtimeOnly fg.deobf("curse.maven:create-328085:${create_version}") - //Removed until fully ported - //testImplementation fg.deobf("site.siredvin.ttoolkit:ttoolkit-${minecraft_version}:${ttoolkit_version}") + // DimStorage + compileOnly fg.deobf("curse.maven:dimstorage-353882:${dimstorage_version}") + compileOnly fg.deobf("curse.maven:edivadlib-638508:${edivadlib_version}") + // runtimeOnly fg.deobf("curse.maven:dimstorage-353882:${dimstorage_version}") + // runtimeOnly fg.deobf("curse.maven:edivadlib-638508:${edivadlib_version}") //Powah compileOnly fg.deobf("curse.maven:powah-633483:${powah_version}") @@ -337,7 +351,7 @@ dependencies { runtimeOnly fg.deobf("me.shedaniel.cloth:cloth-config-forge:8.2.88") runtimeOnly fg.deobf("dev.architectury:architectury-forge:6.2.43") - // Crash utilities. Used to debug the chunky turtle. Can be uncommented if not needed + // Crash utilities. Used to debug the chunky turtle. Can be commented if not needed runtimeOnly fg.deobf("curse.maven:crash-utilities-371813:4406293") testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_version}" @@ -352,9 +366,30 @@ dependencies { // JEI implementation fg.deobf("mezz.jei:jei-${jei_version}") + // Jade + implementation fg.deobf("curse.maven:jade-324717:${jade_version}") + // Create Crafts & Additions compileOnly fg.deobf("curse.maven:createaddition-439890:5099757") // runtimeOnly fg.deobf("curse.maven:createaddition-439890:5099757") + + // Valkyrien Skies 2 + compileOnly("org.joml:joml:1.10.4") + compileOnly("org.joml:joml-primitives:1.10.0") + // compileOnly fg.deobf("org.valkyrienskies:valkyrienskies-119-common:${vs2_version}") + compileOnly fg.deobf("org.valkyrienskies:valkyrienskies-119-forge:${vs2_version}") { + transitive = false + } + compileOnly "org.valkyrienskies.core:api:${vs_core_version}" + compileOnly "org.valkyrienskies.core:api-game:${vs_core_version}" + compileOnly "org.valkyrienskies.core:util:${vs_core_version}" + compileOnly "org.valkyrienskies.core:impl:${vs_core_version}" + runtimeOnly fg.deobf("org.valkyrienskies:valkyrienskies-119-forge:${vs2_version}") { + transitive = false + } + runtimeOnly fg.deobf("curse.maven:valkyrien-skies-258371:${valkyrien_skies_version}") + runtimeOnly fg.deobf("curse.maven:eureka-ships-654384:${eureka_ships_version}") + runtimeOnly fg.deobf("curse.maven:clockwork-807792:${clockwork_version}") } @@ -389,12 +424,12 @@ task setupServer(type: Copy) { } ["Client", "Server"].forEach { name -> - tasks.register("test$name", JavaExec.class).configure { + tasks.register("test${name}", JavaExec.class).configure { it.group('In-game tests') it.description("Runs tests on a temporary Minecraft instance.") - it.dependsOn(setupServer, "prepareRunTest$name", "cleanTest$name", 'compileTestModJava') + it.dependsOn(setupServer, "prepareRunTest${name}", "cleanTest${name}", 'compileTestModJava') - JavaExec exec = tasks.getByName("runTest$name") + JavaExec exec = tasks.getByName("runTest${name}") exec.copyTo(it) it.setClasspath(exec.getClasspath()) it.mainClass = exec.mainClass @@ -433,6 +468,8 @@ jar { jar.finalizedBy('reobfJar') +compileKotlin.enabled = false + tasks.withType(Checkstyle) { reports { xml.required = false diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 7ca06cbc2..a379e1d45 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -37,7 +37,6 @@ - diff --git a/gradle.properties b/gradle.properties index 6b4647d35..b4e3848fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -org.gradle.jvmargs=-Xmx4G org.gradle.daemon=false +org.gradle.jvmargs=-Xmx4G org.gradle.logging.level=info # Minecraft related @@ -7,46 +7,61 @@ mod_id=advancedperipherals # do not include mod_version/minecraft_version with equals sign anywhere else in the file (even in comments) # also do not add space around the equal sign # since we are using poor grep command to do automation :p -mod_version=0.7.38r +mod_version=0.8r minecraft_version=1.19.2 mod_artifact_suffix= -forge_version=43.3.8 + +forge_version=43.5.0 loader_version=43 + release_type=release + mappings_channel=parchment -mappings_version=2022.11.27-1.19.2 -jb_annotations=21.0.1 +mappings_version=2022.11.20-1.19.2 # Test dependencies -junit_version=5.7.2 hamcrest_version=2.2 +jb_annotations=21.0.1 +junit_version=5.7.2 kotlin_version=1.8.0 -kotlinx_coroutines_version=1.6.0-RC3 +kotlinx_coroutines_version=1.7.3 ttoolkit_version=0.1.3 # Mod dependencies cc_version=1.101.3 -curios_version=1.19.2-5.1.4.1 -minecolonies_version=1.19.2-1.1.473-BETA -appliedenergistics_version=12.9.5 -patchouli_version=1.19.2-77 -refinedstorage_version=1.11.6 + +ae2additions_version=4646599 +ae2things_version=4367610 +appliedenergistics_version=12.9.12 +appliedmekanistics_version=4734608 botania_version=1.19.2-440-FORGE -create_version=0.5.1.f-46 +clockwork_version=5171528 +#v0.5.1 +create_version=5797604 createca_version=5099757 +curios_version=1.19.2-5.1.4.1 +dimstorage_version=3927875 +eureka_ships_version=5321628 +kotlinforforge_version=3.12.0 mekanism_version=1.19.2-10.3.9.13 -ae2things_version=4367610 +minecolonies_version=1.19.2-1.1.473-BETA +patchouli_version=1.19.2-77 powah_version=4183078 -ae2additions_version=4646599 -kotlinforforge_version=3.12.0 -appliedmekanistics_version=4734608 +refinedstorage_version=1.11.7 +valkyrien_skies_version=4994898 +vs2_version=2.1.2-beta.1+a04911c932 +vs_core_version=1.1.0+2a62e6a823 # Mod dependencies which are needed for other mods # For minecolonies -structurize_version=1.19.2-1.0.649-BETA -multipiston_version=1.19.2-1.2.21-ALPHA blockui_version=1.19.2-0.0.102-ALPHA domumornamentum_version=1.19-1.0.141-BETA +multipiston_version=1.19.2-1.2.21-ALPHA +structurize_version=1.19.2-1.0.649-BETA + +# For DimStorage +edivadlib_version=3927847 -# Mod dependencies for testing stuff(Only used in the dev environment) -jei_version=1.19.2-forge:11.6.0.1016 \ No newline at end of file +# Mod dependencies for testing stuff (Only used in the dev environment) +jade_version=4914105 +jei_version=1.19.2-forge:11.6.0.1016 diff --git a/qodana.yaml b/qodana.yaml index dfc5cbb26..f2df31528 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -16,7 +16,8 @@ exclude: - src/test/resources/* - src/testMod/resources/* - src/server-files/resources/* -include: - name: CheckDependencyLicenses + +include: - name: TrivialIf - name: NullableProblems \ No newline at end of file diff --git a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b new file mode 100644 index 000000000..beca45b50 --- /dev/null +++ b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b @@ -0,0 +1,3 @@ +// 1.19.2 2025-01-20T07:59:27.474151 Tags for minecraft:item +de4b4f45ec18b2b1f0db1c36882981042e20ee23 data/advancedperipherals/tags/items/p2p_attunements/cable_p2p_tunnel.json +72eba3b11f69e16c87488f7c4ba7cfdad42c378e data/advancedperipherals/tags/items/smart_glasses.json diff --git a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b index f319707e2..fe56a6ce0 100644 --- a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b +++ b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b @@ -1,2 +1,2 @@ -// 1.19.2 2023-07-19T14:31:39.6951106 AP POI Type Tags +// 1.19.2 2024-05-28T14:53:16.655175 AP POI Type Tags d3d6b837660a4e213f287ad9d11e12368b90cd8e data/minecraft/tags/point_of_interest_type/acquirable_job_site.json diff --git a/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf b/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf index cb8219ecf..bc70b7af4 100644 --- a/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf +++ b/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf @@ -1,4 +1,4 @@ -// 1.19.2 2023-07-19T14:31:39.6751301 Turtle Upgrades +// 1.19.2 2024-05-28T14:53:16.655476 Turtle Upgrades b8f19ae0fb5bb898facc08e3787e0f96c8211881 data/advancedperipherals/computercraft/turtle_upgrades/chatty_turtle.json fe98c60e7d61139aacf2d0872873e610aac8a37b data/advancedperipherals/computercraft/turtle_upgrades/chunky_turtle.json ae619da638ad89d7302d832d6c09e2c87401c539 data/advancedperipherals/computercraft/turtle_upgrades/compass_turtle.json @@ -10,4 +10,5 @@ c9b2df2d4fed11f60a8e6f8da77b2fa53dd13572 data/advancedperipherals/computercraft/ 42fc2b9a2601ef44d617cb18302c2c4fff31d282 data/advancedperipherals/computercraft/turtle_upgrades/overpowered_husbandry_automata.json fa7743922ef6b4dd3e633f2857e4047d533f13b5 data/advancedperipherals/computercraft/turtle_upgrades/overpowered_weak_automata.json 4054c59ceb099f17c4555fd5f36b2f8b4109f624 data/advancedperipherals/computercraft/turtle_upgrades/player_turtle.json +fa6624d0dab03bd26c2cccecad51848d5071ecd3 data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json c8059a2717cfac5b02898658c4d2d52fbd5710d4 data/advancedperipherals/computercraft/turtle_upgrades/weak_automata.json diff --git a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 index b767c20d4..ac730fb60 100644 --- a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 +++ b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 @@ -1,14 +1,17 @@ -// 1.19.2 2024-01-15T20:01:57.516745 LootTables -d865e8ac35302c486faf5c7122569c554186186d data/advancedperipherals/loot_tables/blocks/block_reader.json -a6f896cc3dbd8da12737825ec71e32970f54025c data/advancedperipherals/loot_tables/blocks/chat_box.json -f50f506ae1987537f76be4c05a81689b25798f91 data/advancedperipherals/loot_tables/blocks/colony_integrator.json -1d1b858d09538dc66bab2c33a2f9c58361a9c472 data/advancedperipherals/loot_tables/blocks/energy_detector.json -317004b1358ef9bf83957d2d6796529a226161c7 data/advancedperipherals/loot_tables/blocks/environment_detector.json -d5a3964f518b138cbd7305c819a36af3d9340e4a data/advancedperipherals/loot_tables/blocks/geo_scanner.json -8aa1deea908fd02f049e047c8ca16679bbef68a2 data/advancedperipherals/loot_tables/blocks/inventory_manager.json -9a2898a63e2e0c087ce8eba211c63d1c8b9fd4aa data/advancedperipherals/loot_tables/blocks/me_bridge.json -973770040bacb61482adb9739fd1d977f16c107f data/advancedperipherals/loot_tables/blocks/nbt_storage.json -b4b80e8c9d62b53d9252cdfc5918c077d3a01f6e data/advancedperipherals/loot_tables/blocks/peripheral_casing.json -58b6adbea5d4ae43ed9af0b627df2b8a4907acde data/advancedperipherals/loot_tables/blocks/player_detector.json -a58aebcc52684302968e7af4f50a12aff93aaf2d data/advancedperipherals/loot_tables/blocks/redstone_integrator.json -0ef1678f88b8fcb744bfd95261f66745340be8f4 data/advancedperipherals/loot_tables/blocks/rs_bridge.json +// 1.19.2 2025-01-16T15:46:41.860623 LootTables +618b63c020ab64890c8a2d2506dd61cd30259a44 data/advancedperipherals/loot_tables/blocks/block_reader.json +0923665563d05307a7fa7d711a2d7a994a31eb6e data/advancedperipherals/loot_tables/blocks/chat_box.json +bf2a80256cfba0bd8c0283d493882e5816882f1f data/advancedperipherals/loot_tables/blocks/colony_integrator.json +cff4b81aa381bc0d1172b0a4c8bb35c1b954a018 data/advancedperipherals/loot_tables/blocks/distance_detector.json +1c5dbe1a8e07e040a3c2893a002cd535ee41dc20 data/advancedperipherals/loot_tables/blocks/energy_detector.json +8cc03eca1d191f725bc558836f26a85a466cb127 data/advancedperipherals/loot_tables/blocks/environment_detector.json +12589e7642b383029457d97a64637494ea8507a3 data/advancedperipherals/loot_tables/blocks/fluid_detector.json +421a3ece56485bd46374844639bfd606ce4665ec data/advancedperipherals/loot_tables/blocks/gas_detector.json +a2ae352dce564b878daecf47026f268dd432fbcf data/advancedperipherals/loot_tables/blocks/geo_scanner.json +807d449d02c0af701f84d3e806ebac20d3a1f91c data/advancedperipherals/loot_tables/blocks/inventory_manager.json +bb9b442dfad1d5f31397585c8394c85243fa169a data/advancedperipherals/loot_tables/blocks/me_bridge.json +52b1fe2e265be456ebf48d7e0d9ebcc8c994176f data/advancedperipherals/loot_tables/blocks/nbt_storage.json +2651e6053857a31f5bccc360969924848a197ad5 data/advancedperipherals/loot_tables/blocks/peripheral_casing.json +6b5058b6bc49689bf2b858b89f3981a4bb681750 data/advancedperipherals/loot_tables/blocks/player_detector.json +6af6542c7b64aa22dbfcdb01299daf4911827a49 data/advancedperipherals/loot_tables/blocks/redstone_integrator.json +b221c6a82da0875264a112b54f847ac6a1f36797 data/advancedperipherals/loot_tables/blocks/rs_bridge.json diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index 949aa05ae..c4a79999b 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -1,4 +1,5 @@ -// 1.19.2 2024-01-15T20:01:57.5157458 Recipes +// 1.19.2 2024-05-28T14:53:16.657381 Recipes +045608027e4a5ea2d7dee7f402346b8e69f21675 data/advancedperipherals/advancements/recipes/advancedperipheralstab/armor/smart_glasses_netherite.json db2dada2fdf42ca1bbf47f1eb075d1f9de89dfa8 data/advancedperipherals/advancements/recipes/advancedperipheralstab/block_reader.json 77c55e8500be4a344ca563a8bf7642257cdc7b8b data/advancedperipherals/advancements/recipes/advancedperipheralstab/chat_box.json 96208b06b0c3c125762cd517506a5ffb6b1d55ac data/advancedperipherals/advancements/recipes/advancedperipheralstab/chunk_controller.json @@ -16,6 +17,7 @@ d27c1267208fd9036c5c45f7f6cbd4f6f67b3845 data/advancedperipherals/advancements/r d8870644bb7d48c5ae33dcea2afbcfa106729d7b data/advancedperipherals/advancements/recipes/advancedperipheralstab/player_detector.json 7acff70533792bd089a655f8f24cdea6995aac0c data/advancedperipherals/advancements/recipes/advancedperipheralstab/redstone_integrator.json fc0c3d99bec43318802f357083c7d98fde92567f data/advancedperipherals/advancements/recipes/advancedperipheralstab/weak_automata_core.json +66999fea36aa4113567753f104630f6490dda6ba data/advancedperipherals/recipes/armor/smart_glasses_netherite.json b10b5cbcc668438001744d5b90d9838ab4d293cb data/advancedperipherals/recipes/block_reader.json 3c9618832fe0ac32cac0f04fbc5afad225418239 data/advancedperipherals/recipes/chat_box.json a78adfcca4c7579b143aac5648a7eca9085c0dba data/advancedperipherals/recipes/chunk_controller.json @@ -25,8 +27,8 @@ f1f468c732f8c802c27776d3fd7aac432bcac8e3 data/advancedperipherals/recipes/comput 55c257e4e8548d1453a7ab96c547d64c22b3e1d6 data/advancedperipherals/recipes/environment_detector.json 2ddf64c122165bcd3a277db8a1c7e96b4d510c67 data/advancedperipherals/recipes/geo_scanner.json ebe70aa9fe80c5b962c13aa1fbadc32269ba81b9 data/advancedperipherals/recipes/inventory_manager.json -809bc6929cf5eab72648e8f1fb565b58749fec12 data/advancedperipherals/recipes/memory_card.json 82895838af6c6aea0c60e3a3fbf71073ab684167 data/advancedperipherals/recipes/me_bridge.json +809bc6929cf5eab72648e8f1fb565b58749fec12 data/advancedperipherals/recipes/memory_card.json 8a73c4eb66e7a1cdc8e51d33466cf5a30da9270e data/advancedperipherals/recipes/nbt_storage.json 360432f30d61291066aa8c54692629f7a92e178d data/advancedperipherals/recipes/overpowered_end_automata_core.json 4ea6e90d13a61d90ad245539d20020ff9cb843e1 data/advancedperipherals/recipes/overpowered_husbandry_automata_core.json diff --git a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c index b9e492ca6..5821f3f8a 100644 --- a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c +++ b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c @@ -1,6 +1,7 @@ -// 1.19.2 2023-07-19T14:31:39.6815264 Pocket Computer Upgrades +// 1.19.2 2025-01-25T19:46:21.23515 Pocket Computer Upgrades b672635324c0df354e587efc81d0b19a581eae2f data/advancedperipherals/computercraft/pocket_upgrades/chatty_pocket.json 30b8f663613c7ce77048fd69631afcc11a682276 data/advancedperipherals/computercraft/pocket_upgrades/colony_pocket.json +661dc77bd0442bfb2a5ed80cff271071817bb22d data/advancedperipherals/computercraft/pocket_upgrades/distance_pocket.json d4647159c2f2693a9c5e8d12bf740635751d29a8 data/advancedperipherals/computercraft/pocket_upgrades/environment_pocket.json 8216a0a7d8ebe3ae738c8fc3626df25eb0a2e07a data/advancedperipherals/computercraft/pocket_upgrades/geoscanner_pocket.json a38aa83593f7ad0ace98e01bb3b5f06f272ef734 data/advancedperipherals/computercraft/pocket_upgrades/player_pocket.json diff --git a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 index 54d53cf45..01ccc33ab 100644 --- a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 +++ b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 @@ -1,9 +1,12 @@ -// 1.19.2 2024-01-15T20:01:57.5177444 Block States: advancedperipherals +// 1.19.2 2024-05-28T14:53:16.658228 Block States: advancedperipherals 5e28ce1be9a6996d982641e5df1fa7162090b8cc assets/advancedperipherals/blockstates/block_reader.json f42bdde60f84fdb312f7cf3b2be461d9c11ebdc8 assets/advancedperipherals/blockstates/chat_box.json 1227aa092fcf1327547ace6ccc9db230e45891b0 assets/advancedperipherals/blockstates/colony_integrator.json +83144ea6122b3abe70777458ac913b6f217c27cc assets/advancedperipherals/blockstates/distance_detector.json 67420f28031606ca03db9a044141bb22b0fa78b7 assets/advancedperipherals/blockstates/energy_detector.json 340b5baa62e5e6a2c35a05b4411be5937ac2bbb8 assets/advancedperipherals/blockstates/environment_detector.json +f40e0ac205d0473908fd957d035dd747dc64e26a assets/advancedperipherals/blockstates/fluid_detector.json +bbefa012be11f3735da4d9deb1f0d2402c761cd8 assets/advancedperipherals/blockstates/gas_detector.json 57c00996bcf1d783116a9210842f246612089555 assets/advancedperipherals/blockstates/geo_scanner.json d1fe6188b0b0ce8779cb9795a746177858cbaa41 assets/advancedperipherals/blockstates/inventory_manager.json 7f82e776900e3d120cb1a06ec975731905dcaff7 assets/advancedperipherals/blockstates/me_bridge.json @@ -13,15 +16,18 @@ ff12c7217911184266589813a2c8f9b0d46cfd65 assets/advancedperipherals/blockstates/ 726cf2599b0c765bcfacda88a1943be74f985877 assets/advancedperipherals/blockstates/redstone_integrator.json 6b176e8fdb048f7b6678bfbc1c4baf2bcfa67a1f assets/advancedperipherals/blockstates/rs_bridge.json 544ff1ecb58622350b58940036b4b1908e1146da assets/advancedperipherals/models/block/block_reader.json -b28693973b6bbbb61e0c1ffc59e8ca98d8bb7e97 assets/advancedperipherals/models/block/chat_box.json -8361da86b709e26f17374dfd46637940894a2212 assets/advancedperipherals/models/block/colony_integrator.json -96ef564804fdc2b5184462747935f52baa35c651 assets/advancedperipherals/models/block/energy_detector.json -41556ddf5c5e67def6efd8e2e0645718d950af25 assets/advancedperipherals/models/block/environment_detector.json -ba233597a497c1032d884fc3058e27b9d965725e assets/advancedperipherals/models/block/geo_scanner.json -fb58e0b712f1f6ce1b2ea4dcfa0747905cf6ed95 assets/advancedperipherals/models/block/inventory_manager.json -75b59d2b73a96a27e3d4a1ed3b9a928b7dff102e assets/advancedperipherals/models/block/me_bridge.json -a647b86b8a7862af738136c9375a5d27d3b08860 assets/advancedperipherals/models/block/nbt_storage.json -36b6ac01be085492aa6298eeb89e6ecaa3cb6f82 assets/advancedperipherals/models/block/peripheral_casing.json -40369caaaf2f593d786a9c64284647fed8ae3a47 assets/advancedperipherals/models/block/player_detector.json -bed2ba2ba497ccde06c99712483fe220c277b4be assets/advancedperipherals/models/block/redstone_integrator.json -019c10d5062b5e7ae3e641527b9badab7a50878d assets/advancedperipherals/models/block/rs_bridge.json +fbaa69d6c98549d3f2d4a1c7bebd9b6b80d56621 assets/advancedperipherals/models/block/chat_box.json +68f9d37bd85649937150ba0bb8f4496bb2ef218d assets/advancedperipherals/models/block/colony_integrator.json +80b30400b6ebac490a1abaad965f33c1b62c19e9 assets/advancedperipherals/models/block/distance_detector.json +b4c6645fda79d960e9201e2a60eb1c8063a07d18 assets/advancedperipherals/models/block/energy_detector.json +eca505b2bd8db5f1d13f1e28093db329b70af978 assets/advancedperipherals/models/block/environment_detector.json +f6ab51bcfc829c7db490f691e8eb491e5e7028f3 assets/advancedperipherals/models/block/fluid_detector.json +35bbc0e2edf74f6e27029cc23465e203d459f234 assets/advancedperipherals/models/block/gas_detector.json +46ebb4c9a31e224bac13ad20334469c0b55d285c assets/advancedperipherals/models/block/geo_scanner.json +2142aaccd0a0bc56aaa2091128466d2c9a733aab assets/advancedperipherals/models/block/inventory_manager.json +f089dda9e6ac12d638707fd24d099ccd56a54ccc assets/advancedperipherals/models/block/me_bridge.json +65afcae128339b244508dc66620c6c00729fce8e assets/advancedperipherals/models/block/nbt_storage.json +f6cb0dda1ce8217563903d2dfaf5ef0297939750 assets/advancedperipherals/models/block/peripheral_casing.json +5a1679b4dcc8da2d8c67674216d242456bb51366 assets/advancedperipherals/models/block/player_detector.json +d08b8946e1eb01cc9c8af4fa297b582614d1034b assets/advancedperipherals/models/block/redstone_integrator.json +41cf7d22016a995aeda9df9d9cbf1d4069b99f9e assets/advancedperipherals/models/block/rs_bridge.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 index 42f19ff63..c804ec644 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.19.2 2024-01-15T20:01:57.5147447 Languages: en_us -d2006c7f1d9c5f1f768b50a3c445dc8b566bf9dd assets/advancedperipherals/lang/en_us.json +// 1.19.2 2025-01-25T19:46:21.234203 Languages: en_us +e858500d72e9279f0fe0e8b2d03f94469c8d1f65 assets/advancedperipherals/lang/en_us.json diff --git a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 index 042110e02..872307de5 100644 --- a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 +++ b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 @@ -1,4 +1,4 @@ -// 1.19.2 2024-01-15T20:01:57.5177444 Block tags +// 1.19.2 2025-01-16T15:46:41.859383 Block tags e1f71dcb4f9e7e36e29b0ad09d6520dc3adfa4a6 data/forge/tags/blocks/needs_wood_tool.json -dcbdeb0bc268b24e9970e4bada12e8e8da97b8d5 data/minecraft/tags/blocks/mineable/pickaxe.json -1017ee5cf2a99941ddfc00c2c5e07a19644470b6 data/minecraft/tags/blocks/needs_iron_tool.json +03322cd493601129eaad6ba7c2a6d808023dfac1 data/minecraft/tags/blocks/mineable/pickaxe.json +277fe59db076a3eab3c97080531ad345f8ca5f3d data/minecraft/tags/blocks/needs_iron_tool.json diff --git a/src/generated/resources/assets/advancedperipherals/blockstates/distance_detector.json b/src/generated/resources/assets/advancedperipherals/blockstates/distance_detector.json new file mode 100644 index 000000000..4201dd6d7 --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/blockstates/distance_detector.json @@ -0,0 +1,57 @@ +{ + "variants": { + "orientation=down_east": { + "model": "advancedperipherals:block/distance_detector", + "x": 90, + "y": 90 + }, + "orientation=down_north": { + "model": "advancedperipherals:block/distance_detector", + "x": 90 + }, + "orientation=down_south": { + "model": "advancedperipherals:block/distance_detector", + "x": 90, + "y": 180 + }, + "orientation=down_west": { + "model": "advancedperipherals:block/distance_detector", + "x": 90, + "y": 270 + }, + "orientation=east_up": { + "model": "advancedperipherals:block/distance_detector", + "y": 90 + }, + "orientation=north_up": { + "model": "advancedperipherals:block/distance_detector" + }, + "orientation=south_up": { + "model": "advancedperipherals:block/distance_detector", + "y": 180 + }, + "orientation=up_east": { + "model": "advancedperipherals:block/distance_detector", + "x": 270, + "y": 90 + }, + "orientation=up_north": { + "model": "advancedperipherals:block/distance_detector", + "x": 270 + }, + "orientation=up_south": { + "model": "advancedperipherals:block/distance_detector", + "x": 270, + "y": 180 + }, + "orientation=up_west": { + "model": "advancedperipherals:block/distance_detector", + "x": 270, + "y": 270 + }, + "orientation=west_up": { + "model": "advancedperipherals:block/distance_detector", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/blockstates/fluid_detector.json b/src/generated/resources/assets/advancedperipherals/blockstates/fluid_detector.json new file mode 100644 index 000000000..6641af423 --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/blockstates/fluid_detector.json @@ -0,0 +1,57 @@ +{ + "variants": { + "orientation=down_east": { + "model": "advancedperipherals:block/fluid_detector", + "x": 90, + "y": 90 + }, + "orientation=down_north": { + "model": "advancedperipherals:block/fluid_detector", + "x": 90 + }, + "orientation=down_south": { + "model": "advancedperipherals:block/fluid_detector", + "x": 90, + "y": 180 + }, + "orientation=down_west": { + "model": "advancedperipherals:block/fluid_detector", + "x": 90, + "y": 270 + }, + "orientation=east_up": { + "model": "advancedperipherals:block/fluid_detector", + "y": 90 + }, + "orientation=north_up": { + "model": "advancedperipherals:block/fluid_detector" + }, + "orientation=south_up": { + "model": "advancedperipherals:block/fluid_detector", + "y": 180 + }, + "orientation=up_east": { + "model": "advancedperipherals:block/fluid_detector", + "x": 270, + "y": 90 + }, + "orientation=up_north": { + "model": "advancedperipherals:block/fluid_detector", + "x": 270 + }, + "orientation=up_south": { + "model": "advancedperipherals:block/fluid_detector", + "x": 270, + "y": 180 + }, + "orientation=up_west": { + "model": "advancedperipherals:block/fluid_detector", + "x": 270, + "y": 270 + }, + "orientation=west_up": { + "model": "advancedperipherals:block/fluid_detector", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/blockstates/gas_detector.json b/src/generated/resources/assets/advancedperipherals/blockstates/gas_detector.json new file mode 100644 index 000000000..aee9fc55d --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/blockstates/gas_detector.json @@ -0,0 +1,57 @@ +{ + "variants": { + "orientation=down_east": { + "model": "advancedperipherals:block/gas_detector", + "x": 90, + "y": 90 + }, + "orientation=down_north": { + "model": "advancedperipherals:block/gas_detector", + "x": 90 + }, + "orientation=down_south": { + "model": "advancedperipherals:block/gas_detector", + "x": 90, + "y": 180 + }, + "orientation=down_west": { + "model": "advancedperipherals:block/gas_detector", + "x": 90, + "y": 270 + }, + "orientation=east_up": { + "model": "advancedperipherals:block/gas_detector", + "y": 90 + }, + "orientation=north_up": { + "model": "advancedperipherals:block/gas_detector" + }, + "orientation=south_up": { + "model": "advancedperipherals:block/gas_detector", + "y": 180 + }, + "orientation=up_east": { + "model": "advancedperipherals:block/gas_detector", + "x": 270, + "y": 90 + }, + "orientation=up_north": { + "model": "advancedperipherals:block/gas_detector", + "x": 270 + }, + "orientation=up_south": { + "model": "advancedperipherals:block/gas_detector", + "x": 270, + "y": 180 + }, + "orientation=up_west": { + "model": "advancedperipherals:block/gas_detector", + "x": 270, + "y": 270 + }, + "orientation=west_up": { + "model": "advancedperipherals:block/gas_detector", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/lang/en_us.json b/src/generated/resources/assets/advancedperipherals/lang/en_us.json index ed66cc743..3da1acb77 100644 --- a/src/generated/resources/assets/advancedperipherals/lang/en_us.json +++ b/src/generated/resources/assets/advancedperipherals/lang/en_us.json @@ -2,25 +2,28 @@ "advancedperipherals.name": "Advanced Peripherals", "advancements.advancedperipherals.base_toolkit": "Gentleman's set!", "advancements.advancedperipherals.base_toolkit.description": "Collect a redstone integrator, inventory manager and energy detector. How did you even play without this?", - "advancements.advancedperipherals.end_automata_core": "End automata core", + "advancements.advancedperipherals.end_automata_core": "End Automata Core", "advancements.advancedperipherals.end_automata_core.description": "If you can code gps-free position location with this, you're a powerful human being", - "advancements.advancedperipherals.husbandry_automata_core": "Husbandry automata core", + "advancements.advancedperipherals.husbandry_automata_core": "Husbandry Automata Core", "advancements.advancedperipherals.husbandry_automata_core.description": "Is this core gluten-free?", "advancements.advancedperipherals.nbt_toolkit": "No secrets", "advancements.advancedperipherals.nbt_toolkit.description": "Collect a NBT storage and block reader. Now, all the world's secrets are open to you!", - "advancements.advancedperipherals.overpowered_automata_core": "Overpowered automata core", + "advancements.advancedperipherals.overpowered_automata_core": "Overpowered Automata Core", "advancements.advancedperipherals.overpowered_automata_core.description": "Can you handle so much power?", "advancements.advancedperipherals.root": "Advanced Peripherals", "advancements.advancedperipherals.root.description": "Every journey starts with the first block", "advancements.advancedperipherals.sense_toolkit": "The truth can't hide forever", "advancements.advancedperipherals.sense_toolkit.description": "Collect a geo scanner and environmental detector. There are no limits for observability!", - "advancements.advancedperipherals.weak_automata_core": "First automata core", + "advancements.advancedperipherals.weak_automata_core": "First Automata Core", "advancements.advancedperipherals.weak_automata_core.description": "Does the afterlife exist in minecraft?", "block.advancedperipherals.block_reader": "Block Reader", "block.advancedperipherals.chat_box": "Chat Box", "block.advancedperipherals.colony_integrator": "Colony Integrator", + "block.advancedperipherals.distance_detector": "Distance Detector", "block.advancedperipherals.energy_detector": "Energy Detector", "block.advancedperipherals.environment_detector": "Environment Detector", + "block.advancedperipherals.fluid_detector": "Fluid Detector", + "block.advancedperipherals.gas_detector": "Gas Detector", "block.advancedperipherals.geo_scanner": "Geo Scanner", "block.advancedperipherals.inventory_manager": "Inventory Manager", "block.advancedperipherals.me_bridge": "ME Bridge", @@ -29,21 +32,29 @@ "block.advancedperipherals.player_detector": "Player Detector", "block.advancedperipherals.redstone_integrator": "Redstone Integrator", "block.advancedperipherals.rs_bridge": "RS Bridge", + "curios.identifier.glasses": "Glasses", "entity.minecraft.villager.advancedperipherals.computer_scientist": "Computer Scientist", + "item.advancedperipherals.cable_p2p_tunnel": "Cable P2P Tunnel", "item.advancedperipherals.chunk_controller": "Chunk Controller", "item.advancedperipherals.computer_tool": "Computer Tool", "item.advancedperipherals.end_automata_core": "End Automata Core", + "item.advancedperipherals.hotkey_module": "Hotkey Module", "item.advancedperipherals.husbandry_automata_core": "Husbandry Automata Core", "item.advancedperipherals.memory_card": "Memory Card", + "item.advancedperipherals.nightvision_module": "Night Vision Module", + "item.advancedperipherals.overlay_module": "Overlay Module", "item.advancedperipherals.overpowered_end_automata_core": "Overpowered End Automata Core", "item.advancedperipherals.overpowered_husbandry_automata_core": "Overpowered Husbandry Automata Core", "item.advancedperipherals.overpowered_weak_automata_core": "Overpowered Weak Automata Core", + "item.advancedperipherals.smart_glasses": "Smart Glasses", + "item.advancedperipherals.smart_glasses_interface": "Smart Glasses Interface", + "item.advancedperipherals.smart_glasses_netherite": "Netherite reinforced Smart Glasses", "item.advancedperipherals.tooltip.block_reader": "&7Reads nbt data of blocks to interact with blocks which do not have computer support.", "item.advancedperipherals.tooltip.chat_box": "&7Interacts with the ingame chat, can read and write messages.", "item.advancedperipherals.tooltip.chunk_controller": "&7A crafting ingredient for the Chunky Turtle.", "item.advancedperipherals.tooltip.colony_integrator": "&7Interacts with Minecolonies to read data about your colony and citizens.", "item.advancedperipherals.tooltip.computer_tool": "&7This tool was made to tune our blocks. But for now, it's just a blue useless wrench.", - "item.advancedperipherals.tooltip.disabled": "&cThis item is disabled in the config, so you can craft it, but it'll not have any functionality.", + "item.advancedperipherals.tooltip.disabled": "&cThis item is disabled in config, so you can craft it, but it'll not have any functionality.", "item.advancedperipherals.tooltip.end_automata_core": "&7Upgrade for turtles, that allows basic interaction with the world and teleportation in one dimension.", "item.advancedperipherals.tooltip.energy_detector": "&7Can detect energy flow and acts as a resistor.", "item.advancedperipherals.tooltip.environment_detector": "&7This peripheral interacts with the minecraft world.", @@ -57,7 +68,7 @@ "item.advancedperipherals.tooltip.overpowered_end_automata_core": "&7Improved version of the end automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile.", "item.advancedperipherals.tooltip.overpowered_husbandry_automata_core": "&7Improved version of the husbandry automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile.", "item.advancedperipherals.tooltip.overpowered_weak_automata_core": "&7Improved version of the weak automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile.", - "item.advancedperipherals.tooltip.peripheral_casing": "&7An empty hull without the love it deserves. Used as a crafting ingredient", + "item.advancedperipherals.tooltip.peripheral_casing": "&7An empty hull without the love it deserves. Used as crafting ingredient", "item.advancedperipherals.tooltip.player_detector": "&7This peripheral can be used to interact with players, but don't be a stalker.", "item.advancedperipherals.tooltip.redstone_integrator": "&7This block is able to interact with redstone. Works exactly like the redstone api of an computer.", "item.advancedperipherals.tooltip.rs_bridge": "&7The RS Bridge interacts with Refined Storage to manage your items.", @@ -69,22 +80,27 @@ "keybind.advancedperipherals.description": "Show Description", "pocket.advancedperipherals.chatty_pocket": "Chatty", "pocket.advancedperipherals.colony_pocket": "Colony", + "pocket.advancedperipherals.distance_pocket": "Distance Detector", "pocket.advancedperipherals.environment_pocket": "Environment", "pocket.advancedperipherals.geoscanner_pocket": "Geo", "pocket.advancedperipherals.player_pocket": "Player Detector", "text.advancedperipherals.added_player": "Added you to the memory card", - "text.advancedperipherals.automata_core_feed_by_player": "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?", + "text.advancedperipherals.automata_core.feed_by_player": "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?", "text.advancedperipherals.removed_player": "Cleared the memory card", + "text.advancedperipherals.saddle_turtle.dismount_hint": "Controlling %1$s. Press %2$s and %3$s to dismount.", + "text.advancedperipherals.smart_glasses.modules": "Modules", + "text.advancedperipherals.smart_glasses.peripherals": "Peripherals", "turtle.advancedperipherals.chatty_turtle": "Chatty", "turtle.advancedperipherals.chunky_turtle": "Chunky", "turtle.advancedperipherals.compass_turtle": "Compass", - "turtle.advancedperipherals.end_automata": "End automata", + "turtle.advancedperipherals.end_automata": "End Automata", "turtle.advancedperipherals.environment_turtle": "Environment", "turtle.advancedperipherals.geoscanner_turtle": "Geo", - "turtle.advancedperipherals.husbandry_automata": "Husbandry automata", - "turtle.advancedperipherals.overpowered_end_automata": "Overpowered end automata", - "turtle.advancedperipherals.overpowered_husbandry_automata": "Overpowered husbandry automata", - "turtle.advancedperipherals.overpowered_weak_automata": "Overpowered weak automata", + "turtle.advancedperipherals.husbandry_automata": "Husbandry Automata", + "turtle.advancedperipherals.overpowered_end_automata": "Overpowered End Automata", + "turtle.advancedperipherals.overpowered_husbandry_automata": "Overpowered Husbandry Automata", + "turtle.advancedperipherals.overpowered_weak_automata": "Overpowered Weak Automata", "turtle.advancedperipherals.player_turtle": "Player Detector", - "turtle.advancedperipherals.weak_automata": "Weak automata" + "turtle.advancedperipherals.saddle_turtle": "Saddle", + "turtle.advancedperipherals.weak_automata": "Weak Automata" } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/chat_box.json b/src/generated/resources/assets/advancedperipherals/models/block/chat_box.json index 487d0eb4e..ba89671f2 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/chat_box.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/chat_box.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/chat_box", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/chat_box_front", - "particle": "advancedperipherals:block/chat_box_front" + "particle": "advancedperipherals:block/chat_box_front", + "up": "advancedperipherals:block/chat_box_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/colony_integrator.json b/src/generated/resources/assets/advancedperipherals/models/block/colony_integrator.json index 884006124..7f52aebb0 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/colony_integrator.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/colony_integrator.json @@ -2,8 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/colony_integrator", - "down": "minecraft:block/oak_log_top", - "particle": "advancedperipherals:block/colony_integrator", - "up": "minecraft:block/oak_log_top" + "down": "advancedperipherals:block/bottom", + "north": "advancedperipherals:block/colony_integrator_front", + "particle": "advancedperipherals:block/colony_integrator_front", + "up": "advancedperipherals:block/colony_integrator_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/distance_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/distance_detector.json new file mode 100644 index 000000000..0cee7c371 --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/models/block/distance_detector.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "down": "advancedperipherals:block/distance_detector_down", + "east": "advancedperipherals:block/distance_detector_east", + "north": "advancedperipherals:block/distance_detector_north", + "particle": "advancedperipherals:block/distance_detector_north", + "south": "advancedperipherals:block/distance_detector_south", + "up": "advancedperipherals:block/distance_detector_up", + "west": "advancedperipherals:block/distance_detector_west" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/energy_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/energy_detector.json index d1b21431d..ebb28dd2e 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/energy_detector.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/energy_detector.json @@ -2,8 +2,11 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/energy_detector", + "down": "advancedperipherals:block/bottom", + "east": "advancedperipherals:block/energy_detector_east", "north": "advancedperipherals:block/energy_detector_front", "particle": "advancedperipherals:block/energy_detector_front", - "south": "advancedperipherals:block/energy_detector_back" + "south": "advancedperipherals:block/energy_detector_back", + "up": "advancedperipherals:block/energy_detector_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/environment_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/environment_detector.json index e049a94d1..ce251a7af 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/environment_detector.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/environment_detector.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/environment_detector", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/environment_detector_front", - "particle": "advancedperipherals:block/environment_detector_front" + "particle": "advancedperipherals:block/environment_detector_front", + "up": "advancedperipherals:block/environment_detector_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/fluid_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/fluid_detector.json new file mode 100644 index 000000000..6460c20e7 --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/models/block/fluid_detector.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "advancedperipherals:block/fluid_detector", + "down": "advancedperipherals:block/bottom", + "east": "advancedperipherals:block/fluid_detector_east", + "north": "advancedperipherals:block/fluid_detector_front", + "particle": "advancedperipherals:block/fluid_detector_front", + "south": "advancedperipherals:block/fluid_detector_back", + "up": "advancedperipherals:block/fluid_detector_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/gas_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/gas_detector.json new file mode 100644 index 000000000..c03bc40ae --- /dev/null +++ b/src/generated/resources/assets/advancedperipherals/models/block/gas_detector.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "advancedperipherals:block/gas_detector", + "down": "advancedperipherals:block/bottom", + "east": "advancedperipherals:block/gas_detector_east", + "north": "advancedperipherals:block/gas_detector_front", + "particle": "advancedperipherals:block/gas_detector_front", + "south": "advancedperipherals:block/gas_detector_back", + "up": "advancedperipherals:block/gas_detector_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/geo_scanner.json b/src/generated/resources/assets/advancedperipherals/models/block/geo_scanner.json index d81084e52..4870d8a6b 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/geo_scanner.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/geo_scanner.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/geo_scanner", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/geo_scanner_front", - "particle": "advancedperipherals:block/geo_scanner_front" + "particle": "advancedperipherals:block/geo_scanner_front", + "up": "advancedperipherals:block/geo_scanner_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/inventory_manager.json b/src/generated/resources/assets/advancedperipherals/models/block/inventory_manager.json index 16ac6a767..8431aaece 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/inventory_manager.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/inventory_manager.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/inventory_manager", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/inventory_manager_front", - "particle": "advancedperipherals:block/inventory_manager_front" + "particle": "advancedperipherals:block/inventory_manager_front", + "up": "advancedperipherals:block/inventory_manager_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/me_bridge.json b/src/generated/resources/assets/advancedperipherals/models/block/me_bridge.json index 0d5355f55..ab8392272 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/me_bridge.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/me_bridge.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/me_bridge", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/me_bridge_front", - "particle": "advancedperipherals:block/me_bridge_front" + "particle": "advancedperipherals:block/me_bridge_front", + "up": "advancedperipherals:block/me_bridge_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/nbt_storage.json b/src/generated/resources/assets/advancedperipherals/models/block/nbt_storage.json index 4472f8466..8545dbe6a 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/nbt_storage.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/nbt_storage.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/nbt_storage", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/nbt_storage_front", - "particle": "advancedperipherals:block/nbt_storage_front" + "particle": "advancedperipherals:block/nbt_storage_front", + "up": "advancedperipherals:block/nbt_storage_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/peripheral_casing.json b/src/generated/resources/assets/advancedperipherals/models/block/peripheral_casing.json index d6dd9f3cc..598971334 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/peripheral_casing.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/peripheral_casing.json @@ -2,6 +2,7 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/peripheral_casing", + "down": "advancedperipherals:block/bottom", "particle": "advancedperipherals:block/peripheral_casing" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/player_detector.json b/src/generated/resources/assets/advancedperipherals/models/block/player_detector.json index f3d2db295..c658c96c7 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/player_detector.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/player_detector.json @@ -1,12 +1,13 @@ { "parent": "minecraft:block/cube_all", "textures": { - "all": "advancedperipherals:block/player_detector", + "down": "advancedperipherals:block/bottom", "east": "advancedperipherals:block/player_detector_side", "north": "advancedperipherals:block/player_detector_front", "particle": "advancedperipherals:block/player_detector_front", "side": "advancedperipherals:block/player_detector_side", "south": "advancedperipherals:block/player_detector_side", + "up": "advancedperipherals:block/player_detector_top", "west": "advancedperipherals:block/player_detector_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/redstone_integrator.json b/src/generated/resources/assets/advancedperipherals/models/block/redstone_integrator.json index 2fa89aaa5..038dd8561 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/redstone_integrator.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/redstone_integrator.json @@ -1,8 +1,13 @@ { "parent": "minecraft:block/cube_all", "textures": { - "all": "advancedperipherals:block/redstone_integrator", + "down": "advancedperipherals:block/redstone_integrator_bottom", + "east": "advancedperipherals:block/redstone_integrator_side", "north": "advancedperipherals:block/redstone_integrator_front", - "particle": "advancedperipherals:block/redstone_integrator_front" + "particle": "advancedperipherals:block/redstone_integrator_front", + "side": "advancedperipherals:block/redstone_integrator_side", + "south": "advancedperipherals:block/redstone_integrator_side", + "up": "advancedperipherals:block/redstone_integrator_top", + "west": "advancedperipherals:block/redstone_integrator_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/advancedperipherals/models/block/rs_bridge.json b/src/generated/resources/assets/advancedperipherals/models/block/rs_bridge.json index 10e0f003a..b7e3d476b 100644 --- a/src/generated/resources/assets/advancedperipherals/models/block/rs_bridge.json +++ b/src/generated/resources/assets/advancedperipherals/models/block/rs_bridge.json @@ -2,7 +2,9 @@ "parent": "minecraft:block/cube_all", "textures": { "all": "advancedperipherals:block/rs_bridge", + "down": "advancedperipherals:block/bottom", "north": "advancedperipherals:block/rs_bridge_front", - "particle": "advancedperipherals:block/rs_bridge_front" + "particle": "advancedperipherals:block/rs_bridge_front", + "up": "advancedperipherals:block/rs_bridge_top" } } \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/advancements/recipes/advancedperipheralstab/armor/smart_glasses_netherite.json b/src/generated/resources/data/advancedperipherals/advancements/recipes/advancedperipheralstab/armor/smart_glasses_netherite.json new file mode 100644 index 000000000..bb6e067ec --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/advancements/recipes/advancedperipheralstab/armor/smart_glasses_netherite.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:netherite_ingot" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "advancedperipherals:armor/smart_glasses_netherite" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "advancedperipherals:armor/smart_glasses_netherite" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/computercraft/pocket_upgrades/distance_pocket.json b/src/generated/resources/data/advancedperipherals/computercraft/pocket_upgrades/distance_pocket.json new file mode 100644 index 000000000..0d83ccc1d --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/computercraft/pocket_upgrades/distance_pocket.json @@ -0,0 +1,4 @@ +{ + "type": "advancedperipherals:distance_pocket", + "item": "advancedperipherals:distance_detector" +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json b/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json new file mode 100644 index 000000000..0670d5c0b --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json @@ -0,0 +1,4 @@ +{ + "type": "advancedperipherals:saddle_turtle", + "item": "minecraft:saddle" +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/loot_tables/blocks/distance_detector.json b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/distance_detector.json new file mode 100644 index 000000000..4da55fb18 --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/distance_detector.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + } + ], + "name": "advancedperipherals:distance_detector" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/loot_tables/blocks/fluid_detector.json b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/fluid_detector.json new file mode 100644 index 000000000..a57de0eab --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/fluid_detector.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + } + ], + "name": "advancedperipherals:fluid_detector" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/loot_tables/blocks/gas_detector.json b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/gas_detector.json new file mode 100644 index 000000000..be3a1af68 --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/loot_tables/blocks/gas_detector.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + } + ], + "name": "advancedperipherals:gas_detector" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/recipes/armor/smart_glasses_netherite.json b/src/generated/resources/data/advancedperipherals/recipes/armor/smart_glasses_netherite.json new file mode 100644 index 000000000..e46b01d51 --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/recipes/armor/smart_glasses_netherite.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "item": "minecraft:netherite_ingot" + }, + "base": { + "item": "advancedperipherals:smart_glasses" + }, + "result": { + "item": "advancedperipherals:smart_glasses_netherite" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/tags/items/p2p_attunements/cable_p2p_tunnel.json b/src/generated/resources/data/advancedperipherals/tags/items/p2p_attunements/cable_p2p_tunnel.json new file mode 100644 index 000000000..7fc8269c3 --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/tags/items/p2p_attunements/cable_p2p_tunnel.json @@ -0,0 +1,7 @@ +{ + "values": [ + "computercraft:cable", + "computercraft:wired_modem", + "computercraft:wired_modem_full" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/tags/items/smart_glasses.json b/src/generated/resources/data/advancedperipherals/tags/items/smart_glasses.json new file mode 100644 index 000000000..1f793687e --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/tags/items/smart_glasses.json @@ -0,0 +1,6 @@ +{ + "values": [ + "advancedperipherals:smart_glasses", + "advancedperipherals:smart_glasses_netherite" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json index ffd23c4b9..0578bfe7e 100644 --- a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json +++ b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json @@ -1,5 +1,6 @@ { "values": [ - "advancedperipherals:peripheral_casing" + "advancedperipherals:peripheral_casing", + "advancedperipherals:colony_integrator" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index ada8618ef..67218e709 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -1,17 +1,20 @@ { "values": [ - "advancedperipherals:environment_detector", + "advancedperipherals:block_reader", "advancedperipherals:chat_box", - "advancedperipherals:player_detector", - "advancedperipherals:me_bridge", - "advancedperipherals:rs_bridge", + "advancedperipherals:colony_integrator", + "advancedperipherals:distance_detector", "advancedperipherals:energy_detector", - "advancedperipherals:peripheral_casing", + "advancedperipherals:environment_detector", + "advancedperipherals:fluid_detector", + "advancedperipherals:gas_detector", + "advancedperipherals:geo_scanner", "advancedperipherals:inventory_manager", + "advancedperipherals:me_bridge", + "advancedperipherals:nbt_storage", + "advancedperipherals:peripheral_casing", + "advancedperipherals:player_detector", "advancedperipherals:redstone_integrator", - "advancedperipherals:block_reader", - "advancedperipherals:geo_scanner", - "advancedperipherals:colony_integrator", - "advancedperipherals:nbt_storage" + "advancedperipherals:rs_bridge" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json index 002d1e917..5a4f0e2b8 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json +++ b/src/generated/resources/data/minecraft/tags/blocks/needs_iron_tool.json @@ -1,16 +1,19 @@ { "values": [ - "advancedperipherals:environment_detector", + "advancedperipherals:block_reader", "advancedperipherals:chat_box", - "advancedperipherals:player_detector", - "advancedperipherals:me_bridge", - "advancedperipherals:rs_bridge", + "advancedperipherals:colony_integrator", + "advancedperipherals:distance_detector", "advancedperipherals:energy_detector", + "advancedperipherals:environment_detector", + "advancedperipherals:fluid_detector", + "advancedperipherals:gas_detector", + "advancedperipherals:geo_scanner", "advancedperipherals:inventory_manager", + "advancedperipherals:me_bridge", + "advancedperipherals:nbt_storage", + "advancedperipherals:player_detector", "advancedperipherals:redstone_integrator", - "advancedperipherals:block_reader", - "advancedperipherals:geo_scanner", - "advancedperipherals:colony_integrator", - "advancedperipherals:nbt_storage" + "advancedperipherals:rs_bridge" ] } \ No newline at end of file diff --git a/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java b/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java index dcdd0c566..8489c5f95 100644 --- a/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java +++ b/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java @@ -1,8 +1,8 @@ package de.srendi.advancedperipherals; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.setup.APRegistration; import de.srendi.advancedperipherals.common.setup.CCRegistration; -import de.srendi.advancedperipherals.common.setup.Registration; import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; import net.minecraft.core.NonNullList; import net.minecraft.resources.ResourceLocation; @@ -22,7 +22,7 @@ public APCreativeTab() { @Override public void fillItemList(NonNullList items) { - Registration.ITEMS.getEntries().stream().map(RegistryObject::get).forEach(item -> items.add(new ItemStack(item))); + APRegistration.ITEMS.getEntries().stream().map(RegistryObject::get).forEach(item -> items.add(new ItemStack(item))); items.addAll(pocketUpgrade(CCRegistration.ID.COLONY_POCKET)); items.addAll(pocketUpgrade(CCRegistration.ID.CHATTY_POCKET)); items.addAll(pocketUpgrade(CCRegistration.ID.PLAYER_POCKET)); @@ -32,6 +32,7 @@ public void fillItemList(NonNullList items) { items.addAll(turtleUpgrade(CCRegistration.ID.CHATTY_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.CHUNKY_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.COMPASS_TURTLE)); + items.addAll(turtleUpgrade(CCRegistration.ID.SADDLE_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.PLAYER_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.ENVIRONMENT_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.GEOSCANNER_TURTLE)); @@ -57,6 +58,6 @@ private static Collection turtleUpgrade(ResourceLocation pocketId) { @Override @NotNull public ItemStack makeIcon() { - return new ItemStack(Blocks.CHAT_BOX.get()); + return new ItemStack(APBlocks.CHAT_BOX.get()); } } diff --git a/src/main/java/de/srendi/advancedperipherals/AdvancedPeripherals.java b/src/main/java/de/srendi/advancedperipherals/AdvancedPeripherals.java index 40ab9c1a9..8f7a80ffd 100644 --- a/src/main/java/de/srendi/advancedperipherals/AdvancedPeripherals.java +++ b/src/main/java/de/srendi/advancedperipherals/AdvancedPeripherals.java @@ -1,16 +1,18 @@ package de.srendi.advancedperipherals; import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.addons.ae2.AE2Registries; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.Registration; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.setup.APRegistration; import de.srendi.advancedperipherals.common.village.VillageStructures; -import de.srendi.advancedperipherals.network.APNetworking; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; @@ -26,6 +28,7 @@ public class AdvancedPeripherals { public static final Logger LOGGER = LogManager.getLogger(NAME); public static final Random RANDOM = new Random(); public static final APCreativeTab TAB = new APCreativeTab(); + public static final APAddons ADDONS = new APAddons(); public AdvancedPeripherals() { LOGGER.info("AdvancedPeripherals says hello!"); @@ -34,8 +37,10 @@ public AdvancedPeripherals() { APConfig.register(ModLoadingContext.get()); modBus.addListener(this::commonSetup); - Registration.register(); + modBus.addListener(this::onLoadComplete); + APRegistration.register(); MinecraftForge.EVENT_BUS.register(this); + new APAddons(); } public static void debug(String message) { @@ -48,16 +53,28 @@ public static void debug(String message, Level level) { LOGGER.log(level, "[DEBUG] {}", message); } + public static void exception(String message, Exception exception) { + if (APConfig.GENERAL_CONFIG.enableDebugMode.get()) { + LOGGER.error("[DEBUG]", exception); + } + } + public static ResourceLocation getRL(String resource) { return new ResourceLocation(MOD_ID, resource); } public void commonSetup(FMLCommonSetupEvent event) { - APAddons.commonSetup(); event.enqueueWork(() -> { APNetworking.init(); VillageStructures.init(); }); } + public void onLoadComplete(FMLLoadCompleteEvent event) { + event.enqueueWork(() -> { + if (APAddons.appliedEnergisticsLoaded) { + AE2Registries.finishRegister(); + } + }); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java b/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java new file mode 100644 index 000000000..0dfeb5c28 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java @@ -0,0 +1,85 @@ +package de.srendi.advancedperipherals.client; + +import com.mojang.blaze3d.platform.InputConstants; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toserver.SaddleTurtleControlPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.Input; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.client.event.MovementInputUpdateEvent; +import net.minecraftforge.client.event.RenderGuiOverlayEvent; +import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; +import net.minecraftforge.event.entity.EntityMountEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID, value = Dist.CLIENT) +public class ClientEventSubscriber { + @SubscribeEvent + public static void renderingHuds(RenderGuiOverlayEvent.Pre event) { + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.shouldRenderFuelBar() && event.getOverlay().id().equals(VanillaGuiOverlay.EXPERIENCE_BAR.id())) { + event.setCanceled(true); + return; + } + } + + private static boolean sneaking = false; + + @SubscribeEvent + public static void playerTryDismount(InputEvent.Key event) { + Minecraft minecraft = Minecraft.getInstance(); + boolean isShift = minecraft.options.keyShift.matches(event.getKey(), event.getScanCode()); + if (!isShift) { + return; + } + switch (event.getAction()) { + case InputConstants.PRESS: + sneaking = true; + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.isPlayerControllingTurtle()) { + minecraft.options.keyShift.setDown(false); + } + break; + case InputConstants.RELEASE: + sneaking = false; + break; + } + } + + private static Input lastInput = new Input(); + private static boolean lastSneak = false; + + @SubscribeEvent + public static void playerMounting(EntityMountEvent event) { + if (event.isMounting() && event.getEntityMounting() == Minecraft.getInstance().player && event.getEntityBeingMounted() instanceof TurtleSeatEntity) { + // clear last key records + lastInput.up = false; + lastInput.down = false; + lastInput.left = false; + lastInput.right = false; + lastInput.jumping = false; + lastSneak = false; + } + } + + @SubscribeEvent + public static void playerMove(MovementInputUpdateEvent event) { + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.isPlayerControllingTurtle()) { + Input input = event.getInput(); + if (sneaking == lastSneak && lastInput != null) { + if (lastInput.up == input.up && lastInput.down == input.down && lastInput.left == input.left && lastInput.right == input.right && lastInput.jumping == input.jumping) { + return; + } + } + lastInput.up = input.up; + lastInput.down = input.down; + lastInput.left = input.left; + lastInput.right = input.right; + lastInput.jumping = input.jumping; + lastSneak = sneaking; + APNetworking.sendToServer(new SaddleTurtleControlPacket(input.up, input.down, input.left, input.right, input.jumping, sneaking)); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java b/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java index 160836009..4a784dfc3 100644 --- a/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java +++ b/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java @@ -3,15 +3,24 @@ import dan200.computercraft.api.client.ComputerCraftAPIClient; import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.container.InventoryManagerScreen; +import de.srendi.advancedperipherals.client.renderer.DistanceDetectorRenderer; +import de.srendi.advancedperipherals.client.screens.InventoryManagerScreen; +import de.srendi.advancedperipherals.client.screens.SaddleTurtleScreen; +import de.srendi.advancedperipherals.client.screens.SmartGlassesScreen; +import de.srendi.advancedperipherals.client.smartglasses.OverlayModuleOverlay; +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APContainerTypes; import de.srendi.advancedperipherals.common.setup.CCRegistration; -import de.srendi.advancedperipherals.common.setup.ContainerTypes; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.ModelEvent; +import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @@ -21,6 +30,9 @@ public class ClientRegistry { private static final String[] TURTLE_MODELS = new String[]{"turtle_chat_box_upgrade_left", "turtle_chat_box_upgrade_right", "turtle_environment_upgrade_left", "turtle_environment_upgrade_right", "turtle_player_upgrade_left", "turtle_player_upgrade_right", "turtle_geoscanner_upgrade_left", "turtle_geoscanner_upgrade_right"}; + public static final SaddleTurtleScreen SADDLE_TURTLE_OVERLAY = new SaddleTurtleScreen(); + public static final OverlayModuleOverlay OVERLAY_MODULE_OVERLAY = new OverlayModuleOverlay(); + @SubscribeEvent public static void registerModels(ModelEvent.RegisterAdditional event) { for (String model : TURTLE_MODELS) { @@ -30,10 +42,12 @@ public static void registerModels(ModelEvent.RegisterAdditional event) { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { - MenuScreens.register(ContainerTypes.INVENTORY_MANAGER_CONTAINER.get(), InventoryManagerScreen::new); + MenuScreens.register(APContainerTypes.INVENTORY_MANAGER_CONTAINER.get(), InventoryManagerScreen::new); + MenuScreens.register(APContainerTypes.SMART_GLASSES_CONTAINER.get(), SmartGlassesScreen::new); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.CHUNKY_TURTLE.get(), TurtleUpgradeModeller.flatItem()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.COMPASS_TURTLE.get(), TurtleUpgradeModeller.flatItem()); + ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.SADDLE_TURTLE.get(), TurtleUpgradeModeller.flatItem()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.CHAT_BOX_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_chat_box_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_chat_box_upgrade_right"), "inventory"))); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.ENVIRONMENT_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_environment_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_environment_upgrade_right"), "inventory"))); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.GEO_SCANNER_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_geoscanner_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_geoscanner_upgrade_right"), "inventory"))); @@ -44,16 +58,24 @@ public static void onClientSetup(FMLClientSetupEvent event) { ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.HUSBANDRY_TURTLE.get(), new MetaTurtleUpgradeModeller<>()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.END_TURTLE.get(), new MetaTurtleUpgradeModeller<>()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.WEAK_TURTLE.get(), new MetaTurtleUpgradeModeller<>()); + + ItemPropertiesRegistry.register(); + OverlayObjectHolder.registerDecodeObjects(); } @SubscribeEvent - public static void onClientSetup(RegisterKeyMappingsEvent event) { + public static void registeringKeymappings(RegisterKeyMappingsEvent event) { KeyBindings.register(event); } - //TODO change the icon of the curio icon - /*@SubscribeEvent - public static void onTextureStitching(TextureStitchEvent.Pre event) { - event.addSprite(new ResourceLocation(AdvancedPeripherals.MOD_ID, "item/empty_glasses_slot")); - }*/ + @SubscribeEvent + public static void registeringRenderers(EntityRenderersEvent.RegisterRenderers event) { + event.registerBlockEntityRenderer(APBlockEntityTypes.DISTANCE_DETECTOR.get(), DistanceDetectorRenderer::new); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void registeringOverlays(RegisterGuiOverlaysEvent event) { + event.registerAboveAll(SaddleTurtleScreen.ID, SADDLE_TURTLE_OVERLAY); + event.registerAboveAll(OverlayModuleOverlay.ID, OVERLAY_MODULE_OVERLAY); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/client/ItemPropertiesRegistry.java b/src/main/java/de/srendi/advancedperipherals/client/ItemPropertiesRegistry.java new file mode 100644 index 000000000..00ef43539 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/ItemPropertiesRegistry.java @@ -0,0 +1,17 @@ +package de.srendi.advancedperipherals.client; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.setup.APItems; +import net.minecraft.client.renderer.item.ItemProperties; +import net.minecraft.resources.ResourceLocation; + +public class ItemPropertiesRegistry { + + public static void register() { + ItemProperties.register(APItems.MEMORY_CARD.get(), new ResourceLocation(AdvancedPeripherals.MOD_ID, "bounded"), (stack, level, entity, seed) -> { + boolean bounded = stack.getOrCreateTag().contains("owner"); + return bounded ? 1 : 0; + }); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/KeyBindings.java b/src/main/java/de/srendi/advancedperipherals/client/KeyBindings.java index 2cbd46438..37cea5f0d 100644 --- a/src/main/java/de/srendi/advancedperipherals/client/KeyBindings.java +++ b/src/main/java/de/srendi/advancedperipherals/client/KeyBindings.java @@ -7,9 +7,11 @@ public class KeyBindings { public static final KeyMapping DESCRIPTION_KEYBINDING = new KeyMapping("keybind.advancedperipherals.description", GLFW.GLFW_KEY_LEFT_CONTROL, "keybind.advancedperipherals.category"); + public static final KeyMapping GLASSES_HOTKEY_KEYBINDING = new KeyMapping("keybind.advancedperipherals.glasses_hotkey", GLFW.GLFW_KEY_G, "keybind.advancedperipherals.category"); public static void register(RegisterKeyMappingsEvent event) { event.register(DESCRIPTION_KEYBINDING); + event.register(GLASSES_HOTKEY_KEYBINDING); } } diff --git a/src/main/java/de/srendi/advancedperipherals/client/RenderUtil.java b/src/main/java/de/srendi/advancedperipherals/client/RenderUtil.java new file mode 100644 index 000000000..4a4826238 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/RenderUtil.java @@ -0,0 +1,367 @@ +package de.srendi.advancedperipherals.client; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.inventory.InventoryMenu; + +public class RenderUtil { + + public static void drawBox(PoseStack poseStack, VertexConsumer buffer, float r, float g, float b, float a, float pX, float pY, float pZ, float xRot, float yRot, float zRot, float sX, float sY, float sZ) { + poseStack.pushPose(); + sX = sX / 16; //Sizes in pixels please + sY = sY / 16; + sZ = sZ / 16; + pX = pX / 16; + pY = pY / 16; + pZ = pZ / 16; + + poseStack.mulPose(new Quaternion(xRot, yRot, zRot, true)); + + drawPlane(poseStack, buffer, r, g, b, a, Direction.UP, pX, pY, pZ, sX, sY, sZ); + drawPlane(poseStack, buffer, r, g, b, a, Direction.DOWN, pX, pY, pZ, sX, sY, sZ); + drawPlane(poseStack, buffer, r, g, b, a, Direction.EAST, pX, pY, pZ, sX, sY, sZ); + drawPlane(poseStack, buffer, r, g, b, a, Direction.WEST, pX, pY, pZ, sX, sY, sZ); + drawPlane(poseStack, buffer, r, g, b, a, Direction.NORTH, pX, pY, pZ, sX, sY, sZ); + drawPlane(poseStack, buffer, r, g, b, a, Direction.SOUTH, pX, pY, pZ, sX, sY, sZ); + poseStack.popPose(); + } + + public static void drawPlane(PoseStack posestack, VertexConsumer buffer, float r, float g, float b, float a, Direction perspective, float pX, float pY, float pZ, float sX, float sY, float sZ) { + posestack.pushPose(); + + pX = pX + 0.5f; + pY = pY + 0.5f; + pZ = pZ + 0.5f; + + posestack.translate(pX, pY, pZ); + + Matrix4f matrix4f = posestack.last().pose(); + + sX = sX / 2; + sY = sY / 2; + sZ = sZ / 2; + + + if (perspective == Direction.UP) { + buffer.vertex(matrix4f, -sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + if (perspective == Direction.DOWN) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + } + if (perspective == Direction.SOUTH) { + buffer.vertex(matrix4f, sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + } + if (perspective == Direction.NORTH) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + } + if (perspective == Direction.EAST) { + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + if (perspective == Direction.WEST) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, sZ).color(r, g, b, a).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + posestack.popPose(); + } + + public static void drawTorus(PoseStack poseStack, VertexConsumer consumer, float majorRadius, float minorRadius, double pX, double pY, double pZ, float xRot, float yRot, float zRot, float r, float g, float b, float a, int sides, int rings) { + poseStack.pushPose(); + poseStack.translate(pX, pY, pZ); + poseStack.mulPose(new Quaternion(xRot, yRot, zRot, true)); + + Matrix4f matrix4f = poseStack.last().pose(); + TextureAtlasSprite texture = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(new ResourceLocation("block/crimson_stem")); + + float x, y, z; + float nx, ny, nz; + + float ringStep = (float) (2 * Math.PI / rings); + float sideStep = (float) (2 * Math.PI / sides); + float ringAngle, sideAngle; + + for (int i = 0; i < rings; ++i) { + ringAngle = i * ringStep; + float cosRingAngle = (float) Math.cos(ringAngle); + float sinRingAngle = (float) Math.sin(ringAngle); + + float nextRingAngle = (i + 1) * ringStep; + float nextCosRingAngle = (float) Math.cos(nextRingAngle); + float nextSinRingAngle = (float) Math.sin(nextRingAngle); + + // Calculate the center point of the minor circles + float centerX = majorRadius * cosRingAngle; + float centerY = majorRadius * sinRingAngle; + float nextCenterX = majorRadius * nextCosRingAngle; + float nextCenterY = majorRadius * nextSinRingAngle; + + for (int j = 0; j < sides; ++j) { + sideAngle = j * sideStep; + float cosSideAngle = (float) Math.cos(sideAngle); + float sinSideAngle = (float) Math.sin(sideAngle); + + float nextSideAngle = (j + 1) * sideStep; + float nextCosSideAngle = (float) Math.cos(nextSideAngle); + float nextSinSideAngle = (float) Math.sin(nextSideAngle); + + float s = j / sides; + float t = i / rings; + + float u1 = getU(s * sides, texture.getU1(), texture.getU0(), sides); + float u2 = getU((s + 1.0f / sides) * sides, texture.getU1(), texture.getU0(), sides); + float v1 = getV(t * rings, texture.getV1(), texture.getV0(), rings); + float v2 = getV((t + 1.0f / rings) * rings, texture.getV1(), texture.getV0(), rings); + + x = centerX + minorRadius * nextCosSideAngle * cosRingAngle; + y = centerY + minorRadius * nextCosSideAngle * sinRingAngle; + z = minorRadius * nextSinSideAngle; + + nx = x - centerX; + ny = y - centerY; + nz = z; + consumer.vertex(matrix4f, x, y, z).color(r, g, b, a).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx, ny, nz).endVertex(); + + // Calculate vertex positions + x = centerX + minorRadius * cosSideAngle * cosRingAngle; + y = centerY + minorRadius * cosSideAngle * sinRingAngle; + z = minorRadius * sinSideAngle; + + // Calculate normal + nx = x - centerX; + ny = y - centerY; + nz = z; + + consumer.vertex(matrix4f, x, y, z).color(r, g, b, a).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx, ny, nz).endVertex(); + + x = nextCenterX + minorRadius * cosSideAngle * nextCosRingAngle; + y = nextCenterY + minorRadius * cosSideAngle * nextSinRingAngle; + z = minorRadius * sinSideAngle; + + nx = x - nextCenterX; + ny = y - nextCenterY; + nz = z; + consumer.vertex(matrix4f, x, y, z).color(r, g, b, a).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx, ny, nz).endVertex(); + + + x = nextCenterX + minorRadius * nextCosSideAngle * nextCosRingAngle; + y = nextCenterY + minorRadius * nextCosSideAngle * nextSinRingAngle; + z = minorRadius * nextSinSideAngle; + + nx = x - nextCenterX; + ny = y - nextCenterY; + nz = z; + consumer.vertex(matrix4f, x, y, z).color(r, g, b, a).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx, ny, nz).endVertex(); + } + } + + poseStack.popPose(); + } + + public static void drawSphere(PoseStack poseStack, VertexConsumer consumer, float radius, double pX, double pY, double pZ, float xRot, float yRot, float zRot, float r, float g, float b, float a, int sectors, int stacks) { + poseStack.pushPose(); + poseStack.translate(pX, pY, pZ); + poseStack.mulPose(new Quaternion(xRot, yRot, zRot, true)); + + Matrix4f matrix4f = poseStack.last().pose(); + TextureAtlasSprite texture = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation("block/dirt")); + + float z, xy; + float nx1, ny1, nz1, nx2, ny2, nz2, nx3, ny3, nz3, nx4, ny4, nz4, lengthInv = (1.0f / radius); // vertex normal + float s, t; + + float sectorStep = (float) (2 * Math.PI / sectors); + float stackStep = (float) (Math.PI / stacks); + float sectorAngle, stackAngle; + + for (int i = 1; i <= stacks; ++i) { + stackAngle = (float) (Math.PI / 2 - i * stackStep); + + xy = (float) (radius * Math.cos(stackAngle)); + z = (float) (radius * Math.sin(stackAngle)); + + for (int j = 0; j < sectors; ++j) { + + sectorAngle = j * sectorStep; + + float x1 = (float) (xy * Math.cos(sectorAngle)); + float y1 = (float) (xy * Math.sin(sectorAngle)); + + float x2 = (float) (xy * Math.cos(sectorAngle + sectorStep)); + float y2 = (float) (xy * Math.sin(sectorAngle + sectorStep)); + + float x3 = (float) (radius * Math.cos(stackAngle + stackStep) * Math.cos(sectorAngle + sectorStep)); + float y3 = (float) (radius * Math.cos(stackAngle + stackStep) * Math.sin(sectorAngle + sectorStep)); + float z3 = (float) (radius * Math.sin(stackAngle + stackStep)); + + float x4 = (float) (radius * Math.cos(stackAngle + stackStep) * Math.cos(sectorAngle)); + float y4 = (float) (radius * Math.cos(stackAngle + stackStep) * Math.sin(sectorAngle)); + float z4 = (float) (radius * Math.sin(stackAngle + stackStep)); + + nx1 = x1 * lengthInv; + ny1 = y1 * lengthInv; + nz1 = z * lengthInv; + + nx2 = x2 * lengthInv; + ny2 = y2 * lengthInv; + nz2 = z * lengthInv; + + nx3 = x3 * lengthInv; + ny3 = y3 * lengthInv; + nz3 = z3 * lengthInv; + + nx4 = x4 * lengthInv; + ny4 = y4 * lengthInv; + nz4 = z4 * lengthInv; + + s = j / sectors; + t = i / stacks; + + float u1 = getU(s * sectors, texture.getU1(), texture.getU0(), sectors); + float u2 = getU((s + 1.0d / sectors) * sectors, texture.getU1(), texture.getU0(), sectors); + float v1 = getV(t * stacks, texture.getV1(), texture.getV0(), stacks); + float v2 = getV((t + 1.0d / stacks) * stacks, texture.getV1(), texture.getV0(), stacks); + + // For a reason which I am too dumb to understand, the uv coords have a one pixel offset + // So... I just reverse it and it works + v1 -= (texture.getV1() - texture.getV0()) / stacks; + v2 -= (texture.getV1() - texture.getV0()) / stacks; + + consumer.vertex(matrix4f, x1, y1, z).color(r, g, b, a).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx1, ny1, nz1).endVertex(); + consumer.vertex(matrix4f, x2, y2, z).color(r, g, b, a).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx2, ny2, nz2).endVertex(); + consumer.vertex(matrix4f, x3, y3, z3).color(r, g, b, a).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx3, ny3, nz3).endVertex(); + consumer.vertex(matrix4f, x4, y4, z4).color(r, g, b, a).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(nx4, ny4, nz4).endVertex(); + + } + } + poseStack.popPose(); + + } + + private static float getU(double pU, float u1, float u0, float resolution) { + float f = u1 - u0; + return u0 + f * (float) pU / resolution; + } + + private static float getV(double pV, float v1, float v0, float resolution) { + float f = v1 - v0; + return v0 + f * (float) pV / resolution; + } + + public static void drawBox(PoseStack poseStack, VertexConsumer buffer, ResourceLocation texture, float pX, float pY, float pZ, float xRot, float yRot, float zRot, float sX, float sY, float sZ, float pUOffset, float pVOffset, float pWidth, float pHeight) { + poseStack.pushPose(); + sX = sX / 16; //Sizes in pixels please + sY = sY / 16; + sZ = sZ / 16; + pX = pX / 16; + pY = pY / 16; + pZ = pZ / 16; + + poseStack.mulPose(new Quaternion(xRot, yRot, zRot, true)); + + drawPlane(poseStack, buffer, texture, Direction.UP, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + drawPlane(poseStack, buffer, texture, Direction.DOWN, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + drawPlane(poseStack, buffer, texture, Direction.EAST, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + drawPlane(poseStack, buffer, texture, Direction.WEST, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + drawPlane(poseStack, buffer, texture, Direction.NORTH, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + drawPlane(poseStack, buffer, texture, Direction.SOUTH, pX, pY, pZ, sX, sY, sZ, pUOffset, pVOffset, pWidth, pHeight); + poseStack.popPose(); + } + + public static void drawPlane(PoseStack poseStack, VertexConsumer buffer, ResourceLocation texture, Direction perspective, float pX, float pY, float pZ, float sX, float sY, float sZ, float pUOffset, float pVOffset, float pWidth, float pHeight) { + poseStack.pushPose(); + + pX = pX + 0.5f; + pY = pY + 0.5f; + pZ = pZ + 0.5f; + + poseStack.translate(pX, pY, pZ); + + Matrix4f matrix4f = poseStack.last().pose(); + + TextureAtlasSprite stillTexture = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture); + + sX = sX / 2; + sY = sY / 2; + sZ = sZ / 2; + + float u1 = stillTexture.getU(pUOffset); + float u2 = stillTexture.getU(pWidth); + float v1 = stillTexture.getV(pVOffset); + float v2 = stillTexture.getV(pHeight); + + if (perspective == Direction.UP) { + buffer.vertex(matrix4f, -sX, sY, sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + if (perspective == Direction.DOWN) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, -1f, 0f).endVertex(); + } + if (perspective == Direction.SOUTH) { + buffer.vertex(matrix4f, sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + } + if (perspective == Direction.NORTH) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(1f, 0f, 0f).endVertex(); + } + if (perspective == Direction.EAST) { + buffer.vertex(matrix4f, -sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, -sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, -sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + if (perspective == Direction.WEST) { + buffer.vertex(matrix4f, -sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, -sY, sZ).color(1, 1, 1, 1f).uv(u1, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, sX, sY, sZ).color(1, 1, 1, 1f).uv(u2, v1).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + buffer.vertex(matrix4f, -sX, sY, sZ).color(1, 1, 1, 1f).uv(u2, v2).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(0xF000F0).normal(0f, 1f, 0f).endVertex(); + } + poseStack.popPose(); + } + + public static float getBlue(int hex) { + return (hex & 0xFF) / 255.0F; + } + + public static float getGreen(int hex) { + return (hex >> 8 & 0xFF) / 255.0F; + } + + public static float getRed(int hex) { + return (hex >> 16 & 0xFF) / 255.0F; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/renderer/DistanceDetectorRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/renderer/DistanceDetectorRenderer.java new file mode 100644 index 000000000..a0b6f8a7c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/renderer/DistanceDetectorRenderer.java @@ -0,0 +1,104 @@ +package de.srendi.advancedperipherals.client.renderer; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; +import de.srendi.advancedperipherals.common.blocks.blockentities.DistanceDetectorEntity; +import de.srendi.advancedperipherals.common.util.EnumColor; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BeaconRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class DistanceDetectorRenderer implements BlockEntityRenderer { + + public DistanceDetectorRenderer(BlockEntityRendererProvider.Context pContext) { + super(); + } + + @Override + public void render(@NotNull DistanceDetectorEntity pBlockEntity, float pPartialTick, @NotNull PoseStack pPoseStack, MultiBufferSource pBufferSource, int pPackedLight, int pPackedOverlay) { + if (pBlockEntity.getShowLaser()) { + float distance = pBlockEntity.getCurrentDistance(); + float[] color = EnumColor.RED.getRgb(); + if (distance == -1) { + distance = pBlockEntity.getMaxRange(); + color = EnumColor.DARK_RED.getRgb(); + } + renderBeaconBeam(pBlockEntity, pPoseStack, pBufferSource, BeaconRenderer.BEAM_LOCATION, pPartialTick, 1, 0, distance + 0.5f, color, 0.05f, 0.09f); + } + } + + @Override + public boolean shouldRenderOffScreen(@NotNull DistanceDetectorEntity pBlockEntity) { + return true; + } + + @Override + public int getViewDistance() { + return 256; + } + + @Override + public boolean shouldRender(@NotNull DistanceDetectorEntity pBlockEntity, @NotNull Vec3 pCameraPos) { + return true; + } + + public static void renderBeaconBeam(DistanceDetectorEntity detectorEntity, PoseStack pPoseStack, MultiBufferSource pBufferSource, ResourceLocation pBeamLocation, float pPartialTick, float pTextureScale, int pYOffset, float pHeight, float[] pColors, float pBeamRadius, float pGlowRadius) { + long pGameTime = detectorEntity.getLevel().getGameTime(); + float maxX = pYOffset + pHeight; + Direction direction = detectorEntity.getBlockState().getValue(BaseBlock.ORIENTATION).front(); + pPoseStack.pushPose(); + pPoseStack.translate(0.5D, 0.5D, 0.5D); + float degrees = Math.floorMod(pGameTime, 360) + pPartialTick; + float reversedDegrees = pHeight < 0 ? degrees : -degrees; + float time = Mth.frac(reversedDegrees * 0.2F - Mth.floor(reversedDegrees * 0.1F)); + float r = pColors[0]; + float g = pColors[1]; + float b = pColors[2]; + pPoseStack.pushPose(); + pPoseStack.mulPose(direction.getRotation()); + pPoseStack.mulPose(Vector3f.YP.rotationDegrees(degrees * 2.25F - 45.0F)); + float f15 = -1.0F + time; + float f16 = pHeight * pTextureScale * (0.5F / pBeamRadius) + f15; + renderPart(pPoseStack, pBufferSource.getBuffer(RenderType.beaconBeam(pBeamLocation, false)), r, g, b, 1.0F, pYOffset, maxX, 0.0F, pBeamRadius, pBeamRadius, 0.0F, -pBeamRadius, 0.0F, 0.0F, -pBeamRadius, 0.0F, 1.0F, f16, f15); + pPoseStack.popPose(); + pPoseStack.mulPose(direction.getRotation()); + f15 = -1.0F + time; + f16 = pHeight * pTextureScale + f15; + renderPart(pPoseStack, pBufferSource.getBuffer(RenderType.beaconBeam(pBeamLocation, true)), r, g, b, 0.225F, pYOffset, maxX, -pGlowRadius, -pGlowRadius, pGlowRadius, -pGlowRadius, -pBeamRadius, pGlowRadius, pGlowRadius, pGlowRadius, 0.0F, 1.0F, f16, f15); + pPoseStack.popPose(); + } + + private static void renderPart(PoseStack pPoseStack, VertexConsumer pConsumer, float pRed, float pGreen, float pBlue, float pAlpha, int pMinY, float pMaxY, float pX0, float pZ0, float pX1, float pZ1, float pX2, float pZ2, float pX3, float pZ3, float pMinU, float pMaxU, float pMinV, float pMaxV) { + PoseStack.Pose posestackPose = pPoseStack.last(); + Matrix4f matrix4f = posestackPose.pose(); + Matrix3f matrix3f = posestackPose.normal(); + renderQuad(matrix4f, matrix3f, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMaxY, pX0, pZ0, pX1, pZ1, pMinU, pMaxU, pMinV, pMaxV); + renderQuad(matrix4f, matrix3f, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMaxY, pX3, pZ3, pX2, pZ2, pMinU, pMaxU, pMinV, pMaxV); + renderQuad(matrix4f, matrix3f, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMaxY, pX1, pZ1, pX3, pZ3, pMinU, pMaxU, pMinV, pMaxV); + renderQuad(matrix4f, matrix3f, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMaxY, pX2, pZ2, pX0, pZ0, pMinU, pMaxU, pMinV, pMaxV); + } + + private static void renderQuad(Matrix4f pPose, Matrix3f pNormal, VertexConsumer pConsumer, float pRed, float pGreen, float pBlue, float pAlpha, int pMinY, float pMaxY, float pMinX, float pMinZ, float pMaxX, float pMaxZ, float pMinU, float pMaxU, float pMinV, float pMaxV) { + addVertex(pPose, pNormal, pConsumer, pRed, pGreen, pBlue, pAlpha, pMaxY, pMinX, pMinZ, pMaxU, pMinV); + addVertex(pPose, pNormal, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMinX, pMinZ, pMaxU, pMaxV); + addVertex(pPose, pNormal, pConsumer, pRed, pGreen, pBlue, pAlpha, pMinY, pMaxX, pMaxZ, pMinU, pMaxV); + addVertex(pPose, pNormal, pConsumer, pRed, pGreen, pBlue, pAlpha, pMaxY, pMaxX, pMaxZ, pMinU, pMinV); + } + + private static void addVertex(Matrix4f pPose, Matrix3f pNormal, VertexConsumer pConsumer, float pRed, float pGreen, float pBlue, float pAlpha, float pY, float pX, float pZ, float pU, float pV) { + pConsumer.vertex(pPose, pX, pY, pZ).color(pRed, pGreen, pBlue, pAlpha).uv(pU, pV).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(15728880).normal(pNormal, 0.0F, 1.0F, 0.0F).endVertex(); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/InventoryManagerScreen.java similarity index 78% rename from src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerScreen.java rename to src/main/java/de/srendi/advancedperipherals/client/screens/InventoryManagerScreen.java index e4d88e29c..d1730b50b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerScreen.java +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/InventoryManagerScreen.java @@ -1,7 +1,8 @@ -package de.srendi.advancedperipherals.common.container; +package de.srendi.advancedperipherals.client.screens; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.container.base.BaseScreen; +import de.srendi.advancedperipherals.client.screens.base.BaseScreen; +import de.srendi.advancedperipherals.common.container.InventoryManagerContainer; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; diff --git a/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java new file mode 100644 index 000000000..7dc79a758 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java @@ -0,0 +1,156 @@ +package de.srendi.advancedperipherals.client.screens; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.util.FormattedCharSequence; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; + +public class SaddleTurtleScreen extends GuiComponent implements IGuiOverlay { + public static final String ID = "saddle_turtle_overlay"; + + private static final long ACTIVE_TIMEOUT = 5000; + + private ForgeGui gui; + private int screenWidth = 0; + private int screenHeight = 0; + + private int fuelLevel = 0; + private int fuelLimit = 0; + private int barColor = 0; + private long lastActived = 0; + + public SaddleTurtleScreen() {} + + protected Font getFont() { + return this.gui.getMinecraft().font; + } + + protected int textWidth(String text) { + return getFont().width(text); + } + + protected int textWidth(FormattedText text) { + return getFont().width(text); + } + + protected int textWidth(FormattedCharSequence text) { + return getFont().width(text); + } + + public static boolean isPlayerControllingTurtle() { + LocalPlayer player = Minecraft.getInstance().player; + return player != null && player.getVehicle() instanceof TurtleSeatEntity; + } + + public static boolean isPlayerMountedOnTurtle() { + LocalPlayer player = Minecraft.getInstance().player; + return player != null && player.getRootVehicle() instanceof TurtleSeatEntity; + } + + public boolean shouldRenderFuelBar() { + if (this.lastActived == 0) { + return false; + } + if (!isPlayerMountedOnTurtle()) { + this.hide(); + return false; + } + return this.lastActived + ACTIVE_TIMEOUT > System.currentTimeMillis(); + } + + public void hide() { + this.fuelLevel = 0; + this.fuelLimit = 0; + this.barColor = 0; + this.lastActived = 0; + } + + public void keepAlive() { + this.lastActived = System.currentTimeMillis(); + } + + public void setFuelLevel(int level) { + if (level < 0) { + level = 0; + } + if (this.fuelLevel != level) { + this.fuelLevel = level; + this.keepAlive(); + } + } + + public void setFuelLimit(int limit) { + if (this.fuelLimit != limit) { + this.fuelLimit = limit; + this.keepAlive(); + } + } + + public void setBarColor(int color) { + if (this.barColor != color) { + this.barColor = color; + this.keepAlive(); + } + } + + private void renderFuelBar(PoseStack stack) { + // TODO: use a better looking bar here, and/or find someway to change the bar's color + RenderSystem.setShaderTexture(0, GuiComponent.GUI_ICONS_LOCATION); + int fontColor = 0x80ff20; + + int width = 182; + int left = this.screenWidth / 2 - 91; + int top = this.screenHeight - 32 + 3; + this.blit(stack, left, top, 0, 64, width, 5); + if (fuelLevel > 0 && fuelLimit > 0) { + int progWidth = fuelLevel * width / fuelLimit; + this.blit(stack, left, top, 0, 69, progWidth, 5); + } + + String text = fuelLimit > 0 ? String.format("%d / %d", fuelLevel, fuelLimit) : "Infinity"; + int x = (this.screenWidth - getFont().width(text)) / 2; + int y = this.screenHeight - 31; + getFont().draw(stack, text, (float)(x + 1), (float) y, 0); + getFont().draw(stack, text, (float)(x - 1), (float) y, 0); + getFont().draw(stack, text, (float) x, (float)(y + 1), 0); + getFont().draw(stack, text, (float) x, (float)(y - 1), 0); + getFont().draw(stack, text, (float) x, (float) y, fontColor); + } + + private void renderDismountHint(PoseStack stack) { + Minecraft minecraft = Minecraft.getInstance(); + Component name = Component.translatable("block.computercraft.turtle_normal.upgraded", Component.translatable("turtle.advancedperipherals.saddle_turtle")); + // TODO: get and render turtle's label if exists + Component text = Component.translatable("text.advancedperipherals.saddle_turtle.dismount_hint", + name, minecraft.options.keyShift.getTranslatedKeyMessage(), minecraft.options.keyInventory.getTranslatedKeyMessage()); + float top = 10; + float x = (float)(this.screenWidth / 2 - textWidth(text) / 2); + getFont().drawShadow(stack, text, x, top, 0xffffff); + } + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + if (!isPlayerMountedOnTurtle()) { + return; + } + + this.gui = gui; + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + if (this.shouldRenderFuelBar()) { + this.renderFuelBar(poseStack); + } + if (isPlayerControllingTurtle()) { + this.renderDismountHint(poseStack); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/screens/SmartGlassesScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/SmartGlassesScreen.java new file mode 100644 index 000000000..c81884b59 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/SmartGlassesScreen.java @@ -0,0 +1,78 @@ +package de.srendi.advancedperipherals.client.screens; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import dan200.computercraft.client.gui.ComputerScreenBase; +import dan200.computercraft.client.gui.widgets.ComputerSidebar; +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.widgets.SmartGlassesSettingsSwitch; +import de.srendi.advancedperipherals.common.container.SmartGlassesContainer; +import de.srendi.advancedperipherals.common.smartglasses.SlotType; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.world.entity.player.Inventory; +import org.jetbrains.annotations.NotNull; + +public class SmartGlassesScreen extends ComputerScreenBase { + + private static final ResourceLocation BACKGROUND = new ResourceLocation(AdvancedPeripherals.MOD_ID, "textures/gui/smart_glasses_gui.png"); + public static final ResourceLocation SIDEBAR = new ResourceLocation(AdvancedPeripherals.MOD_ID, "textures/gui/corners_glasses.png"); + + private static final int TEX_WIDTH = 254; + private static final int TEX_HEIGHT = 217; + private SlotType currentType = SlotType.defaultType(); + + public SmartGlassesScreen(SmartGlassesContainer container, Inventory player, Component title) { + super(container, player, title, ContainerTurtle.BORDER); + + imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH; + imageHeight = TEX_HEIGHT; + } + + @Override + protected void init() { + super.init(); + addRenderableWidget(new SmartGlassesSettingsSwitch(254, 147, SlotType.PERIPHERALS, this)); + addRenderableWidget(new SmartGlassesSettingsSwitch(254, 170, SlotType.MODULES, this)); + } + + @Override + protected WidgetTerminal createTerminal() { + return new WidgetTerminal(terminalData, input, leftPos + ContainerTurtle.BORDER + ComputerSidebar.WIDTH, topPos + ContainerTurtle.BORDER); + } + + @Override + protected void renderBg(@NotNull PoseStack transform, float partialTicks, int mouseX, int mouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); + blit(transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT); + + if (currentType == SlotType.PERIPHERALS) + blit(transform, leftPos + ComputerSidebar.WIDTH + 222, topPos + 183, 186, 183, 18, 18); + + RenderSystem.setShaderTexture(0, SIDEBAR); + ComputerSidebar.renderBackground(transform, leftPos, topPos + sidebarYOffset); + } + + @Override + protected void renderTooltip(@NotNull PoseStack poseStack, int x, int y) { + super.renderTooltip(poseStack, x, y); + renderables.forEach(renderable -> { + if (renderable instanceof SmartGlassesSettingsSwitch smartGlassesSettingsSwitch) { + smartGlassesSettingsSwitch.renderTooltip(poseStack, x, y); + } + }); + } + + @Override + protected void renderLabels(@NotNull PoseStack poseStack, int x, int y) { + FormattedCharSequence formattedcharsequence = currentType.getName().getVisualOrderText(); + this.font.draw(poseStack, formattedcharsequence, (212 + ComputerSidebar.WIDTH - (float) this.font.width(formattedcharsequence) / 2), 133, 4210752); + } + + public void setCurrentType(SlotType currentType) { + this.currentType = currentType; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseItemScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseItemScreen.java similarity index 73% rename from src/main/java/de/srendi/advancedperipherals/common/container/base/BaseItemScreen.java rename to src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseItemScreen.java index 527878f10..a7e7e9476 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseItemScreen.java +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseItemScreen.java @@ -1,16 +1,18 @@ -package de.srendi.advancedperipherals.common.container.base; +package de.srendi.advancedperipherals.client.screens.base; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.common.container.base.BaseItemContainer; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import org.jetbrains.annotations.NotNull; public abstract class BaseItemScreen extends AbstractContainerScreen { - public BaseItemScreen(T screenContainer, Inventory inv, Component titleIn) { + protected BaseItemScreen(T screenContainer, Inventory inv, Component titleIn) { super(screenContainer, inv, titleIn); imageWidth = getSizeX(); @@ -18,14 +20,14 @@ public BaseItemScreen(T screenContainer, Inventory inv, Component titleIn) { } @Override - public void render(PoseStack matrixStack, int x, int y, float partialTicks) { + public void render(@NotNull PoseStack matrixStack, int x, int y, float partialTicks) { renderBackground(matrixStack); super.render(matrixStack, x, y, partialTicks); renderTooltip(matrixStack, x, y); } @Override - protected void renderBg(PoseStack matrixStack, float partialTicks, int x, int y) { + protected void renderBg(@NotNull PoseStack matrixStack, float partialTicks, int x, int y) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderTexture(0, getTexture()); diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseScreen.java similarity index 86% rename from src/main/java/de/srendi/advancedperipherals/common/container/base/BaseScreen.java rename to src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseScreen.java index f9311435e..9390fa902 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseScreen.java +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/base/BaseScreen.java @@ -1,7 +1,8 @@ -package de.srendi.advancedperipherals.common.container.base; +package de.srendi.advancedperipherals.client.screens.base; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.common.container.base.BaseContainer; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.Component; @@ -11,7 +12,7 @@ public abstract class BaseScreen extends AbstractContainerScreen { - public BaseScreen(T screenContainer, Inventory inv, Component titleIn) { + protected BaseScreen(T screenContainer, Inventory inv, Component titleIn) { super(screenContainer, inv, titleIn); imageWidth = getSizeX(); imageHeight = getSizeY(); diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleLevelRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleLevelRenderer.java new file mode 100644 index 000000000..1a8aa23c2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleLevelRenderer.java @@ -0,0 +1,115 @@ +package de.srendi.advancedperipherals.client.smartglasses; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexConsumer; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.client.smartglasses.objects.threedim.IThreeDObjectRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.util.EnumColor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderLevelStageEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE, modid = AdvancedPeripherals.MOD_ID) +public class OverlayModuleLevelRenderer { + + @SubscribeEvent + public static void renderLevelState(RenderLevelStageEvent event) { + PoseStack posestack = event.getPoseStack(); + Vec3 view = Minecraft.getInstance().getEntityRenderDispatcher().camera.getPosition(); + + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS) { + Map, List> batches = new HashMap<>(); + + for (RenderableObject object : OverlayObjectHolder.getObjects()) { + if (!object.isEnabled() || !(object.getRenderObject() instanceof IThreeDObjectRenderer)) + continue; + + ThreeDimensionalObject threeDimObject = (ThreeDimensionalObject) object; + + Class objectClass = threeDimObject.getClass(); + + if (batches.containsKey(objectClass)) { + batches.get(objectClass).add(threeDimObject); + continue; + } + + List newBatchArray = new ArrayList<>(); + newBatchArray.add(threeDimObject); + batches.put(objectClass, newBatchArray); + } + + for (List batch : batches.values()) { + ((IThreeDObjectRenderer) batch.get(0).getRenderObject()).renderBatch(batch, event, posestack, view, bufferbuilder); + } + + //TODO Everything below here is just for debugging and testing. Will be removed before we push to production + BlockPos blockPos = new BlockPos(2, 100, 0); + + float[] colors = EnumColor.DARK_PURPLE.getRgb(); + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + bufferbuilder.begin(RenderType.translucent().mode(), DefaultVertexFormat.POSITION_COLOR_NORMAL); + posestack.pushPose(); + + posestack.translate(-view.x + blockPos.getX(), -view.y + blockPos.getY(), -view.z + blockPos.getZ()); + + RenderUtil.drawPlane(posestack, bufferbuilder, colors[0], colors[1], colors[2], 0.8f, Direction.UP, 0f, 0.5f, 0f, 0.5f, 0f, 1f); + + BufferUploader.drawWithShader(bufferbuilder.end()); + posestack.popPose(); + + VertexConsumer boxVertexConsumer = Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(RenderType.entityCutout(InventoryMenu.BLOCK_ATLAS)); + //RenderSystem.setShader(GameRenderer::getPositionColorLightmapShader); + + //bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_LIGHTMAP); + posestack.pushPose(); + colors = EnumColor.WHITE.getRgb(); + + blockPos = new BlockPos(0, 100, 0); + posestack.translate(-view.x + blockPos.getX(), -view.y + blockPos.getY(), -view.z + blockPos.getZ()); + + RenderUtil.drawSphere(posestack, boxVertexConsumer, 2f, 0f, 0f, 0f, 270f, 0f, 0f, colors[0], colors[1], colors[2], 0.4f, 16, 128); + + //BufferUploader.drawWithShader(bufferbuilder.end()); + posestack.popPose(); + + boxVertexConsumer = Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(RenderType.entityCutout(InventoryMenu.BLOCK_ATLAS)); + + //bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_NORMAL); + posestack.pushPose(); + + colors = EnumColor.WHITE.getRgb(); + blockPos = new BlockPos(6, 100, 0); + posestack.translate(-view.x + blockPos.getX(), -view.y + blockPos.getY(), -view.z + blockPos.getZ()); + + RenderUtil.drawTorus(posestack, boxVertexConsumer, 1f, 0.4f, 0f, 0f, 0f, 0f, 0f, 0f, colors[0], colors[1], colors[2], 1f, 48, 48); + + //BufferUploader.drawWithShader(bufferbuilder.end()); + posestack.popPose(); + + } + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleOverlay.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleOverlay.java new file mode 100644 index 000000000..6ef3fab90 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayModuleOverlay.java @@ -0,0 +1,56 @@ +package de.srendi.advancedperipherals.client.smartglasses; + +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.ITwoDObjectRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.RectangleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.TextObject; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +public class OverlayModuleOverlay implements IGuiOverlay { + public static final String ID = "overlay_module_overlay"; + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + poseStack.pushPose(); + + Map, List>> prioritizedBatches = new TreeMap<>(); + + for (RenderableObject object : OverlayObjectHolder.getObjects()) { + if (!object.isEnabled() || !(object.getRenderObject() instanceof ITwoDObjectRenderer)) { + continue; + } + + // We need to sort the objects by their weight, some things can't be rendered before something else. + // For example, when texts are rendered before our circles, rectangles, etc., the other objects can't be transparent anymore + int weight = object.getRenderObject().getWeight(); + Class objectClass = object.getClass(); + + // Get or create the batch map for the current weight + Map, List> batchesForWeight = prioritizedBatches.computeIfAbsent(weight, k -> new HashMap<>()); + + List batch = batchesForWeight.computeIfAbsent(objectClass, k -> new ArrayList<>()); + + batch.add(object); + } + + for (Map, List> batchesForWeight : prioritizedBatches.values()) { + for (List batch : batchesForWeight.values()) { + + if (!batch.isEmpty()) { + ((ITwoDObjectRenderer) batch.get(0).getRenderObject()).renderBatch(batch, gui, poseStack, partialTick, screenWidth, screenHeight); + } + } + } + poseStack.popPose(); + + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayObjectHolder.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayObjectHolder.java new file mode 100644 index 000000000..e319679fd --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/OverlayObjectHolder.java @@ -0,0 +1,60 @@ +package de.srendi.advancedperipherals.client.smartglasses; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectDecodeRegistry; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BlockObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BoxObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.SphereObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.TorusObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.ItemObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.LineObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.RectangleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.TextObject; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Static holder for client side renderable objects - will change + */ +public class OverlayObjectHolder { + + public static Map objects = new HashMap<>(); + + public static void addOrUpdateObject(RenderableObject object) { + objects.put(object.getId(), object); + } + + public static void addOrUpdateObjects(Collection objects) { + for (RenderableObject renderableObject : objects) { + addOrUpdateObject(renderableObject); + } + } + + public static void removeObject(int id) { + objects.remove(id); + } + + public static Collection getObjects() { + return objects.values(); + } + + public static void clear() { + objects.clear(); + } + + public static void registerDecodeObjects() { + ObjectDecodeRegistry.register(RectangleObject.TYPE_ID, RectangleObject::decode); + ObjectDecodeRegistry.register(CircleObject.TYPE_ID, CircleObject::decode); + ObjectDecodeRegistry.register(TextObject.TYPE_ID, TextObject::decode); + ObjectDecodeRegistry.register(ItemObject.TYPE_ID, ItemObject::decode); + ObjectDecodeRegistry.register(LineObject.TYPE_ID, LineObject::decode); + + ObjectDecodeRegistry.register(BoxObject.TYPE_ID, BoxObject::decode); + ObjectDecodeRegistry.register(BlockObject.TYPE_ID, BlockObject::decode); + ObjectDecodeRegistry.register(SphereObject.TYPE_ID, SphereObject::decode); + ObjectDecodeRegistry.register(TorusObject.TYPE_ID, TorusObject::decode); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/IObjectRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/IObjectRenderer.java new file mode 100644 index 000000000..aeefb36a9 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/IObjectRenderer.java @@ -0,0 +1,13 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects; + +public interface IObjectRenderer { + /** + * Get the weight of the renderer. Lower weight means higher priority and it will render first. + * Some things need to be rendered before others to prevent color and opacity issues. + * @return the weight of the renderer. + */ + default int getWeight() { + return 100; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BlockRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BlockRenderer.java new file mode 100644 index 000000000..152f9c3fe --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BlockRenderer.java @@ -0,0 +1,65 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.threedim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Quaternion; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BlockObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import de.srendi.advancedperipherals.common.util.RegistryUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.RenderLevelStageEvent; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.List; + +public class BlockRenderer implements IThreeDObjectRenderer { + + @Override + public void renderBatch(List batch, RenderLevelStageEvent event, PoseStack poseStack, Vec3 view, BufferBuilder bufferBuilder) { + poseStack.pushPose(); + + for (ThreeDimensionalObject obj : batch) { + poseStack.pushPose(); + onPreRender(obj); + + bufferBuilder.begin(RenderType.solid().mode(), DefaultVertexFormat.BLOCK); + + BlockObject block = (BlockObject) obj; + + poseStack.translate(-view.x + block.getX(), -view.y + block.getY(), -view.z + block.getZ()); + poseStack.mulPose(new Quaternion(block.rotX, block.rotY, block.rotZ, true)); + poseStack.translate(-0.5f, -0.5f, -0.5f); + float alpha = block.opacity; + float red = RenderUtil.getRed(block.color); + float green = RenderUtil.getGreen(block.color); + float blue = RenderUtil.getBlue(block.color); + + RenderSystem.setShader(GameRenderer::getBlockShader); + RenderSystem.setShaderColor(red, green, blue, alpha); + + Block blockToRender = RegistryUtil.getRegistryEntry(block.block, ForgeRegistries.BLOCKS); + BlockPos blockPos = new BlockPos(obj.getX(), obj.getY(), obj.getZ()); + + if (blockToRender != null) + Minecraft.getInstance().getBlockRenderer().renderBatched(blockToRender.defaultBlockState(), blockPos, event.getCamera().getEntity().level, poseStack, bufferBuilder, false, event.getCamera().getEntity().level.random); + + poseStack.popPose(); + BufferUploader.drawWithShader(bufferBuilder.end()); + onPostRender(obj); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + } + + + poseStack.popPose(); + + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BoxRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BoxRenderer.java new file mode 100644 index 000000000..e773a6ec4 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/BoxRenderer.java @@ -0,0 +1,47 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.threedim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BoxObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.RenderLevelStageEvent; + +import java.util.List; + +public class BoxRenderer implements IThreeDObjectRenderer { + + @Override + public void renderBatch(List batch, RenderLevelStageEvent event, PoseStack poseStack, Vec3 view, BufferBuilder bufferBuilder) { + poseStack.pushPose(); + + for (ThreeDimensionalObject obj : batch) { + poseStack.pushPose(); + onPreRender(obj); + bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_NORMAL); + + BoxObject box = (BoxObject) obj; + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + float alpha = box.opacity; + float red = RenderUtil.getRed(box.color); + float green = RenderUtil.getGreen(box.color); + float blue = RenderUtil.getBlue(box.color); + + poseStack.translate(-view.x + box.getX(), -view.y + box.getY(), -view.z + box.getZ()); + RenderUtil.drawBox(poseStack, bufferBuilder, red, green, blue, alpha, box.x, box.y, box.z, obj.rotX, obj.rotY, obj.rotZ, obj.maxX, obj.maxY, obj.maxZ); + BufferUploader.drawWithShader(bufferBuilder.end()); + onPostRender(obj); + + poseStack.popPose(); + } + + poseStack.popPose(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/IThreeDObjectRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/IThreeDObjectRenderer.java new file mode 100644 index 000000000..119277f6f --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/IThreeDObjectRenderer.java @@ -0,0 +1,30 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.threedim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.RenderLevelStageEvent; + +import java.util.List; + +public interface IThreeDObjectRenderer extends IObjectRenderer { + + void renderBatch(List batch, RenderLevelStageEvent event, PoseStack poseStack, Vec3 view, BufferBuilder bufferBuilder); + + default void onPostRender(ThreeDimensionalObject object) { + if (object.disableCulling) + RenderSystem.enableCull(); + if (object.disableDepthTest) + RenderSystem.enableDepthTest(); + } + + default void onPreRender(ThreeDimensionalObject object) { + if (object.disableCulling) + RenderSystem.disableCull(); + if (object.disableDepthTest) + RenderSystem.disableDepthTest(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/SphereRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/SphereRenderer.java new file mode 100644 index 000000000..71388a20e --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/SphereRenderer.java @@ -0,0 +1,49 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.threedim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.SphereObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.RenderLevelStageEvent; + +import java.util.List; + +public class SphereRenderer implements IThreeDObjectRenderer { + + @Override + public void renderBatch(List batch, RenderLevelStageEvent event, PoseStack poseStack, Vec3 view, BufferBuilder bufferBuilder) { + poseStack.pushPose(); + + for (ThreeDimensionalObject obj : batch) { + poseStack.pushPose(); + onPreRender(obj); + VertexConsumer boxVertexConsumer = Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(RenderType.entitySmoothCutout(TextureAtlas.LOCATION_BLOCKS)); + + SphereObject sphere = (SphereObject) obj; + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + float alpha = sphere.opacity; + float red = RenderUtil.getRed(sphere.color); + float green = RenderUtil.getRed(sphere.color); + float blue = RenderUtil.getRed(sphere.color); + + poseStack.translate(-view.x, -view.y, -view.z); + RenderUtil.drawSphere(poseStack, boxVertexConsumer, sphere.radius, sphere.x, sphere.y, sphere.z, sphere.rotX, sphere.rotY, sphere.rotZ, red, green, blue, alpha, sphere.sectors, sphere.stacks); + onPostRender(obj); + + poseStack.popPose(); + } + + + poseStack.popPose(); + + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/TorusRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/TorusRenderer.java new file mode 100644 index 000000000..7921b8a71 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/threedim/TorusRenderer.java @@ -0,0 +1,47 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.threedim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.ThreeDimensionalObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.TorusObject; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.RenderLevelStageEvent; + +import java.util.List; + +public class TorusRenderer implements IThreeDObjectRenderer { + + @Override + public void renderBatch(List batch, RenderLevelStageEvent event, PoseStack poseStack, Vec3 view, BufferBuilder bufferBuilder) { + poseStack.pushPose(); + + for (ThreeDimensionalObject obj : batch) { + poseStack.pushPose(); + onPreRender(obj); + bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_NORMAL); + + TorusObject torus = (TorusObject) obj; + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + float alpha = torus.opacity; + float red = RenderUtil.getRed(torus.color); + float green = RenderUtil.getGreen(torus.color); + float blue = RenderUtil.getBlue(torus.color); + + poseStack.translate(-view.x + torus.x, -view.y + torus.y, -view.z + torus.z); + RenderUtil.drawTorus(poseStack, bufferBuilder, torus.majorRadius, torus.minorRadius, 0, 0, 0, torus.rotX, torus.rotY, torus.rotZ, red, green, blue, alpha, torus.rings, torus.sides); + BufferUploader.drawWithShader(bufferBuilder.end()); + onPostRender(obj); + + poseStack.popPose(); + } + + poseStack.popPose(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/CircleRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/CircleRenderer.java new file mode 100644 index 000000000..5929b3e8e --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/CircleRenderer.java @@ -0,0 +1,189 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.math.Matrix4f; +import com.mojang.math.Quaternion; +import com.mojang.math.Vector3f; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraftforge.client.gui.overlay.ForgeGui; + +import java.util.List; + +public class CircleRenderer implements ITwoDObjectRenderer { + + @Override + public void renderBatch(List objects, ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + for (RenderableObject obj : objects) { + + CircleObject circle = (CircleObject) obj; + + float alpha = circle.opacity; + float red = RenderUtil.getRed(circle.color); + float green = RenderUtil.getGreen(circle.color); + float blue = RenderUtil.getBlue(circle.color); + + drawCircle(poseStack, circle, red, green, blue, alpha); + } + } + + public void drawCircle(PoseStack t, CircleObject circle, float red, float green, float blue, float alpha) { + float r = circle.radius; + float cx = circle.x; + float cy = circle.y; + float cz = circle.z; + float rotX = circle.rotX; + float rotY = circle.rotY; + float rotZ = circle.rotZ; + float borderWidth = circle.borderWidth; + int segments = circle.segments; + + boolean isFilled = circle.filled; + boolean isPixelated = circle.pixelated; + + PoseStack poseStack = new PoseStack(); + + poseStack.translate(cx, cy, cz); + + poseStack.pushPose(); + + poseStack.mulPose(Vector3f.XP.rotationDegrees(rotX)); + poseStack.mulPose(Vector3f.YP.rotationDegrees(rotY)); + poseStack.mulPose(Vector3f.ZP.rotationDegrees(rotZ)); + + RenderSystem.disableCull(); + + RenderSystem.setShader(GameRenderer::getPositionColorShader); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + + Matrix4f matrix = poseStack.last().pose(); + + // Normal, smooth lines + if (!isPixelated) { + if (isFilled) { + + bufferbuilder.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR); + + bufferbuilder.vertex(matrix, 0, 0, 0f).color(red, green, blue, alpha).endVertex(); + + double angleStep = Math.PI * 2 / segments; + + for (int i = 0; i <= segments; i++) { + double angle = i * angleStep; + double x = r * Math.sin(angle); + double y = r * Math.cos(angle); + + bufferbuilder.vertex(matrix, (float) x, (float) y, 0).color(red, green, blue, alpha).endVertex(); + } + + } else { + float outerRadius = r; + float innerRadius = r - borderWidth; + + bufferbuilder.begin(VertexFormat.Mode.TRIANGLE_STRIP, DefaultVertexFormat.POSITION_COLOR); + + double angleStep = Math.PI * 2 / segments; + + for (int i = 0; i <= segments; i++) { + double angle = i * angleStep; + + // Outer circle vertex + double outerX = innerRadius * Math.sin(angle); + double outerY = innerRadius * Math.cos(angle); + bufferbuilder.vertex(matrix, (float) outerX, (float) outerY, 0f).color(red, green, blue, alpha).endVertex(); + + // Inner circle vertex + double innerX = outerRadius * Math.sin(angle); + double innerY = outerRadius * Math.cos(angle); + bufferbuilder.vertex(matrix, (float) innerX, (float) innerY, 0f).color(red, green, blue, alpha).endVertex(); + } + } + + BufferUploader.drawWithShader(bufferbuilder.end()); + + return; + } + + // Pixelated lines + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + + final float PIXEL_SIZE = borderWidth; // Defines the size of each "pixel" square + + // The thickness of the hollow line in terms of pixel units. + // A value of 1.0f means the line will be roughly one pixel thick. + final float LINE_THICKNESS_PIXELS = 1f; + + // Calculate the effective min/max coordinates in the relative space + float effectiveMinX = -r - PIXEL_SIZE; + float effectiveMaxX = r + PIXEL_SIZE; + float effectiveMinY = -r - PIXEL_SIZE; + float effectiveMaxY = r + PIXEL_SIZE; + +// Start the loop at the first multiple of PIXEL_SIZE that is less than or equal to effectiveMinX/Y + float startX = (float) Math.floor(effectiveMinX / PIXEL_SIZE) * PIXEL_SIZE; + float startY = (float) Math.floor(effectiveMinY / PIXEL_SIZE) * PIXEL_SIZE; + + + for (float x = startX; x <= effectiveMaxX; x += PIXEL_SIZE) { + for (float y = startY; y <= effectiveMaxY; y += PIXEL_SIZE) { + // Calculate the center of the current pixel cell. + // This is where you determine if the *center* of this block should be drawn. + float pixelCenterX = x + (PIXEL_SIZE / 2.0F); + float pixelCenterY = y + (PIXEL_SIZE / 2.0F); + + // Distance is calculated from (pixelCenterX, pixelCenterY) to (0,0) + double distanceToCenter = Math.sqrt( + Math.pow(pixelCenterX, 2) + Math.pow(pixelCenterY, 2) + ); + + boolean shouldDrawPixel; + + if (!isFilled) { + float outerRadius = r + (LINE_THICKNESS_PIXELS * (PIXEL_SIZE / 2.0F)); + float innerRadius = r - (LINE_THICKNESS_PIXELS * (PIXEL_SIZE / 2.0F)); + + if (innerRadius < 0) innerRadius = 0; + + shouldDrawPixel = (distanceToCenter <= outerRadius) && (distanceToCenter >= innerRadius); + } else { + shouldDrawPixel = distanceToCenter <= r + (PIXEL_SIZE / 2.0F); + } + + if (shouldDrawPixel) { + // Vertices for the QUAD (a PIXEL_SIZE x PIXEL_SIZE square) + // These coordinates are now relative to the current origin (0,0,0) + float p_x1 = x; + float p_y1 = y; + float p_z = 0f; // z-coordinate is relative to cz, so 0 in this space + + float p_x2 = x + PIXEL_SIZE; + float p_y2 = y + PIXEL_SIZE; + + // Vertices for the QUAD + // Ensure proper winding order (counter-clockwise for front face) + bufferbuilder.vertex(matrix, p_x1, p_y2, p_z).color(red, green, blue, alpha).endVertex(); // Bottom-left + bufferbuilder.vertex(matrix, p_x2, p_y2, p_z).color(red, green, blue, alpha).endVertex(); // Bottom-right + bufferbuilder.vertex(matrix, p_x2, p_y1, p_z).color(red, green, blue, alpha).endVertex(); // Top-right + bufferbuilder.vertex(matrix, p_x1, p_y1, p_z).color(red, green, blue, alpha).endVertex(); // Top-left + } + } + } + + RenderSystem.enableCull(); + + BufferUploader.drawWithShader(bufferbuilder.end()); + + + poseStack.popPose(); + + } +} + diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ITwoDObjectRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ITwoDObjectRenderer.java new file mode 100644 index 000000000..543f3580c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ITwoDObjectRenderer.java @@ -0,0 +1,14 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraftforge.client.gui.overlay.ForgeGui; + +import java.util.List; + +public interface ITwoDObjectRenderer extends IObjectRenderer { + + void renderBatch(List object, ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight); + +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ItemRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ItemRenderer.java new file mode 100644 index 000000000..6d2ff7ccb --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/ItemRenderer.java @@ -0,0 +1,29 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.ItemObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.util.RegistryUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.List; + +public class ItemRenderer implements ITwoDObjectRenderer { + + @Override + public void renderBatch(List objects, ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + Minecraft minecraft = Minecraft.getInstance(); + + for (RenderableObject obj : objects) { + Item renderItem = RegistryUtil.getRegistryEntry(((ItemObject) obj).item, ForgeRegistries.ITEMS); + if (renderItem == null) + continue; + minecraft.getItemRenderer().renderGuiItem(new ItemStack(renderItem), (int) obj.x, (int) obj.y); + } + + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/LineRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/LineRenderer.java new file mode 100644 index 000000000..71579398a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/LineRenderer.java @@ -0,0 +1,103 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.math.Matrix4f; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.LineObject; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraftforge.client.gui.overlay.ForgeGui; + +import java.util.List; + +public class LineRenderer implements ITwoDObjectRenderer { + + @Override + public void renderBatch(List objects, ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + RenderSystem.setShader(GameRenderer::getPositionColorShader); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + Matrix4f matrix = poseStack.last().pose(); + + for (RenderableObject obj : objects) { + + LineObject line = (LineObject) obj; + + float alpha = obj.opacity; + float red = RenderUtil.getRed(obj.color); + float green = RenderUtil.getGreen(obj.color); + float blue = RenderUtil.getBlue(obj.color); + + // Start and end points of the line + float x1 = obj.x; + float y1 = obj.y; + float z1 = obj.z; + + float x2 = obj.maxX; + float y2 = obj.maxY; + float z2 = obj.maxZ; + + // Normal, smooth lines + if (!line.pixelated) { + bufferbuilder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); + bufferbuilder.vertex(matrix, x1, y1, 0).color(red, green, blue, alpha).endVertex(); + bufferbuilder.vertex(matrix, x2, y2, 0).color(red, green, blue, alpha).endVertex(); + BufferUploader.drawWithShader(bufferbuilder.end()); + + continue; // Skip the rest of the loop for this object + } + + // Pixelated lines + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + + // Calculate the delta for each axis + float dx = x2 - x1; + float dy = y2 - y1; + float dz = z2 - z1; + + final float PIXEL_SIZE = line.pixelSize; + + float maxDim = Math.max(Math.abs(dx), Math.max(Math.abs(dy), Math.abs(dz))); + int numPixels = (int) Math.ceil(maxDim / PIXEL_SIZE); + + if (numPixels == 0) { + numPixels = 1; // Always draw at least one pixel for very short lines + } + + // Iterate and draw a square for each "pixel" + for (int i = 0; i <= numPixels; i++) { + float t = (float) i / numPixels; // Interpolation factor (0.0 to 1.0) + + // Calculate the exact point on the line + float currentX = x1 + dx * t; + float currentY = y1 + dy * t; + float currentZ = z1 + dz * t; + + // Snap current point to the nearest pixel grid for consistent placement. + // This is key for placing pixels at corners or full side of each other. + currentX = Math.round(currentX / PIXEL_SIZE) * PIXEL_SIZE; + currentY = Math.round(currentY / PIXEL_SIZE) * PIXEL_SIZE; + currentZ = Math.round(currentZ / PIXEL_SIZE) * PIXEL_SIZE; + + float p_x1 = currentX; + float p_y1 = currentY; + float p_z1 = currentZ; + + float p_x2 = currentX + PIXEL_SIZE; + float p_y2 = currentY + PIXEL_SIZE; + float p_z2 = currentZ; + + bufferbuilder.vertex(matrix, p_x1, p_y2, p_z1).color(red, green, blue, alpha).endVertex(); // Bottom-left + bufferbuilder.vertex(matrix, p_x2, p_y2, p_z1).color(red, green, blue, alpha).endVertex(); // Bottom-right + bufferbuilder.vertex(matrix, p_x2, p_y1, p_z2).color(red, green, blue, alpha).endVertex(); // Top-right + bufferbuilder.vertex(matrix, p_x1, p_y1, p_z2).color(red, green, blue, alpha).endVertex(); // Top-left + } + BufferUploader.drawWithShader(bufferbuilder.end()); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/RectangleRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/RectangleRenderer.java new file mode 100644 index 000000000..55618cf74 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/RectangleRenderer.java @@ -0,0 +1,60 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import de.srendi.advancedperipherals.client.RenderUtil; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraftforge.client.gui.overlay.ForgeGui; + +import java.util.List; + +public class RectangleRenderer implements ITwoDObjectRenderer { + + @Override + public void renderBatch(List objects, ForgeGui gui, PoseStack ignored, float partialTick, int screenWidth, int screenHeight) { + RenderSystem.setShader(GameRenderer::getPositionColorShader); + BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder(); + + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + + for (RenderableObject obj : objects) { + float rotX = obj.rotX; + float rotY = obj.rotY; + float rotZ = obj.rotZ; + + PoseStack poseStack = new PoseStack(); + + poseStack.translate(obj.x, obj.y, obj.z); + + poseStack.pushPose(); + + Matrix4f matrix = poseStack.last().pose(); + + poseStack.mulPose(Vector3f.XP.rotationDegrees(rotX)); + poseStack.mulPose(Vector3f.YP.rotationDegrees(rotY)); + poseStack.mulPose(Vector3f.ZP.rotationDegrees(rotZ)); + + float alpha = obj.opacity; + float red = RenderUtil.getRed(obj.color); + float green = RenderUtil.getGreen(obj.color); + float blue = RenderUtil.getBlue(obj.color); + + bufferbuilder.vertex(matrix, 0, obj.maxY - obj.y, 0).color(red, green, blue, alpha).endVertex(); + bufferbuilder.vertex(matrix, obj.maxX - obj.x, obj.maxY - obj.y, 0).color(red, green, blue, alpha).endVertex(); + bufferbuilder.vertex(matrix, obj.maxX - obj.x, 0, 0).color(red, green, blue, alpha).endVertex(); + bufferbuilder.vertex(matrix, 0, 0, 0).color(red, green, blue, alpha).endVertex(); + poseStack.popPose(); + + } + + BufferUploader.drawWithShader(bufferbuilder.end()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/TextRenderer.java b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/TextRenderer.java new file mode 100644 index 000000000..ecde02ad7 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/smartglasses/objects/twodim/TextRenderer.java @@ -0,0 +1,55 @@ +package de.srendi.advancedperipherals.client.smartglasses.objects.twodim; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.TextObject; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.gui.overlay.ForgeGui; + +import java.util.List; + +public class TextRenderer implements ITwoDObjectRenderer { + + @Override + public void renderBatch(List objects, ForgeGui gui, PoseStack ignored, float partialTick, int screenWidth, int screenHeight) { + Minecraft minecraft = Minecraft.getInstance(); + for (RenderableObject obj : objects) { + TextObject text = (TextObject) obj; + float rotX = obj.rotX; + float rotY = obj.rotY; + float rotZ = obj.rotZ; + + float x = text.x; + + if (text.center) { + x -= (minecraft.font.width(text.content) * text.fontSize) / 2f; + } + + PoseStack poseStack = new PoseStack(); + + poseStack.translate(x / text.fontSize, text.y / text.fontSize, obj.z); + + poseStack.pushPose(); + + poseStack.mulPose(Vector3f.XP.rotationDegrees(rotX)); + poseStack.mulPose(Vector3f.YP.rotationDegrees(rotY)); + poseStack.mulPose(Vector3f.ZP.rotationDegrees(rotZ)); + + poseStack.scale(text.fontSize, text.fontSize, 1); + + if (!text.shadow) { + minecraft.font.drawShadow(poseStack, text.content, 0, 0, text.color); + } else { + minecraft.font.draw(poseStack, text.content, 0, 0, text.color); + } + poseStack.popPose(); + } + } + + @Override + public int getWeight() { + return 110; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/widgets/SmartGlassesSettingsSwitch.java b/src/main/java/de/srendi/advancedperipherals/client/widgets/SmartGlassesSettingsSwitch.java new file mode 100644 index 000000000..a6ab0c0cc --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/widgets/SmartGlassesSettingsSwitch.java @@ -0,0 +1,85 @@ +package de.srendi.advancedperipherals.client.widgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import dan200.computercraft.client.gui.widgets.ComputerSidebar; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.screens.SmartGlassesScreen; +import de.srendi.advancedperipherals.common.smartglasses.SlotType; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesSlot; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.inventory.Slot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; + +public class SmartGlassesSettingsSwitch extends AbstractWidget { + + private static final ResourceLocation BACKGROUND = new ResourceLocation(AdvancedPeripherals.MOD_ID, "textures/gui/smart_glasses_gui.png"); + + private final SmartGlassesScreen screen; + private final SlotType type; + private boolean isEnabled; + + public SmartGlassesSettingsSwitch(int x, int y, SlotType type, SmartGlassesScreen screen) { + super(screen.getGuiLeft() + x + ComputerSidebar.WIDTH, screen.getGuiTop() + y, 21, 22, type.getName()); + this.screen = screen; + this.type = type; + this.isEnabled = type == SlotType.defaultType(); + } + + @Override + public void render(@NotNull PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) { + renderBg(pPoseStack, Minecraft.getInstance(), pMouseX, pMouseY); + } + + @Override + public void renderButton(@NotNull PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) { + // Disable rendering of default buttons + } + + @Override + protected void renderBg(@NotNull PoseStack pPoseStack, @NotNull Minecraft pMinecraft, int pMouseX, int pMouseY) { + RenderSystem.setShaderTexture(0, BACKGROUND); + if (isEnabled) { + blit(pPoseStack, this.x - 3, this.y, 45, 217, 24, 22); + } else { + blit(pPoseStack, this.x, this.y, 23, 217, 21, 22); + } + } + + @Override + public void onClick(double pMouseX, double pMouseY) { + if (this.isEnabled) + return; + for (Slot slot : screen.getMenu().slots) { + if (slot instanceof SmartGlassesSlot smartGlassesSlot) { + if (smartGlassesSlot.slotType == this.type) { + smartGlassesSlot.setEnabled(true); + continue; + } + smartGlassesSlot.setEnabled(false); + } + } + screen.renderables.forEach(renderable -> { + if (renderable instanceof SmartGlassesSettingsSwitch smartGlassesSettingsSwitch) { + smartGlassesSettingsSwitch.isEnabled = false; + } + }); + screen.setCurrentType(this.type); + this.isEnabled = true; + } + + public void renderTooltip(PoseStack poseStack, int x, int y) { + if (screen != null && isMouseOver(x, y)) + screen.renderComponentTooltip(poseStack, Collections.singletonList(type.getName()), x, y); + } + + @Override + public void updateNarration(@NotNull NarrationElementOutput pNarrationElementOutput) { + + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/APAddons.java b/src/main/java/de/srendi/advancedperipherals/common/addons/APAddons.java index c26e2652a..bdc4e4265 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/APAddons.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/APAddons.java @@ -1,41 +1,72 @@ package de.srendi.advancedperipherals.common.addons; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RefinedStorage; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSApi; +import de.srendi.advancedperipherals.common.addons.valkyrienskies.ValkyrienSkies; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.InterModComms; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; +import top.theillusivec4.curios.api.CuriosApi; +import top.theillusivec4.curios.api.SlotResult; +import top.theillusivec4.curios.api.SlotTypeMessage; + +import java.util.List; @Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class APAddons { - public static final String CURIOS_MODID = "curios"; - public static final String REFINEDSTORAGE_MODID = "refinedstorage"; - public static final String AE_THINGS_MODID = "ae2things"; public static final String AE_ADDITIONS_MODID = "ae2additions"; + public static final String AE_THINGS_MODID = "ae2things"; + public static final String APPLIEDENERGISTICS_MODID = "ae2"; public static final String APP_MEKANISTICS_MODID = "appmek"; + public static final String BOTANIA_MODID = "botania"; + public static final String CREATE_MODID = "create"; + public static final String CURIOS_MODID = "curios"; + public static final String DIMSTORAGE_MODID = "dimstorage"; + public static final String MEKANISM_MODID = "mekanism"; + public static final String POWAH_MODID = "powah"; + public static final String REFINEDSTORAGE_MODID = "refinedstorage"; + public static final String VALKYRIEN_SKIES_MODID = "valkyrienskies"; - public static boolean curiosLoaded; - public static boolean refinedStorageLoaded; - public static boolean aeThingsLoaded; public static boolean aeAdditionsLoaded; + public static boolean aeThingsLoaded; public static boolean appMekLoaded; + public static boolean appliedEnergisticsLoaded; + public static boolean botaniaLoaded; + public static boolean createLoaded; + public static boolean curiosLoaded; + public static boolean dimstorageLoaded; + public static boolean mekanismLoaded; + public static boolean powahLoaded; + public static boolean refinedStorageLoaded; + public static boolean vs2Loaded; - private APAddons() { - } - - public static void commonSetup() { + // Use static so these checks run as early as possible, so we can use them for our registries + static { ModList modList = ModList.get(); - curiosLoaded = modList.isLoaded(CURIOS_MODID); - refinedStorageLoaded = modList.isLoaded(REFINEDSTORAGE_MODID); - aeThingsLoaded = modList.isLoaded(AE_THINGS_MODID); aeAdditionsLoaded = modList.isLoaded(AE_ADDITIONS_MODID); + aeThingsLoaded = modList.isLoaded(AE_THINGS_MODID); appMekLoaded = modList.isLoaded(APP_MEKANISTICS_MODID); + appliedEnergisticsLoaded = modList.isLoaded(APPLIEDENERGISTICS_MODID); + botaniaLoaded = modList.isLoaded(BOTANIA_MODID); + createLoaded = modList.isLoaded(CREATE_MODID); + curiosLoaded = modList.isLoaded(CURIOS_MODID); + dimstorageLoaded = modList.isLoaded(DIMSTORAGE_MODID); + mekanismLoaded = modList.isLoaded(MEKANISM_MODID); + powahLoaded = modList.isLoaded(POWAH_MODID); + refinedStorageLoaded = modList.isLoaded(REFINEDSTORAGE_MODID); + vs2Loaded = modList.isLoaded(VALKYRIEN_SKIES_MODID); - if (refinedStorageLoaded) - RefinedStorage.instance = new RefinedStorage(); - + if (refinedStorageLoaded) { + RSApi.instance = new RSApi(); + } } @SubscribeEvent @@ -43,6 +74,27 @@ public static void interModComms(InterModEnqueueEvent event) { if (!curiosLoaded) return; - // InterModComms.sendTo("curios", SlotTypeMessage.REGISTER_TYPE, () -> new SlotTypeMessage.Builder("glasses").size(1).build()); + InterModComms.sendTo(CURIOS_MODID, SlotTypeMessage.REGISTER_TYPE, + () -> new SlotTypeMessage.Builder("glasses") + .size(1) + .icon(new ResourceLocation(AdvancedPeripherals.MOD_ID, "slot/empty_glasses_slot")) + .build()); + } + + public static ItemStack getCurioGlasses(Player player) { + if (!curiosLoaded) + return ItemStack.EMPTY; + List curioSlots = CuriosApi.getCuriosHelper().findCurios(player, "glasses"); + if (curioSlots.isEmpty()) + return ItemStack.EMPTY; + + return curioSlots.get(0).stack(); + } + + public static boolean isBlockOnShip(Level level, BlockPos pos) { + if (!vs2Loaded) { + return false; + } + return ValkyrienSkies.isBlockOnShip(level, pos); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AE2Registries.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AE2Registries.java new file mode 100644 index 000000000..b4759df1d --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AE2Registries.java @@ -0,0 +1,42 @@ +package de.srendi.advancedperipherals.common.addons.ae2; + +import appeng.api.features.P2PTunnelAttunement; +import appeng.api.parts.IPart; +import appeng.api.parts.IPartItem; +import appeng.api.parts.PartModels; +import appeng.items.parts.PartItem; +import appeng.items.parts.PartModelsHelper; +import dan200.computercraft.shared.Registry.ModItems; +import de.srendi.advancedperipherals.common.setup.APRegistration; +import net.minecraft.data.tags.TagsProvider; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraftforge.registries.RegistryObject; + +import java.util.function.Function; + +public final class AE2Registries { + private AE2Registries() {} + + public static final RegistryObject> CABLE_P2P_TUNNEL = registerPart("cable_p2p_tunnel", WiredCableP2PTunnelPart.class, WiredCableP2PTunnelPart::new); + + private static RegistryObject> registerPart(String id, Class clazz, Function, T> factory) { + PartModels.registerModels(PartModelsHelper.createModels(clazz)); + return APRegistration.ITEMS.register(id, () -> new PartItem<>(new Item.Properties(), clazz, factory)); + } + + public static void finishRegister() { + P2PTunnelAttunement.registerAttunementTag(CABLE_P2P_TUNNEL.get()); + } + + public static TagKey getCableP2PTag() { + return P2PTunnelAttunement.getAttunementTag(CABLE_P2P_TUNNEL.get()); + } + + public static void registerTags(Function, TagsProvider.TagAppender> tagger) { + tagger.apply(getCableP2PTag()) + .add(ModItems.CABLE.get()) + .add(ModItems.WIRED_MODEM.get()) + .add(ModItems.WIRED_MODEM_FULL.get()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AEApi.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AEApi.java new file mode 100644 index 000000000..51958de66 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AEApi.java @@ -0,0 +1,961 @@ +package de.srendi.advancedperipherals.common.addons.ae2; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.inventories.InternalInventory; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridNode; +import appeng.api.networking.crafting.CraftingJobStatus; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingService; +import appeng.api.networking.storage.IStorageService; +import appeng.api.stacks.AEFluidKey; +import appeng.api.stacks.AEItemKey; +import appeng.api.stacks.AEKey; +import appeng.api.stacks.AEKeyType; +import appeng.api.stacks.GenericStack; +import appeng.api.stacks.KeyCounter; +import appeng.api.storage.AEKeyFilter; +import appeng.api.storage.IStorageProvider; +import appeng.api.storage.MEStorage; +import appeng.api.storage.cells.IBasicCellItem; +import appeng.blockentity.storage.DriveBlockEntity; +import appeng.crafting.execution.CraftingCpuLogic; +import appeng.crafting.pattern.EncodedPatternItem; +import appeng.helpers.iface.PatternContainer; +import appeng.items.storage.BasicStorageCell; +import appeng.me.cells.BasicCellHandler; +import appeng.me.cells.BasicCellInventory; +import appeng.me.cluster.implementations.CraftingCPUCluster; +import appeng.parts.storagebus.StorageBusPart; +import com.the9grounds.aeadditions.item.storage.StorageCell; +import com.the9grounds.aeadditions.item.storage.SuperStorageCell; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; +import de.srendi.advancedperipherals.common.util.inventory.GenericFilter; +import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; +import io.github.projectet.ae2things.item.DISKDrive; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import me.ramidzkh.mekae2.ae2.MekanismKey; +import me.ramidzkh.mekae2.ae2.MekanismKeyType; +import me.ramidzkh.mekae2.item.ChemicalStorageCell; +import mekanism.api.chemical.merged.MergedChemicalTank; +import mekanism.common.tile.TileEntityChemicalTank; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class AEApi { + + public static Pair findAEStackFromStack(MEStorage monitor, @Nullable ICraftingService crafting, ItemStack item) { + return findAEStackFromFilter(monitor, crafting, ItemFilter.fromStack(item)); + } + + public static Pair findAEStackFromFilter(MEStorage monitor, @Nullable ICraftingService crafting, ItemFilter item) { + for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { + if (temp.getKey() instanceof AEItemKey key && item.test(key.toStack())) + return Pair.of(temp.getLongValue(), key); + } + + if (crafting == null) + return Pair.of(0L, AEItemKey.of(ItemStack.EMPTY)); + + for (var temp : crafting.getCraftables(param -> true)) { + if (temp instanceof AEItemKey key && item.test(key.toStack())) + return Pair.of(0L, key); + } + + return Pair.of(0L, AEItemKey.of(ItemStack.EMPTY)); + } + + public static Pair findAEFluidFromStack(MEStorage monitor, @Nullable ICraftingService crafting, FluidStack item) { + return findAEFluidFromFilter(monitor, crafting, FluidFilter.fromStack(item)); + } + + public static Pair findAEFluidFromFilter(MEStorage monitor, @Nullable ICraftingService crafting, FluidFilter item) { + for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { + if (temp.getKey() instanceof AEFluidKey key && item.test(key.toStack(1))) + return Pair.of(temp.getLongValue(), key); + } + + if (crafting == null) + return Pair.of(0L, AEFluidKey.of(FluidStack.EMPTY)); + + for (var temp : crafting.getCraftables(param -> true)) { + if (temp instanceof AEFluidKey key && item.test(key.toStack(1))) + return Pair.of(0L, key); + } + + return Pair.of(0L, AEFluidKey.of(FluidStack.EMPTY)); + } + + /** + * Finds a pattern from filters. + * + * @param grid The grid to search patterns from. + * @param level The level of the grid. + * @param inputFilter The input filter to apply, can be null to ignore input filter. + * @param outputFilter The output filter to apply, can be null to ignore output filter. + * @return A Pair object containing the matched pattern and an error message if no pattern is found. + * The pattern can be null if no pattern is found. + * The error message is "NO_PATTERN_FOUND" if no pattern is found. + */ + public static Pair findPatternFromFilters(IGrid grid, Level level, @Nullable GenericFilter inputFilter, @Nullable GenericFilter outputFilter) { + for (IPatternDetails pattern : getPatterns(grid, level)) { + if (pattern.getInputs().length == 0) + continue; + if (pattern.getOutputs().length == 0) + continue; + + boolean inputMatch = false; + boolean outputMatch = false; + + if (inputFilter != null) { + outerLoop: + for (IPatternDetails.IInput input : pattern.getInputs()) { + for (GenericStack possibleInput : input.getPossibleInputs()) { + if (inputFilter.testAE(possibleInput)) { + inputMatch = true; + break outerLoop; + } + } + } + } else { + inputMatch = true; + } + + if (outputFilter != null) { + for (GenericStack output : pattern.getOutputs()) { + if (outputFilter.testAE(output)) { + outputMatch = true; + break; + } + } + } else { + outputMatch = true; + } + + if (inputMatch && outputMatch) + return Pair.of(pattern, null); + } + + return Pair.of(null, "NO_PATTERN_FOUND"); + } + + + public static List listStacks(MEStorage monitor, ICraftingService service) { + List items = new ArrayList<>(); + KeyCounter keyCounter = monitor.getAvailableStacks(); + for (Object2LongMap.Entry aeKey : keyCounter) { + if (aeKey.getKey() instanceof AEItemKey itemKey) { + items.add(parseAeStack(Pair.of(aeKey.getLongValue(), itemKey), service)); + } + } + return items; + } + + public static List listCraftableStacks(MEStorage monitor, ICraftingService service) { + List items = new ArrayList<>(); + KeyCounter keyCounter = monitor.getAvailableStacks(); + Set craftables = service.getCraftables(AEKeyFilter.none()); + for (AEKey aeKey : craftables) { + if (aeKey instanceof AEItemKey) { + items.add(parseAeStack(Pair.of(keyCounter.get(aeKey), aeKey), service)); + } + } + return items; + } + + public static List listFluids(MEStorage monitor, ICraftingService service) { + List items = new ArrayList<>(); + for (Object2LongMap.Entry aeKey : monitor.getAvailableStacks()) { + if (aeKey.getKey() instanceof AEFluidKey itemKey) { + items.add(parseAeStack(Pair.of(aeKey.getLongValue(), itemKey), service)); + } + } + return items; + } + + public static List listGases(MEStorage monitor, ICraftingService service) { + List items = new ArrayList<>(); + for (Object2LongMap.Entry aeKey : monitor.getAvailableStacks()) { + if (APAddons.appMekLoaded && aeKey.getKey() instanceof MekanismKey itemKey) { + items.add(parseAeStack(Pair.of(aeKey.getLongValue(), itemKey), service)); + } + } + return items; + } + + public static List listCraftableFluids(MEStorage monitor, ICraftingService service) { + List items = new ArrayList<>(); + KeyCounter keyCounter = monitor.getAvailableStacks(); + Set craftables = service.getCraftables(AEKeyFilter.none()); + for (AEKey aeKey : craftables) { + if (aeKey instanceof AEFluidKey) { + items.add(parseAeStack(Pair.of(keyCounter.get(aeKey), aeKey), service)); + } + } + return items; + } + + public static List getPatterns(IGrid grid, Level level) { + List patterns = new ArrayList<>(); + for (var machineClass : grid.getMachineClasses()) { + var containerClass = tryCastMachineToContainer(machineClass); + if (containerClass == null) + continue; + + for (var container : grid.getActiveMachines(containerClass)) { + for (ItemStack patternItem : container.getTerminalPatternInventory()) { + if (patternItem.getItem() instanceof EncodedPatternItem item) { + IPatternDetails patternDetails = item.decode(patternItem, level, false); + if (patternDetails == null) + continue; + + patterns.add(patternDetails); + } + } + } + } + return patterns; + } + + public static List listPatterns(IGrid grid, Level level) { + return getPatterns(grid, level).stream().map(AEApi::parsePattern).collect(Collectors.toList()); + } + + public static List listDrives(IGrid grid) { + List drives = new ArrayList<>(); + + for (IGridNode node : grid.getMachineNodes(DriveBlockEntity.class)) { + DriveBlockEntity drive = (DriveBlockEntity) node.getService(IStorageProvider.class); + + // A normal drive has a cellCount of 10 + if (drive == null || drive.getCellCount() != 10) + continue; + + drives.add(parseDrive(drive)); + } + + return drives; + } + + private static Class tryCastMachineToContainer(Class machineClass) { + if (PatternContainer.class.isAssignableFrom(machineClass)) + return machineClass.asSubclass(PatternContainer.class); + + return null; + } + + public static Map parseAeStack(Pair stack, @Nullable ICraftingService service) { + if (stack == null || stack.getRight() == null) + return Collections.emptyMap(); + if (stack.getRight() instanceof AEItemKey itemKey) + return parseItemStack(Pair.of(stack.getLeft(), itemKey), service); + if (stack.getRight() instanceof AEFluidKey fluidKey) + return parseFluidStack(Pair.of(stack.getLeft(), fluidKey), service); + if (APAddons.appMekLoaded && (stack.getRight() instanceof MekanismKey gasKey)) + return parseChemStack(Pair.of(stack.getLeft(), gasKey)); + + AdvancedPeripherals.debug("Could not create table from unknown stack " + stack.getRight().getClass() + " - Report this to the maintainer of ap", org.apache.logging.log4j.Level.WARN); + return Collections.emptyMap(); + } + + public static Map parseGenericStack(GenericStack stack) { + if (stack.what() == null) + return Collections.emptyMap(); + if (stack.what() instanceof AEItemKey aeItemKey) + return parseItemStack(Pair.of(stack.amount(), aeItemKey), null); + if (stack.what() instanceof AEFluidKey aeFluidKey) + return parseFluidStack(Pair.of(stack.amount(), aeFluidKey), null); + + AdvancedPeripherals.debug("Could not create table from unknown stack " + stack.getClass() + " - Report this to the maintainer of ap", org.apache.logging.log4j.Level.WARN); + return Collections.emptyMap(); + } + + public static List parseKeyCounter(KeyCounter counter) { + List parsedKeys = new ArrayList<>(); + for (AEKey key : counter.keySet()) { + parsedKeys.add(parseGenericStack(new GenericStack(key, counter.get(key)))); + } + + return parsedKeys; + } + + public static Map parseDrive(DriveBlockEntity drive) { + Map map = new HashMap<>(); + + map.put("powered", drive.isPowered()); + + long totalBytes = 0; + long usedBytes = 0; + + if (drive.getCellCount() != 10) + return map; + + List driveCells = new ArrayList<>(); + for (ItemStack item : drive.getInternalInventory()) { + if (item.getItem() instanceof BasicStorageCell cell) { + BasicCellInventory cellInventory = BasicCellHandler.INSTANCE.getCellInventory(item, null); + totalBytes += cellInventory.getTotalBytes(); + usedBytes += cellInventory.getUsedBytes(); + + driveCells.add(parseCell(cell, item)); + } + } + + map.put("usedBytes", usedBytes); + map.put("totalBytes", totalBytes); + map.put("cells", driveCells); + map.put("priority", drive.getPriority()); + map.put("menuIcon", LuaConverter.itemToObject(drive.getMainMenuIcon().getItem())); + map.put("position", LuaConverter.posToObject(drive.getBlockPos())); + map.put("name", drive.getCustomInventoryName().getString()); + + return map; + } + + public static Map parseCell(IBasicCellItem cell, ItemStack cellItem) { + Map map = new HashMap<>(); + BasicCellInventory cellInventory = BasicCellHandler.INSTANCE.getCellInventory(cellItem, null); + + map.put("item", LuaConverter.itemToObject(cellItem.getItem())); + map.put("type", cell.getKeyType().toString()); + map.put("bytes", cell.getBytes(cellItem)); + map.put("bytesPerType", cell.getBytesPerType(cellItem)); + map.put("usedBytes", cellInventory.getUsedBytes()); + map.put("totalTypes", cell.getTotalTypes(cellItem)); + map.put("fuzzyMode", cell.getFuzzyMode(cellItem).toString()); + + return map; + } + + private static Map parseItemStack(Pair stack, @Nullable ICraftingService craftingService) { + Map map = LuaConverter.itemStackToObject(stack.getRight().toStack()); + map.put("isCraftable", craftingService != null && craftingService.isCraftable(stack.getRight())); + map.put("count", stack.getLeft()); + return map; + } + + private static Map parseFluidStack(Pair stack, @Nullable ICraftingService craftingService) { + Map map = LuaConverter.fluidStackToObject(stack.getRight().toStack(1)); + map.put("count", stack.getLeft()); + map.put("isCraftable", craftingService != null && craftingService.isCraftable(stack.getRight())); + return map; + } + + private static Map parseChemStack(Pair stack) { + Map map = new HashMap<>(); + long amount = stack.getLeft(); + map.put("name", stack.getRight().getStack().getTypeRegistryName().toString()); + map.put("amount", amount); + map.put("displayName", stack.getRight().getDisplayName().getString()); + map.put("tags", LuaConverter.tagsToList(() -> stack.getRight().getStack().getType().getTags())); + + return map; + } + + public static Map parsePattern(IPatternDetails pattern) { + Map map = new HashMap<>(); + + map.put("inputs", Arrays.stream(pattern.getInputs()).map(AEApi::parsePatternInput).collect(Collectors.toList())); + map.put("outputs", Arrays.stream(pattern.getOutputs()).map(AEApi::parseGenericStack).collect(Collectors.toList())); + map.put("primaryOutput", parseGenericStack(pattern.getPrimaryOutput())); + return map; + } + + public static Map parsePatternInput(IPatternDetails.IInput patternInput) { + Map map = new HashMap<>(); + map.put("primaryInput", parseGenericStack(patternInput.getPossibleInputs()[0])); + map.put("possibleInputs", + Arrays.stream(Arrays.copyOfRange(patternInput.getPossibleInputs(), 1, patternInput.getPossibleInputs().length)) + .map(AEApi::parseGenericStack)); + map.put("multiplier", patternInput.getMultiplier()); + map.put("remaining", patternInput.getRemainingKey(patternInput.getPossibleInputs()[0].what())); + return map; + } + + public static Map parseCraftingCPU(ICraftingCPU cpu, boolean recursive) { + Map map = new HashMap<>(); + long storage = cpu.getAvailableStorage(); + int coProcessors = cpu.getCoProcessors(); + boolean isBusy = cpu.isBusy(); + map.put("storage", storage); + map.put("coProcessors", coProcessors); + map.put("isBusy", isBusy); + if (!recursive) + map.put("craftingJob", cpu.getJobStatus() != null ? parseCraftingJob(cpu.getJobStatus(), null, null) : null); + map.put("name", cpu.getName() != null ? cpu.getName().getString() : "Unnamed"); + map.put("selectionMode", cpu.getSelectionMode().toString()); + + return map; + } + + public static Object parseCraftingJob(CraftingJobStatus status, AECraftJob craftJob, @Nullable ICraftingCPU cpu) { + Map properties = new HashMap<>(); + + properties.put("bridge_id", craftJob == null ? -1 : craftJob.getId()); + properties.put("quantity", status.crafting().amount()); + properties.put("resource", parseGenericStack(status.crafting())); + + if (cpu != null) { + CraftingCpuLogic craftingCpuLogic = ((CraftingCPUCluster) cpu).craftingLogic; + long pending = craftingCpuLogic.getPendingOutputs(status.crafting().what()); + long active = craftingCpuLogic.getWaitingFor(status.crafting().what()); + long crafted = status.crafting().amount() - (pending + active); + properties.put("completion", crafted / (double) status.crafting().amount()); + properties.put("crafted", crafted); + + properties.put("id", craftingCpuLogic.getLastLink().getCraftingID().toString()); + + properties.put("cpu", parseCraftingCPU(cpu, true)); + } + + return properties; + } + + public static MEStorage getMonitor(IGridNode node) { + return node.getGrid().getService(IStorageService.class).getInventory(); + } + + public static boolean isCrafting(ICraftingService grid, GenericFilter filter, + @Nullable ICraftingCPU craftingCPU) { + + // If the passed cpu is null, check all cpus + if (craftingCPU == null) { + // Loop through all crafting cpus and check if the item is being crafted. + for (ICraftingCPU cpu : grid.getCpus()) { + if (cpu.isBusy()) { + CraftingJobStatus jobStatus = cpu.getJobStatus(); + + // avoid null pointer exception + if (jobStatus == null) + continue; + + if (filter.testAE(jobStatus.crafting())) + return true; + } + } + } else { + if (craftingCPU.isBusy()) { + CraftingJobStatus jobStatus = craftingCPU.getJobStatus(); + + // avoid null pointer exception + if (jobStatus == null) + return false; + + return filter.testAE(jobStatus.crafting()); + } + } + + return false; + } + + /// External Storage + /// Total + + public static long getTotalExternalItemStorage(IGridNode node) { + long total = 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + Level level = bus.getLevel(); + BlockPos connectedInventoryPos = bus.getHost().getBlockEntity().getBlockPos().relative(bus.getSide()); + BlockEntity connectedInventoryEntity = level.getBlockEntity(connectedInventoryPos); + + if (connectedInventoryEntity == null) + continue; + + LazyOptional itemHandler = connectedInventoryEntity.getCapability(ForgeCapabilities.ITEM_HANDLER); + if (itemHandler.isPresent()) { + IItemHandler handler = itemHandler.orElse(null); + for (int i = 0; i < handler.getSlots(); i++) { + total += handler.getSlotLimit(i); + } + } + } + + return total; + } + + public static long getTotalExternalFluidStorage(IGridNode node) { + long total = 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + Level level = bus.getLevel(); + BlockPos connectedInventoryPos = bus.getHost().getBlockEntity().getBlockPos().relative(bus.getSide()); + BlockEntity connectedInventoryEntity = level.getBlockEntity(connectedInventoryPos); + + if (connectedInventoryEntity == null) + continue; + + LazyOptional fluidHandler = connectedInventoryEntity.getCapability(ForgeCapabilities.FLUID_HANDLER); + if (fluidHandler.isPresent()) { + IFluidHandler handler = fluidHandler.orElse(null); + for (int i = 0; i < handler.getTanks(); i++) { + total += handler.getTankCapacity(i); + } + } + } + + return total; + } + + public static long getTotalExternalChemicalStorage(IGridNode node) { + long total = 0; + + if (!APAddons.appMekLoaded) + return 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + Level level = bus.getLevel(); + BlockPos connectedInventoryPos = bus.getHost().getBlockEntity().getBlockPos().relative(bus.getSide()); + BlockEntity connectedInventoryEntity = level.getBlockEntity(connectedInventoryPos); + + if (connectedInventoryEntity == null) + continue; + + if (connectedInventoryEntity instanceof TileEntityChemicalTank tank) { + MergedChemicalTank.Current current = tank.getChemicalTank().getCurrent() == MergedChemicalTank.Current.EMPTY ? MergedChemicalTank.Current.GAS : tank.getChemicalTank().getCurrent(); + total += tank.getChemicalTank().getTankFromCurrent(current).getCapacity(); + } + } + + return total; + } + + /// Used + + public static long getUsedExternalItemStorage(IGridNode node) { + long used = 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + KeyCounter keyCounter = bus.getInternalHandler().getAvailableStacks(); + + for (Object2LongMap.Entry aeKey : keyCounter) { + if (aeKey.getKey() instanceof AEItemKey) + used += aeKey.getLongValue(); + } + } + + return used; + } + + public static long getUsedExternalFluidStorage(IGridNode node) { + long used = 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + KeyCounter keyCounter = bus.getInternalHandler().getAvailableStacks(); + + for (Object2LongMap.Entry aeKey : keyCounter) { + if (aeKey.getKey() instanceof AEFluidKey) + used += aeKey.getLongValue(); + } + } + + return used; + } + + public static long getUsedExternalChemicalStorage(IGridNode node) { + long used = 0; + + if (!APAddons.appMekLoaded) + return 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(StorageBusPart.class)) { + StorageBusPart bus = (StorageBusPart) iGridNode.getService(IStorageProvider.class); + KeyCounter keyCounter = bus.getInternalHandler().getAvailableStacks(); + + for (Object2LongMap.Entry aeKey : keyCounter) { + if (aeKey.getKey() instanceof MekanismKey) + used += aeKey.getLongValue(); + } + } + + return used; + } + + /// Internal Storage + /// Total + + public static long getTotalItemStorage(IGridNode node) { + long total = 0; + + // note: do not query DriveBlockEntity.class specifically here, because it will avoid subclasses, e.g. the ME Extended Drive from ExtendedAE + Iterator iterator = node.getGrid().getNodes().iterator(); + + while (iterator.hasNext()) { + if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.isEmpty()) + continue; + + if (stack.getItem() instanceof IBasicCellItem cell) { + if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.items().getClass())) { + total += cell.getBytes(null); + } + } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { + if (disk.getKeyType().toString().equals("ae2:i")) { + total += disk.getBytes(null); + } + } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof SuperStorageCell superStorageCell)) { + total += superStorageCell.getKiloBytes() * 1024L; + } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof StorageCell storageCell)) { + if (storageCell.getKeyType() != AEKeyType.items()) + continue; + total += storageCell.getKiloBytes() * 1024; + } + } + } + return total; + } + + public static long getTotalFluidStorage(IGridNode node) { + long total = 0; + + Iterator iterator = node.getGrid().getNodes().iterator(); + + while (iterator.hasNext()) { + if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.isEmpty()) + continue; + + if (stack.getItem() instanceof IBasicCellItem cell) { + if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.fluids().getClass())) { + total += cell.getBytes(null); + } + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell superStorageCell) { + total += superStorageCell.getKiloBytes() * 1024L; + } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof StorageCell storageCell)) { + if (storageCell.getKeyType() != AEKeyType.fluids()) + continue; + total += storageCell.getKiloBytes() * 1024; + } + } + } + + return total; + } + + public static long getTotalChemicalStorage(IGridNode node) { + long total = 0; + + if (!APAddons.appMekLoaded) + return 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(DriveBlockEntity.class)) { + DriveBlockEntity entity = (DriveBlockEntity) iGridNode.getService(IStorageProvider.class); + if (entity == null) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.isEmpty()) + continue; + + if (stack.getItem() instanceof ChemicalStorageCell cell) { + if (cell.getKeyType() instanceof MekanismKeyType) { + total += cell.getBytes(null); + } + } + } + } + + return total; + } + + /// Used + + public static long getUsedItemStorage(IGridNode node) { + long used = 0; + + Iterator iterator = node.getGrid().getNodes().iterator(); + + while (iterator.hasNext()) { + if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.isEmpty()) + continue; + + if (stack.getItem() instanceof IBasicCellItem cell) { + if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.items().getClass())) { + BasicCellInventory cellInventory = BasicCellHandler.INSTANCE.getCellInventory(stack, null); + + used += cellInventory.getUsedBytes(); + } + } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { + if (disk.getKeyType().toString().equals("ae2:i")) { + if (stack.getTag() == null) + continue; + long numBytesInCell = stack.getTag().getLong("ic"); + used += numBytesInCell; + } + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell) { + if (stack.getTag() == null) + continue; + long numItemsInCell = stack.getTag().getLong("ic"); + + used += numItemsInCell; + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof StorageCell storageCell) { + if (storageCell.getKeyType() != AEKeyType.items()) + continue; + if (stack.getTag() == null) + continue; + long numItemsInCell = stack.getTag().getLong("ic"); + + used += numItemsInCell; + } + } + } + + return used; + } + + public static long getUsedFluidStorage(IGridNode node) { + long used = 0; + + Iterator iterator = node.getGrid().getNodes().iterator(); + + while (iterator.hasNext()) { + if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.getItem() instanceof IBasicCellItem cell) { + if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.fluids().getClass())) { + BasicCellInventory cellInventory = BasicCellHandler.INSTANCE.getCellInventory(stack, null); + + used += cellInventory.getUsedBytes(); + } + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell) { + if (stack.getTag() == null) + continue; + long numItemsInCell = stack.getTag().getLong("ic"); + + used += numItemsInCell; + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof StorageCell storageCell) { + if (storageCell.getKeyType() != AEKeyType.fluids()) + continue; + if (stack.getTag() == null) + continue; + long numItemsInCell = stack.getTag().getLong("ic"); + + used += numItemsInCell; + } + } + } + + return used; + } + + public static long getUsedChemicalStorage(IGridNode node) { + long used = 0; + + if (!APAddons.appMekLoaded) + return 0; + + for (IGridNode iGridNode : node.getGrid().getMachineNodes(DriveBlockEntity.class)) { + DriveBlockEntity entity = (DriveBlockEntity) iGridNode.getService(IStorageProvider.class); + if (entity == null) + continue; + + InternalInventory inventory = entity.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.getItem() instanceof ChemicalStorageCell) { + BasicCellInventory cellInventory = BasicCellHandler.INSTANCE.getCellInventory(stack, null); + + used = cellInventory.getUsedBytes() / MekanismKeyType.TYPE.getAmountPerByte(); + } + } + } + + return used; + } + + /// Available Storage + + /** + * Calculates the available item storage on a given grid node. + * It subtracts the used item storage from the total item storage. + * + * @param node The grid node to calculate the available item storage for. + * @return The available item storage in bytes. + */ + public static long getAvailableItemStorage(IGridNode node) { + return getTotalItemStorage(node) - getUsedItemStorage(node); + } + + /** + * Calculates the available fluid storage in a given grid node. + * + * @param node The grid node to calculate the available fluid storage for. + * @return The available fluid storage in bytes. + */ + public static long getAvailableFluidStorage(IGridNode node) { + return getTotalFluidStorage(node) - getUsedFluidStorage(node); + } + + public static long getAvailableChemicalStorage(IGridNode node) { + return getTotalChemicalStorage(node) - getUsedChemicalStorage(node); + } + + /** + * Calculates the available external item storage of a given grid node. + * + * @param node The grid node for which to calculate the available external item storage. + * @return The available external item storage. + */ + public static long getAvailableExternalItemStorage(IGridNode node) { + return getTotalExternalItemStorage(node) - getUsedExternalItemStorage(node); + } + + /** + * Calculates the available external fluid storage on a given grid node by subtracting the used external fluid storage + * from the total external fluid storage. + * + * @param node The grid node on which to calculate the available external fluid storage. + * @return The available external fluid storage on the grid node. + */ + public static long getAvailableExternalFluidStorage(IGridNode node) { + return getTotalExternalFluidStorage(node) - getUsedExternalFluidStorage(node); + } + + public static long getAvailableExternalChemicalStorage(IGridNode node) { + return getTotalExternalChemicalStorage(node) - getUsedExternalChemicalStorage(node); + } + + public static ICraftingCPU getCraftingCPU(IGridNode node, String cpuName) { + if (cpuName.isEmpty()) return null; + ICraftingService grid = node.getGrid().getService(ICraftingService.class); + if (grid == null) return null; + + Iterator iterator = grid.getCpus().iterator(); + if (!iterator.hasNext()) return null; + + while (iterator.hasNext()) { + ICraftingCPU cpu = iterator.next(); + + if (cpu.getName() != null && cpu.getName().getString().equals(cpuName)) { + return cpu; + } + } + + return null; + } + + public static List listCells(IGridNode node) { + List items = new ArrayList<>(); + + Iterator iterator = node.getGrid().getNodes().iterator(); + + if (!iterator.hasNext()) return items; + while (iterator.hasNext()) { + IStorageProvider entity = iterator.next().getService(IStorageProvider.class); + if (!(entity instanceof DriveBlockEntity drive)) + continue; + + InternalInventory inventory = drive.getInternalInventory(); + + for (int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + + if (stack.isEmpty()) + continue; + + if (stack.getItem() instanceof IBasicCellItem cell) { + items.add(parseCell(cell, stack)); + } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { + items.add(getObjectFromDisk(disk, stack)); + } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell superStorageCell) { + items.add(getObjectFromSuperCell(superStorageCell, stack)); + } + } + } + + return items; + } + + private static Map getObjectFromDisk(DISKDrive drive, ItemStack stack) { + Map map = new HashMap<>(); + + map.put("item", stack.getItem().toString()); + + String cellType = ""; + + if (drive.getKeyType().toString().equals("ae2:i")) { + cellType = "item"; + } else if (drive.getKeyType().toString().equals("ae2:f")) { + cellType = "fluid"; + } + + map.put("cellType", cellType); + map.put("totalBytes", drive.getBytes(null)); + + return map; + } + + private static Map getObjectFromSuperCell(SuperStorageCell cell, ItemStack stack) { + Map map = new HashMap<>(); + + map.put("item", stack.getItem().toString()); + + String cellType = "all"; + + map.put("cellType", cellType); + map.put("totalBytes", cell.getBytes(stack)); + + return map; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AECraftJob.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AECraftJob.java new file mode 100644 index 000000000..f59291c09 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AECraftJob.java @@ -0,0 +1,312 @@ +package de.srendi.advancedperipherals.common.addons.ae2; + +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridNode; +import appeng.api.networking.crafting.CalculationStrategy; +import appeng.api.networking.crafting.CraftingJobStatus; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingLink; +import appeng.api.networking.crafting.ICraftingPlan; +import appeng.api.networking.crafting.ICraftingRequester; +import appeng.api.networking.crafting.ICraftingService; +import appeng.api.networking.crafting.ICraftingSimulationRequester; +import appeng.api.networking.crafting.ICraftingSubmitResult; +import appeng.api.networking.security.IActionSource; +import appeng.api.stacks.AEKey; +import appeng.api.stacks.KeyCounter; +import appeng.me.cluster.implementations.CraftingCPUCluster; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.IComputerAccess; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity; +import de.srendi.advancedperipherals.common.util.BasicCraftJob; +import de.srendi.advancedperipherals.common.util.StatusConstants; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.function.Supplier; + +//TODO needs to persistent - should be stored in the me bridge +// We also need to do the same for the rs bridge. So we want to create a proper interface to keep the lua functions the same +public class AECraftJob extends BasicCraftJob { + + private final IGridNode node; + private final IActionSource source; + private final ICraftingSimulationRequester simulationRequester; + private final ICraftingRequester requester; + private ICraftingCPU targetCpu; + private final AEKey toCraft; + + private Future futureJob; + private ICraftingPlan currentJob; + @Nullable + private ICraftingLink jobLink; // Job after calculation was done + // Because the properties in `CraftingJobStatus` are set when the object is created, we need to create a supplier which + // always re-fetches the object from the cpu + private Supplier jobStatus; + // In the case the job is done and would return null, we have this cached one. + private CraftingJobStatus cachedStatus; + + public AECraftJob(Level world, final IComputerAccess computer, IGridNode node, AEKey item, long amount, MeBridgeEntity bridge, ICraftingCPU target) { + super(computer, "ae", world, amount); + this.node = node; + this.source = bridge; + this.toCraft = item; + this.simulationRequester = bridge; + this.requester = bridge; + this.targetCpu = target; + } + + @LuaFunction + public final Object getCraftingCPU() { + return AEApi.parseCraftingCPU(targetCpu, true); + } + + @Nullable + public ICraftingLink getJobLink() { + return jobLink; + } + + public ICraftingCPU getTargetCpu() { + return targetCpu; + } + + public AEKey getToCraft() { + return toCraft; + } + + @Override + protected boolean isJobDone() { + return jobLink != null && jobLink.isDone(); + } + + @Override + protected boolean isJobCanceled() { + return jobLink != null && jobLink.isCanceled(); + } + + @Override + public Object getParsedRequestedItem() { + if (getJobStatus() == null) { + return null; + } + return AEApi.parseGenericStack(getJobStatus().crafting()); + } + + @Override + public long getElapsedTime() { + if (getJobStatus() == null) { + return -1; + } + return getJobStatus().elapsedTimeNanos(); + } + + @Override + public long getTotalItems() { + if (getJobStatus() == null) { + return -1; + } + return getJobStatus().totalItems(); + } + + @Override + public long getItemProgress() { + if (getJobStatus() == null) { + return -1; + } + return getJobStatus().progress(); + } + + @Override + public Object getEmittedItems() { + if (currentJob == null) { + return null; + } + return AEApi.parseKeyCounter(currentJob.emittedItems()); + } + + @Override + public Object getUsedItems() { + if (currentJob == null) { + return null; + } + return AEApi.parseKeyCounter(currentJob.usedItems()); + } + + @Override + public Object getMissingItems() { + if (currentJob == null) { + return null; + } + return AEApi.parseKeyCounter(currentJob.missingItems()); + } + + @Override + public boolean hasMultiplePaths() { + if (currentJob == null) { + return false; + } + return currentJob.multiplePaths(); + } + + @Override + public Object getFinalOutput() { + if (currentJob == null) { + return null; + } + return AEApi.parseGenericStack(currentJob.finalOutput()); + } + + @Override + public boolean cancel() { + if (targetCpu instanceof CraftingCPUCluster cluster) { + if (cluster.isBusy()) { + cluster.cancel(); + return true; + } + } + return false; + } + + @LuaFunction + public long getUsedBytes() { + if (currentJob == null) { + return -1; + } + return currentJob.bytes(); + } + + public AECraftJob withJobStatus(Supplier jobStatus) { + this.jobStatus = jobStatus; + return this; + } + + public AECraftJob withCPU(ICraftingCPU craftingCpu) { + if (this.targetCpu == null) { + this.targetCpu = craftingCpu; + } + return this; + } + + public void startCalculation() { + if (startedCalculation) { + return; + } + startedCalculation = true; + + IGrid grid = node.getGrid(); + + ICraftingService craftingService = grid.getService(ICraftingService.class); + + if (!craftingService.isCraftable(toCraft)) { + fireEvent(true, StatusConstants.NOT_CRAFTABLE); + calculationNotSuccessful = true; + return; + } + + futureJob = craftingService.beginCraftingCalculation(world, this.simulationRequester, toCraft, amount, CalculationStrategy.REPORT_MISSING_ITEMS); + fireEvent(false, StatusConstants.CALCULATION_STARTED); + } + + public void maybeCraft() { + if (startedCrafting || futureJob == null || !futureJob.isDone()) { + return; + } + ICraftingPlan job; + + try { + job = futureJob.get(); + } catch (ExecutionException | InterruptedException ex) { + AdvancedPeripherals.debug("Tried to get job, but job calculation is not done. Should be done.", org.apache.logging.log4j.Level.ERROR); + ex.printStackTrace(); + fireEvent(true, StatusConstants.UNKNOWN_ERROR); + return; + } + + if (job == null) { + AdvancedPeripherals.debug("Job is null, should not be null.", org.apache.logging.log4j.Level.ERROR); + fireEvent(true, StatusConstants.UNKNOWN_ERROR); + return; + } + this.currentJob = job; + + KeyCounter missing = job.missingItems(); + if (!missing.isEmpty()) { + fireEvent(true, StatusConstants.MISSING_ITEMS); + calculationNotSuccessful = true; + return; + } + + IGrid grid = node.getGrid(); + + ICraftingService craftingService = grid.getService(ICraftingService.class); + ICraftingSubmitResult submitResult = craftingService.submitJob(job, requester, targetCpu, false, this.source); + if (!submitResult.successful()) { + calculationNotSuccessful = true; + fireEvent(true, submitResult.errorCode().toString()); + return; + } + + this.jobLink = submitResult.link(); + this.futureJob = null; + setStartedCrafting(); + prepareCPUAndStatus(craftingService); + } + + public void jobStateChanged() { + ICraftingLink jobLink = this.jobLink; + if (jobLink == null) { + fireEvent(true, StatusConstants.UNKNOWN_ERROR); + return; + } + + if (jobLink.isCanceled() && !isJobCanceled) { + fireEvent(false, StatusConstants.JOB_CANCELED); + setJobCanceled(); + return; + } + + if (jobLink.isDone() && !isJobDone) { + fireEvent(false, StatusConstants.JOB_DONE); + setJobDone(); + } + } + + private void prepareCPUAndStatus(ICraftingService service) { + if (jobLink == null || jobStatus != null || !startedCrafting) { + return; + } + for (ICraftingCPU cpu : service.getCpus()) { + if (cpu instanceof CraftingCPUCluster cpuCluster) { + if (cpuCluster.craftingLogic.getLastLink() != null && cpuCluster.craftingLogic.getLastLink().getCraftingID().equals(jobLink.getCraftingID())) { + this.jobStatus = () -> { + // Compare the id of the job in the cpu. This job object can exist longer than the job needs time to complete. So the cpu could have a new job + if (cpuCluster.craftingLogic.getLastLink() != null && cpuCluster.craftingLogic.getLastLink().getCraftingID().equals(jobLink.getCraftingID())) + return cpuCluster.getJobStatus(); + return null; + }; + cpuCluster.craftingLogic.addListener((key) -> { + // The last time the listeners are called from the cpu logic is when the job is finished + // These listeners are not intended by ae2 to be used like this, but it works, and we don't modify the key + if (cpuCluster.getJobStatus() != null) { + this.cachedStatus = cpuCluster.getJobStatus(); + } + }); + this.targetCpu = cpu; + return; + } + } + } + AdvancedPeripherals.debug("Could not find CPU or job link even after job started", org.apache.logging.log4j.Level.WARN); + } + + private CraftingJobStatus getJobStatus() { + if (jobStatus == null || jobStatus.get() == null && cachedStatus != null) { + return cachedStatus; + } + cachedStatus = jobStatus.get(); + return jobStatus.get(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeBridgeEntityListener.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEBridgeEntityListener.java similarity index 57% rename from src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeBridgeEntityListener.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEBridgeEntityListener.java index 1aee16c85..439caf900 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeBridgeEntityListener.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEBridgeEntityListener.java @@ -1,21 +1,20 @@ -package de.srendi.advancedperipherals.common.addons.appliedenergistics; +package de.srendi.advancedperipherals.common.addons.ae2; import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNodeListener; import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity; -//TODO: Maybe do something special with these methods? -public class MeBridgeEntityListener implements IGridNodeListener { +public class MEBridgeEntityListener implements IGridNodeListener { - public static final MeBridgeEntityListener INSTANCE = new MeBridgeEntityListener(); + public static final MEBridgeEntityListener INSTANCE = new MEBridgeEntityListener(); @Override public void onSecurityBreak(MeBridgeEntity nodeOwner, IGridNode node) { - + // Maybe do something special with these methods? } @Override public void onSaveChanges(MeBridgeEntity nodeOwner, IGridNode node) { - + // Maybe do something special with these methods? } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEFluidHandler.java similarity index 77% rename from src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeFluidHandler.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEFluidHandler.java index 8072a777d..73936fb83 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEFluidHandler.java @@ -1,9 +1,10 @@ -package de.srendi.advancedperipherals.common.addons.appliedenergistics; +package de.srendi.advancedperipherals.common.addons.ae2; import appeng.api.config.Actionable; import appeng.api.networking.security.IActionSource; import appeng.api.stacks.AEFluidKey; import appeng.api.storage.MEStorage; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MEBridgePeripheral; import de.srendi.advancedperipherals.common.util.Pair; import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemFluidHandler; @@ -12,23 +13,24 @@ /** * Used to transfer item between an inventory and the ME system. - * @see de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MeBridgePeripheral + * + * @see MEBridgePeripheral */ -public class MeFluidHandler implements IStorageSystemFluidHandler { +public class MEFluidHandler implements IStorageSystemFluidHandler { @NotNull private final MEStorage storageMonitor; @NotNull private final IActionSource actionSource; - public MeFluidHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource actionSource) { + public MEFluidHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource actionSource) { this.storageMonitor = storageMonitor; this.actionSource = actionSource; } @Override public int fill(FluidStack resource, FluidAction action) { - if(resource.isEmpty()) + if (resource.isEmpty()) return 0; AEFluidKey itemKey = AEFluidKey.of(resource.getFluid()); long inserted = storageMonitor.insert(itemKey, resource.getAmount(), action == FluidAction.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); @@ -39,8 +41,8 @@ public int fill(FluidStack resource, FluidAction action) { @NotNull @Override public FluidStack drain(FluidFilter filter, FluidAction simulate) { - Pair itemKey = AppEngApi.findAEFluidFromFilter(storageMonitor, null, filter); - if(itemKey == null) + Pair itemKey = AEApi.findAEFluidFromFilter(storageMonitor, null, filter); + if (itemKey == null) return FluidStack.EMPTY; long extracted = storageMonitor.extract(itemKey.getRight(), filter.getCount(), simulate == FluidAction.SIMULATE ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); return new FluidStack(itemKey.getRight().getFluid(), (int) Math.min(extracted, Integer.MAX_VALUE)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEItemHandler.java similarity index 82% rename from src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeItemHandler.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEItemHandler.java index a3542cda3..4fdc79dac 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/MeItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/MEItemHandler.java @@ -1,9 +1,10 @@ -package de.srendi.advancedperipherals.common.addons.appliedenergistics; +package de.srendi.advancedperipherals.common.addons.ae2; import appeng.api.config.Actionable; import appeng.api.networking.security.IActionSource; import appeng.api.stacks.AEItemKey; import appeng.api.storage.MEStorage; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MEBridgePeripheral; import de.srendi.advancedperipherals.common.util.Pair; import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemItemHandler; import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; @@ -13,16 +14,16 @@ /** * Used to transfer item between an inventory and the ME system. * - * @see de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MeBridgePeripheral + * @see MEBridgePeripheral */ -public class MeItemHandler implements IStorageSystemItemHandler { +public class MEItemHandler implements IStorageSystemItemHandler { @NotNull private final MEStorage storageMonitor; @NotNull private final IActionSource actionSource; - public MeItemHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource actionSource) { + public MEItemHandler(@NotNull MEStorage storageMonitor, @NotNull IActionSource actionSource) { this.storageMonitor = storageMonitor; this.actionSource = actionSource; } @@ -40,7 +41,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate @Override public ItemStack extractItem(ItemFilter filter, int count, boolean simulate) { - Pair itemKey = AppEngApi.findAEStackFromFilter(storageMonitor, null, filter); + Pair itemKey = AEApi.findAEStackFromFilter(storageMonitor, null, filter); if (itemKey.getRight() == null) return ItemStack.EMPTY; long extracted = storageMonitor.extract(itemKey.getRight(), count, simulate ? Actionable.SIMULATE : Actionable.MODULATE, actionSource); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/WiredCableP2PTunnelPart.java b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/WiredCableP2PTunnelPart.java new file mode 100644 index 000000000..596ce5e62 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/ae2/WiredCableP2PTunnelPart.java @@ -0,0 +1,174 @@ +package de.srendi.advancedperipherals.common.addons.ae2; + +import appeng.api.networking.IGridNodeListener; +import appeng.api.parts.IPartItem; +import appeng.api.parts.IPartModel; +import appeng.items.parts.PartModels; +import appeng.parts.p2p.CapabilityP2PTunnelPart; +import appeng.parts.p2p.P2PModels; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.network.wired.IWiredElement; +import dan200.computercraft.api.network.wired.IWiredNetworkChange; +import dan200.computercraft.api.network.wired.IWiredNode; +import dan200.computercraft.shared.Capabilities; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.annotation.Nonnull; + +public class WiredCableP2PTunnelPart extends CapabilityP2PTunnelPart { + private static final P2PModels MODELS = new P2PModels(AdvancedPeripherals.getRL("part/p2p/p2p_tunnel_cable")); + + private final IWiredElement element = new P2PWiredElement(); + private final IWiredElement outElement = new P2PWiredElement(); + private final IWiredNode node = this.element.getNode(); + private Set connected = new HashSet<>(); + private boolean activated = false; + + public WiredCableP2PTunnelPart(IPartItem partItem) { + super(partItem, Capabilities.CAPABILITY_WIRED_ELEMENT); + this.inputHandler = outElement; + this.outputHandler = outElement; + this.emptyHandler = null; // should never used + } + + @PartModels + public static List getModels() { + return MODELS.getModels(); + } + + @Override + public IPartModel getStaticModels() { + return MODELS.getModel(this.isPowered(), this.isActive()); + } + + @Override + public void onTunnelConfigChange() { + super.onTunnelConfigChange(); + this.connectionsChanged(); + } + + @Override + public void onTunnelNetworkChange() { + super.onTunnelNetworkChange(); + this.connectionsChanged(); + } + + protected void connectionsChanged() { + if (this.isClientSide()) { + return; + } + if (!this.isActive()) { + return; + } + if (!this.activated) { + this.activated = true; + this.node.connectTo(this.outElement.getNode()); + } + + Stream nodeStream = this.getOutputStream().filter(out -> out != this); + WiredCableP2PTunnelPart in = this.getInput(); + if (in != null && in != this) { + nodeStream = Stream.concat(nodeStream, Stream.of(in)); + } + Set nodes = nodeStream.collect(Collectors.toCollection(HashSet::new)); + + for (WiredCableP2PTunnelPart part : this.connected.stream().filter(n -> !nodes.contains(n)).collect(Collectors.toList())) { + if (part.connected.contains(this)) { + this.node.disconnectFrom(part.node); + part.connected.remove(this); + } + this.connected.remove(part); + } + + for (WiredCableP2PTunnelPart part : nodes) { + if (!this.connected.contains(part)) { + this.node.connectTo(part.node); + this.connected.add(part); + part.connected.add(this); + } + } + } + + @Override + protected void onMainNodeStateChanged(IGridNodeListener.State reason) { + super.onMainNodeStateChanged(reason); + if (reason == IGridNodeListener.State.GRID_BOOT) { + return; + } + if (this.isActive()) { + if (!this.getMainNode().hasGridBooted()) { + return; + } + this.connectionsChanged(); + this.refreshConnection(); + } else if (this.activated) { + this.activated = false; + this.node.remove(); + this.connected.clear(); + } + } + + protected BlockPos getFacingPos() { + return this.getHost().getLocation().getPos().relative(this.getSide()); + } + + protected void refreshConnection() { + BlockEntity cable = this.getLevel().getBlockEntity(this.getFacingPos()); + IWiredElement elem = cable == null ? null : cable.getCapability(Capabilities.CAPABILITY_WIRED_ELEMENT, this.getSide().getOpposite()).orElse(null); + if (elem == null) { + return; + } + elem.getNode().connectTo(this.outElement.getNode()); + } + + @Override + public void onNeighborChanged(BlockGetter level, BlockPos pos, BlockPos neighbor) { + if (!this.getFacingPos().equals(neighbor)) { + return; + } + if (this.activated) { + this.refreshConnection(); + } + } + + private class P2PWiredElement implements IWiredElement { + private final IWiredNode node = ComputerCraftAPI.createWiredNodeForElement(this); + + @Nonnull + @Override + public IWiredNode getNode() { + return node; + } + + @Nonnull + @Override + public String getSenderID() { + return "p2p"; + } + + @Nonnull + @Override + public Level getLevel() { + return WiredCableP2PTunnelPart.this.getLevel(); + } + + @Nonnull + @Override + public Vec3 getPosition() { + return Vec3.atCenterOf(WiredCableP2PTunnelPart.this.getBlockEntity().getBlockPos()); + } + + @Override + public void networkChanged(IWiredNetworkChange change) {} + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AppEngApi.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AppEngApi.java deleted file mode 100644 index 3bc0c6d8e..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/AppEngApi.java +++ /dev/null @@ -1,641 +0,0 @@ -package de.srendi.advancedperipherals.common.addons.appliedenergistics; - -import appeng.api.inventories.InternalInventory; -import appeng.api.networking.IGridNode; -import appeng.api.networking.crafting.CraftingJobStatus; -import appeng.api.networking.crafting.ICraftingCPU; -import appeng.api.networking.crafting.ICraftingService; -import appeng.api.networking.storage.IStorageService; -import appeng.api.stacks.*; -import appeng.api.storage.AEKeyFilter; -import appeng.api.storage.IStorageProvider; -import appeng.api.storage.MEStorage; -import appeng.api.storage.cells.IBasicCellItem; -import appeng.blockentity.storage.DriveBlockEntity; -import appeng.parts.storagebus.StorageBusPart; -import com.the9grounds.aeadditions.item.storage.StorageCell; -import com.the9grounds.aeadditions.item.storage.SuperStorageCell; -import dan200.computercraft.shared.util.NBTUtil; -import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.addons.APAddons; -import de.srendi.advancedperipherals.common.util.LuaConverter; -import de.srendi.advancedperipherals.common.util.Pair; -import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; -import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; -import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; -import io.github.projectet.ae2things.item.DISKDrive; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import me.ramidzkh.mekae2.ae2.MekanismKey; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.registries.ForgeRegistries; -import org.apache.logging.log4j.Level; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -public class AppEngApi { - - public static Pair findAEStackFromStack(MEStorage monitor, @Nullable ICraftingService crafting, ItemStack item) { - return findAEStackFromFilter(monitor, crafting, ItemFilter.fromStack(item)); - } - - public static Pair findAEStackFromFilter(MEStorage monitor, @Nullable ICraftingService crafting, ItemFilter item) { - for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { - if (temp.getKey() instanceof AEItemKey key && item.test(key.toStack())) - return Pair.of(temp.getLongValue(), key); - } - - if (crafting == null) - return Pair.of(0L, AEItemKey.of(ItemStack.EMPTY)); - - for (var temp : crafting.getCraftables(param -> true)) { - if (temp instanceof AEItemKey key && item.test(key.toStack())) - return Pair.of(0L, key); - } - - return Pair.of(0L, AEItemKey.of(ItemStack.EMPTY)); - } - - public static Pair findAEFluidFromStack(MEStorage monitor, @Nullable ICraftingService crafting, FluidStack item) { - return findAEFluidFromFilter(monitor, crafting, FluidFilter.fromStack(item)); - } - - public static Pair findAEFluidFromFilter(MEStorage monitor, @Nullable ICraftingService crafting, FluidFilter item) { - for (Object2LongMap.Entry temp : monitor.getAvailableStacks()) { - if (temp.getKey() instanceof AEFluidKey key && item.test(key.toStack(1))) - return Pair.of(temp.getLongValue(), key); - } - - if (crafting == null) - return null; - - for (var temp : crafting.getCraftables(param -> true)) { - if (temp instanceof AEFluidKey key && item.test(key.toStack(1))) - return Pair.of(0L, key); - } - - return null; - } - - public static List listStacks(MEStorage monitor, ICraftingService service) { - List items = new ArrayList<>(); - KeyCounter keyCounter = monitor.getAvailableStacks(); - for (Object2LongMap.Entry aeKey : keyCounter) { - if (aeKey.getKey() instanceof AEItemKey itemKey) { - items.add(getObjectFromStack(Pair.of(aeKey.getLongValue(), itemKey), service)); - } - } - return items; - } - - public static List listCraftableStacks(MEStorage monitor, ICraftingService service) { - List items = new ArrayList<>(); - KeyCounter keyCounter = monitor.getAvailableStacks(); - Set craftables = service.getCraftables(AEKeyFilter.none()); - for (AEKey aeKey : craftables) { - if (aeKey instanceof AEItemKey) { - items.add(getObjectFromStack(Pair.of(keyCounter.get(aeKey), aeKey), service)); - } - } - return items; - } - - public static List listFluids(MEStorage monitor, ICraftingService service) { - List items = new ArrayList<>(); - for (Object2LongMap.Entry aeKey : monitor.getAvailableStacks()) { - if (aeKey.getKey() instanceof AEFluidKey itemKey) { - items.add(getObjectFromStack(Pair.of(aeKey.getLongValue(), itemKey), service)); - } - } - return items; - } - - public static List listGases(MEStorage monitor, ICraftingService service, int flag) { - List items = new ArrayList<>(); - for (Object2LongMap.Entry aeKey : monitor.getAvailableStacks()) { - if (APAddons.appMekLoaded && aeKey.getKey() instanceof MekanismKey itemKey) { - items.add(getObjectFromStack(Pair.of(aeKey.getLongValue(), itemKey), service)); - } - } - return items; - } - - public static List listCraftableFluids(MEStorage monitor, ICraftingService service) { - List items = new ArrayList<>(); - KeyCounter keyCounter = monitor.getAvailableStacks(); - Set craftables = service.getCraftables(AEKeyFilter.none()); - for (AEKey aeKey : craftables) { - if (aeKey instanceof AEFluidKey) { - items.add(getObjectFromStack(Pair.of(keyCounter.get(aeKey), aeKey), service)); - } - } - return items; - } - - public static Map getObjectFromStack(Pair stack, @Nullable ICraftingService service) { - if (stack.getRight() == null) - return Collections.emptyMap(); - if (stack.getRight() instanceof AEItemKey itemKey) - return getObjectFromItemStack(Pair.of(stack.getLeft(), itemKey), service); - if (stack.getRight() instanceof AEFluidKey fluidKey) - return getObjectFromFluidStack(Pair.of(stack.getLeft(), fluidKey), service); - if (APAddons.appMekLoaded && (stack.getRight() instanceof MekanismKey gasKey)) - return getObjectFromGasStack(Pair.of(stack.getLeft(), gasKey), service); - - AdvancedPeripherals.debug("Could not create table from unknown stack " + stack.getRight().getClass() + " - Report this to the maintainer of ap", Level.ERROR); - return Collections.emptyMap(); - } - - private static Map getObjectFromItemStack(Pair stack, @Nullable ICraftingService craftingService) { - Map map = new HashMap<>(); - String displayName = stack.getRight().getDisplayName().getString(); - CompoundTag nbt = stack.getRight().toTag(); - long amount = stack.getLeft(); - map.put("fingerprint", ItemUtil.getFingerprint(stack.getRight().toStack())); - map.put("name", ItemUtil.getRegistryKey(stack.getRight().getItem()).toString()); - map.put("amount", amount); - map.put("displayName", displayName); - map.put("nbt", NBTUtil.toLua(nbt)); - map.put("tags", LuaConverter.tagsToList(() -> stack.getRight().getItem().builtInRegistryHolder().tags())); - map.put("isCraftable", craftingService != null && craftingService.isCraftable(stack.getRight())); - - return map; - } - - private static Map getObjectFromFluidStack(Pair stack, @Nullable ICraftingService craftingService) { - Map map = new HashMap<>(); - long amount = stack.getLeft(); - map.put("name", ForgeRegistries.FLUIDS.getKey(stack.getRight().getFluid()).toString()); - map.put("amount", amount); - map.put("displayName", stack.getRight().getDisplayName().getString()); - map.put("tags", LuaConverter.tagsToList(() -> stack.getRight().getFluid().builtInRegistryHolder().tags())); - map.put("isCraftable", craftingService != null && craftingService.isCraftable(stack.getRight())); - - return map; - } - - private static Map getObjectFromGasStack(Pair stack, @Nullable ICraftingService craftingService) { - Map map = new HashMap<>(); - long amount = stack.getLeft(); - map.put("name", stack.getRight().getStack().getTypeRegistryName().toString()); - map.put("amount", amount); - map.put("displayName", stack.getRight().getDisplayName().getString()); - map.put("tags", LuaConverter.tagsToList(() -> stack.getRight().getStack().getType().getTags())); - - return map; - } - - public static Map getObjectFromCPU(ICraftingCPU cpu) { - Map map = new HashMap<>(); - long storage = cpu.getAvailableStorage(); - int coProcessors = cpu.getCoProcessors(); - boolean isBusy = cpu.isBusy(); - map.put("storage", storage); - map.put("coProcessors", coProcessors); - map.put("isBusy", isBusy); - map.put("craftingJob", cpu.getJobStatus() != null ? getObjectFromJob(cpu.getJobStatus()) : null); - map.put("name", cpu.getName() != null ? cpu.getName().getString() : "Unnamed"); - map.put("selectionMode", cpu.getSelectionMode().toString()); - - return map; - } - - public static Map getObjectFromJob(CraftingJobStatus job) { - Map map = new HashMap<>(); - map.put("storage", getObjectFromGenericStack(job.crafting())); - map.put("elapsedTimeNanos", job.elapsedTimeNanos()); - map.put("totalItem", job.totalItems()); - map.put("progress", job.progress()); - - return map; - } - - public static Map getObjectFromGenericStack(GenericStack stack) { - if (stack.what() == null) - return Collections.emptyMap(); - if (stack.what() instanceof AEItemKey aeItemKey) - return getObjectFromItemStack(Pair.of(stack.amount(), aeItemKey), null); - if (stack.what() instanceof AEFluidKey aeFluidKey) - return getObjectFromFluidStack(Pair.of(stack.amount(), aeFluidKey), null); - return Collections.emptyMap(); - } - - public static MEStorage getMonitor(IGridNode node) { - return node.getGrid().getService(IStorageService.class).getInventory(); - } - - public static boolean isItemCrafting(MEStorage monitor, ICraftingService grid, ItemFilter filter, - @Nullable ICraftingCPU craftingCPU) { - Pair stack = AppEngApi.findAEStackFromFilter(monitor, grid, filter); - - // If the item stack does not exist, it cannot be crafted. - if (stack == null) - return false; - - // If the passed cpu is null, check all cpus - if (craftingCPU == null) { - // Loop through all crafting cpus and check if the item is being crafted. - for (ICraftingCPU cpu : grid.getCpus()) { - if (cpu.isBusy()) { - CraftingJobStatus jobStatus = cpu.getJobStatus(); - - // avoid null pointer exception - if (jobStatus == null) - continue; - - if (jobStatus.crafting().what().equals(stack.getRight())) - return true; - } - } - } else { - if (craftingCPU.isBusy()) { - CraftingJobStatus jobStatus = craftingCPU.getJobStatus(); - - // avoid null pointer exception - if (jobStatus == null) - return false; - - return jobStatus.crafting().what().equals(stack.getRight()); - } - } - - return false; - } - - public static boolean isFluidCrafting(MEStorage monitor, ICraftingService grid, FluidFilter filter, - @Nullable ICraftingCPU craftingCPU) { - Pair stack = AppEngApi.findAEFluidFromFilter(monitor, grid, filter); - - // If the fluid stack does not exist, it cannot be crafted. - if (stack == null) - return false; - - // If the passed cpu is null, check all cpus - if (craftingCPU == null) { - // Loop through all crafting cpus and check if the fluid is being crafted. - for (ICraftingCPU cpu : grid.getCpus()) { - if (cpu.isBusy()) { - CraftingJobStatus jobStatus = cpu.getJobStatus(); - - // avoid null pointer exception - if (jobStatus == null) - continue; - - if (jobStatus.crafting().what().equals(stack.getRight())) - return true; - } - } - } else { - if (craftingCPU.isBusy()) { - CraftingJobStatus jobStatus = craftingCPU.getJobStatus(); - - // avoid null pointer exception - if (jobStatus == null) - return false; - - return jobStatus.crafting().what().equals(stack.getRight()); - } - } - - return false; - } - - public static long getTotalItemStorage(IGridNode node) { - long total = 0; - - // note: do not query DriveBlockEntity.class specifically here, because it will avoid subclasses, e.g. the ME Extended Drive from ExtendedAE - Iterator iterator = node.getGrid().getNodes().iterator(); - - while (iterator.hasNext()) { - if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) - continue; - - InternalInventory inventory = entity.getInternalInventory(); - - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStackInSlot(i); - - if (stack.isEmpty()) - continue; - - if (stack.getItem() instanceof IBasicCellItem cell) { - if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.items().getClass())) { - total += cell.getBytes(null); - } - } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { - if (disk.getKeyType().toString().equals("ae2:i")) { - total += disk.getBytes(null); - } - } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof SuperStorageCell superStorageCell)) { - total += superStorageCell.getKiloBytes() * 1024; - } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof StorageCell storageCell)) { - if (storageCell.getKeyType() != AEKeyType.items()) - continue; - total += storageCell.getKiloBytes() * 1024; - } - } - } - - iterator = node.getGrid().getMachineNodes(StorageBusPart.class).iterator(); - - while (iterator.hasNext()) { - StorageBusPart bus = (StorageBusPart) iterator.next().getService(IStorageProvider.class); - net.minecraft.world.level.Level level = bus.getLevel(); - BlockPos connectedInventoryPos = bus.getHost().getBlockEntity().getBlockPos().relative(bus.getSide()); - BlockEntity connectedInventoryEntity = level.getBlockEntity(connectedInventoryPos); - if (connectedInventoryEntity == null) - continue; - - LazyOptional itemHandler = connectedInventoryEntity.getCapability(ForgeCapabilities.ITEM_HANDLER); - if (itemHandler.isPresent()) { - IItemHandler handler = itemHandler.orElse(null); - for (int i = 0; i < handler.getSlots(); i++) { - total += handler.getSlotLimit(i); - } - } - } - - return total; - } - - public static long getTotalFluidStorage(IGridNode node) { - long total = 0; - - Iterator iterator = node.getGrid().getNodes().iterator(); - - while (iterator.hasNext()) { - if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) - continue; - - InternalInventory inventory = entity.getInternalInventory(); - - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStackInSlot(i); - - if (stack.isEmpty()) - continue; - - if (stack.getItem() instanceof IBasicCellItem cell) { - if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.fluids().getClass())) { - total += cell.getBytes(null); - } - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell superStorageCell) { - total += superStorageCell.getKiloBytes() * 1024; - } else if (APAddons.aeAdditionsLoaded && (stack.getItem() instanceof StorageCell storageCell)) { - if (storageCell.getKeyType() != AEKeyType.fluids()) - continue; - total += storageCell.getKiloBytes() * 1024; - } - } - } - - iterator = node.getGrid().getMachineNodes(StorageBusPart.class).iterator(); - - while (iterator.hasNext()) { - StorageBusPart bus = (StorageBusPart) iterator.next().getService(IStorageProvider.class); - net.minecraft.world.level.Level level = bus.getLevel(); - BlockPos connectedInventoryPos = bus.getHost().getBlockEntity().getBlockPos().relative(bus.getSide()); - BlockEntity connectedInventoryEntity = level.getBlockEntity(connectedInventoryPos); - if (connectedInventoryEntity == null) - continue; - - LazyOptional fluidHandler = connectedInventoryEntity.getCapability(ForgeCapabilities.FLUID_HANDLER); - if (fluidHandler.isPresent()) { - IFluidHandler handler = fluidHandler.orElse(null); - for (int i = 0; i < handler.getTanks(); i++) { - total += handler.getTankCapacity(i); - } - } - } - - return total; - } - - public static long getUsedItemStorage(IGridNode node) { - long used = 0; - - Iterator iterator = node.getGrid().getNodes().iterator(); - - while (iterator.hasNext()) { - if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) - continue; - - InternalInventory inventory = entity.getInternalInventory(); - - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStackInSlot(i); - - if (stack.isEmpty()) - continue; - - if (stack.getItem() instanceof IBasicCellItem cell) { - int bytesPerType = cell.getBytesPerType(null); - - if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.items().getClass())) { - if (stack.getTag() == null) - continue; - int numOfType = stack.getTag().getLongArray("amts").length; - long numItemsInCell = stack.getTag().getLong("ic"); - - used += ((int) Math.ceil(((double) numItemsInCell) / 8)) + ((long) bytesPerType * numOfType); - } - } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { - if (disk.getKeyType().toString().equals("ae2:i")) { - if (stack.getTag() == null) - continue; - long numBytesInCell = stack.getTag().getLong("ic"); - used += numBytesInCell; - } - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell) { - if (stack.getTag() == null) - continue; - long numItemsInCell = stack.getTag().getLong("ic"); - - used += numItemsInCell; - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof StorageCell storageCell) { - if (storageCell.getKeyType() != AEKeyType.items()) - continue; - if (stack.getTag() == null) - continue; - long numItemsInCell = stack.getTag().getLong("ic"); - - used += numItemsInCell; - } - } - } - - iterator = node.getGrid().getMachineNodes(StorageBusPart.class).iterator(); - - while (iterator.hasNext()) { - StorageBusPart bus = (StorageBusPart) iterator.next().getService(IStorageProvider.class); - KeyCounter keyCounter = bus.getInternalHandler().getAvailableStacks(); - - for (Object2LongMap.Entry aeKey : keyCounter) { - if (aeKey.getKey() instanceof AEItemKey) { - used += aeKey.getLongValue(); - } - } - } - - return used; - } - - public static long getUsedFluidStorage(IGridNode node) { - long used = 0; - - Iterator iterator = node.getGrid().getNodes().iterator(); - - while (iterator.hasNext()) { - if (!(iterator.next().getService(IStorageProvider.class) instanceof DriveBlockEntity entity)) - continue; - - InternalInventory inventory = entity.getInternalInventory(); - - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStackInSlot(i); - - if (stack.getItem() instanceof IBasicCellItem cell) { - int bytesPerType = cell.getBytesPerType(null); - - if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.fluids().getClass())) { - if (stack.getTag() == null) - continue; - int numOfType = stack.getTag().getLongArray("amts").length; - long numBucketsInCell = stack.getTag().getLong("ic") / 1000; - - used += ((int) Math.ceil(((double) numBucketsInCell) / 8)) + ((long) bytesPerType * numOfType); - } - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell) { - if (stack.getTag() == null) - continue; - long numItemsInCell = stack.getTag().getLong("ic"); - - used += numItemsInCell; - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof StorageCell storageCell) { - if (storageCell.getKeyType() != AEKeyType.fluids()) - continue; - if (stack.getTag() == null) - continue; - long numItemsInCell = stack.getTag().getLong("ic"); - - used += numItemsInCell; - } - } - } - - iterator = node.getGrid().getMachineNodes(StorageBusPart.class).iterator(); - - while (iterator.hasNext()) { - StorageBusPart bus = (StorageBusPart) iterator.next().getService(IStorageProvider.class); - KeyCounter keyCounter = bus.getInternalHandler().getAvailableStacks(); - - for (Object2LongMap.Entry aeKey : keyCounter) { - if (aeKey.getKey() instanceof AEFluidKey fluidKey) { - used += aeKey.getLongValue(); - } - } - } - - return used; - } - - public static long getAvailableItemStorage(IGridNode node) { - return getTotalItemStorage(node) - getUsedItemStorage(node); - } - - public static long getAvailableFluidStorage(IGridNode node) { - return getTotalFluidStorage(node) - getUsedFluidStorage(node); - } - - public static List listCells(IGridNode node) { - List items = new ArrayList<>(); - - Iterator iterator = node.getGrid().getNodes().iterator(); - - if (!iterator.hasNext()) return items; - while (iterator.hasNext()) { - IStorageProvider entity = iterator.next().getService(IStorageProvider.class); - if (!(entity instanceof DriveBlockEntity drive)) - continue; - - InternalInventory inventory = drive.getInternalInventory(); - - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStackInSlot(i); - - if (stack.isEmpty()) - continue; - - if (stack.getItem() instanceof IBasicCellItem cell) { - items.add(getObjectFromCell(cell, stack)); - } else if (APAddons.aeThingsLoaded && stack.getItem() instanceof DISKDrive disk) { - items.add(getObjectFromDisk(disk, stack)); - } else if (APAddons.aeAdditionsLoaded && stack.getItem() instanceof SuperStorageCell superStorageCell) { - items.add(getObjectFromSuperCell(superStorageCell, stack)); - } - } - } - - return items; - } - - private static Map getObjectFromCell(IBasicCellItem cell, ItemStack stack) { - Map map = new HashMap<>(); - - map.put("item", ItemUtil.getRegistryKey(stack.getItem()).toString()); - - String cellType = ""; - - if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.items().getClass())) { - cellType = "item"; - } else if (cell.getKeyType().getClass().isAssignableFrom(AEKeyType.fluids().getClass())) { - cellType = "fluid"; - } - - map.put("cellType", cellType); - map.put("bytesPerType", cell.getBytesPerType(null)); - map.put("totalBytes", cell.getBytes(null)); - - return map; - } - - private static Map getObjectFromDisk(DISKDrive drive, ItemStack stack) { - Map map = new HashMap<>(); - - map.put("item", stack.getItem().toString()); - - String cellType = ""; - - if (drive.getKeyType().toString().equals("ae2:i")) { - cellType = "item"; - } else if (drive.getKeyType().toString().equals("ae2:f")) { - cellType = "fluid"; - } - - map.put("cellType", cellType); - map.put("totalBytes", drive.getBytes(null)); - - return map; - } - - private static Map getObjectFromSuperCell(SuperStorageCell cell, ItemStack stack) { - Map map = new HashMap<>(); - - map.put("item", stack.getItem().toString()); - - String cellType = "all"; - - map.put("cellType", cellType); - map.put("totalBytes", cell.getBytes(stack)); - - return map; - } -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/CraftJob.java b/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/CraftJob.java deleted file mode 100644 index 1b2d5d9a9..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/appliedenergistics/CraftJob.java +++ /dev/null @@ -1,135 +0,0 @@ -package de.srendi.advancedperipherals.common.addons.appliedenergistics; - -import appeng.api.networking.IGrid; -import appeng.api.networking.IGridNode; -import appeng.api.networking.crafting.*; -import appeng.api.networking.security.IActionSource; -import appeng.api.stacks.AEKey; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import de.srendi.advancedperipherals.AdvancedPeripherals; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -public class CraftJob implements ILuaCallback { - - public static final String EVENT = "crafting"; - - private final IComputerAccess computer; - private final IGridNode node; - private final IActionSource source; - private final ICraftingSimulationRequester requester; - private final ICraftingCPU target; - private final AEKey item; - - private final long amount; - private final Level world; - private Future futureJob; - private boolean startedCrafting = false; - - private MethodResult result; - private LuaException exception; - - public CraftJob(Level world, final IComputerAccess computer, IGridNode node, AEKey item, long amount, IActionSource source, - ICraftingSimulationRequester requester, ICraftingCPU target) { - this.computer = computer; - this.node = node; - this.world = world; - this.source = source; - this.item = item; - this.amount = amount; - this.requester = requester; - this.target = target; - } - - protected void fireEvent(boolean success, @Nullable String exception) { - this.result = MethodResult.of(success, exception); - this.exception = new LuaException(exception); - this.computer.queueEvent(EVENT, success, exception); - - } - - protected void fireNotConnected() { - fireEvent(false, "not connected"); - } - - public void setStartedCrafting(boolean startedCrafting) { - this.startedCrafting = startedCrafting; - } - - public boolean isCraftingStarted() { - return startedCrafting; - } - - public void startCrafting() { - IGrid grid = node.getGrid(); - if (grid == null) { //true when the block is not connected - fireNotConnected(); - return; - } - - ICraftingService crafting = grid.getService(ICraftingService.class); - - if (item == null) { - AdvancedPeripherals.debug("Could not get AEItem from monitor", org.apache.logging.log4j.Level.FATAL); - return; - } - - if (!crafting.isCraftable(item)) { - fireEvent(false, item.getId().toString() + " is not craftable"); - return; - } - - futureJob = crafting.beginCraftingCalculation(world, this.requester, item, amount, CalculationStrategy.REPORT_MISSING_ITEMS); - fireEvent(true, "Started calculation of the recipe. After it's finished, the system will start crafting the item."); - } - - public void maybeCraft() { - if (startedCrafting || futureJob == null || !futureJob.isDone()) - return; - ICraftingPlan job; - try { - job = futureJob.get(); - } catch (ExecutionException | InterruptedException ex) { - AdvancedPeripherals.debug("Tried to get job, but job calculation is not done. Should be done.", org.apache.logging.log4j.Level.FATAL); - ex.printStackTrace(); - return; - } - - if (job == null) { - AdvancedPeripherals.debug("Job is null, should not be null.", org.apache.logging.log4j.Level.FATAL); - return; - } - - if (job.simulation()) { - return; - } - - IGrid grid = node.getGrid(); - if (grid == null) { - return; - } - - //TODO: Create events or methods like `isCraftingFinished` or `getCraftingJobState` - ICraftingService crafting = grid.getService(ICraftingService.class); - crafting.submitJob(job, null, target, false, this.source); - - setStartedCrafting(true); - - this.futureJob = null; - } - - @NotNull - @Override - public MethodResult resume(Object[] objects) { - if (result != null) return result; - if (exception != null) return MethodResult.of(exception); - return MethodResult.of(); - } -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaFlowerIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaFlowerIntegration.java index a4eb92215..fd45750e4 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaFlowerIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaFlowerIntegration.java @@ -16,7 +16,7 @@ public ManaFlowerIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "manaFlower"; + return "mana_flower"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaPoolIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaPoolIntegration.java index cea44bbe9..2d2fb83c9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaPoolIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/ManaPoolIntegration.java @@ -15,7 +15,7 @@ public ManaPoolIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "manaPool"; + return "mana_pool"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/SpreaderIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/SpreaderIntegration.java index e0ea451f9..d615db44f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/botania/SpreaderIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/botania/SpreaderIntegration.java @@ -16,7 +16,7 @@ public SpreaderIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "manaSpreader"; + return "mana_spreader"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/BeaconIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/BeaconIntegration.java index 09e655726..0a35755df 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/BeaconIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/BeaconIntegration.java @@ -2,7 +2,6 @@ import dan200.computercraft.api.lua.LuaFunction; import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; @@ -20,9 +19,7 @@ public BeaconIntegration(BlockEntity entity) { @LuaFunction(mainThread = true) public final int getLevel() { - // because levels are now protected field .... why? - CompoundTag savedData = blockEntity.saveWithoutMetadata(); - return savedData.getInt("Levels"); + return blockEntity.levels; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/IntegrationPeripheralProvider.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/IntegrationPeripheralProvider.java index f5c2fef95..eaf6cda03 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/IntegrationPeripheralProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/integrations/IntegrationPeripheralProvider.java @@ -3,6 +3,7 @@ import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheralProvider; import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.addons.APAddons; import de.srendi.advancedperipherals.common.util.Platform; import de.srendi.advancedperipherals.lib.integrations.IPeripheralIntegration; import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; @@ -23,7 +24,14 @@ public class IntegrationPeripheralProvider implements IPeripheralProvider { - private static final String[] SUPPORTED_MODS = new String[]{"botania", "create", "mekanism", "powah"}; + private static final String[] SUPPORTED_MODS = new String[]{ + APAddons.BOTANIA_MODID, + APAddons.CREATE_MODID, + APAddons.MEKANISM_MODID, + APAddons.POWAH_MODID, + APAddons.DIMSTORAGE_MODID, + APAddons.VALKYRIEN_SKIES_MODID, + }; private static final PriorityQueue integrations = new PriorityQueue<>(Comparator.comparingInt(IPeripheralIntegration::getPriority)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java index b86b1aa39..5ed3604c4 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java @@ -7,7 +7,8 @@ import java.util.Map; public enum SimpleFreeOperation implements IPeripheralOperation { - CHAT_MESSAGE(100); + CHAT_MESSAGE(1000), + SADDLE_CAPTURE(5000); private final int defaultCooldown; private ForgeConfigSpec.IntValue cooldown; @@ -18,7 +19,7 @@ public enum SimpleFreeOperation implements IPeripheralOperation { @Override public void addToConfig(ForgeConfigSpec.Builder builder) { - cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 1_000, Integer.MAX_VALUE); + cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 100, Integer.MAX_VALUE); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java index 90205db17..980c329b9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java @@ -5,16 +5,20 @@ import java.util.HashMap; import java.util.Map; -import java.util.function.Function; +import java.util.function.UnaryOperator; public enum SingleOperation implements IPeripheralOperation { DIG(1000, 1), USE_ON_BLOCK(5000, 1), + UPDATE_BLOCK(500, 1), SUCK(1000, 1), USE_ON_ANIMAL(2500, 10), CAPTURE_ANIMAL(50_000, 100), WARP(1000, DistancePolicy.IGNORED, CountPolicy.MULTIPLY, 1, DistancePolicy.SQRT, CountPolicy.MULTIPLY), - ACCURE_PLACE(1000, DistancePolicy.IGNORED, CountPolicy.MULTIPLY, 1, DistancePolicy.LINEAR, CountPolicy.MULTIPLY); + ACCURE_PLACE(1000, DistancePolicy.IGNORED, CountPolicy.MULTIPLY, 1, DistancePolicy.LINEAR, CountPolicy.MULTIPLY), + PREPARE_PORTAL(3_000, 600), + ACTIVE_PORTAL(60_000, 1), + MOUNT_SHIP(1000, 1); private final int defaultCooldown; private final DistancePolicy distanceCooldownPolicy; @@ -35,7 +39,7 @@ public enum SingleOperation implements IPeripheralOperation d), SQRT(d -> (int) Math.sqrt(d)); - private final Function factorFunction; + private final UnaryOperator factorFunction; - DistancePolicy(Function factorFunction) { + DistancePolicy(UnaryOperator factorFunction) { this.factorFunction = factorFunction; } @@ -90,11 +94,12 @@ public int getFactor(int distance) { } public enum CountPolicy { + IGNORED(c -> 1), MULTIPLY(c -> c); - private final Function factorFunction; + private final UnaryOperator factorFunction; - CountPolicy(Function factorFunction) { + CountPolicy(UnaryOperator factorFunction) { this.factorFunction = factorFunction; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java index 147b06400..54217cede 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java @@ -9,7 +9,8 @@ public enum SphereOperation implements IPeripheralOperation { SCAN_BLOCKS(2_000, 8, 16, 0.17), - SCAN_ENTITIES(2_000, 8, 16, 0.17); + SCAN_ENTITIES(2_000, 8, 16, 0.17), + SCAN_SHIPS(2_500, 8 * 3, 16 * 10 /* common view distance */, 0.17); private final int defaultCooldown; private final int defaultMaxFreeRadius; @@ -29,7 +30,7 @@ public enum SphereOperation implements IPeripheralOperation, IOwnerAbility> abilities; - public BasePeripheralOwner() { + protected BasePeripheralOwner() { abilities = new HashMap<>(); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/BlockEntityPeripheralOwner.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/BlockEntityPeripheralOwner.java index 2ea0bd6a3..0a593045a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/BlockEntityPeripheralOwner.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/BlockEntityPeripheralOwner.java @@ -1,7 +1,7 @@ package de.srendi.advancedperipherals.common.addons.computercraft.owner; +import dan200.computercraft.api.peripheral.IPeripheral; import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; -import de.srendi.advancedperipherals.common.blocks.blockentities.InventoryManagerEntity; import de.srendi.advancedperipherals.common.util.DataStorageUtil; import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralTileEntity; @@ -11,16 +11,16 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Nameable; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.JigsawBlock; import net.minecraft.world.level.block.entity.BlockEntity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Objects; -import java.util.function.Function; +import org.apache.commons.lang3.NotImplementedException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class BlockEntityPeripheralOwner extends BasePeripheralOwner { @@ -61,7 +61,7 @@ public BlockPos getPos() { @NotNull @Override public Direction getFacing() { - return tileEntity.getBlockState().getValue(JigsawBlock.ORIENTATION).front(); + return getOrientation().front(); } @NotNull @@ -70,11 +70,15 @@ public FrontAndTop getOrientation() { return tileEntity.getBlockState().getValue(BaseBlock.ORIENTATION); } + @Nullable + @Override + public Entity getHoldingEntity() { + return null; + } + @Nullable @Override public Player getOwner() { - if (tileEntity instanceof InventoryManagerEntity inventoryManagerEntity) - return inventoryManagerEntity.getOwnerPlayer(); return null; } @@ -90,8 +94,8 @@ public void markDataStorageDirty() { } @Override - public T1 withPlayer(Function function) { - throw new RuntimeException("Not implemented yet"); + public T1 withPlayer(APFakePlayer.Action function) { + throw new NotImplementedException(); } @Override @@ -102,7 +106,7 @@ public ItemStack getToolInMainHand() { @Override public ItemStack storeItem(ItemStack stored) { // TODO: tricks with capability needed - throw new RuntimeException("Not implemented yet"); + throw new NotImplementedException(); } @Override @@ -124,4 +128,9 @@ public BlockEntityPeripheralOwner attachFuel() { attachAbility(PeripheralOwnerAbility.FUEL, new TileEntityFuelAbility<>(this)); return this; } + + @Override + public U getConnectedPeripheral(Class type) { + throw new NotImplementedException(); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/FuelAbility.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/FuelAbility.java index 07245d648..80ecdefb0 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/FuelAbility.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/FuelAbility.java @@ -14,7 +14,7 @@ public abstract class FuelAbility implements IOwnerA protected @NotNull T owner; - public FuelAbility(@NotNull T owner) { + protected FuelAbility(@NotNull T owner) { this.owner = owner; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/IPeripheralOwner.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/IPeripheralOwner.java index c99e9442b..fc737aa5a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/IPeripheralOwner.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/IPeripheralOwner.java @@ -1,19 +1,26 @@ package de.srendi.advancedperipherals.common.addons.computercraft.owner; +import dan200.computercraft.api.peripheral.IPeripheral; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.addons.valkyrienskies.ValkyrienSkies; import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralOperation; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.OwnableEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import net.minecraft.world.phys.Vec3; import java.util.Collection; -import java.util.function.Function; +import java.util.HashSet; +import java.util.Set; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface IPeripheralOwner { @@ -23,17 +30,47 @@ public interface IPeripheralOwner { @NotNull BlockPos getPos(); + @NotNull + default Vec3 getCenterPos() { + return Vec3.atCenterOf(getPos()); + } + @NotNull Direction getFacing(); @NotNull FrontAndTop getOrientation(); - @Nullable Player getOwner(); + @NotNull + default Vec3 getDirection() { + Vec3 dir = Vec3.atLowerCornerOf(getFacing().getNormal()); + if (!APAddons.vs2Loaded) { + return dir; + } + return ValkyrienSkies.transformToWorldDir(getLevel(), getPos(), dir); + } + + @Nullable Entity getHoldingEntity(); + + @Nullable + default Player getOwner() { + Entity owner = getHoldingEntity(); + Set checked = new HashSet<>(); + while (owner != null && checked.add(owner)) { + if (owner instanceof Player player) { + return (Player) player; + } + if (!(owner instanceof OwnableEntity ownable)) { + break; + } + owner = ownable.getOwner(); + } + return null; + } @NotNull CompoundTag getDataStorage(); void markDataStorageDirty(); - T withPlayer(Function function); + T withPlayer(APFakePlayer.Action function); ItemStack getToolInMainHand(); @@ -64,4 +101,10 @@ default void attachOperation(Collection> operations) { for (IPeripheralOperation operation : operations) operationAbility.registerOperation(operation); } + + T getConnectedPeripheral(Class type); + + default boolean hasConnectedPeripheral(Class type) { + return getConnectedPeripheral(type) != null; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/InventoryManagerOwner.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/InventoryManagerOwner.java new file mode 100644 index 000000000..c9bc48605 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/InventoryManagerOwner.java @@ -0,0 +1,17 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.owner; + +import de.srendi.advancedperipherals.common.blocks.blockentities.InventoryManagerEntity; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.Nullable; + +public class InventoryManagerOwner extends BlockEntityPeripheralOwner { + public InventoryManagerOwner(InventoryManagerEntity tile) { + super(tile); + } + + @Nullable + @Override + public Player getOwner() { + return tileEntity.getOwnerPlayer(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PeripheralOwnerAbility.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PeripheralOwnerAbility.java index 4f5627f5e..fefa8a5be 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PeripheralOwnerAbility.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PeripheralOwnerAbility.java @@ -5,6 +5,6 @@ public class PeripheralOwnerAbility { public static final PeripheralOwnerAbility> FUEL = new PeripheralOwnerAbility<>(); public static final PeripheralOwnerAbility OPERATION = new PeripheralOwnerAbility<>(); - public PeripheralOwnerAbility() { + private PeripheralOwnerAbility() { } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PocketPeripheralOwner.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PocketPeripheralOwner.java index 5cd8e588c..21dc65ae6 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PocketPeripheralOwner.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/PocketPeripheralOwner.java @@ -1,30 +1,35 @@ package de.srendi.advancedperipherals.common.addons.computercraft.owner; +import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.common.util.DataStorageUtil; import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; +import de.srendi.advancedperipherals.lib.peripherals.IBasePeripheral; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; - public class PocketPeripheralOwner extends BasePeripheralOwner { private final IPocketAccess pocket; + private final IPocketUpgrade upgrade; - public PocketPeripheralOwner(IPocketAccess pocket) { + public PocketPeripheralOwner(IPocketAccess pocket, IPocketUpgrade upgrade) { super(); this.pocket = pocket; - if(APConfig.PERIPHERALS_CONFIG.disablePocketFuelConsumption.get()) + this.upgrade = upgrade; + if (APConfig.PERIPHERALS_CONFIG.disablePocketFuelConsumption.get()) { attachAbility(PeripheralOwnerAbility.FUEL, new InfinitePocketFuelAbility(this)); + } } @Nullable @@ -37,48 +42,58 @@ public String getCustomName() { @Override public Level getLevel() { Entity owner = pocket.getEntity(); - if (owner == null) return null; - return owner.getCommandSenderWorld(); + return owner == null ? null : owner.getCommandSenderWorld(); } @NotNull @Override public BlockPos getPos() { Entity owner = pocket.getEntity(); - if (owner == null) return new BlockPos(0, 0, 0); - return owner.blockPosition(); + return owner == null ? BlockPos.ZERO : new BlockPos(owner.getEyePosition()); } @NotNull @Override - public Direction getFacing() { + public Vec3 getCenterPos() { Entity owner = pocket.getEntity(); - if (owner == null) return Direction.NORTH; - return owner.getDirection(); + return owner == null ? Vec3.ZERO : owner.getEyePosition(); } + @NotNull + @Override + public Direction getFacing() { + Vec3 dir = getDirection(); + return Direction.getNearest(dir.x, dir.y, dir.z); + } - /** - * Not used for pockets - */ @NotNull @Override public FrontAndTop getOrientation() { - return FrontAndTop.NORTH_UP; + Entity owner = pocket.getEntity(); + if (owner == null) { + return FrontAndTop.NORTH_UP; + } + Vec3 up = owner.getUpVector(1.0f); + return FrontAndTop.fromFrontAndTop(getFacing(), Direction.getNearest(up.x, up.y, up.z)); } - @Nullable + @NotNull @Override - public Player getOwner() { + public Vec3 getDirection() { Entity owner = pocket.getEntity(); - if (owner instanceof Player player) return player; - return null; + return owner == null ? /* North */ new Vec3(0, 0, -1) : owner.getLookAngle(); + } + + @Nullable + @Override + public Entity getHoldingEntity() { + return pocket.getEntity(); } @NotNull @Override public CompoundTag getDataStorage() { - return DataStorageUtil.getDataStorage(pocket); + return DataStorageUtil.getDataStorage(pocket, upgrade); } @Override @@ -87,8 +102,8 @@ public void markDataStorageDirty() { } @Override - public T withPlayer(Function function) { - throw new RuntimeException("Not implemented yet"); + public T withPlayer(APFakePlayer.Action function) { + throw new NotImplementedException(); } @Override @@ -98,13 +113,12 @@ public ItemStack getToolInMainHand() { @Override public ItemStack storeItem(ItemStack stored) { - // Tricks with inventory needed - throw new RuntimeException("Not implemented yet"); + throw new NotImplementedException(); } @Override public void destroyUpgrade() { - throw new RuntimeException("Not implemented yet"); + throw new NotImplementedException(); } @Override @@ -116,4 +130,18 @@ public boolean isMovementPossible(@NotNull Level level, @NotNull BlockPos pos) { public boolean move(@NotNull Level level, @NotNull BlockPos pos) { return false; } + + @Override + public T getConnectedPeripheral(Class type) { + IPeripheral foundPeripheral = pocket.getUpgrades().values().stream() + .filter(peripheral -> { + if (peripheral == null || type.isInstance(peripheral)) { + return false; + } + return peripheral instanceof IBasePeripheral basePeripheral ? basePeripheral.isEnabled() : true; + }) + .findFirst() + .orElse(null); + return (T) foundPeripheral; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/TurtlePeripheralOwner.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/TurtlePeripheralOwner.java index c2709e02d..e8365fcc7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/TurtlePeripheralOwner.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/owner/TurtlePeripheralOwner.java @@ -2,6 +2,7 @@ import com.mojang.authlib.GameProfile; import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.TurtlePermissions; @@ -9,17 +10,20 @@ import de.srendi.advancedperipherals.common.util.DataStorageUtil; import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; import de.srendi.advancedperipherals.common.util.fakeplayer.FakePlayerProviderTurtle; +import de.srendi.advancedperipherals.lib.peripherals.IBasePeripheral; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraftforge.items.wrapper.InvWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; +import java.util.stream.Stream; public class TurtlePeripheralOwner extends BasePeripheralOwner { public final ITurtleAccess turtle; @@ -61,6 +65,12 @@ public FrontAndTop getOrientation() { return FrontAndTop.fromFrontAndTop(getFacing(), Direction.UP); } + @Nullable + @Override + public Entity getHoldingEntity() { + return null; + } + @Nullable @Override public Player getOwner() { @@ -81,7 +91,7 @@ public void markDataStorageDirty() { } @Override - public T withPlayer(Function function) { + public T withPlayer(APFakePlayer.Action function) { return FakePlayerProviderTurtle.withPlayer(turtle, function); } @@ -92,7 +102,7 @@ public ItemStack getToolInMainHand() { @Override public ItemStack storeItem(ItemStack stored) { - return InventoryUtil.storeItems(stored, turtle.getItemHandler(), turtle.getSelectedSlot()); + return InventoryUtil.storeItems(stored, new InvWrapper(turtle.getInventory()), turtle.getSelectedSlot()); } @Override @@ -131,4 +141,19 @@ public TurtlePeripheralOwner attachFuel(int maxFuelConsumptionLevel) { attachAbility(PeripheralOwnerAbility.FUEL, new TurtleFuelAbility(this, maxFuelConsumptionLevel)); return this; } + + @Override + public T getConnectedPeripheral(Class type) { + IPeripheral foundPeripheral = Stream.of(TurtleSide.values()) + .map(side -> turtle.getPeripheral(side)) + .filter(peripheral -> { + if (peripheral == null || type.isInstance(peripheral)) { + return false; + } + return peripheral instanceof IBasePeripheral basePeripheral ? basePeripheral.isEnabled() : true; + }) + .findFirst() + .orElse(null); + return (T) foundPeripheral; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BaseDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BaseDetectorPeripheral.java new file mode 100644 index 000000000..843c5554f --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BaseDetectorPeripheral.java @@ -0,0 +1,42 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; +import de.srendi.advancedperipherals.common.blocks.base.BaseDetectorEntity; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; + +public abstract class BaseDetectorPeripheral extends BasePeripheral> { + protected BaseDetectorPeripheral(String type, E tileEntity) { + super(type, new BlockEntityPeripheralOwner<>(tileEntity)); + } + + @LuaFunction + public final long getMaxTransferRate() { + return owner.tileEntity.getMaxTransferRate(); + } + + @LuaFunction + public final long getTransferRateLimit() { + return owner.tileEntity.getTransferRateLimit(); + } + + @LuaFunction + public final void setTransferRateLimit(long transferRate) { + owner.tileEntity.setTransferRateLimit(transferRate); + } + + @LuaFunction + public final long getTransferRate() { + return owner.tileEntity.getTransferRate(); + } + + @LuaFunction + public final String getLastTransferedId() { + return owner.tileEntity.getLastTransferedId(); + } + + @LuaFunction + public final String getReadyTransferId() { + return owner.tileEntity.getReadyTransferId(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BlockReaderPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BlockReaderPeripheral.java index 086fa4fe9..ce78b5077 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BlockReaderPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/BlockReaderPeripheral.java @@ -18,7 +18,7 @@ public class BlockReaderPeripheral extends BasePeripheral> { - public static final String PERIPHERAL_TYPE = "blockReader"; + public static final String PERIPHERAL_TYPE = "block_reader"; public BlockReaderPeripheral(BlockReaderEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChatBoxPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChatBoxPeripheral.java index 91f82b2e2..920f64f13 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChatBoxPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChatBoxPeripheral.java @@ -7,6 +7,7 @@ import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import de.srendi.advancedperipherals.AdvancedPeripherals; @@ -17,16 +18,16 @@ import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.common.events.Events; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toclient.ToastToClientPacket; import de.srendi.advancedperipherals.common.util.CoordUtil; import de.srendi.advancedperipherals.common.util.StringUtil; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralFunction; -import de.srendi.advancedperipherals.network.APNetworking; -import de.srendi.advancedperipherals.network.toclient.ToastToClientPacket; import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentContents; -import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; @@ -35,7 +36,6 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.minecraftforge.server.ServerLifecycleHooks; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,12 +44,12 @@ import java.util.UUID; import java.util.function.Predicate; -import static de.srendi.advancedperipherals.common.commands.APCommands.ROOT_SAFE_EXEC_LITERAL; import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SimpleFreeOperation.CHAT_MESSAGE; +import static de.srendi.advancedperipherals.common.commands.APCommands.ROOT_SAFE_EXEC_LITERAL; public class ChatBoxPeripheral extends BasePeripheral { - public static final String PERIPHERAL_TYPE = "chatBox"; + public static final String PERIPHERAL_TYPE = "chat_box"; private long lastConsumedMessage; @@ -67,8 +67,8 @@ public ChatBoxPeripheral(ITurtleAccess turtle, TurtleSide side) { this(new TurtlePeripheralOwner(turtle, side)); } - public ChatBoxPeripheral(IPocketAccess pocket) { - this(new PocketPeripheralOwner(pocket)); + public ChatBoxPeripheral(IPocketAccess pocket, IPocketUpgrade upgrade) { + this(new PocketPeripheralOwner(pocket, upgrade)); } @Override @@ -251,7 +251,7 @@ public final MethodResult sendFormattedMessage(@NotNull IArguments arguments) th if (!APConfig.PERIPHERALS_CONFIG.chatBoxMultiDimensional.get() && player.getLevel().dimension() != dimension) { continue; } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { player.sendSystemMessage(preparedMessage); } } @@ -294,7 +294,7 @@ public final MethodResult sendMessage(@NotNull IArguments arguments) throws LuaE if (!APConfig.PERIPHERALS_CONFIG.chatBoxMultiDimensional.get() && player.getLevel().dimension() != dimension) { continue; } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { player.sendSystemMessage(preparedMessage); } } @@ -341,7 +341,7 @@ public final MethodResult sendFormattedMessageToPlayer(@NotNull IArguments argum return MethodResult.of(false, "NOT_SAME_DIMENSION"); } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { player.sendSystemMessage(preparedMessage); } return MethodResult.of(true); @@ -399,7 +399,7 @@ public final MethodResult sendFormattedToastToPlayer(@NotNull IArguments argumen return MethodResult.of(false, "NOT_SAME_DIMENSION"); } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { ToastToClientPacket packet = new ToastToClientPacket(titleComponent, preparedMessage); APNetworking.sendTo(packet, player); } @@ -438,7 +438,7 @@ public final MethodResult sendMessageToPlayer(@NotNull IArguments arguments) thr return MethodResult.of(false, "NOT_SAME_DIMENSION"); } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { player.sendSystemMessage(preparedMessage, false); } return MethodResult.of(true); @@ -477,7 +477,7 @@ public final MethodResult sendToastToPlayer(@NotNull IArguments arguments) throw return MethodResult.of(false, "NOT_SAME_DIMENSION"); } - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, maxRange)) { + if (CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, maxRange)) { ToastToClientPacket packet = new ToastToClientPacket(Component.literal(title), preparedMessage); APNetworking.sendTo(packet, player); } @@ -485,6 +485,7 @@ public final MethodResult sendToastToPlayer(@NotNull IArguments arguments) throw }); } + @Override public void update() { lastConsumedMessage = Events.traverseChatMessages(lastConsumedMessage, message -> { for (IComputerAccess computer : getConnectedComputers()) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java index 94829b12f..428574bcb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ChunkyPeripheral.java @@ -1,5 +1,6 @@ package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; +import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; @@ -44,6 +45,11 @@ public boolean isEnabled() { return APConfig.PERIPHERALS_CONFIG.enableChunkyTurtle.get(); } + @LuaFunction + public int getRadius() { + return ChunkManager.getMaxLoadRadius(); + } + public void updateChunkState() { // TODO: should find someway to update after turtle moved or while moving, but not every tick ServerLevel level = (ServerLevel) getLevel(); @@ -72,7 +78,7 @@ protected void setLoadedChunk(@Nullable ChunkPos newChunk, ChunkManager manager, } @Override - public void attach(IComputerAccess computer) { + public void attach(@NotNull IComputerAccess computer) { super.attach(computer); ServerLevel level = (ServerLevel) owner.getLevel(); ChunkManager manager = ChunkManager.get(Objects.requireNonNull(level)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ColonyPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ColonyPeripheral.java index 5a689c538..8b5a9a1e9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ColonyPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/ColonyPeripheral.java @@ -18,6 +18,7 @@ import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; @@ -32,12 +33,17 @@ import net.minecraft.resources.ResourceLocation; import net.minecraftforge.fml.ModList; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; public class ColonyPeripheral extends BasePeripheral { - public static final String PERIPHERAL_TYPE = "colonyIntegrator"; + public static final String PERIPHERAL_TYPE = "colony_integrator"; protected boolean hasPermission = true; @@ -45,8 +51,8 @@ public ColonyPeripheral(PeripheralBlockEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); } - public ColonyPeripheral(IPocketAccess access) { - super(PERIPHERAL_TYPE, new PocketPeripheralOwner(access)); + public ColonyPeripheral(IPocketAccess access, IPocketUpgrade upgrade) { + super(PERIPHERAL_TYPE, new PocketPeripheralOwner(access, upgrade)); } @Override @@ -272,7 +278,7 @@ public final Object getRequests() throws LuaException { map.put("state", request.getState().toString()); map.put("count", deliverableRequest.getCount()); map.put("minCount", deliverableRequest.getMinimumCount()); - map.put("items", request.getDisplayStacks().stream().map(LuaConverter::stackToObject).collect(Collectors.toList())); + map.put("items", request.getDisplayStacks().stream().map(LuaConverter::itemStackToObject).collect(Collectors.toList())); map.put("target", request.getRequester().getRequesterDisplayName(requestManager, request).getString()); result.add(map); }); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/DistanceDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/DistanceDetectorPeripheral.java new file mode 100644 index 000000000..8b595fdf8 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/DistanceDetectorPeripheral.java @@ -0,0 +1,332 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.PocketPeripheralOwner; +import de.srendi.advancedperipherals.common.blocks.blockentities.DistanceDetectorEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.util.HitResultUtil; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +public class DistanceDetectorPeripheral extends BasePeripheral { + + public static final String PERIPHERAL_TYPE = "distance_detector"; + + private final AtomicBoolean isDirty = new AtomicBoolean(false); + private final DistanceDetectorEntity tileEntity; + private final AtomicInteger maxRange; + private volatile float currentDistance; + private final AtomicBoolean showLaser; + private volatile boolean calculatePeriodically; + private volatile boolean ignoreTransparent; + private final AtomicReference detectionType; + + public DistanceDetectorPeripheral(DistanceDetectorEntity tileEntity) { + super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); + this.tileEntity = tileEntity; + // TODO: let distance detector block also use data storage + this.maxRange = new AtomicInteger(Float.floatToRawIntBits(this.tileEntity.getMaxRange())); + this.currentDistance = this.tileEntity.getCurrentDistance(); + this.showLaser = new AtomicBoolean(this.tileEntity.getShowLaser()); + this.calculatePeriodically = this.tileEntity.getCalculatePeriodically(); + this.ignoreTransparent = this.tileEntity.getIgnoreTransparent(); + this.detectionType = new AtomicReference<>(this.tileEntity.getDetectionType()); + } + + protected DistanceDetectorPeripheral(IPeripheralOwner owner) { + super(PERIPHERAL_TYPE, owner); + this.tileEntity = null; + CompoundTag data = this.owner.getDataStorage(); + this.maxRange = new AtomicInteger(Float.floatToRawIntBits(data.contains("maxRange") ? data.getFloat("maxRange") : this.getConfiguredMaxRange())); + this.currentDistance = data.contains("currentDistance") ? data.getFloat("currentDistance") : -1; + this.showLaser = new AtomicBoolean(data.contains("showLaser") ? data.getBoolean("showLaser") : true); + this.calculatePeriodically = data.contains("calculatePeriodically") ? data.getBoolean("calculatePeriodically") : false; + this.ignoreTransparent = data.contains("ignoreTransparent") ? data.getBoolean("ignoreTransparent") : true; + this.detectionType = new AtomicReference<>(data.contains("detectionType") ? DetectionType.values()[data.getByte("detectionType")] : DetectionType.BOTH); + } + + public DistanceDetectorPeripheral(IPocketAccess pocket, IPocketUpgrade upgrade) { + this(new PocketPeripheralOwner(pocket, upgrade)); + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableDistanceDetector.get(); + } + + public float getConfiguredMaxRange() { + return APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue(); + } + + public int getUpdateRate() { + return APConfig.PERIPHERALS_CONFIG.distanceDetectorUpdateRate.get(); + } + + public float getMaxRange() { + return Float.intBitsToFloat(this.maxRange.get()); + } + + public void setMaxRange(float maxRange) { + maxRange = Math.min(Math.max(maxRange, 0), this.getConfiguredMaxRange()); + int maxRangeBits = Float.floatToRawIntBits(maxRange); + if (this.maxRange.getAndSet(maxRangeBits) == maxRange) { + return; + } + if (this.tileEntity != null) { + this.tileEntity.setMaxRange(maxRange); + this.tileEntity.sendUpdate(); + } + this.isDirty.set(true); + } + + public float getCurrentDistance() { + return this.currentDistance; + } + + public void setCurrentDistance(float currentDistance) { + this.currentDistance = currentDistance; + if (this.tileEntity != null) { + this.tileEntity.setCurrentDistance(currentDistance); + this.tileEntity.sendUpdate(); + } + this.isDirty.set(true); + } + + public boolean getCalculatePeriodically() { + return this.calculatePeriodically; + } + + public void setCalculatePeriodically(boolean calculatePeriodically) { + this.calculatePeriodically = calculatePeriodically; + if (this.tileEntity != null) { + this.tileEntity.setCalculatePeriodically(calculatePeriodically); + } + this.isDirty.set(true); + } + + public boolean getShowLaser() { + return this.showLaser.get(); + } + + public void setShowLaser(boolean showLaser) { + if (this.showLaser.getAndSet(showLaser) == showLaser) { + return; + } + if (this.tileEntity != null) { + this.tileEntity.setShowLaser(showLaser); + this.tileEntity.sendUpdate(); + } + this.isDirty.set(true); + } + + public boolean getIgnoreTransparent() { + return this.ignoreTransparent; + } + + public void setIgnoreTransparent(boolean ignoreTransparent) { + this.ignoreTransparent = ignoreTransparent; + if (this.tileEntity != null) { + this.tileEntity.setIgnoreTransparent(ignoreTransparent); + } + this.isDirty.set(true); + } + + public DetectionType getDetectionType() { + return this.detectionType.get(); + } + + public void setDetectionType(DetectionType detectionType) { + if (this.detectionType.getAndSet(detectionType) == detectionType) { + return; + } + if (this.tileEntity != null) { + this.tileEntity.setDetectionType(detectionType); + } + this.isDirty.set(true); + } + + @LuaFunction + public final void setLaserVisibility(boolean laser) { + this.setShowLaser(laser); + } + + @LuaFunction + public final boolean getLaserVisibility() { + return this.getShowLaser(); + } + + @LuaFunction(value = "setIgnoreTransparency") + public final void setIgnoreTransparencyLua(boolean enable) { + this.setIgnoreTransparent(enable); + } + + @LuaFunction + public final boolean ignoresTransparency() { + return this.getIgnoreTransparent(); + } + + @LuaFunction + public final void setDetectionMode(IArguments args) throws LuaException { + Object mode = args.get(0); + if (mode == null) { + throw new LuaException("arg #1 must provide a mode name or an index between [0, 2]"); + } + DetectionType detectionType; + if (mode instanceof Number modeInd) { + int index = Math.min(Math.max(modeInd.intValue(), 0), 2); + detectionType = DetectionType.values()[index]; + } else if (mode instanceof String modeStr) { + detectionType = switch (modeStr.toUpperCase()) { + case "BLOCK" -> DetectionType.BLOCK; + case "ENTITY" -> DetectionType.ENTITY; + case "BOTH" -> DetectionType.BOTH; + default -> throw new LuaException("Unknown detection mode '" + mode + "'"); + }; + } else { + throw new LuaException("arg #1 must be a string or a number"); + } + this.setDetectionType(detectionType); + } + + @LuaFunction + public final boolean detectsEntities() { + return this.getDetectionType().detectEntity(); + } + + @LuaFunction + public final boolean detectsBlocks() { + return this.getDetectionType().detectBlock(); + } + + @LuaFunction + public final String getDetectionMode() { + return this.getDetectionType().toString(); + } + + @LuaFunction + public final double getDistance() { + return this.getCurrentDistance(); + } + + @LuaFunction(mainThread = true) + public final double calculateDistance() { + return this.calculateAndUpdateDistance(); + } + + @LuaFunction + public final boolean shouldCalculatePeriodically() { + return this.getCalculatePeriodically(); + } + + @LuaFunction(value = "setCalculatePeriodically") + public final void setCalculatePeriodicallyLua(boolean shouldCalculatePeriodically) { + this.setCalculatePeriodically(shouldCalculatePeriodically); + } + + @LuaFunction(value = "setMaxRange") + public final void setMaxRangeLua(double maxDistance) { + this.setMaxRange((float) maxDistance); + } + + @LuaFunction(value = "getMaxRange") + public final double getMaxRangeLua() { + return this.getMaxRange(); + } + + protected double calculateDistanceImpl() { + final double maxRange = this.getMaxRange(); + Vec3 direction = this.owner.getDirection(); + Vec3 center = this.getPhysicsPos(); + Vec3 from = center; + Vec3 to = from.add(direction.scale(maxRange)); + + HitResult result = this.getHitResult(from, to); + if (result.getType() == HitResult.Type.MISS) { + return -1; + } + double distance = result.getLocation().distanceTo(center); + if (this.tileEntity != null) { + distance -= 0.5; + } + return distance; + } + + /** + * calculateAndUpdateDistance should only invokes from server main thread + */ + public double calculateAndUpdateDistance() { + double distance = this.calculateDistanceImpl(); + this.setCurrentDistance((float) distance); + return distance; + } + + @Override + public void update() { + if (this.getCalculatePeriodically() && this.getLevel().getGameTime() % this.getUpdateRate() == 0) { + // We calculate the distance every 2 ticks, so we do not have to run the getDistance function of the peripheral + // on the main thread which prevents the 1 tick yield time of the function. + // The calculateDistance function is not thread safe, so we have to run it on the main thread. + // It should be okay to run that function every 2 ticks, calculating it does not take too much time. + this.calculateAndUpdateDistance(); + } + + if (this.isDirty.getAndSet(false)) { + if (this.tileEntity == null) { + CompoundTag data = this.owner.getDataStorage(); + data.putFloat("maxRange", this.getMaxRange()); + data.putFloat("currentDistance", this.getCurrentDistance()); + data.putBoolean("showLaser", this.getShowLaser()); + data.putBoolean("calculatePeriodically", this.getCalculatePeriodically()); + data.putBoolean("ignoreTransparent", this.getIgnoreTransparent()); + data.putByte("detectionType", (byte) this.getDetectionType().ordinal()); + } + this.owner.markDataStorageDirty(); + } + } + + protected HitResult getHitResult(Vec3 from, Vec3 to) { + Level level = this.getLevel(); + ClipContext.ShapeGetter shapeGetter = this.ignoreTransparent ? HitResultUtil.IgnoreNoOccludedContext.INSTANCE : ClipContext.Block.COLLIDER; + return switch (this.getDetectionType()) { + case ENTITY -> HitResultUtil.getEntityHitResult(from, to, level, this.owner.getHoldingEntity()); + case BLOCK -> HitResultUtil.getBlockHitResult(from, to, level, shapeGetter, this.getPos()); + case BOTH -> HitResultUtil.getHitResult(from, to, level, shapeGetter, this.owner); + }; + } + + public enum DetectionType { + BLOCK(true, false), + ENTITY(false, true), + BOTH(true, true); + + private final boolean block, entity; + + DetectionType(boolean block, boolean entity) { + this.block = block; + this.entity = entity; + } + + public boolean detectBlock() { + return this.block; + } + + public boolean detectEntity() { + return this.entity; + } + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnergyDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnergyDetectorPeripheral.java index 8b0e016f2..5aff47acd 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnergyDetectorPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnergyDetectorPeripheral.java @@ -1,37 +1,18 @@ package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; -import dan200.computercraft.api.lua.LuaFunction; -import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; import de.srendi.advancedperipherals.common.blocks.blockentities.EnergyDetectorEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; -public class EnergyDetectorPeripheral extends BasePeripheral> { +public class EnergyDetectorPeripheral extends BaseDetectorPeripheral { - public static final String PERIPHERAL_TYPE = "energyDetector"; + public static final String TYPE = "energy_detector"; public EnergyDetectorPeripheral(EnergyDetectorEntity tileEntity) { - super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); + super(TYPE, tileEntity); } @Override public boolean isEnabled() { return APConfig.PERIPHERALS_CONFIG.enableEnergyDetector.get(); } - - @LuaFunction(mainThread = true) - public final int getTransferRateLimit() { - return owner.tileEntity.storageProxy.getMaxTransferRate(); - } - - @LuaFunction(mainThread = true) - public final void setTransferRateLimit(long transferRate) { - transferRate = Math.max(0, Math.min(APConfig.PERIPHERALS_CONFIG.energyDetectorMaxFlow.get(), transferRate)); - owner.tileEntity.storageProxy.setMaxTransferRate((int) transferRate); - } - - @LuaFunction(mainThread = true) - public final int getTransferRate() { - return owner.tileEntity.transferRate; - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnvironmentDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnvironmentDetectorPeripheral.java index f37aa156e..62db06f6a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnvironmentDetectorPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/EnvironmentDetectorPeripheral.java @@ -4,10 +4,11 @@ import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; + import de.srendi.advancedperipherals.common.addons.computercraft.operations.SphereOperationContext; import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; @@ -18,13 +19,12 @@ import de.srendi.advancedperipherals.common.util.LuaConverter; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralPlugin; -import net.minecraft.core.BlockPos; + import net.minecraft.resources.ResourceKey; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LightLayer; @@ -32,28 +32,35 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.SleepingTimeCheckEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.server.ServerLifecycleHooks; -import org.jetbrains.annotations.NotNull; - -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Function; +import org.jetbrains.annotations.NotNull; import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SphereOperation.SCAN_ENTITIES; public class EnvironmentDetectorPeripheral extends BasePeripheral { - public static final String PERIPHERAL_TYPE = "environmentDetector"; - private static final List> PERIPHERAL_PLUGINS = new LinkedList<>(); + public static final String PERIPHERAL_TYPE = "environment_detector"; + private static final List> PERIPHERAL_PLUGINS = new ArrayList<>(); protected EnvironmentDetectorPeripheral(IPeripheralOwner owner) { super(PERIPHERAL_TYPE, owner); owner.attachOperation(SCAN_ENTITIES); - for (Function plugin : PERIPHERAL_PLUGINS) + for (Function plugin : PERIPHERAL_PLUGINS) { addPlugin(plugin.apply(owner)); + } } public EnvironmentDetectorPeripheral(PeripheralBlockEntity tileEntity) { @@ -64,8 +71,8 @@ public EnvironmentDetectorPeripheral(ITurtleAccess turtle, TurtleSide side) { this(new TurtlePeripheralOwner(turtle, side).attachFuel(1)); } - public EnvironmentDetectorPeripheral(IPocketAccess pocket) { - this(new PocketPeripheralOwner(pocket)); + public EnvironmentDetectorPeripheral(IPocketAccess pocket, IPocketUpgrade upgrade) { + this(new PocketPeripheralOwner(pocket, upgrade)); } private static int estimateCost(int radius) { @@ -89,24 +96,24 @@ public boolean isEnabled() { @LuaFunction(mainThread = true) public final String getBiome() { - Optional> biome = getLevel().getBiome(getPos()).unwrapKey(); + Optional> biome = getLevel().getBiome(this.getPhysicsBlockPos()).unwrapKey(); return biome.map(biomeResourceKey -> biomeResourceKey.location().toString()).orElse("unknown"); } @LuaFunction(mainThread = true) public final int getSkyLightLevel() { - return getLevel().getBrightness(LightLayer.SKY, getPos().offset(0, 1, 0)); + return getLevel().getBrightness(LightLayer.SKY, this.getPhysicsBlockPos().offset(0, 1, 0)); } @LuaFunction(mainThread = true) public final int getBlockLightLevel() { - return getLevel().getBrightness(LightLayer.BLOCK, getPos().offset(0, 1, 0)); + return getLevel().getBrightness(LightLayer.BLOCK, this.getPhysicsBlockPos().offset(0, 1, 0)); } @LuaFunction(mainThread = true) public final int getDayLightLevel() { Level level = getLevel(); - int i = level.getBrightness(LightLayer.SKY, getPos().offset(0, 1, 0)) - level.getSkyDarken(); + int i = level.getBrightness(LightLayer.SKY, this.getPhysicsBlockPos().offset(0, 1, 0)) - level.getSkyDarken(); float f = level.getSunAngle(1.0F); if (i > 0) { float f1 = f < (float) Math.PI ? 0.0F : ((float) Math.PI * 2F); @@ -124,7 +131,7 @@ public final long getTime() { @LuaFunction(mainThread = true) public final boolean isSlimeChunk() { - ChunkPos chunkPos = new ChunkPos(getPos()); + ChunkPos chunkPos = new ChunkPos(this.getPhysicsBlockPos()); return WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel) getLevel()).getSeed(), 987234911L).nextInt(10) == 0; } @@ -173,13 +180,10 @@ private Map getCurrentMoonPhase() { case 5 -> moon.put(5, "Waxing crescent"); case 6 -> moon.put(6, "First quarter"); case 7 -> moon.put(7, "Waxing gibbous"); - default -> - //should never happen - moon.put(0, "What is a moon"); + default -> moon.put(0, "What is a moon"); } } else { - //Yay, easter egg - //Returns when the function is not used in the overworld + // aren't we in the overworld? moon.put(0, "Moon.exe not found..."); } return moon; @@ -201,17 +205,15 @@ public final boolean isSunny() { } @LuaFunction(mainThread = true) - public final MethodResult scanEntities(@NotNull IComputerAccess access, @NotNull IArguments arguments) throws LuaException { + public final MethodResult scanEntities(@NotNull IArguments arguments) throws LuaException { int radius = arguments.getInt(0); + boolean detailed = arguments.count() > 1 ? arguments.getBoolean(1) : false; return withOperation(SCAN_ENTITIES, new SphereOperationContext(radius), context -> { - if (radius > SCAN_ENTITIES.getMaxCostRadius()) - return MethodResult.of(null, "Radius exceeds max value"); - return null; + return context.getRadius() > SCAN_ENTITIES.getMaxCostRadius() ? MethodResult.of(null, "Radius exceeds max value") : null; }, context -> { - BlockPos pos = owner.getPos(); - AABB box = new AABB(pos); - List> entities = new ArrayList<>(); - getLevel().getEntities((Entity) null, box.inflate(radius), LivingEntity.class::isInstance).forEach(entity -> entities.add(LuaConverter.completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos))); + Vec3 pos = this.getPhysicsPos(); + AABB box = new AABB(pos, pos); + List> entities = getLevel().getEntities((Entity) null, box.inflate(context.getRadius() + 0.5), entity -> entity instanceof LivingEntity && entity.isAlive()).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, pos, detailed)).toList(); return MethodResult.of(entities); }, null); } @@ -232,10 +234,10 @@ public final MethodResult canSleepHere() { @LuaFunction(mainThread = true) public final MethodResult canSleepPlayer(String playername) { Player player = ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayerByName(playername); - if(player == null) + if (player == null) return MethodResult.of(false, "player_not_online"); - if(!player.level.dimensionType().bedWorks()) + if (!player.level.dimensionType().bedWorks()) return MethodResult.of(false, "not_allowed_in_dimension"); SleepingTimeCheckEvent evt = new SleepingTimeCheckEvent(player, Optional.empty()); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/FluidDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/FluidDetectorPeripheral.java new file mode 100644 index 000000000..60cd76182 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/FluidDetectorPeripheral.java @@ -0,0 +1,18 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import de.srendi.advancedperipherals.common.blocks.blockentities.FluidDetectorEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; + +public class FluidDetectorPeripheral extends BaseDetectorPeripheral { + + public static final String TYPE = "fluid_detector"; + + public FluidDetectorPeripheral(FluidDetectorEntity tileEntity) { + super(TYPE, tileEntity); + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableFluidDetector.get(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GasDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GasDetectorPeripheral.java new file mode 100644 index 000000000..c5a293179 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GasDetectorPeripheral.java @@ -0,0 +1,18 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import de.srendi.advancedperipherals.common.blocks.blockentities.GasDetectorEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; + +public class GasDetectorPeripheral extends BaseDetectorPeripheral { + + public static final String TYPE = "gas_detector"; + + public GasDetectorPeripheral(GasDetectorEntity tileEntity) { + super(TYPE, tileEntity); + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableGasDetector.get(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GeoScannerPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GeoScannerPeripheral.java index 438815585..6a9ccacb8 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GeoScannerPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/GeoScannerPeripheral.java @@ -5,6 +5,7 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SphereOperationContext; @@ -24,6 +25,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.Tags; import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.NotNull; @@ -41,7 +43,7 @@ public class GeoScannerPeripheral extends BasePeripheral { Highly inspired by https://github.com/SquidDev-CC/plethora/ BlockScanner */ - public static final String PERIPHERAL_TYPE = "geoScanner"; + public static final String PERIPHERAL_TYPE = "geo_scanner"; protected GeoScannerPeripheral(IPeripheralOwner owner) { super(PERIPHERAL_TYPE, owner); @@ -56,17 +58,16 @@ public GeoScannerPeripheral(ITurtleAccess turtle, TurtleSide side) { this(new TurtlePeripheralOwner(turtle, side).attachFuel(1)); } - public GeoScannerPeripheral(IPocketAccess pocket) { - this(new PocketPeripheralOwner(pocket)); + public GeoScannerPeripheral(IPocketAccess pocket, IPocketUpgrade upgrade) { + this(new PocketPeripheralOwner(pocket, upgrade)); } - private static List> scan(Level level, BlockPos center, int radius) { - List> result = new ArrayList<>(); + private static List> scan(List> result, Level level, Vec3 center, int radius) { ScanUtils.relativeTraverseBlocks(level, center, radius, (state, pos) -> { HashMap data = new HashMap<>(6); - data.put("x", pos.getX()); - data.put("y", pos.getY()); - data.put("z", pos.getZ()); + data.put("x", pos.x); + data.put("y", pos.y); + data.put("z", pos.z); Block block = state.getBlock(); ResourceLocation name = ForgeRegistries.BLOCKS.getKey(block); @@ -103,7 +104,7 @@ public final MethodResult cost(int radius) { public final MethodResult chunkAnalyze() throws LuaException { return withOperation(SCAN_BLOCKS, SCAN_BLOCKS.free(), null, ignored -> { Level level = getLevel(); - LevelChunk chunk = level.getChunkAt(getPos()); + LevelChunk chunk = level.getChunkAt(getPhysicsBlockPos()); ChunkPos chunkPos = chunk.getPos(); HashMap data = new HashMap<>(); for (int x = chunkPos.getMinBlockX(); x <= chunkPos.getMaxBlockX(); x++) { @@ -131,6 +132,18 @@ public final MethodResult scan(@NotNull IArguments arguments) throws LuaExceptio return MethodResult.of(null, "Radius is exceed max value"); } return null; - }, context -> MethodResult.of(scan(getLevel(), getPos(), context.getRadius())), null); + }, context -> { + List> result = new ArrayList<>(); + scan(result, getLevel(), getCenterPos(), context.getRadius()); + if (isOnShip()) { + int i = result.size(); + scan(result, getLevel(), getPhysicsPos(), context.getRadius()); + for (; i < result.size(); i++) { + Map data = result.get(i); + data.put("notOnShip", true); + } + } + return MethodResult.of(result); + }, null); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/InventoryManagerPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/InventoryManagerPeripheral.java index 1a8002bd0..72fda1b7f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/InventoryManagerPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/InventoryManagerPeripheral.java @@ -4,7 +4,7 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.InventoryManagerOwner; import de.srendi.advancedperipherals.common.blocks.blockentities.InventoryManagerEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.common.util.LuaConverter; @@ -29,12 +29,12 @@ import java.util.List; import java.util.Map; -public class InventoryManagerPeripheral extends BasePeripheral> { +public class InventoryManagerPeripheral extends BasePeripheral { - public static final String PERIPHERAL_TYPE = "inventoryManager"; + public static final String PERIPHERAL_TYPE = "inventory_manager"; public InventoryManagerPeripheral(InventoryManagerEntity tileEntity) { - super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); + super(PERIPHERAL_TYPE, new InventoryManagerOwner(tileEntity)); } @Override @@ -103,13 +103,13 @@ private MethodResult removeItemCommon(String invDirection, ItemFilter filter) th @LuaFunction(value = {"list", "getItems"}, mainThread = true) public final List getItems() throws LuaException { List items = new ArrayList<>(); - int i = 0; //Used to let users easily sort the items by the slots. Also, a better way for the user to see where an item actually is - for (ItemStack stack : getOwnerPlayer().getInventory().items) { - ItemStack copiedStack = stack.copy(); - if (!copiedStack.isEmpty()) - items.add(LuaConverter.stackToObjectWithSlot(copiedStack, i)); - - i++; + List stacks = getOwnerPlayer().getInventory().items; + // Used to let users easily sort the items by the slots. Also, a better way for the user to see where an item actually is + for (int slot = 0; slot < stacks.size(); slot++) { + ItemStack stack = stacks.get(slot); + if (!stack.isEmpty()) { + items.add(LuaConverter.stackToObjectWithSlot(stack, slot)); + } } return items; } @@ -127,7 +127,7 @@ public final MethodResult getItemsChest(String target) throws LuaException { List items = new ArrayList<>(); for (int slot = 0; slot < inventoryTo.getSlots(); slot++) { if (!inventoryTo.getStackInSlot(slot).isEmpty()) { - items.add(LuaConverter.stackToObjectWithSlot(inventoryTo.getStackInSlot(slot).copy(), slot)); + items.add(LuaConverter.stackToObjectWithSlot(inventoryTo.getStackInSlot(slot), slot)); } } return MethodResult.of(items); @@ -137,9 +137,8 @@ public final MethodResult getItemsChest(String target) throws LuaException { public final List getArmor() throws LuaException { List items = new ArrayList<>(); for (ItemStack stack : getOwnerPlayer().getInventory().armor) { - ItemStack copiedStack = stack.copy(); - if (!copiedStack.isEmpty()) { - items.add(LuaConverter.stackToObjectWithSlot(copiedStack, ArmorSlot.getSlotForItem(copiedStack))); + if (!stack.isEmpty()) { + items.add(LuaConverter.stackToObjectWithSlot(stack, ArmorSlot.getSlotForItem(stack))); } } return items; @@ -157,24 +156,18 @@ public final boolean isPlayerEquipped() throws LuaException { @LuaFunction(mainThread = true) public final boolean isWearing(int index) throws LuaException { - int i = 0; - for (ItemStack stack : getOwnerPlayer().getInventory().armor) { - if (!stack.isEmpty()) { - if (index == i - 100) return true; - i++; - } - } - return false; + List armor = getOwnerPlayer().getInventory().armor; + return 0 <= index && index < armor.size() && !armor.get(index).isEmpty(); } @LuaFunction(mainThread = true) public final int getEmptySpace() throws LuaException { - int i = 0; + int count = 0; for (ItemStack stack : getOwnerPlayer().getInventory().items) { if (stack.isEmpty()) - i++; + count++; } - return i; + return count; } @LuaFunction(mainThread = true) @@ -187,14 +180,19 @@ public final int getFreeSlot() throws LuaException { return getOwnerPlayer().getInventory().getFreeSlot(); } + @LuaFunction(mainThread = true) + public final int getHandSlot() throws LuaException { + return getOwnerPlayer().getInventory().selected; + } + @LuaFunction(mainThread = true) public final Map getItemInHand() throws LuaException { - return LuaConverter.stackToObject(getOwnerPlayer().getMainHandItem().copy()); + return LuaConverter.itemStackToObject(getOwnerPlayer().getMainHandItem(), getOwnerPlayer().getInventory().selected); } @LuaFunction(mainThread = true) public final Map getItemInOffHand() throws LuaException { - return LuaConverter.stackToObject(getOwnerPlayer().getOffhandItem().copy()); + return LuaConverter.itemStackToObject(getOwnerPlayer().getOffhandItem()); } private Player getOwnerPlayer() throws LuaException { diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java new file mode 100644 index 000000000..17f9541b0 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MEBridgePeripheral.java @@ -0,0 +1,819 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import appeng.api.crafting.IPatternDetails; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IManagedGridNode; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingService; +import appeng.api.stacks.AEFluidKey; +import appeng.api.stacks.AEItemKey; +import appeng.api.storage.MEStorage; +import appeng.me.cluster.implementations.CraftingCPUCluster; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.lua.ObjectLuaTable; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.core.apis.TableHelper; +import dan200.computercraft.core.computer.ComputerSide; +import de.srendi.advancedperipherals.common.addons.ae2.AEApi; +import de.srendi.advancedperipherals.common.addons.ae2.AECraftJob; +import de.srendi.advancedperipherals.common.addons.ae2.MEFluidHandler; +import de.srendi.advancedperipherals.common.addons.ae2.MEItemHandler; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; +import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.ServerWorker; +import de.srendi.advancedperipherals.common.util.StatusConstants; +import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; +import de.srendi.advancedperipherals.common.util.inventory.FluidUtil; +import de.srendi.advancedperipherals.common.util.inventory.GenericFilter; +import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemPeripheral; +import de.srendi.advancedperipherals.common.util.inventory.InventoryUtil; +import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.core.Direction; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +public class MEBridgePeripheral extends BasePeripheral> implements IStorageSystemPeripheral { + + public static final String PERIPHERAL_TYPE = "me_bridge"; + + private final MeBridgeEntity bridge; + private final ICapabilityProvider capabilityWrapper = new CapabilityWrapper(this); + private IGridNode node; + + public MEBridgePeripheral(MeBridgeEntity tileEntity) { + super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); + this.bridge = tileEntity; + this.node = tileEntity.getActionableNode(); + } + + public void setNode(IManagedGridNode node) { + this.node = node.getNode(); + } + + @Override + public Object getTarget() { + return capabilityWrapper; + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableMEBridge.get(); + } + + private ICraftingService getCraftingService() { + return node.getGrid().getCraftingService(); + } + + protected MEItemHandler getItemHandler() { + return new MEItemHandler(AEApi.getMonitor(node), bridge); + } + + protected MEFluidHandler getFluidHandler() { + return new MEFluidHandler(AEApi.getMonitor(node), bridge); + } + + /** + * exports an item out of the system to a valid inventory + * + * @param arguments the arguments given by the computer + * @param targetInventory the give inventory + * @return the exportable amount or null with a string if something went wrong + */ + protected MethodResult exportToChest(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { + MEItemHandler itemHandler = getItemHandler(); + Pair filter = ItemFilter.parse(arguments.getTable(0)); + + if (filter.rightPresent()) + return MethodResult.of(0, filter.getRight()); + + if (targetInventory == null) + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND.toString()); + + return MethodResult.of(InventoryUtil.moveItem(itemHandler, targetInventory, filter.getLeft()), null); + } + + /** + * exports a fluid out of the system to a valid tank + * + * @param arguments the arguments given by the computer + * @param targetTank the give tank + * @return the exportable amount or null with a string if something went wrong + */ + protected MethodResult exportToTank(@NotNull IArguments arguments, @Nullable IFluidHandler targetTank) throws LuaException { + MEFluidHandler fluidHandler = getFluidHandler(); + Pair filter = FluidFilter.parse(arguments.getTable(0)); + + if (filter.rightPresent()) + return MethodResult.of(0, filter.getRight()); + + if (targetTank == null) + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND.toString()); + + return MethodResult.of(InventoryUtil.moveFluid(fluidHandler, targetTank, filter.getLeft()), null); + } + + /** + * imports an item to the system from a valid inventory + * + * @param arguments the arguments given by the computer + * @param targetInventory the give inventory + * @return the imported amount or null with a string if something went wrong + */ + protected MethodResult importToME(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { + MEItemHandler itemHandler = getItemHandler(); + Pair filter = ItemFilter.parse(arguments.getTable(0)); + + if (filter.rightPresent()) + return MethodResult.of(0, filter.getRight()); + + if (targetInventory == null) + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND.toString()); + + return MethodResult.of(InventoryUtil.moveItem(targetInventory, itemHandler, filter.getLeft()), null); + } + + /** + * imports a fluid to the system from a valid tank + * + * @param arguments the arguments given by the computer + * @param targetTank the give tank + * @return the imported amount or null with a string if something went wrong + */ + protected MethodResult importToME(@NotNull IArguments arguments, @Nullable IFluidHandler targetTank) throws LuaException { + MEFluidHandler fluidHandler = getFluidHandler(); + Pair filter = FluidFilter.parse(arguments.getTable(0)); + + if (filter.rightPresent()) + return MethodResult.of(0, filter.getRight()); + + if (targetTank == null) + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND.toString()); + + return MethodResult.of(InventoryUtil.moveFluid(targetTank, fluidHandler, filter.getLeft()), null); + } + + private MethodResult notConnected(@Nullable Object defaultValue) { + return MethodResult.of(defaultValue, StatusConstants.NOT_CONNECTED.toString()); + } + + private boolean isAvailable() { + return node.getGrid() != null && node.hasGridBooted(); + } + + @Override + @LuaFunction(mainThread = true) + public final boolean isConnected() { + return isAvailable(); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult isOnline() { + return MethodResult.of(node.isOnline()); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getItem(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + MEStorage monitor = AEApi.getMonitor(node); + Pair filter = ItemFilter.parse(arguments.getTable(0)); + if (filter.rightPresent()) + return MethodResult.of(null, filter.getRight()); + + ItemFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(null, StatusConstants.EMPTY_FILTER.toString()); + + return MethodResult.of(AEApi.parseAeStack(AEApi.findAEStackFromFilter(monitor, getCraftingService(), parsedFilter), getCraftingService())); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getFluid(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + Pair filter = FluidFilter.parse(arguments.getTable(0)); + if (filter.rightPresent()) + return MethodResult.of(null, filter.getRight()); + + FluidFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(null, StatusConstants.EMPTY_FILTER.toString()); + + return MethodResult.of(AEApi.parseAeStack(AEApi.findAEFluidFromFilter(AEApi.getMonitor(node), getCraftingService(), parsedFilter), getCraftingService())); + } + + @Override + public MethodResult getChemical(IArguments arguments) throws LuaException { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getItems(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listStacks(AEApi.getMonitor(node), getCraftingService())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getFluids(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listFluids(AEApi.getMonitor(node), getCraftingService())); + } + + @Override + public MethodResult getChemicals(IArguments arguments) { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getCraftableItems(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listCraftableStacks(AEApi.getMonitor(node), getCraftingService())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getCraftableFluids(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listCraftableFluids(AEApi.getMonitor(node), getCraftingService())); + } + + @Override + public MethodResult getCraftableChemicals(IArguments arguments) { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getCells() { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listCells(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getDrives() { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(AEApi.listDrives(node.getGrid())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult importItem(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + String side = arguments.getString(1); + IItemHandler inventory; + + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); + } + + return importToME(arguments, inventory); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult exportItem(IComputerAccess computer, @NotNull IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + String side = arguments.getString(1); + IItemHandler inventory; + + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); + } + + return exportToChest(arguments, inventory); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getPatterns(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + // Expected input is a table with either an input table, an output table or both to filter for both + Map filterTable; + + Optional> optionalTable = arguments.optTable(0); + if (optionalTable.isEmpty()) + return MethodResult.of(AEApi.listPatterns(node.getGrid(), getLevel())); + + filterTable = optionalTable.get(); + + boolean hasInputFilter = filterTable.containsKey("input"); + boolean hasOutputFilter = filterTable.containsKey("output"); + boolean hasAnyFilter = hasInputFilter || hasOutputFilter; + + // If the player tries to filter for nothing, return nothing. + if (!hasAnyFilter) + return MethodResult.of(null, StatusConstants.MISSING_FILTER.toString()); + + GenericFilter inputFilter = null; + GenericFilter outputFilter = null; + + if (hasInputFilter) { + Map inputFilterTable = TableHelper.getTableField(filterTable, "input"); + + inputFilter = GenericFilter.parseGeneric(inputFilterTable).getLeft(); + } + if (hasOutputFilter) { + Map outputFilterTable = TableHelper.getTableField(filterTable, "output"); + + outputFilter = GenericFilter.parseGeneric(outputFilterTable).getLeft(); + } + + Pair pattern = AEApi.findPatternFromFilters(node.getGrid(), getLevel(), inputFilter, outputFilter); + + if (pattern.getRight() != null) + return MethodResult.of(null, pattern.getRight()); + + return MethodResult.of(AEApi.parsePattern(pattern.getLeft())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getStoredEnergy() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(node.getGrid().getEnergyService().getStoredPower()); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getEnergyCapacity() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(node.getGrid().getEnergyService().getMaxStoredPower()); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getEnergyUsage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(node.getGrid().getEnergyService().getAvgPowerUsage()); + } + + @LuaFunction(mainThread = true) + public final MethodResult getAverageEnergyInput() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(node.getGrid().getEnergyService().getAvgPowerInjection()); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getTotalExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalExternalItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getTotalExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalExternalFluidStorage(node)); + } + + @LuaFunction(mainThread = true) + public MethodResult getTotalExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalExternalChemicalStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getTotalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getTotalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalFluidStorage(node)); + } + + @LuaFunction(mainThread = true) + public MethodResult getTotalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getTotalChemicalStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getUsedExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedExternalItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getUsedExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedExternalFluidStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getUsedExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedExternalChemicalStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedFluidStorage(node)); + } + + @LuaFunction(mainThread = true) + public MethodResult getUsedChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getUsedChemicalStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getAvailableExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableExternalItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getAvailableExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableExternalFluidStorage(node)); + } + + @LuaFunction(mainThread = true) + public MethodResult getAvailableExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableExternalChemicalStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableItemStorage(node)); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableFluidStorage(node)); + } + + @LuaFunction(mainThread = true) + public MethodResult getAvailableChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(AEApi.getAvailableChemicalStorage(node)); + } + + @Override + @LuaFunction + public final MethodResult craftItem(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + Pair filter = ItemFilter.parse(arguments.getTable(0)); + if (filter.rightPresent()) + return MethodResult.of(null, filter.getRight()); + + ItemFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(null, StatusConstants.EMPTY_FILTER.toString()); + + String cpuName = arguments.optString(1, ""); + + return new CraftJobCallback(computer, () -> { + ICraftingCPU target = AEApi.getCraftingCPU(node, cpuName); + if (!cpuName.isEmpty() && target == null) { + return MethodResult.of(null, StatusConstants.CPU_NOT_FOUND.withInfo(cpuName)); + } + + ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); + Pair stack = AEApi.findAEStackFromFilter(AEApi.getMonitor(bridge.getGridNode()), craftingGrid, parsedFilter); + if (stack.getRight() == null && stack.getLeft() == 0) { + return MethodResult.of(null, StatusConstants.NOT_CRAFTABLE.toString()); + } + + AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), bridge, target); + bridge.addJob(job); + return MethodResult.of(job.withCPU(target)); + }).pull; + } + + @Override + @LuaFunction + public final MethodResult craftFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + Pair filter = FluidFilter.parse(arguments.getTable(0)); + if (filter.rightPresent()) + return MethodResult.of(false, filter.getRight()); + + FluidFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(false, StatusConstants.EMPTY_FILTER.toString()); + + String cpuName = arguments.optString(1, ""); + return new CraftJobCallback(computer, () -> { + ICraftingCPU target = AEApi.getCraftingCPU(node, cpuName); + if (!cpuName.isEmpty() && target == null) + return MethodResult.of(null, StatusConstants.CPU_NOT_FOUND.withInfo(cpuName)); + + ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); + Pair stack = AEApi.findAEFluidFromFilter(AEApi.getMonitor(bridge.getGridNode()), craftingGrid, parsedFilter); + if (stack.getRight() == null && stack.getLeft() == 0) + return MethodResult.of(false, StatusConstants.NOT_CRAFTABLE.toString()); + + AECraftJob job = new AECraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), bridge, target); + bridge.addJob(job); + return MethodResult.of(job.withCPU(target)); + }).pull; + } + + @Override + public MethodResult craftChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getCraftingTasks() { + if (!isAvailable()) + return notConnected(null); + + ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); + + List jobs = new ArrayList<>(); + + for (AECraftJob job : bridge.getJobs()) { + for (ICraftingCPU cpu : craftingGrid.getCpus()) { + if (cpu.isBusy() && job.getToCraft().matches(cpu.getJobStatus().crafting())) + jobs.add(AEApi.parseCraftingJob(cpu.getJobStatus(), job, cpu)); + } + } + return MethodResult.of(jobs); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getCraftingTask(int id) { + if (!isAvailable()) + return notConnected(null); + + AECraftJob foundJob = null; + + for (AECraftJob job : bridge.getJobs()) { + if (job.getId() == id) { + foundJob = job; + } + } + return MethodResult.of(foundJob); + } + + + @Override + @LuaFunction(mainThread = true) + public MethodResult cancelCraftingTasks(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); + + Pair, String> filter = GenericFilter.parseGeneric(arguments.getTable(0)); + if (filter.getRight() != null) + return MethodResult.of(0, filter.getRight()); + + GenericFilter parsedFilter = filter.getLeft(); + + int jobsCanceled = 0; + for (ICraftingCPU cpu : craftingGrid.getCpus()) { + if (cpu.getJobStatus() != null && parsedFilter.testAE(cpu.getJobStatus().crafting())) { + if (cpu instanceof CraftingCPUCluster cpuCluster) { + cpuCluster.cancel(); + jobsCanceled++; + } + } + } + return MethodResult.of(jobsCanceled); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult isCraftable(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(false); + + Pair, String> filter = GenericFilter.parseGeneric(new ObjectLuaTable(arguments.getTable(0))); + if (filter.getRight() != null) + return MethodResult.of(false, filter.getRight()); + + GenericFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(false, StatusConstants.EMPTY_FILTER.toString()); + + return MethodResult.of(AEApi.findPatternFromFilters(node.getGrid(), getLevel(), null, parsedFilter).getLeft() != null); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult exportFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + String side = arguments.getString(1); + IFluidHandler fluidHandler; + + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + fluidHandler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + fluidHandler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); + } + + return exportToTank(arguments, fluidHandler); + } + + @Override + public MethodResult importChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; + } + + @Override + public MethodResult exportChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult importFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + String side = arguments.getString(1); + IFluidHandler fluidHandler; + + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + fluidHandler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + fluidHandler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); + } + + return importToME(arguments, fluidHandler); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult isCrafting(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(false); + + ICraftingService grid = node.getGrid().getService(ICraftingService.class); + + Pair, String> filter = GenericFilter.parseGeneric(new ObjectLuaTable(arguments.getTable(0))); + if (filter.getRight() != null) + return MethodResult.of(false, filter.getRight()); + + GenericFilter parsedFilter = filter.getLeft(); + if (parsedFilter.isEmpty()) + return MethodResult.of(false, StatusConstants.EMPTY_FILTER.toString()); + + String cpuName = arguments.optString(1, ""); + ICraftingCPU craftingCPU = AEApi.getCraftingCPU(node, cpuName); + + return MethodResult.of(AEApi.isCrafting(grid, parsedFilter, craftingCPU)); + } + + @LuaFunction(mainThread = true) + public final MethodResult getCraftingCPUs() { + if (!isAvailable()) + return notConnected(null); + + ICraftingService grid = node.getGrid().getService(ICraftingService.class); + List map = new ArrayList<>(); + + for (ICraftingCPU iCraftingCPU : grid.getCpus()) { + Object cpu = AEApi.parseCraftingCPU(iCraftingCPU, false); + map.add(cpu); + } + return MethodResult.of(map); + } + + private static final class CapabilityWrapper implements ICapabilityProvider { + private final MEBridgePeripheral peripheral; + + private CapabilityWrapper(MEBridgePeripheral peripheral) { + this.peripheral = peripheral; + } + + @Override + public LazyOptional getCapability(final Capability cap, final Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) { + return LazyOptional.of(this.peripheral::getItemHandler).cast(); + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + return LazyOptional.of(this.peripheral::getFluidHandler).cast(); + } + return LazyOptional.empty(); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MeBridgePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MeBridgePeripheral.java deleted file mode 100644 index 216e27702..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/MeBridgePeripheral.java +++ /dev/null @@ -1,558 +0,0 @@ -package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; - -import appeng.api.networking.IGridNode; -import appeng.api.networking.IManagedGridNode; -import appeng.api.networking.crafting.ICraftingCPU; -import appeng.api.networking.crafting.ICraftingService; -import appeng.api.stacks.AEFluidKey; -import appeng.api.stacks.AEItemKey; -import appeng.api.storage.MEStorage; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.AppEngApi; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.CraftJob; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.MeFluidHandler; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.MeItemHandler; -import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; -import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity; -import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.util.Pair; -import de.srendi.advancedperipherals.common.util.ServerWorker; -import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; -import de.srendi.advancedperipherals.common.util.inventory.FluidUtil; -import de.srendi.advancedperipherals.common.util.inventory.InventoryUtil; -import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; -import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandler; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public class MeBridgePeripheral extends BasePeripheral> { - - public static final String PERIPHERAL_TYPE = "meBridge"; - private final MeBridgeEntity tile; - private IGridNode node; - - public MeBridgePeripheral(MeBridgeEntity tileEntity) { - super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); - this.tile = tileEntity; - this.node = tileEntity.getActionableNode(); - } - - public void setNode(IManagedGridNode node) { - this.node = node.getNode(); - } - - @Override - public boolean isEnabled() { - return APConfig.PERIPHERALS_CONFIG.enableMEBridge.get(); - } - - private ICraftingService getCraftingService() { - return node.getGrid().getCraftingService(); - } - - /** - * exports an item out of the system to a valid inventory - * - * @param arguments the arguments given by the computer - * @param targetInventory the give inventory - * @return the exportable amount or null with a string if something went wrong - */ - protected MethodResult exportToChest(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { - MEStorage monitor = AppEngApi.getMonitor(node); - MeItemHandler itemHandler = new MeItemHandler(monitor, tile); - Pair filter = ItemFilter.parse(arguments.getTable(0)); - - if (filter.rightPresent()) - return MethodResult.of(0, filter.getRight()); - - if (targetInventory == null) - return MethodResult.of(0, "Target Inventory does not exist"); - - return MethodResult.of(InventoryUtil.moveItem(itemHandler, targetInventory, filter.getLeft()), null); - } - - /** - * exports a fluid out of the system to a valid tank - * - * @param arguments the arguments given by the computer - * @param targetTank the give tank - * @return the exportable amount or null with a string if something went wrong - */ - protected MethodResult exportToTank(@NotNull IArguments arguments, @Nullable IFluidHandler targetTank) throws LuaException { - MEStorage monitor = AppEngApi.getMonitor(node); - MeFluidHandler fluidHandler = new MeFluidHandler(monitor, tile); - Pair filter = FluidFilter.parse(arguments.getTable(0)); - - if (filter.rightPresent()) - return MethodResult.of(0, filter.getRight()); - - if (targetTank == null) - return MethodResult.of(0, "Target Tank does not exist"); - - return MethodResult.of(InventoryUtil.moveFluid(fluidHandler, targetTank, filter.getLeft()), null); - } - - /** - * imports an item to the system from a valid inventory - * - * @param arguments the arguments given by the computer - * @param targetInventory the give inventory - * @return the imported amount or null with a string if something went wrong - */ - protected MethodResult importToME(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { - MEStorage monitor = AppEngApi.getMonitor(node); - MeItemHandler itemHandler = new MeItemHandler(monitor, tile); - Pair filter = ItemFilter.parse(arguments.getTable(0)); - - if (filter.rightPresent()) - return MethodResult.of(0, filter.getRight()); - - if (targetInventory == null) - return MethodResult.of(0, "Target Inventory does not exist"); - - return MethodResult.of(InventoryUtil.moveItem(targetInventory, itemHandler, filter.getLeft()), null); - } - - /** - * imports a fluid to the system from a valid tank - * - * @param arguments the arguments given by the computer - * @param targetTank the give tank - * @return the imported amount or null with a string if something went wrong - */ - protected MethodResult importToME(@NotNull IArguments arguments, @Nullable IFluidHandler targetTank) throws LuaException { - MEStorage monitor = AppEngApi.getMonitor(node); - MeFluidHandler fluidHandler = new MeFluidHandler(monitor, tile); - Pair filter = FluidFilter.parse(arguments.getTable(0)); - - if (filter.rightPresent()) - return MethodResult.of(0, filter.getRight()); - - if (targetTank == null) - return MethodResult.of(0, "Target Tank does not exist"); - - return MethodResult.of(InventoryUtil.moveFluid(targetTank, fluidHandler, filter.getLeft()), null); - } - - private MethodResult notConnected() { - return MethodResult.of(null, "NOT_CONNECTED"); - } - - @LuaFunction(mainThread = true) - public final boolean isConnected() { - return node.getGrid() != null && node.hasGridBooted() && node.isActive(); - } - - @LuaFunction - public final MethodResult craftItem(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - - String cpuName = arguments.optString(1, ""); - ICraftingCPU target = getCraftingCPU(cpuName); - if (!cpuName.isEmpty() && target == null) - return MethodResult.of(false, "CPU " + cpuName + " does not exists"); - - ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); - Pair stack = AppEngApi.findAEStackFromFilter(AppEngApi.getMonitor(tile.getGridNode()), craftingGrid, filter.getLeft()); - if (stack.getRight() == null && stack.getLeft() == 0) - return MethodResult.of(null, "NOT_CRAFTABLE"); - - CraftJob job = new CraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), tile, tile, target); - tile.addJob(job); - ServerWorker.add(job::startCrafting); - return MethodResult.of(true); - } - - @LuaFunction - public final MethodResult craftFluid(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - Pair filter = FluidFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - FluidFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - - String cpuName = arguments.optString(1, ""); - ICraftingCPU target = getCraftingCPU(cpuName); - if (!cpuName.isEmpty() && target == null) - return MethodResult.of(false, "CPU " + cpuName + " does not exists"); - - ICraftingService craftingGrid = node.getGrid().getService(ICraftingService.class); - Pair stack = AppEngApi.findAEFluidFromFilter(AppEngApi.getMonitor(tile.getGridNode()), craftingGrid, filter.getLeft()); - if (stack.getRight() == null && stack.getLeft() == 0) - return MethodResult.of(null, "NOT_CRAFTABLE"); - - CraftJob job = new CraftJob(owner.getLevel(), computer, node, stack.getRight(), parsedFilter.getCount(), tile, tile, target); - tile.addJob(job); - ServerWorker.add(job::startCrafting); - return MethodResult.of(true); - } - - @LuaFunction(mainThread = true) - public final MethodResult getEnergyUsage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(node.getGrid().getEnergyService().getAvgPowerUsage()); - } - - @LuaFunction(mainThread = true) - public final MethodResult getEnergyStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(node.getGrid().getEnergyService().getStoredPower()); - } - - @LuaFunction(mainThread = true) - public final MethodResult getAvgPowerUsage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(node.getGrid().getEnergyService().getAvgPowerUsage()); - } - - @LuaFunction(mainThread = true) - public final MethodResult getAvgPowerInjection() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(node.getGrid().getEnergyService().getAvgPowerInjection()); - } - - - @LuaFunction(mainThread = true) - public final MethodResult getMaxEnergyStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(node.getGrid().getEnergyService().getMaxStoredPower()); - } - - @LuaFunction(mainThread = true) - public final MethodResult isItemCrafting(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - MEStorage monitor = AppEngApi.getMonitor(node); - ICraftingService grid = node.getGrid().getService(ICraftingService.class); - - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - String cpuName = arguments.optString(1, ""); - ICraftingCPU craftingCPU = getCraftingCPU(cpuName); - - return MethodResult.of(AppEngApi.isItemCrafting(monitor, grid, parsedFilter, craftingCPU)); - } - - @LuaFunction(mainThread = true) - public final MethodResult isItemCraftable(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - - AEItemKey item = AEItemKey.of(parsedFilter.toItemStack()); - - return MethodResult.of(getCraftingService().isCraftable(item)); - } - - @LuaFunction(mainThread = true) - public final MethodResult isFluidCrafting(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - MEStorage monitor = AppEngApi.getMonitor(node); - ICraftingService grid = node.getGrid().getService(ICraftingService.class); - - Pair filter = FluidFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - FluidFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - String cpuName = arguments.optString(1, ""); - ICraftingCPU craftingCPU = getCraftingCPU(cpuName); - - return MethodResult.of(AppEngApi.isFluidCrafting(monitor, grid, parsedFilter, craftingCPU)); - } - - @LuaFunction(mainThread = true) - public final MethodResult isFluidCraftable(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - Pair filter = FluidFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); - - FluidFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - - AEFluidKey fluid = AEFluidKey.of(parsedFilter.toFluidStack()); - - return MethodResult.of(getCraftingService().isCraftable(fluid)); - } - - @LuaFunction(mainThread = true) - public final MethodResult exportFluid(@NotNull IArguments arguments) throws LuaException { - IFluidHandler handler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); - return exportToTank(arguments, handler); - } - - @LuaFunction(mainThread = true) - public final MethodResult exportFluidToPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - IFluidHandler handler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); - - if (handler == null) - return MethodResult.of(0, "The target tank does not exist. Make sure the bridge is exposed in the computer network. Reach out to our discord or our documentation for help."); - - return exportToTank(arguments, handler); - } - - @LuaFunction(mainThread = true) - public final MethodResult importFluid(IArguments arguments) throws LuaException { - IFluidHandler handler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); - return importToME(arguments, handler); - } - - @LuaFunction(mainThread = true) - public final MethodResult importFluidFromPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - IFluidHandler handler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); - - if (handler == null) - return MethodResult.of(0, "The target tank does not exist. Make sure the bridge is exposed in the computer network. Reach out to our discord or our documentation for help."); - - return importToME(arguments, handler); - } - - @LuaFunction(mainThread = true) - public final MethodResult exportItem(@NotNull IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - IItemHandler inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); - return exportToChest(arguments, inventory); - } - - @LuaFunction(mainThread = true) - public final MethodResult exportItemToPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - IItemHandler inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); - - if (inventory == null) - return MethodResult.of(0, "The target inventory does not exist. Make sure the bridge is exposed in the computer network. Reach out to our discord or our documentation for help."); - - return exportToChest(arguments, inventory); - } - - @LuaFunction(mainThread = true) - public final MethodResult importItem(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - IItemHandler inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); - return importToME(arguments, inventory); - } - - @LuaFunction(mainThread = true) - public final MethodResult importItemFromPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - IItemHandler inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); - - if (inventory == null) - return MethodResult.of(0, "The target inventory does not exist. Make sure the bridge is exposed in the computer network. Reach out to our discord or our documentation for help."); - - return importToME(arguments, inventory); - } - - @LuaFunction(mainThread = true) - public final MethodResult getItem(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - - MEStorage monitor = AppEngApi.getMonitor(node); - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(null, filter.getRight()); - - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(null, "EMPTY_FILTER"); - - Pair item = AppEngApi.findAEStackFromFilter(monitor, getCraftingService(), parsedFilter); - if (item.getRight() == null && item.getLeft() == 0) - return MethodResult.of(null, "NOT_FOUND"); - return MethodResult.of(AppEngApi.getObjectFromStack(item, getCraftingService())); - } - - @LuaFunction(mainThread = true) - public final MethodResult listItems() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listStacks(AppEngApi.getMonitor(node), getCraftingService())); - } - - @LuaFunction(mainThread = true) - public final MethodResult listCraftableItems() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listCraftableStacks(AppEngApi.getMonitor(node), getCraftingService())); - } - - @LuaFunction(mainThread = true) - public final MethodResult listFluid() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listFluids(AppEngApi.getMonitor(node), getCraftingService())); - } - - @LuaFunction(mainThread = true) - public final MethodResult listGas() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listGases(AppEngApi.getMonitor(node), getCraftingService(), 0)); - } - - @LuaFunction(mainThread = true) - public final MethodResult listCraftableFluid() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listCraftableFluids(AppEngApi.getMonitor(node), getCraftingService())); - } - - @LuaFunction(mainThread = true) - public final MethodResult getTotalItemStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getTotalItemStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getTotalFluidStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getTotalFluidStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getUsedItemStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getUsedItemStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getUsedFluidStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getUsedFluidStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getAvailableItemStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getAvailableItemStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getAvailableFluidStorage() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.getAvailableFluidStorage(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult listCells() { - if (!isConnected()) - return notConnected(); - - return MethodResult.of(AppEngApi.listCells(node)); - } - - @LuaFunction(mainThread = true) - public final MethodResult getCraftingCPUs() throws LuaException { - if (!isConnected()) - return notConnected(); - - ICraftingService grid = node.getGrid().getService(ICraftingService.class); - List map = new ArrayList<>(); - - for (ICraftingCPU iCraftingCPU : grid.getCpus()) { - Object cpu = AppEngApi.getObjectFromCPU(iCraftingCPU); - map.add(cpu); - } - return MethodResult.of(map); - } - - public final ICraftingCPU getCraftingCPU(String cpuName) { - if (cpuName.isEmpty()) return null; - ICraftingService grid = node.getGrid().getService(ICraftingService.class); - if (grid == null) return null; - - Iterator iterator = grid.getCpus().iterator(); - if (!iterator.hasNext()) return null; - - while (iterator.hasNext()) { - ICraftingCPU cpu = iterator.next(); - - if (cpu.getName() != null && cpu.getName().getString().equals(cpuName)) { - return cpu; - } - } - - return null; - } -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/NBTStoragePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/NBTStoragePeripheral.java index 5e327d1f6..957594180 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/NBTStoragePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/NBTStoragePeripheral.java @@ -18,7 +18,7 @@ public class NBTStoragePeripheral extends BasePeripheral> { - public static final String PERIPHERAL_TYPE = "nbtStorage"; + public static final String PERIPHERAL_TYPE = "nbt_storage"; public NBTStoragePeripheral(NBTStorageEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/PlayerDetectorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/PlayerDetectorPeripheral.java index 8a6bf1913..b5f418993 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/PlayerDetectorPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/PlayerDetectorPeripheral.java @@ -5,6 +5,7 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; @@ -13,22 +14,27 @@ import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.events.Events; import de.srendi.advancedperipherals.common.util.CoordUtil; import de.srendi.advancedperipherals.common.util.LuaConverter; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.server.ServerLifecycleHooks; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class PlayerDetectorPeripheral extends BasePeripheral { - public static final String PERIPHERAL_TYPE = "playerDetector"; + public static final String PERIPHERAL_TYPE = "player_detector"; private static final int MAX_RANGE = APConfig.PERIPHERALS_CONFIG.playerDetMaxRange.get(); + private long lastConsumedMessage = Events.getLastPlayerMessageID() - 1; public PlayerDetectorPeripheral(PeripheralBlockEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); @@ -38,8 +44,8 @@ public PlayerDetectorPeripheral(ITurtleAccess access, TurtleSide side) { super(PERIPHERAL_TYPE, new TurtlePeripheralOwner(access, side)); } - public PlayerDetectorPeripheral(IPocketAccess pocket) { - super(PERIPHERAL_TYPE, new PocketPeripheralOwner(pocket)); + public PlayerDetectorPeripheral(IPocketAccess pocket, IPocketUpgrade upgrade) { + super(PERIPHERAL_TYPE, new PocketPeripheralOwner(pocket, upgrade)); } private boolean isAllowedMultiDimensional() { @@ -67,10 +73,12 @@ public final MethodResult getPlayersInCoords(Map firstCoord, Map sec ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) + if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) { continue; - if (CoordUtil.isInRange(getPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE)) + } + if (CoordUtil.isInRange(getPhysicsPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE)) { playersName.add(player.getName().getString()); + } } return MethodResult.of(playersName); } @@ -81,10 +89,9 @@ public final List getPlayersInCubic(int x, int y, int z) { ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, x, y, z, MAX_RANGE)) + if (player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, x, y, z, MAX_RANGE)) { playersName.add(player.getName().getString()); + } } return playersName; } @@ -95,10 +102,9 @@ public final List getPlayersInRange(int range) { ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, MAX_RANGE)) + if (player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, MAX_RANGE)) { playersName.add(player.getName().getString()); + } } return playersName; } @@ -112,9 +118,12 @@ public final boolean isPlayersInCoords(Map firstCoord, Map secondCoo ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) + if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) { continue; - if (CoordUtil.isInRange(getPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE)) return true; + } + if (CoordUtil.isInRange(getPhysicsPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE)) { + return true; + } } return false; } @@ -126,9 +135,9 @@ public final boolean isPlayersInCubic(int x, int y, int z) { ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, x, y, z, MAX_RANGE)) return true; + if (player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, x, y, z, MAX_RANGE)) { + return true; + } } return false; } @@ -140,9 +149,9 @@ public final boolean isPlayersInRange(int range) { ResourceKey dimension = getLevel().dimension(); for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, MAX_RANGE)) return true; + if (player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, MAX_RANGE)) { + return true; + } } return false; } @@ -153,44 +162,27 @@ public final boolean isPlayerInCoords(Map firstCoord, Map secondCoor BlockPos secondPos = LuaConverter.convertToBlockPos(secondCoord); ResourceKey dimension = getLevel().dimension(); - for (Player player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE)) - if(player.getName().getString().equals(username)) - return true; + ServerPlayer player = getPlayer(username); + if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) { + return false; } - return false; + return CoordUtil.isInRange(getPhysicsPos(), player, getLevel(), firstPos, secondPos, MAX_RANGE); } @LuaFunction(mainThread = true) public final boolean isPlayerInCubic(int x, int y, int z, String username) { ResourceKey dimension = getLevel().dimension(); - for (Player player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, x, y, z, MAX_RANGE)) { - if(player.getName().getString().equals(username)) - return true; - } - } - return false; + ServerPlayer player = getPlayer(username); + return player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, x, y, z, MAX_RANGE); } @LuaFunction(mainThread = true) public final boolean isPlayerInRange(int range, String username) { ResourceKey dimension = getLevel().dimension(); - for (Player player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (CoordUtil.isInRange(getPos(), getLevel(), player, range, MAX_RANGE)) { - if(player.getName().getString().equals(username)) - return true; - } - } - return false; + ServerPlayer player = getPlayer(username); + return player.getLevel().dimension() == dimension && CoordUtil.isInRange(getPhysicsPos(), getLevel(), player, range, MAX_RANGE); } @LuaFunction(value = {"getPlayerPos", "getPlayer"}, mainThread = true) @@ -198,23 +190,22 @@ public final Map getPlayerPos(IArguments arguments) throws LuaEx if (!APConfig.PERIPHERALS_CONFIG.playerSpy.get()) throw new LuaException("This function is disabled in the config. Activate it or ask an admin if he can activate it."); ResourceKey dimension = getLevel().dimension(); + Vec3 pos = getPhysicsPos(); - ServerPlayer existingPlayer = null; - for (ServerPlayer player : getPlayers()) { - if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) - continue; - if (player.getName().getString().equals(arguments.getString(0))) { - if (MAX_RANGE == -1 || CoordUtil.isInRange(getPos(), getLevel(), player, MAX_RANGE, MAX_RANGE)) - existingPlayer = player; - break; - } + ServerPlayer player = getPlayer(arguments.getString(0)); + if (player == null) { + return null; + } + if (!isAllowedMultiDimensional() && player.getLevel().dimension() != dimension) { + return null; + } + if (MAX_RANGE != -1 && !CoordUtil.isInRange(pos, getLevel(), player, MAX_RANGE, MAX_RANGE)) { + return null; } - if (existingPlayer == null) - return Collections.emptyMap(); Map info = new HashMap<>(); - double x = existingPlayer.getX(), y = existingPlayer.getY(), z = existingPlayer.getZ(); + double x = player.getX(), y = player.getY(), z = player.getZ(); if (APConfig.PERIPHERALS_CONFIG.playerSpyRandError.get()) { // We apply random error to the returned player position if so enabled in the configuration. @@ -235,7 +226,7 @@ public final Map getPlayerPos(IArguments arguments) throws LuaEx maxDistance = Math.max(minDistance, maxDistance); // Calculate Euclidean distance between the player locator and the player in question - double distanceFromPlayer = Math.sqrt(Math.pow(x - getPos().getX(), 2) + Math.pow(y - getPos().getY(), 2) + Math.pow(z - getPos().getZ(), 2)); + double distanceFromPlayer = Math.sqrt(Math.pow(x - pos.x, 2) + Math.pow(y - pos.y, 2) + Math.pow(z - pos.z, 2)); distanceFromPlayer -= minDistance; if (distanceFromPlayer > 0) { @@ -255,18 +246,16 @@ public final Map getPlayerPos(IArguments arguments) throws LuaEx info.put("y", Math.floor(y * unit) / unit); info.put("z", Math.floor(z * unit) / unit); if (APConfig.PERIPHERALS_CONFIG.morePlayerInformation.get()) { - info.put("yaw", existingPlayer.yRotO); - info.put("pitch", existingPlayer.xRotO); - info.put("dimension", existingPlayer.getLevel().dimension().location().toString()); - info.put("eyeHeight", existingPlayer.getEyeHeight()); - info.put("health", existingPlayer.getHealth()); - // TODO: remove the next line in next major version - info.put("maxHeatlh", existingPlayer.getMaxHealth()); // keep this for backward compatibility - info.put("maxHealth", existingPlayer.getMaxHealth()); - info.put("airSupply", existingPlayer.getAirSupply()); - info.put("respawnPosition", LuaConverter.posToObject(existingPlayer.getRespawnPosition())); - info.put("respawnDimension", existingPlayer.getRespawnDimension().location().toString()); - info.put("respawnAngle", existingPlayer.getRespawnAngle()); + info.put("yaw", player.yRotO); + info.put("pitch", player.xRotO); + info.put("dimension", player.getLevel().dimension().location().toString()); + info.put("eyeHeight", player.getEyeHeight()); + info.put("health", player.getHealth()); + info.put("maxHealth", player.getMaxHealth()); + info.put("airSupply", player.getAirSupply()); + info.put("respawnPosition", LuaConverter.posToObject(player.getRespawnPosition())); + info.put("respawnDimension", player.getRespawnDimension().location().toString()); + info.put("respawnAngle", player.getRespawnAngle()); } return info; } @@ -274,4 +263,17 @@ public final Map getPlayerPos(IArguments arguments) throws LuaEx private List getPlayers() { return ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers(); } + + private ServerPlayer getPlayer(String name) { + return ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayerByName(name); + } + + @Override + public void update() { + lastConsumedMessage = Events.traversePlayerMessages(lastConsumedMessage, message -> getConnectedComputers().forEach(computer -> { + if(message.eventName().equals("playerChangedDimension")) { + computer.queueEvent(message.eventName(), message.playerName(), message.fromDimension(), message.toDimension()); + } else computer.queueEvent(message.eventName(), message.playerName(), message.fromDimension()); + })); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RedstoneIntegratorPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RedstoneIntegratorPeripheral.java index ec70aa47c..5e6625c4b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RedstoneIntegratorPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RedstoneIntegratorPeripheral.java @@ -10,7 +10,7 @@ public class RedstoneIntegratorPeripheral extends BasePeripheral> { - public static final String PERIPHERAL_TYPE = "redstoneIntegrator"; + public static final String PERIPHERAL_TYPE = "redstone_integrator"; public RedstoneIntegratorPeripheral(RedstoneIntegratorEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); @@ -21,27 +21,28 @@ public boolean isEnabled() { return APConfig.PERIPHERALS_CONFIG.enableRedstoneIntegrator.get(); } - @LuaFunction(mainThread = true) + @LuaFunction public final boolean getInput(String direction) throws LuaException { Direction dir = validateSide(direction); - return owner.tileEntity.getRedstoneInput(dir) > 0; + return owner.tileEntity.getInput(dir) > 0; } - @LuaFunction(mainThread = true) + @LuaFunction public final boolean getOutput(String direction) throws LuaException { - return owner.tileEntity.power[validateSide(direction).get3DDataValue()] > 0; + Direction dir = validateSide(direction); + return owner.tileEntity.getOutput(dir) > 0; } - @LuaFunction(value = {"getAnalogueInput", "getAnalogInput"}, mainThread = true) + @LuaFunction(value = {"getAnalogueInput", "getAnalogInput"}) public final int getAnalogInput(String direction) throws LuaException { Direction dir = validateSide(direction); - return owner.tileEntity.getRedstoneInput(dir); + return owner.tileEntity.getInput(dir); } - @LuaFunction(value = {"getAnalogueOutput", "getAnalogOutput"}, mainThread = true) + @LuaFunction(value = {"getAnalogueOutput", "getAnalogOutput"}) public final int getAnalogOutput(String direction) throws LuaException { Direction dir = validateSide(direction); - return owner.tileEntity.power[dir.get3DDataValue()]; + return owner.tileEntity.getOutput(dir); } @LuaFunction @@ -53,6 +54,9 @@ public final void setOutput(String direction, boolean power) throws LuaException @LuaFunction(value = {"setAnalogueOutput", "setAnalogOutput"}) public final void setAnalogOutput(String direction, int power) throws LuaException { Direction dir = validateSide(direction); + if (power > 15 || power < 0) { + throw new LuaException("redstone power exceeds the range [0,15]"); + } owner.tileEntity.setOutput(dir, power); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RsBridgePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RsBridgePeripheral.java index 87fd927b7..a0b002894 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RsBridgePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/RsBridgePeripheral.java @@ -1,7 +1,7 @@ package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; -import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; -import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import dan200.computercraft.api.lua.IArguments; @@ -9,18 +9,31 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IComputerAccess; -import de.srendi.advancedperipherals.AdvancedPeripherals; +import dan200.computercraft.core.apis.TableHelper; +import dan200.computercraft.core.computer.ComputerSide; import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RefinedStorage; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RefinedStorageNode; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RsFluidHandler; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RsItemHandler; -import de.srendi.advancedperipherals.common.blocks.blockentities.RsBridgeEntity; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSApi; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSCraftJob; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSNode; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSFluidHandler; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSItemHandler; +import de.srendi.advancedperipherals.common.blocks.blockentities.RSBridgeEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.common.util.Pair; -import de.srendi.advancedperipherals.common.util.inventory.*; +import de.srendi.advancedperipherals.common.util.StatusConstants; +import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; +import de.srendi.advancedperipherals.common.util.inventory.FluidUtil; +import de.srendi.advancedperipherals.common.util.inventory.GenericFilter; +import de.srendi.advancedperipherals.common.util.inventory.IStorageSystemPeripheral; +import de.srendi.advancedperipherals.common.util.inventory.InventoryUtil; +import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; @@ -29,16 +42,23 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; -public class RsBridgePeripheral extends BasePeripheral> { +public class RsBridgePeripheral extends BasePeripheral> implements IStorageSystemPeripheral { - public static final String PERIPHERAL_TYPE = "rsBridge"; + public static final String PERIPHERAL_TYPE = "rs_bridge"; - public RsBridgePeripheral(RsBridgeEntity tileEntity) { + private final RSBridgeEntity bridge; + private final ICapabilityProvider capabilityWrapper = new CapabilityWrapper(this); + + public RsBridgePeripheral(RSBridgeEntity tileEntity) { super(PERIPHERAL_TYPE, new BlockEntityPeripheralOwner<>(tileEntity)); + this.bridge = tileEntity; } - private RefinedStorageNode getNode() { + private RSNode getNode() { return owner.tileEntity.getNode(); } @@ -46,8 +66,18 @@ private INetwork getNetwork() { return getNode().getNetwork(); } - private MethodResult notConnected() { - return MethodResult.of(null, "NOT_CONNECTED"); + private MethodResult notConnected(@Nullable Object defaultValue) { + return MethodResult.of(defaultValue, StatusConstants.NOT_CONNECTED.toString()); + } + + + private boolean isAvailable() { + return getNetwork() != null; + } + + @Override + public Object getTarget() { + return capabilityWrapper; } @Override @@ -55,125 +85,338 @@ public boolean isEnabled() { return APConfig.PERIPHERALS_CONFIG.enableRSBridge.get(); } + protected RSItemHandler getItemHandler() { + return new RSItemHandler(getNetwork()); + } + + protected RSFluidHandler getFluidHandler() { + return new RSFluidHandler(getNetwork()); + } + + @Override @LuaFunction(mainThread = true) public final boolean isConnected() { - return getNetwork() != null; + return isAvailable(); } + @Override @LuaFunction(mainThread = true) - public final MethodResult listItems() { - if (!isConnected()) - return notConnected(); + public final MethodResult isOnline() { + // Is there a more proper method? + return MethodResult.of(getNode().isActive()); + } - return MethodResult.of(RefinedStorage.listItems(getNetwork())); + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getItems(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(RSApi.listItems(getNetwork())); } + @Override @LuaFunction(mainThread = true) - public final MethodResult listCraftableItems() { - if (!isConnected()) - return notConnected(); + public final MethodResult getCraftableItems(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); List items = new ArrayList<>(); - RefinedStorage.getCraftableItems(getNetwork()).forEach(item -> items.add(RefinedStorage.getObjectFromStack(item, getNetwork()))); + RSApi.getCraftableItems(getNetwork()).forEach(item -> items.add(RSApi.parseItemStack(item, getNetwork()))); return MethodResult.of(items); } + @Override @LuaFunction(mainThread = true) - public final Object listCraftableFluids() { - if (!isConnected()) - return notConnected(); + public final MethodResult getCraftableFluids(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); List fluids = new ArrayList<>(); - RefinedStorage.getCraftableFluids(getNetwork()).forEach(fluid -> fluids.add(RefinedStorage.getObjectFromFluid(fluid, getNetwork()))); + RSApi.getCraftableFluids(getNetwork()).forEach(fluid -> fluids.add(RSApi.parseFluidStack(fluid, getNetwork()))); return MethodResult.of(fluids); } + @Override + public MethodResult getCraftableChemicals(IArguments arguments) { + return null; + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getCells() { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(RSApi.getStorageDisks(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getDrives() { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(RSApi.getDiskDrives(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getTotalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxItemDiskStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getTotalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxFluidDiskStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getTotalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(-1); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getUsedItemExternalStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getUsedFluidExternalStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getUsedExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(-1); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getUsedItemDiskStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getUsedFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getUsedFluidDiskStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getUsedChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(-1); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxItemExternalStorage(getNetwork()) - RSApi.getUsedItemExternalStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxFluidExternalStorage(getNetwork()) - RSApi.getUsedFluidExternalStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult getAvailableExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(-1); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableItemStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxItemDiskStorage(getNetwork()) - RSApi.getUsedItemDiskStorage(getNetwork())); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult getAvailableFluidStorage() { + if (!isAvailable()) + return notConnected(0); + + return MethodResult.of(RSApi.getMaxFluidDiskStorage(getNetwork()) - RSApi.getUsedFluidDiskStorage(getNetwork())); + } + + @Override @LuaFunction(mainThread = true) - public final MethodResult getMaxItemDiskStorage() { - if (!isConnected()) - return notConnected(); + public MethodResult getAvailableChemicalStorage() { + if (!isAvailable()) + return notConnected(0); - return MethodResult.of(RefinedStorage.getMaxItemDiskStorage(getNetwork())); + return MethodResult.of(-1); } + @Override @LuaFunction(mainThread = true) - public final MethodResult getMaxFluidDiskStorage() { - if (!isConnected()) - return notConnected(); + public final MethodResult getTotalExternalItemStorage() { + if (!isAvailable()) + return notConnected(0); - return MethodResult.of(RefinedStorage.getMaxFluidDiskStorage(getNetwork())); + return MethodResult.of(RSApi.getMaxItemExternalStorage(getNetwork())); } + @Override @LuaFunction(mainThread = true) - public final MethodResult getMaxItemExternalStorage() { - if (!isConnected()) - return notConnected(); + public final MethodResult getTotalExternalFluidStorage() { + if (!isAvailable()) + return notConnected(0); - return MethodResult.of(RefinedStorage.getMaxItemExternalStorage(getNetwork())); + return MethodResult.of(RSApi.getMaxFluidExternalStorage(getNetwork())); } + @Override @LuaFunction(mainThread = true) - public final MethodResult getMaxFluidExternalStorage() { - if (!isConnected()) - return notConnected(); + public MethodResult getTotalExternalChemicalStorage() { + if (!isAvailable()) + return notConnected(0); - return MethodResult.of(RefinedStorage.getMaxFluidExternalStorage(getNetwork())); + return MethodResult.of(-1); } + @Override @LuaFunction(mainThread = true) - public final MethodResult listFluids() { - if (!isConnected()) - return notConnected(); + public final MethodResult getFluids(IArguments arguments) { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(RSApi.listFluids(getNetwork())); + } - return MethodResult.of(RefinedStorage.listFluids(getNetwork())); + @Override + public MethodResult getChemicals(IArguments arguments) { + return null; } + @Override @LuaFunction(mainThread = true) public final MethodResult getEnergyUsage() { - if (!isConnected()) - return notConnected(); + if (!isAvailable()) + return notConnected(0); return MethodResult.of(getNetwork().getEnergyUsage()); } + @Override @LuaFunction(mainThread = true) - public final MethodResult getMaxEnergyStorage() { - if (!isConnected()) - return notConnected(); + public final MethodResult getEnergyCapacity() { + if (!isAvailable()) + return notConnected(0); return MethodResult.of(getNetwork().getEnergyStorage().getMaxEnergyStored()); } + @Override @LuaFunction(mainThread = true) - public final MethodResult getEnergyStorage() { - if (!isConnected()) - return notConnected(); + public final MethodResult getStoredEnergy() { + if (!isAvailable()) + return notConnected(0); return MethodResult.of(getNetwork().getEnergyStorage().getEnergyStored()); } @LuaFunction(mainThread = true) - public final MethodResult getPattern(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult getAverageEnergyInput() { + return MethodResult.of(0); + } - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); + @Override + @LuaFunction(mainThread = true) + public final MethodResult getPatterns(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); + + // Expected input is a table with either an input table, an output table or both to filter for both + Map filterTable; + Optional> optionalTable = arguments.optTable(0); + if (optionalTable.isEmpty()) + return MethodResult.of(RSApi.getPatterns(getNetwork())); + + filterTable = optionalTable.get(); - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); + boolean hasInputFilter = filterTable.containsKey("input"); + boolean hasOutputFilter = filterTable.containsKey("output"); + boolean hasAnyFilter = hasInputFilter || hasOutputFilter; - ItemStack patternItem = RefinedStorage.findStackFromFilter(getNetwork(), getNetwork().getCraftingManager(), parsedFilter); + // If the player tries to filter for nothing, return nothing. + if (!hasAnyFilter) + return MethodResult.of(null, StatusConstants.MISSING_FILTER.toString()); - return MethodResult.of(RefinedStorage.getObjectFromPattern(getNetwork().getCraftingManager().getPattern(patternItem), getNetwork())); + GenericFilter inputFilter = null; + GenericFilter outputFilter = null; + + if (hasInputFilter) { + Map inputFilterTable = TableHelper.getTableField(filterTable, "input"); + + inputFilter = GenericFilter.parseGeneric(inputFilterTable).getLeft(); + } + if (hasOutputFilter) { + Map outputFilterTable = TableHelper.getTableField(filterTable, "output"); + + outputFilter = GenericFilter.parseGeneric(outputFilterTable).getLeft(); + } + + Pair pattern = RSApi.findPatternFromFilters(getNetwork(), inputFilter, outputFilter); + + if (pattern.getRight() != null) + return MethodResult.of(null, pattern.getRight()); + + return MethodResult.of(RSApi.parsePattern(pattern.getLeft(), getNetwork())); } protected MethodResult exportToChest(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { - RsItemHandler itemHandler = new RsItemHandler(getNetwork()); + RSItemHandler itemHandler = new RSItemHandler(getNetwork()); if (targetInventory == null) - return MethodResult.of(0, "INVALID_TARGET"); + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND); Pair filter = ItemFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) @@ -183,9 +426,9 @@ protected MethodResult exportToChest(@NotNull IArguments arguments, @Nullable II } protected MethodResult importToSystem(@NotNull IArguments arguments, @Nullable IItemHandler targetInventory) throws LuaException { - RsItemHandler itemHandler = new RsItemHandler(getNetwork()); + RSItemHandler itemHandler = new RSItemHandler(getNetwork()); if (targetInventory == null) - return MethodResult.of(0, "INVALID_TARGET"); + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND); Pair filter = ItemFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) @@ -195,9 +438,9 @@ protected MethodResult importToSystem(@NotNull IArguments arguments, @Nullable I } protected MethodResult exportToTank(@NotNull IArguments arguments, @Nullable IFluidHandler targetInventory) throws LuaException { - RsFluidHandler itemHandler = new RsFluidHandler(getNetwork()); + RSFluidHandler itemHandler = new RSFluidHandler(getNetwork()); if (targetInventory == null) - return MethodResult.of(0, "INVALID_TARGET"); + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND); Pair filter = FluidFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) @@ -207,9 +450,9 @@ protected MethodResult exportToTank(@NotNull IArguments arguments, @Nullable IFl } protected MethodResult importToSystem(@NotNull IArguments arguments, @Nullable IFluidHandler targetInventory) throws LuaException { - RsFluidHandler itemHandler = new RsFluidHandler(getNetwork()); + RSFluidHandler itemHandler = new RSFluidHandler(getNetwork()); if (targetInventory == null) - return MethodResult.of(0, "INVALID_TARGET"); + return MethodResult.of(0, StatusConstants.TARGET_NOT_FOUND); Pair filter = FluidFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) @@ -218,169 +461,290 @@ protected MethodResult importToSystem(@NotNull IArguments arguments, @Nullable I return MethodResult.of(InventoryUtil.moveFluid(targetInventory, itemHandler, filter.getLeft()), null); } + @Override @LuaFunction(mainThread = true) - public final MethodResult exportItem(@NotNull IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult exportItem(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); - IItemHandler inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); - return exportToChest(arguments, inventory); - } + String side = arguments.getString(1); + IItemHandler inventory; - @LuaFunction(mainThread = true) - public final MethodResult exportItemToPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); + } - IItemHandler inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); return exportToChest(arguments, inventory); } + @Override @LuaFunction(mainThread = true) - public final MethodResult importItem(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult importItem(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); - IItemHandler inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); - return importToSystem(arguments, inventory); - } + String side = arguments.getString(1); + IItemHandler inventory; - @LuaFunction(mainThread = true) - public final MethodResult importItemFromPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + inventory = InventoryUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); + } - IItemHandler inventory = InventoryUtil.getHandlerFromName(computer, arguments.getString(1)); return importToSystem(arguments, inventory); } + @Override @LuaFunction(mainThread = true) - public final MethodResult exportFluid(@NotNull IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult exportFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); - IFluidHandler inventory = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); - return exportToTank(arguments, inventory); - } + String side = arguments.getString(1); + IFluidHandler fluidHandler; - @LuaFunction(mainThread = true) - public final MethodResult exportFluidToPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + fluidHandler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + fluidHandler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); + } - IFluidHandler inventory = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); - return exportToTank(arguments, inventory); + return exportToTank(arguments, fluidHandler); } - @LuaFunction(mainThread = true) - public final MethodResult importFluid(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + @Override + public MethodResult importChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; + } - IFluidHandler inventory = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); - return importToSystem(arguments, inventory); + @Override + public MethodResult exportChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; } + @Override @LuaFunction(mainThread = true) - public final MethodResult importFluidFromPeripheral(IComputerAccess computer, IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult importFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); - IFluidHandler inventory = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); - return importToSystem(arguments, inventory); + String side = arguments.getString(1); + IFluidHandler fluidHandler; + + if (Direction.byName(side.toUpperCase(Locale.ROOT)) == null && ComputerSide.valueOfInsensitive(side.toUpperCase(Locale.ROOT)) == null) { + fluidHandler = FluidUtil.getHandlerFromDirection(arguments.getString(1), owner); + } else { + fluidHandler = FluidUtil.getHandlerFromName(computer, arguments.getString(1)); + } + + return importToSystem(arguments, fluidHandler); } + @Override @LuaFunction(mainThread = true) public final MethodResult getItem(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + if (!isAvailable()) + return notConnected(0); Pair filter = ItemFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) return MethodResult.of(null, filter.getRight()); - ItemStack item = RefinedStorage.findStackFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); - if (item.isEmpty()) - return MethodResult.of(null, "NOT_FOUND"); - return MethodResult.of(RefinedStorage.getObjectFromStack(item, getNetwork())); + return MethodResult.of(RSApi.parseItemStack(RSApi.findItemFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()), getNetwork())); } + @Override @LuaFunction(mainThread = true) - public final MethodResult craftItem(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult getFluid(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + Pair filter = FluidFilter.parse(arguments.getTable(0)); + if (filter.rightPresent()) + return MethodResult.of(null, filter.getRight()); + + return MethodResult.of(RSApi.parseFluidStack(RSApi.findFluidFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()), getNetwork())); + } + + @Override + public MethodResult getChemical(IArguments arguments) throws LuaException { + return null; + } + + @Override + @LuaFunction + public final MethodResult craftItem(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); Pair filter = ItemFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) return MethodResult.of(null, filter.getRight()); - ItemStack stack = RefinedStorage.findStackFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); - if (stack.isEmpty()) - return MethodResult.of(null, "NOT_CRAFTABLE"); + return new CraftJobCallback(computer, () -> { + ItemStack stack = RSApi.findItemFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); + if (stack.isEmpty()) + return MethodResult.of(null, "NOT_CRAFTABLE"); - ICalculationResult result = getNetwork().getCraftingManager().create(stack, filter.getLeft().getCount()); - CalculationResultType type = result.getType(); - if (type == CalculationResultType.OK) - getNetwork().getCraftingManager().start(result.getTask()); - AdvancedPeripherals.debug("Crafting Result of '" + ItemUtil.getRegistryKey(stack).toString() + "':" + type); - return MethodResult.of(type == CalculationResultType.OK); + RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getCount(), stack, getNetwork().getCraftingManager()); + bridge.addJob(job); + return MethodResult.of(job); + }).pull; } - @LuaFunction(mainThread = true) - public final MethodResult craftFluid(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + @Override + @LuaFunction + public final MethodResult craftFluid(IComputerAccess computer, IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(null); Pair filter = FluidFilter.parse(arguments.getTable(0)); if (filter.rightPresent()) return MethodResult.of(null, filter.getRight()); - FluidStack stack = RefinedStorage.findFluidFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); - if (stack.isEmpty()) - return MethodResult.of(null, "NOT_CRAFTABLE"); + return new CraftJobCallback(computer, () -> { + FluidStack stack = RSApi.findFluidFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); + if (stack.isEmpty()) + return MethodResult.of(null, "NOT_CRAFTABLE"); + + RSCraftJob job = new RSCraftJob(computer, getLevel(), filter.getLeft().getCount(), stack, getNetwork().getCraftingManager()); + bridge.addJob(job); + return MethodResult.of(job); + }).pull; + } + + @Override + public MethodResult craftChemical(IComputerAccess computer, IArguments arguments) throws LuaException { + return null; + } - ICalculationResult result = getNetwork().getCraftingManager().create(stack, filter.getLeft().getCount()); - getNetwork().getCraftingManager().getPatterns(); - CalculationResultType type = result.getType(); - if (type == CalculationResultType.OK) - getNetwork().getCraftingManager().start(result.getTask()); - AdvancedPeripherals.debug("Crafting Result of '" + FluidUtil.getRegistryKey(stack).toString() + "':" + type); - return MethodResult.of(type == CalculationResultType.OK); + @Override + @LuaFunction(mainThread = true) + public MethodResult getCraftingTasks() { + if (!isAvailable()) + return notConnected(null); + + return MethodResult.of(RSApi.getCraftingTasks(getNetwork(), bridge)); } + @Override @LuaFunction(mainThread = true) - public final MethodResult isItemCrafting(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) + public MethodResult getCraftingTask(int id) { + if (!isAvailable()) + return notConnected(null); + + RSCraftJob foundJob = null; + + for (RSCraftJob job : bridge.getJobs()) { + if (job.getId() == id) { + foundJob = job; + } + } + return MethodResult.of(foundJob); + } + + @Override + @LuaFunction(mainThread = true) + public MethodResult cancelCraftingTasks(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(0); + + Pair, String> filter = GenericFilter.parseGeneric(arguments.getTable(0)); + if (filter.getRight() != null) + return MethodResult.of(null, filter.getRight()); + + ICraftingManager craftingManager = getNetwork().getCraftingManager(); + int canceled = 0; + + for (ICraftingTask task : craftingManager.getTasks()) { + if (filter.getLeft() instanceof ItemFilter itemFilter) { + if (itemFilter.test(task.getRequested().getItem())) { + craftingManager.cancel(task.getId()); + canceled++; + } + } + + if (filter.getLeft() instanceof FluidFilter fluidFilter) { + if (fluidFilter.test(task.getRequested().getFluid())) { + craftingManager.cancel(task.getId()); + canceled++; + } + } + } + + return MethodResult.of(canceled); + } + + @Override + @LuaFunction(mainThread = true) + public final MethodResult isCrafting(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(false); + + Pair, String> filter = GenericFilter.parseGeneric(arguments.getTable(0)); + if (filter.getRight() != null) return MethodResult.of(null, filter.getRight()); - ItemStack stack = RefinedStorage.findStackFromFilter(getNetwork(), getNetwork().getCraftingManager(), filter.getLeft()); - if (stack.isEmpty()) - return MethodResult.of(null, "NOT_CRAFTABLE"); + GenericFilter parsedFilter = filter.getLeft(); - for (ICraftingTask task : getNetwork().getCraftingManager().getTasks()) { - ItemStack taskStack = task.getRequested().getItem(); - if (taskStack != null && taskStack.sameItem(stack)) - return MethodResult.of(true); + if (parsedFilter instanceof ItemFilter itemFilter) { + ItemStack stack = RSApi.findItemFromFilter(getNetwork(), getNetwork().getCraftingManager(), itemFilter); + if (stack.isEmpty()) + return MethodResult.of(null, "NOT_CRAFTABLE"); + + for (ICraftingTask task : getNetwork().getCraftingManager().getTasks()) { + ItemStack taskStack = task.getRequested().getItem(); + if (taskStack != null && taskStack.sameItem(stack)) + return MethodResult.of(true); + } + } + if (parsedFilter instanceof FluidFilter itemFilter) { + FluidStack stack = RSApi.findFluidFromFilter(getNetwork(), getNetwork().getCraftingManager(), itemFilter); + if (stack.isEmpty()) + return MethodResult.of(null, "NOT_CRAFTABLE"); + + for (ICraftingTask task : getNetwork().getCraftingManager().getTasks()) { + FluidStack taskStack = task.getRequested().getFluid(); + if (taskStack != null && taskStack.isFluidEqual(stack)) + return MethodResult.of(true); + } } return MethodResult.of(false); } + @Override @LuaFunction(mainThread = true) - public final MethodResult isItemCraftable(IArguments arguments) throws LuaException { - if (!isConnected()) - return notConnected(); + public final MethodResult isCraftable(IArguments arguments) throws LuaException { + if (!isAvailable()) + return notConnected(false); - Pair filter = ItemFilter.parse(arguments.getTable(0)); - if (filter.rightPresent()) - return MethodResult.of(false, filter.getRight()); + Pair, String> filter = GenericFilter.parseGeneric(arguments.getTable(0)); + if (filter.getRight() != null) + return MethodResult.of(null, filter.getRight()); + + GenericFilter parsedFilter = filter.getLeft(); - ItemFilter parsedFilter = filter.getLeft(); - if (parsedFilter.isEmpty()) - return MethodResult.of(false, "EMPTY_FILTER"); - return MethodResult.of(RefinedStorage.isItemCraftable(getNetwork(), parsedFilter.toItemStack())); + return MethodResult.of(RSApi.findPatternFromFilters(getNetwork(), null, parsedFilter).getLeft() != null); + } + + private static final class CapabilityWrapper implements ICapabilityProvider { + private final RsBridgePeripheral peripheral; + + private CapabilityWrapper(RsBridgePeripheral peripheral) { + this.peripheral = peripheral; + } + + @Override + public LazyOptional getCapability(final Capability cap, final Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) { + return LazyOptional.of(this.peripheral::getItemHandler).cast(); + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + return LazyOptional.of(this.peripheral::getFluidHandler).cast(); + } + return LazyOptional.empty(); + } } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java new file mode 100644 index 000000000..b80b62428 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java @@ -0,0 +1,229 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toclient.SaddleTurtleInfoPacket; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.common.util.TeleportUtil; +import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySelector; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Predicate; + +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SimpleFreeOperation.SADDLE_CAPTURE; + +public class SaddlePeripheral extends BasePeripheral { + + private static final int ANIM_DURATION = 8; // Should be same as TurtleBrain.ANIM_DURATION + + public static final String PERIPHERAL_TYPE = "saddle"; + private TurtleSeatEntity seat = null; + private volatile Entity rider = null; + private BlockPos lastPos = null; + private int moveProg = 0; + private int tickCount = 0; + + private int barColor = 0; + + public SaddlePeripheral(ITurtleAccess turtle, TurtleSide side) { + super(PERIPHERAL_TYPE, new TurtlePeripheralOwner(turtle, side)); + owner.attachOperation(SADDLE_CAPTURE); + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableSaddleTurtle.get(); + } + + @Nullable + public Entity getRidingEntity() { + return this.isEntityRiding() ? this.rider : null; + } + + public boolean isEntityRiding() { + return this.seat != null && this.rider != null && this.seat.isAlive() && this.seat.hasPassenger(this.rider); + } + + @Override + public void attach(@NotNull IComputerAccess computer) { + super.attach(computer); + this.lastPos = this.owner.getPos(); + } + + @Override + public void detach(@NotNull IComputerAccess computer) { + this.standUp(); + super.detach(computer); + } + + public void update() { + if (this.seat != null) { + if (!isEntityRiding()) { + this.standUp(); + return; + } + this.seat.keepAlive(); + BlockPos pos = this.owner.getPos(); + Level level = this.owner.getLevel(); + if (this.seat.getLevel() != this.owner.getLevel()) { + this.seat = TeleportUtil.teleportToWithPassengers(this.seat, (ServerLevel) level, this.seat.getTurtlePos()); + this.seat.setTurtle(this.owner.getTurtle()); + this.seat.keepAlive(); + this.rider = this.seat.getFirstPassenger(); + this.moveProg = 0; + this.lastPos = pos; + } else { + BlockPos dir = pos.subtract(this.lastPos); + int dist = Math.abs(dir.getX()) + Math.abs(dir.getY()) + Math.abs(dir.getZ()); + if (dist != 0) { + Vec3 newPos = this.seat.getTurtlePos(); + if (dist == 1 && ++this.moveProg < ANIM_DURATION) { + float step = ((float) this.moveProg) / ANIM_DURATION; + newPos = newPos.add(Vec3.atLowerCornerOf(dir).scale(step - 1)); + } else { + this.moveProg = 0; + this.lastPos = pos; + } + this.seat.moveTo(newPos); + } + } + this.tickCount++; + if (this.tickCount > 40) { + this.tickCount = 0; + this.sendHUD(); + } + } + } + + private void sendHUD() { + if (this.rider instanceof ServerPlayer player) { + ITurtleAccess turtle = this.owner.getTurtle(); + SaddleTurtleInfoPacket packet = new SaddleTurtleInfoPacket(turtle.getFuelLevel(), turtle.getFuelLimit(), barColor); + APNetworking.sendTo(packet, player); + } + } + + private boolean sitDown(@NotNull Entity entity) { + Level world = this.owner.getLevel(); + this.seat = new TurtleSeatEntity(this.owner.getTurtle()); + this.seat.setPos(this.seat.getTurtlePos()); + if (!world.addFreshEntity(this.seat)) { + return false; + } + if (!entity.startRiding(this.seat)) { + return false; + } + if (entity instanceof TamableAnimal tamable) { + tamable.setInSittingPose(true); + } + this.seat.keepAlive(); + this.rider = entity; + this.sendHUD(); + return true; + } + + private boolean standUp() { + if (this.seat == null) { + return false; + } + Entity passenger = this.seat.getFirstPassenger(); + if (passenger != null) { + this.seat.ejectPassengers(); + BlockPos pos = this.owner.getPos(); + passenger.dismountTo(pos.getX() + 0.5, pos.getY() + 0.9, pos.getZ() + 0.5); + } + this.seat.discard(); + this.seat = null; + this.rider = null; + if (owner.getTurtle() instanceof TurtleBrain brain) { + brain.getOwner().createServerComputer().queueEvent("saddle_release"); + } + return passenger != null; + } + + @LuaFunction(mainThread = true) + public MethodResult capture() throws LuaException { + if (isEntityRiding()) { + return MethodResult.of(null, "Another entity is riding"); + } + return withOperation(SADDLE_CAPTURE, null, null, context -> { + Predicate suitableEntity = EntitySelector.NO_SPECTATORS + .and((entity) -> entity instanceof LivingEntity || entity instanceof AbstractMinecart || entity instanceof Boat) + .and((entity) -> !entity.isPassenger()); + if (!APConfig.PERIPHERALS_CONFIG.allowSaddleTurtleCapturePlayer.get()) { + suitableEntity = suitableEntity.and((entity) -> !(entity instanceof Player)); + } + final Predicate finalSuitableEntity = suitableEntity; + final APFakePlayer.Action action = (player) -> player.findHit(false, true, finalSuitableEntity); + HitResult entityHit = owner.withPlayer(action); + if (entityHit.getType() == HitResult.Type.MISS) { + entityHit = owner.withPlayer(APFakePlayer.wrapActionWithReachRange(1, APFakePlayer.wrapActionWithRot(0, -90, action))); + if (entityHit.getType() == HitResult.Type.MISS) { + return MethodResult.of(null, "Nothing found"); + } + } + Entity entity = ((EntityHitResult) entityHit).getEntity(); + if (!sitDown(entity)) { + return MethodResult.of(null, "Entity cannot sit"); + } + if (owner.getTurtle() instanceof TurtleBrain brain) { + brain.getOwner().createServerComputer().queueEvent("saddle_capture"); + } + return MethodResult.of(true); + }, null); + } + + @LuaFunction(mainThread = true) + public MethodResult release() { + if (!standUp()) { + return MethodResult.of(null, "No entity is riding"); + } + return MethodResult.of(true); + } + + @LuaFunction + public boolean hasRider() { + return this.rider != null; + } + + @LuaFunction(mainThread = true) + public MethodResult getRider(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; + Entity entity = getRidingEntity(); + if (entity == null) { + return MethodResult.of(null, "No entity is riding"); + } + Map data = LuaConverter.completeEntityToLua(entity, getPeripheralOwner().getToolInMainHand(), detailed); + if (data.get("pitch") instanceof Number pitch) { + data.put("pitch", (pitch.floatValue() - owner.getTurtle().getDirection().toYRot() + 360 + 180) % 360 - 180); + } + return MethodResult.of(data); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/EndAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/EndAutomataCorePeripheral.java index 90f6ceda7..bb50f1d60 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/EndAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/EndAutomataCorePeripheral.java @@ -10,7 +10,7 @@ public class EndAutomataCorePeripheral extends WeakAutomataCorePeripheral { - public static final String TYPE = "endAutomata"; + public static final String TYPE = "end_automata"; public EndAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { this(TYPE, turtle, side, AutomataCoreTier.TIER2); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/HusbandryAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/HusbandryAutomataCorePeripheral.java index baba65bfd..ba89f1629 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/HusbandryAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/HusbandryAutomataCorePeripheral.java @@ -14,7 +14,7 @@ import java.util.function.Predicate; public class HusbandryAutomataCorePeripheral extends WeakAutomataCorePeripheral { - public static final String TYPE = "husbandryAutomata"; + public static final String TYPE = "husbandry_automata"; private static final Predicate isAnimal = entity1 -> entity1.getType().getCategory().isFriendly(); private static final Predicate isLivingEntity = LivingEntity.class::isInstance; diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredEndAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredEndAutomataCorePeripheral.java index 40a991573..c925da8c1 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredEndAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredEndAutomataCorePeripheral.java @@ -2,22 +2,18 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.operations.AutomataCoreTier; -import de.srendi.advancedperipherals.common.configuration.APConfig; public class OverpoweredEndAutomataCorePeripheral extends EndAutomataCorePeripheral { - public static final String TYPE = "overpoweredEndAutomata"; + public static final String TYPE = "overpowered_end_automata"; public OverpoweredEndAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { super(TYPE, turtle, side, AutomataCoreTier.OVERPOWERED_TIER2); - setAttribute(ATTR_STORING_TOOL_DURABILITY); } - public void addRotationCycle(int count) { - super.addRotationCycle(count); - if (AdvancedPeripherals.RANDOM.nextDouble() <= APConfig.METAPHYSICS_CONFIG.overpoweredAutomataBreakChance.get()) - owner.destroyUpgrade(); + @Override + public boolean canActiveOverpower() { + return true; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredHusbandryAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredHusbandryAutomataCorePeripheral.java index fc8f7e980..2fee520d5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredHusbandryAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredHusbandryAutomataCorePeripheral.java @@ -2,22 +2,18 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.operations.AutomataCoreTier; -import de.srendi.advancedperipherals.common.configuration.APConfig; public class OverpoweredHusbandryAutomataCorePeripheral extends HusbandryAutomataCorePeripheral { - public static final String TYPE = "overpoweredHusbandryAutomata"; + public static final String TYPE = "overpowered_husbandry_automata"; public OverpoweredHusbandryAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { super(TYPE, turtle, side, AutomataCoreTier.OVERPOWERED_TIER2); - setAttribute(ATTR_STORING_TOOL_DURABILITY); } - public void addRotationCycle(int count) { - super.addRotationCycle(count); - if (AdvancedPeripherals.RANDOM.nextDouble() <= APConfig.METAPHYSICS_CONFIG.overpoweredAutomataBreakChance.get()) - owner.destroyUpgrade(); + @Override + public boolean canActiveOverpower() { + return true; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredWeakAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredWeakAutomataCorePeripheral.java index cca911a2a..d8ed7a2c7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredWeakAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/OverpoweredWeakAutomataCorePeripheral.java @@ -2,22 +2,18 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.operations.AutomataCoreTier; -import de.srendi.advancedperipherals.common.configuration.APConfig; public class OverpoweredWeakAutomataCorePeripheral extends WeakAutomataCorePeripheral { - public static final String TYPE = "overpoweredWeakAutomata"; + public static final String TYPE = "overpowered_weak_automata"; public OverpoweredWeakAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { super(TYPE, turtle, side, AutomataCoreTier.OVERPOWERED_TIER1); - setAttribute(ATTR_STORING_TOOL_DURABILITY); } - public void addRotationCycle(int count) { - super.addRotationCycle(count); - if (AdvancedPeripherals.RANDOM.nextDouble() <= APConfig.METAPHYSICS_CONFIG.overpoweredAutomataBreakChance.get()) - owner.destroyUpgrade(); + @Override + public boolean canActiveOverpower() { + return true; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/WeakAutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/WeakAutomataCorePeripheral.java index afaae9ebc..f7befdfe0 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/WeakAutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/metaphysics/WeakAutomataCorePeripheral.java @@ -11,9 +11,23 @@ import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.lib.metaphysics.IAutomataCoreTier; import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral; +import de.srendi.advancedperipherals.lib.peripherals.IPeripheralPlugin; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; public class WeakAutomataCorePeripheral extends AutomataCorePeripheral { - public static final String TYPE = "weakAutomata"; + public static final String TYPE = "weak_automata"; + private static final List> PERIPHERAL_PLUGINS = new ArrayList<>(); + + static { + addIntegrationPlugin(AutomataItemSuckPlugin::new); + addIntegrationPlugin(AutomataLookPlugin::new); + addIntegrationPlugin(AutomataBlockHandPlugin::new); + addIntegrationPlugin(AutomataSoulFeedingPlugin::new); + addIntegrationPlugin(AutomataChargingPlugin::new); + } public WeakAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { this(TYPE, turtle, side, AutomataCoreTier.TIER1); @@ -21,15 +35,22 @@ public WeakAutomataCorePeripheral(ITurtleAccess turtle, TurtleSide side) { protected WeakAutomataCorePeripheral(String type, ITurtleAccess turtle, TurtleSide side, IAutomataCoreTier tier) { super(type, turtle, side, tier); - addPlugin(new AutomataItemSuckPlugin(this)); - addPlugin(new AutomataLookPlugin(this)); - addPlugin(new AutomataBlockHandPlugin(this)); - addPlugin(new AutomataSoulFeedingPlugin(this)); - addPlugin(new AutomataChargingPlugin(this)); + for (Function plugin : PERIPHERAL_PLUGINS) { + addPlugin(plugin.apply(this)); + } + } + + public static void addIntegrationPlugin(Function plugin) { + PERIPHERAL_PLUGINS.add(plugin); } @Override public boolean isEnabled() { return APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore.get(); } + + @Override + public double getBreakChance() { + return APConfig.METAPHYSICS_CONFIG.overpoweredAutomataBreakChance.get(); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataBlockHandPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataBlockHandPlugin.java index a92143043..d767c30ec 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataBlockHandPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataBlockHandPlugin.java @@ -5,7 +5,6 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.core.apis.TableHelper; import dan200.computercraft.shared.turtle.core.TurtlePlayer; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperationContext; @@ -27,24 +26,25 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.SignItem; import net.minecraft.world.item.context.DirectionalPlaceContext; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity; -import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.event.entity.player.PlayerInteractEvent; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.util.Collections; import java.util.Map; -import java.util.stream.Stream; +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.ACCURE_PLACE; import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.DIG; +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.UPDATE_BLOCK; import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.USE_ON_BLOCK; -import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.ACCURE_PLACE; public class AutomataBlockHandPlugin extends AutomataCorePlugin { @@ -54,7 +54,7 @@ public AutomataBlockHandPlugin(AutomataCorePeripheral automataCore) { @Override public @Nullable IPeripheralOperation[] getOperations() { - return new IPeripheralOperation[]{DIG, USE_ON_BLOCK}; + return new IPeripheralOperation[]{ACCURE_PLACE, DIG, UPDATE_BLOCK, USE_ON_BLOCK}; } @LuaFunction(mainThread = true) @@ -69,12 +69,12 @@ public final MethodResult digBlock(@NotNull IArguments arguments) throws LuaExce int previousDamageValue = selectedTool.getDamageValue(); Pair result = owner.withPlayer(APFakePlayer.wrapActionWithShiftKey(sneak, APFakePlayer.wrapActionWithRot(yaw, pitch, APFakePlayer::digBlock))); if (!result.getLeft()) { - return MethodResult.of(null, result.getRight()); + return MethodResult.of(false, result.getRight()); } - if (automataCore.hasAttribute(AutomataCorePeripheral.ATTR_STORING_TOOL_DURABILITY)) { + if (automataCore.canActiveOverpower() && automataCore.afterOverpowerAction()) { selectedTool.setDamageValue(previousDamageValue); } - return MethodResult.of(true); + return MethodResult.of(true, result.getRight()); }); } @@ -89,16 +89,70 @@ public final MethodResult useOnBlock(@NotNull IArguments arguments) throws LuaEx ItemStack selectedTool = owner.getToolInMainHand(); int previousDamageValue = selectedTool.getDamageValue(); InteractionResult result = owner.withPlayer(APFakePlayer.wrapActionWithShiftKey(sneak, APFakePlayer.wrapActionWithRot(yaw, pitch, APFakePlayer::useOnBlock))); - if (automataCore.hasAttribute(AutomataCorePeripheral.ATTR_STORING_TOOL_DURABILITY)) { + if (result.consumesAction() && automataCore.canActiveOverpower() && automataCore.afterOverpowerAction()) { + selectedTool.setDamageValue(previousDamageValue); + } + return MethodResult.of(result.consumesAction(), result.toString()); + }); + } + + /** + * updateBlock method let turtle update specific block's status. + * It require a compass to be equipped to perform actions. + * + * @param options A table contains where to find the block and how to update the block + * yaw: relative yaw + * pitch: relative pitch + * + * text: the text going to write if the target is a sign. + */ + @LuaFunction(mainThread = true) + public final MethodResult updateBlock(@NotNull IArguments arguments) throws LuaException { + if (!automataCore.getPeripheralOwner().hasConnectedPeripheral(CompassPeripheral.class)) { + return MethodResult.of(false, "COMPASS_NOT_EQUIPPED"); + } + Map opts = arguments.count() > 0 ? arguments.getTable(0) : Collections.emptyMap(); + float yaw = opts != null ? (float) TableHelper.optNumberField(opts, "yaw", 0) : 0; + float pitch = opts != null ? (float) TableHelper.optNumberField(opts, "pitch", 0) : 0; + return automataCore.withOperation(UPDATE_BLOCK, context -> { + TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); + ItemStack selectedTool = owner.getToolInMainHand(); + int previousDamageValue = selectedTool.getDamageValue(); + InteractionResult result = owner.withPlayer(APFakePlayer.wrapActionWithRot(yaw, pitch, (player) -> this.updateBlock(player, opts))); + if (result.consumesAction() && automataCore.canActiveOverpower() && automataCore.afterOverpowerAction()) { selectedTool.setDamageValue(previousDamageValue); } return MethodResult.of(result.consumesAction(), result.toString()); }); } + private InteractionResult updateBlock(APFakePlayer player, Map options) { + Level world = player.getLevel(); + HitResult hit = player.findHit(true, false); + if (!(hit instanceof BlockHitResult blockHit)) { + return InteractionResult.PASS; + } + BlockPos pos = blockHit.getBlockPos(); + BlockEntity block = world.getBlockEntity(pos); + if (block instanceof SignBlockEntity sign) { + String text; + try { + text = TableHelper.optStringField(options, "text", null); + } catch (LuaException e) { + // Why not allow empty catch block? TAT + text = null; + } + if (text != null) { + setSignText(world, sign, StringUtil.convertAndToSectionMark(text)); + return InteractionResult.CONSUME; + } + } + return InteractionResult.PASS; + } + /** * placeBlock method will let turtle place a block with more details when compass has equipped. - * It should not able to place fluids / use any item, because compass do not recognize them. + * It should not able to place fluids / use any item, because compass does not recognize them. * * @param options A table contains how to place the block: * x: the x offset relative to the turtle. Default 0 @@ -110,10 +164,9 @@ public final MethodResult useOnBlock(@NotNull IArguments arguments) throws LuaEx * text: the text going to write on the sign. Default is null */ @LuaFunction(mainThread = true) - public MethodResult placeBlock(@NotNull Map options) throws LuaException { + public final MethodResult placeBlock(@NotNull Map options) throws LuaException { ITurtleAccess turtle = automataCore.getPeripheralOwner().getTurtle(); - CompassPeripheral compassPeripheral = Stream.of(TurtleSide.values()).map(side -> turtle.getPeripheral(side) instanceof CompassPeripheral compass ? compass : null).filter(peripheral -> peripheral != null).findFirst().orElse(null); - if (compassPeripheral == null || !compassPeripheral.isEnabled()) { + if (!automataCore.getPeripheralOwner().hasConnectedPeripheral(CompassPeripheral.class)) { return MethodResult.of(false, "COMPASS_NOT_EQUIPPED"); } int x = TableHelper.optIntField(options, "x", 0); @@ -176,12 +229,12 @@ private String deployOn(ItemStack stack, BlockPos position, Direction anchor, Di if (!(item instanceof BlockItem)) { return "NOT_BLOCK"; } - BlockItem block = (BlockItem) item; - InteractionResult res = block.place(context); + BlockItem blockItem = (BlockItem) item; + InteractionResult res = blockItem.place(context); if (!res.consumesAction()) { return "CANNOT_PLACE"; } - if (block instanceof SignItem) { + if (blockItem instanceof SignItem) { BlockEntity blockEntity = world.getBlockEntity(position); if (blockEntity instanceof SignBlockEntity sign) { String text = StringUtil.convertAndToSectionMark(TableHelper.optStringField(options, "text", null)); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataChargingPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataChargingPlugin.java index d47108ac4..2ffdb4d43 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataChargingPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataChargingPlugin.java @@ -11,8 +11,8 @@ import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.capabilities.ForgeCapabilities; - import org.jetbrains.annotations.NotNull; + import java.util.Objects; public class AutomataChargingPlugin extends AutomataCorePlugin { diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java index 09731f3e2..2139e4ab5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java @@ -18,9 +18,9 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.util.Collections; import java.util.List; import java.util.Map; @@ -53,9 +53,9 @@ public final MethodResult useOnAnimal(@NotNull IArguments arguments) throws LuaE ItemStack selectedTool = owner.getToolInMainHand(); int previousDamageValue = selectedTool.getDamageValue(); InteractionResult result = owner.withPlayer(APFakePlayer.wrapActionWithShiftKey(sneak, APFakePlayer.wrapActionWithRot(yaw, pitch, p -> p.useOnFilteredEntity(suitableEntity)))); - if (automataCore.hasAttribute(AutomataCorePeripheral.ATTR_STORING_TOOL_DURABILITY)) + if (automataCore.canActiveOverpower() && automataCore.afterOverpowerAction()) { selectedTool.setDamageValue(previousDamageValue); - + } return MethodResult.of(result.consumesAction(), result.toString()); }); } @@ -76,17 +76,18 @@ public final MethodResult inspectAnimal(@NotNull IArguments arguments) throws Lu if (!(entity instanceof Animal animal)) return MethodResult.of(null, "Well, entity is not animal entity, but how?"); - return MethodResult.of(LuaConverter.animalToLua(animal, owner.getToolInMainHand())); + return MethodResult.of(LuaConverter.completeEntityToLua(animal, owner.getToolInMainHand(), true)); } @LuaFunction(mainThread = true) - public final MethodResult searchAnimals() { + public final MethodResult searchAnimals(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; automataCore.addRotationCycle(); TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); BlockPos currentPos = owner.getPos(); AABB box = new AABB(currentPos); ItemStack itemInHand = owner.getToolInMainHand(); - List> entities = owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, itemInHand, currentPos)).toList(); + List> entities = owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, itemInHand, currentPos, detailed)).toList(); return MethodResult.of(entities); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java index e46ca4356..9f0d30166 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java @@ -18,9 +18,9 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.util.Collections; import java.util.Map; import java.util.function.Predicate; @@ -120,8 +120,12 @@ public final MethodResult releaseAnimal() { } @LuaFunction(mainThread = true) - public final MethodResult getCapturedAnimal() { + public final MethodResult getCapturedAnimal(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; Entity extractedEntity = extractEntity(); - return MethodResult.of(LuaConverter.completeEntityToLua(extractedEntity, automataCore.getPeripheralOwner().getToolInMainHand())); + if (extractedEntity == null) { + return MethodResult.of(null, "No entity is stored"); + } + return MethodResult.of(LuaConverter.completeEntityToLua(extractedEntity, automataCore.getPeripheralOwner().getToolInMainHand(), detailed)); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataItemSuckPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataItemSuckPlugin.java index 526ffd532..796e8f386 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataItemSuckPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataItemSuckPlugin.java @@ -15,8 +15,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraftforge.registries.ForgeRegistries; - import org.jetbrains.annotations.NotNull; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -84,7 +84,7 @@ public final MethodResult scanItems() { int index = 1; for (ItemEntity item : items) { ItemStack stack = item.getItem(); - Map itemData = LuaConverter.stackToObject(stack); + Map itemData = LuaConverter.itemStackToObject(stack); itemData.put("entityID", item.getId()); data.put(index, itemData); index++; diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java index 2b27487bf..cba185c95 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java @@ -5,21 +5,26 @@ import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.core.apis.TableHelper; +import de.srendi.advancedperipherals.common.addons.APAddons; import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; +import de.srendi.advancedperipherals.common.addons.valkyrienskies.ValkyrienSkies; import de.srendi.advancedperipherals.common.util.LuaConverter; import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral; + +import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.jetbrains.annotations.NotNull; public class AutomataLookPlugin extends AutomataCorePlugin { @@ -36,16 +41,25 @@ public final MethodResult lookAtBlock(@NotNull IArguments arguments) throws LuaE automataCore.addRotationCycle(); TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); HitResult result = owner.withPlayer(APFakePlayer.wrapActionWithRot(yaw, pitch, p -> p.findHit(true, false))); - if (result.getType() == HitResult.Type.MISS) + if (result.getType() == HitResult.Type.MISS) { return MethodResult.of(null, "No block find"); + } BlockHitResult blockHit = (BlockHitResult) result; - BlockState state = owner.getLevel().getBlockState(blockHit.getBlockPos()); + BlockPos blockPos = blockHit.getBlockPos(); + BlockState state = owner.getLevel().getBlockState(blockPos); Map data = new HashMap<>(); ResourceLocation blockName = ForgeRegistries.BLOCKS.getKey(state.getBlock()); - if (blockName != null) - data.put("name", blockName.toString()); + data.put("name", blockName == null ? null : blockName.toString()); data.put("tags", LuaConverter.tagsToList(() -> state.getBlock().builtInRegistryHolder().tags())); + Vec3 pos = blockHit.getLocation(); + Vec3 origin = automataCore.getPhysicsPos(); + data.put("x", pos.x - origin.x); + data.put("y", pos.y - origin.y); + data.put("z", pos.z - origin.z); + if (APAddons.vs2Loaded) { + ValkyrienSkies.encodeShipInfo(automataCore.getLevel(), blockPos, data); + } return MethodResult.of(data); } @@ -57,11 +71,13 @@ public final MethodResult lookAtEntity(@NotNull IArguments arguments) throws Lua automataCore.addRotationCycle(); HitResult result = automataCore.getPeripheralOwner().withPlayer(APFakePlayer.wrapActionWithRot(yaw, pitch, p -> p.findHit(false, true))); - if (result.getType() == HitResult.Type.MISS) + if (result.getType() == HitResult.Type.MISS) { return MethodResult.of(null, "No entity find"); + } EntityHitResult entityHit = (EntityHitResult) result; - return MethodResult.of(LuaConverter.entityToLua(entityHit.getEntity())); + Vec3 origin = automataCore.getPhysicsPos(); + return MethodResult.of(LuaConverter.completeEntityWithPositionToLua(entityHit.getEntity(), origin, true)); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java index 712ce2c29..b07c0e3ee 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java @@ -1,31 +1,41 @@ package de.srendi.advancedperipherals.common.addons.computercraft.peripheral.plugins; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.ILuaCallback; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.turtle.ITurtleAccess; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperationContext; import de.srendi.advancedperipherals.common.addons.computercraft.owner.FuelAbility; import de.srendi.advancedperipherals.common.addons.computercraft.owner.PeripheralOwnerAbility; import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.entity.TurtleEnderPearl; +import de.srendi.advancedperipherals.common.util.LuaConverter; import de.srendi.advancedperipherals.common.util.NBTUtil; import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.ServerWorker; import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralOperation; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.WARP; +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.*; public class AutomataWarpingPlugin extends AutomataCorePlugin { private static final String POINT_DATA_MARK = "warp_points"; - private static final String WORLD_DATA_MARK = "warp_world"; + + private final Map shipPearls = new HashMap<>(); public AutomataWarpingPlugin(AutomataCorePeripheral automataCore) { super(automataCore); @@ -33,26 +43,36 @@ public AutomataWarpingPlugin(AutomataCorePeripheral automataCore) { @Override public @Nullable IPeripheralOperation[] getOperations() { - return new IPeripheralOperation[]{WARP}; + return new IPeripheralOperation[]{WARP, PREPARE_PORTAL, ACTIVE_PORTAL}; } @NotNull protected Pair getPointData() { TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); CompoundTag settings = owner.getDataStorage(); - if (!settings.contains(WORLD_DATA_MARK)) { - settings.putString(WORLD_DATA_MARK, owner.getLevel().dimension().location().toString()); - } else { - String worldName = settings.getString(WORLD_DATA_MARK); - if (!owner.getLevel().dimension().location().toString().equals(worldName)) - return Pair.onlyLeft(MethodResult.of(null, "Incorrect world for this upgrade")); - } - if (!settings.contains(POINT_DATA_MARK)) + if (!settings.contains(POINT_DATA_MARK)) { settings.put(POINT_DATA_MARK, new CompoundTag()); + } return Pair.onlyRight(settings.getCompound(POINT_DATA_MARK)); } + protected Pair getPoint(String name) { + Pair res = getPointData(); + if (res.leftPresent()) { + return Pair.onlyLeft(res.getLeft()); + } + CompoundTag points = res.getRight(); + if (!points.contains(name)) { + return Pair.onlyLeft(MethodResult.of(null, "Warp point not exists")); + } + return Pair.onlyRight(points.getCompound(name)); + } + + private SingleOperationContext getWarpContext(Level level, BlockPos pos) { + return level == automataCore.getPeripheralOwner().getLevel() ? automataCore.toDistance(pos) : new SingleOperationContext(getCostsToLevel(level), 1); + } + private int getWarpCost(SingleOperationContext context) { FuelAbility fuelAbility = automataCore.getPeripheralOwner().getAbility(PeripheralOwnerAbility.FUEL); Objects.requireNonNull(fuelAbility); @@ -63,14 +83,18 @@ private int getWarpCost(SingleOperationContext context) { public final MethodResult savePoint(String name) { automataCore.addRotationCycle(); Pair pairData = getPointData(); - if (pairData.leftPresent()) + if (pairData.leftPresent()) { return pairData.getLeft(); + } CompoundTag data = pairData.getRight(); - if (data.getAllKeys().size() >= APConfig.METAPHYSICS_CONFIG.endAutomataCoreWarpPointLimit.get()) + if (data.getAllKeys().size() >= APConfig.METAPHYSICS_CONFIG.endAutomataCoreWarpPointLimit.get()) { return MethodResult.of(null, "Cannot add new point, limit reached"); + } - data.put(name, NBTUtil.toNBT(automataCore.getPeripheralOwner().getPos())); + TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); + Level level = owner.getLevel(); + data.put(name, NBTUtil.toNBT(level, owner.getPos())); return MethodResult.of(true); } @@ -78,12 +102,14 @@ public final MethodResult savePoint(String name) { public final MethodResult deletePoint(String name) { automataCore.addRotationCycle(); Pair pairData = getPointData(); - if (pairData.leftPresent()) + if (pairData.leftPresent()) { return pairData.getLeft(); + } CompoundTag data = pairData.getRight(); - if (!data.contains(name)) + if (!data.contains(name)) { return MethodResult.of(null, "Cannot find point to delete"); + } data.remove(name); return MethodResult.of(true); @@ -92,8 +118,9 @@ public final MethodResult deletePoint(String name) { @LuaFunction(mainThread = true) public final MethodResult points() { Pair pairData = getPointData(); - if (pairData.leftPresent()) + if (pairData.leftPresent()) { return pairData.getLeft(); + } CompoundTag data = pairData.getRight(); return MethodResult.of(data.getAllKeys()); @@ -101,46 +128,220 @@ public final MethodResult points() { @LuaFunction(mainThread = true) public final MethodResult warpToPoint(String name) throws LuaException { - Pair pairData = getPointData(); - if (pairData.leftPresent()) + Pair pairData = getPoint(name); + if (pairData.leftPresent()) { return pairData.getLeft(); + } TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); - Level level = owner.getLevel(); - CompoundTag data = pairData.getRight(); - BlockPos newPosition = NBTUtil.blockPosFromNBT(data.getCompound(name)); - return automataCore.withOperation(WARP, automataCore.toDistance(newPosition), context -> { - boolean result = owner.move(level, newPosition); - if (!result) + Pair newLevelAndPosition = NBTUtil.levelAndBlockPosFromNBT(pairData.getRight()); + Level newLevel = newLevelAndPosition.getLeft(); + BlockPos newPosition = newLevelAndPosition.getRight(); + + return automataCore.withOperation(WARP, getWarpContext(newLevel, newPosition), context -> { + boolean result = owner.move(newLevel, newPosition); + if (!result) { return MethodResult.of(null, "Cannot teleport to location"); + } return MethodResult.of(true); }, context -> { - if (!owner.isMovementPossible(level, newPosition)) + if (!owner.isMovementPossible(newLevel, newPosition)) { return MethodResult.of(null, "Move forbidden"); + } return null; }); } @LuaFunction(mainThread = true) public final MethodResult estimateWarpCost(String name) { - Pair pairData = getPointData(); - if (pairData.leftPresent()) + Pair pairData = getPoint(name); + if (pairData.leftPresent()) { return pairData.getLeft(); + } - CompoundTag data = pairData.getRight(); - BlockPos newPosition = NBTUtil.blockPosFromNBT(data.getCompound(name)); - return MethodResult.of(getWarpCost(automataCore.toDistance(newPosition))); + Pair newLevelAndPosition = NBTUtil.levelAndBlockPosFromNBT(pairData.getRight()); + return MethodResult.of(getWarpCost(getWarpContext(newLevelAndPosition.getLeft(), newLevelAndPosition.getRight()))); } @LuaFunction(mainThread = true) public final MethodResult distanceToPoint(String name) { - Pair pairData = getPointData(); - if (pairData.leftPresent()) + Pair pairData = getPoint(name); + if (pairData.leftPresent()) { return pairData.getLeft(); + } - CompoundTag data = pairData.getRight(); - BlockPos newPosition = NBTUtil.blockPosFromNBT(data.getCompound(name)); - return MethodResult.of(newPosition.distManhattan(automataCore.getPeripheralOwner().getPos())); + TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); + Pair newLevelAndPosition = NBTUtil.levelAndBlockPosFromNBT(pairData.getRight()); + if (newLevelAndPosition.getLeft() != owner.getLevel()) { + return MethodResult.of(-1); + } + return MethodResult.of(newLevelAndPosition.getRight().distManhattan(owner.getPos())); + } + + /** + * This method will prepare to teleport to the other side of the portal. + * Prepare will always costs constant fuel. + * + * @return table | nil, string + * the result will looks like: + *
+     * 
+     * {
+     *   name = "minecraft:nether", -- the target dimension's name
+     *   pos = { -- the position turtle will teleport to
+     *     x = 0,
+     *     y = 0,
+     *     z = 0,
+     *   },
+     *   facing = "north", -- where will the turtle face after teleport
+     *   costs = 10000, -- the costs to cross the portal
+     *   canSpawn = true, -- if the target position is not blocked and turtle are able to spawn there
+     *   shipId = "xxx", -- the random id used for ship the portal. You have to call portalShipActive(shipId) if needed.
+     * }
+     * 
+     * 
+ */ + @LuaFunction + public final MethodResult portalShipPrepare(IArguments arguments) throws LuaException { + Direction direction; + switch (arguments.optString(0).orElse("").toLowerCase()) { + case "up": + case "top": + direction = Direction.UP; + break; + case "down": + case "bottom": + direction = Direction.DOWN; + break; + case "front": + case "": + direction = null; + break; + default: + return MethodResult.of(null, "Direction can only be 'up', 'top', 'down', 'bottom', or 'front'"); + } + + TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); + ITurtleAccess turtle = owner.getTurtle(); + TurtleEnderPearl shipPearl = new TurtleEnderPearl(turtle, direction); + String shipId = shipPearl.getStringUUID(); + ServerWorker.add(() -> { + MethodResult res; + try { + res = automataCore.withOperation(PREPARE_PORTAL, new SingleOperationContext(1, 1), context -> { + shipPearl.setCallback(pearl -> { + if (pearl == null || pearl.isRemoved()) { + automataCore.queueEvent(PortalPrepareCallback.FAILED_EVENT_ID, shipId, "PEARL_GONE"); + shipPearls.remove(shipId); + return; + } + Level level = pearl.getLevel(); + if (level == turtle.getLevel()) { + automataCore.queueEvent(PortalPrepareCallback.FAILED_EVENT_ID, shipId, "NO_PORTAL_FOUND"); + pearl.discard(); + return; + } + BlockPos pos = pearl.blockPosition(); + Map data = new HashMap<>(); + data.put("name", level.dimension().location().toString()); + data.put("pos", LuaConverter.posToObject(pos)); + data.put("facing", pearl.getDirection().getName()); + data.put("costs", getCostsToLevel(level)); + data.put("canSpawn", owner.isMovementPossible(level, pos)); + data.put("shipId", shipId); + shipPearls.put(shipId, pearl); + automataCore.queueEvent(PortalPrepareCallback.EVENT_ID, data); + }); + turtle.getLevel().addFreshEntity(shipPearl); + return null; + }, null); + } catch (LuaException e) { + res = MethodResult.of(null, "Unexpected java error: " + e.toString()); + } + if (res != null) { + Object err = res.getResult()[1]; + automataCore.queueEvent(PortalPrepareCallback.FAILED_EVENT_ID, shipId, err); + } + }); + return new PortalPrepareCallback(shipId).pull; + } + + /** + * @param id the random shipId, one of the result from portalShipPrepare() + * @return true | nil, string + */ + @LuaFunction(mainThread = true) + public final MethodResult portalShipActive(String id) throws LuaException { + TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); + TurtleEnderPearl shipPearl = shipPearls.get(id); + if (shipPearl == null) { + return MethodResult.of(null, "ID_NOT_EXISTS"); + } + if (shipPearl.isRemoved()) { + shipPearls.remove(id); + return MethodResult.of(null, "ID_NOT_EXISTS"); + } + Level level = shipPearl.getLevel(); + BlockPos newPosition = shipPearl.blockPosition(); + return automataCore.withOperation(ACTIVE_PORTAL, new SingleOperationContext(getCostsToLevel(level), 1), context -> { + shipPearl.discard(); + boolean result = owner.move(level, newPosition); + if (!result) { + return MethodResult.of(null, "Cannot teleport to location"); + } + shipPearls.remove(id); + return MethodResult.of(true); + }, context -> { + if (!owner.isMovementPossible(level, newPosition)) { + return MethodResult.of(null, "Move forbidden"); + } + return null; + }); + } + + private static int getCostsToLevel(Level level) { + String dimension = level.dimension().location().toString(); + // TODO: load fuel costs from config + switch (dimension) { + case "minecraft:overworld": + return 10000; + case "minecraft:the_nether": + return 20000; + case "minecraft:the_end": + return 50000; + } + return 10000; } + private static final class PortalPrepareCallback implements ILuaCallback { + static final String EVENT_ID = "portal_prepare"; + static final String FAILED_EVENT_ID = "portal_prepare_failed"; + final MethodResult pull = MethodResult.pullEvent(null, this); + private final String id; + + PortalPrepareCallback(String id) { + this.id = id; + } + + @NotNull + @Override + public MethodResult resume(Object[] datas) { + if (datas.length <= 0) { + return pull; + } + if (FAILED_EVENT_ID.equals(datas[0])) { + if (datas.length != 3 || !id.equals(datas[1])) { + return pull; + } + return MethodResult.of(null, datas[2]); + } + if (!EVENT_ID.equals(datas[0]) || datas.length != 2) { + return pull; + } + if (!(datas[1] instanceof Map data) || !id.equals(data.get("shipId"))) { + return pull; + } + return MethodResult.of(data); + } + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketChatBoxUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketChatBoxUpgrade.java index e0a17833b..5264a1b46 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketChatBoxUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketChatBoxUpgrade.java @@ -15,8 +15,8 @@ public PocketChatBoxUpgrade(ResourceLocation id, ItemStack stack) { @Nullable @Override - public ChatBoxPeripheral getPeripheral(IPocketAccess access) { - return new ChatBoxPeripheral(access); + public ChatBoxPeripheral getPeripheral(IPocketAccess pocketAccess) { + return new ChatBoxPeripheral(pocketAccess, this); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketColonyIntegratorUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketColonyIntegratorUpgrade.java index 752ccb18e..6c439404f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketColonyIntegratorUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketColonyIntegratorUpgrade.java @@ -13,7 +13,7 @@ public PocketColonyIntegratorUpgrade(ResourceLocation id, ItemStack stack) { } @Override - protected ColonyPeripheral getPeripheral(IPocketAccess access) { - return new ColonyPeripheral(access); + protected ColonyPeripheral getPeripheral(IPocketAccess pocketAccess) { + return new ColonyPeripheral(pocketAccess, this); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketDistanceDetectorUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketDistanceDetectorUpgrade.java new file mode 100644 index 000000000..82b47d31f --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketDistanceDetectorUpgrade.java @@ -0,0 +1,23 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.pocket; + +import dan200.computercraft.api.pocket.IPocketAccess; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.DistanceDetectorPeripheral; +import de.srendi.advancedperipherals.lib.pocket.BasePocketUpgrade; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PocketDistanceDetectorUpgrade extends BasePocketUpgrade { + + public PocketDistanceDetectorUpgrade(ResourceLocation id, ItemStack stack) { + super(id, stack); + } + + @Nullable + @Override + public DistanceDetectorPeripheral getPeripheral(@NotNull IPocketAccess pocketAccess) { + return new DistanceDetectorPeripheral(pocketAccess, this); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketEnvironmentUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketEnvironmentUpgrade.java index dc6719b17..dd23a28b8 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketEnvironmentUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketEnvironmentUpgrade.java @@ -16,8 +16,8 @@ public PocketEnvironmentUpgrade(ResourceLocation id, ItemStack stack) { @Nullable @Override - public EnvironmentDetectorPeripheral getPeripheral(@NotNull IPocketAccess iPocketAccess) { - return new EnvironmentDetectorPeripheral(iPocketAccess); + public EnvironmentDetectorPeripheral getPeripheral(@NotNull IPocketAccess pocketAccess) { + return new EnvironmentDetectorPeripheral(pocketAccess, this); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketGeoScannerUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketGeoScannerUpgrade.java index 98823d94a..03d23d26a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketGeoScannerUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketGeoScannerUpgrade.java @@ -16,8 +16,8 @@ public PocketGeoScannerUpgrade(ResourceLocation id, ItemStack stack) { @Nullable @Override - public GeoScannerPeripheral getPeripheral(@NotNull IPocketAccess iPocketAccess) { - return new GeoScannerPeripheral(iPocketAccess); + public GeoScannerPeripheral getPeripheral(@NotNull IPocketAccess pocketAccess) { + return new GeoScannerPeripheral(pocketAccess, this); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketPlayerDetectorUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketPlayerDetectorUpgrade.java index 1e2b6bb43..422b02e0f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketPlayerDetectorUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/pocket/PocketPlayerDetectorUpgrade.java @@ -16,8 +16,8 @@ public PocketPlayerDetectorUpgrade(ResourceLocation id, ItemStack stack) { @Nullable @Override - public PlayerDetectorPeripheral getPeripheral(@NotNull IPocketAccess iPocketAccess) { - return new PlayerDetectorPeripheral(iPocketAccess); + public PlayerDetectorPeripheral getPeripheral(@NotNull IPocketAccess pocketAccess) { + return new PlayerDetectorPeripheral(pocketAccess, this); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleChatBoxUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleChatBoxUpgrade.java index b82aafab2..f8d9f7e4d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleChatBoxUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleChatBoxUpgrade.java @@ -29,15 +29,4 @@ public ModelResourceLocation getRightModel() { protected ChatBoxPeripheral buildPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { return new ChatBoxPeripheral(turtle, side); } - - @Override - public void update(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { - super.update(turtle, side); - if (turtle.getLevel().isClientSide) - return; - - if (turtle.getPeripheral(side) instanceof ChatBoxPeripheral chatBox) { - chatBox.update(); - } - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java new file mode 100644 index 000000000..d1098f63d --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java @@ -0,0 +1,45 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.turtles; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleSide; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.SaddlePeripheral; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.lib.turtle.PeripheralTurtleUpgrade; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class TurtleSaddleUpgrade extends PeripheralTurtleUpgrade { + + public TurtleSaddleUpgrade(ResourceLocation id, ItemStack stack) { + super(id, stack); + } + + @Override + public ModelResourceLocation getLeftModel() { + return null; + } + + @Override + public ModelResourceLocation getRightModel() { + return null; + } + + @Override + protected SaddlePeripheral buildPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { + return new SaddlePeripheral(turtle, side); + } + + @Override + public void update(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { + super.update(turtle, side); + if (APConfig.PERIPHERALS_CONFIG.enableSaddleTurtle.get()) { + IPeripheral peripheral = turtle.getPeripheral(side); + if (peripheral instanceof SaddlePeripheral saddlePeripheral) { + saddlePeripheral.update(); + } + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/create/BasinIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/create/BasinIntegration.java index fd94787a9..ab7ffce5c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/create/BasinIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/create/BasinIntegration.java @@ -6,10 +6,10 @@ import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -68,7 +68,7 @@ public final List getOutputFluids() { @LuaFunction(mainThread = true) public final Map getFilter() { - return LuaConverter.stackToObject(blockEntity.getFilter().getFilter()); + return LuaConverter.itemStackToObject(blockEntity.getFilter().getFilter()); } @LuaFunction(mainThread = true) @@ -78,7 +78,7 @@ public final List getInventory() { IItemHandler handler = handlerOptional.get(); List items = new ArrayList<>(); for (int slot = 0; slot < handler.getSlots(); slot++) { - items.add(LuaConverter.stackToObject(handler.getStackInSlot(slot))); + items.add(LuaConverter.itemStackToObject(handler.getStackInSlot(slot))); } return items; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/create/BlazeBurnerIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/create/BlazeBurnerIntegration.java index 88bde5dca..eb45e1f28 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/create/BlazeBurnerIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/create/BlazeBurnerIntegration.java @@ -18,7 +18,7 @@ public BlazeBurnerIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "blazeBurner"; + return "blaze_burner"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/create/FluidTankIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/create/FluidTankIntegration.java index e8d4b0779..cc59643e2 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/create/FluidTankIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/create/FluidTankIntegration.java @@ -19,7 +19,7 @@ public FluidTankIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "fluidTank"; + return "fluid_tank"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/create/MechanicalMixerIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/create/MechanicalMixerIntegration.java index 0c87f7763..91140fd47 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/create/MechanicalMixerIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/create/MechanicalMixerIntegration.java @@ -16,7 +16,7 @@ public MechanicalMixerIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "mechanicalMixer"; + return "mechanical_mixer"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/create/ScrollValueBehaviourIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/create/ScrollValueBehaviourIntegration.java index 32dbc4a1d..81e58614b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/create/ScrollValueBehaviourIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/create/ScrollValueBehaviourIntegration.java @@ -19,7 +19,7 @@ public ScrollValueBehaviourIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "scrollBehaviourEntity"; + return "scroll_behaviour_entity"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/DimChestIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/DimChestIntegration.java new file mode 100644 index 000000000..037775037 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/DimChestIntegration.java @@ -0,0 +1,55 @@ +package de.srendi.advancedperipherals.common.addons.dimstorage; + +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; +import edivad.dimstorage.api.Frequency; +import edivad.dimstorage.blockentities.BlockEntityDimChest; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class DimChestIntegration extends BlockEntityIntegrationPeripheral { + + protected DimChestIntegration(BlockEntity entity) { + super(entity); + } + + @NotNull + @Override + public String getType() { + return "dimChest"; + } + + @LuaFunction(mainThread = true) + public final String getOwnerUUID() { + UUID uuid = blockEntity.getFrequency().getOwnerUUID(); + if (uuid == null) + return null; + return uuid.toString(); + } + + @LuaFunction(mainThread = true) + public final String getOwner() { + return blockEntity.getFrequency().getOwner(); + } + + @LuaFunction(mainThread = true) + public final boolean hasOwner() { + return blockEntity.getFrequency().hasOwner(); + } + + @LuaFunction(mainThread = true) + public final int getChannel() { + return blockEntity.getFrequency().getChannel(); + } + + @LuaFunction(mainThread = true) + public final boolean setChannel(int channel) { + Frequency fre = blockEntity.getFrequency(); + if (fre.hasOwner()) return false; + fre.setChannel(channel); + blockEntity.setFrequency(fre); + return true; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/Integration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/Integration.java new file mode 100644 index 000000000..a74e46b62 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/dimstorage/Integration.java @@ -0,0 +1,12 @@ +package de.srendi.advancedperipherals.common.addons.dimstorage; + +import de.srendi.advancedperipherals.common.addons.computercraft.integrations.IntegrationPeripheralProvider; +import edivad.dimstorage.blockentities.BlockEntityDimChest; + +public class Integration implements Runnable { + + @Override + public void run() { + IntegrationPeripheralProvider.registerBlockEntityIntegration(DimChestIntegration::new, BlockEntityDimChest.class); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/mekanism/MekanismCapabilities.java b/src/main/java/de/srendi/advancedperipherals/common/addons/mekanism/MekanismCapabilities.java new file mode 100644 index 000000000..026e1c25a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/mekanism/MekanismCapabilities.java @@ -0,0 +1,11 @@ +package de.srendi.advancedperipherals.common.addons.mekanism; + +import mekanism.api.chemical.gas.IGasHandler; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityToken; + +import static net.minecraftforge.common.capabilities.CapabilityManager.get; + +public class MekanismCapabilities { + public static final Capability GAS_HANDLER = get(new CapabilityToken<>() {}); +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/minecolonies/MineColonies.java b/src/main/java/de/srendi/advancedperipherals/common/addons/minecolonies/MineColonies.java index 96ec59d49..7f5cae76c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/minecolonies/MineColonies.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/minecolonies/MineColonies.java @@ -9,7 +9,11 @@ import com.minecolonies.api.colony.permissions.Action; import com.minecolonies.api.colony.workorders.IWorkOrder; import com.minecolonies.api.entity.citizen.Skill; -import com.minecolonies.api.research.*; +import com.minecolonies.api.research.IGlobalResearch; +import com.minecolonies.api.research.IGlobalResearchTree; +import com.minecolonies.api.research.ILocalResearch; +import com.minecolonies.api.research.ILocalResearchTree; +import com.minecolonies.api.research.IResearchRequirement; import com.minecolonies.api.research.costs.IResearchCost; import com.minecolonies.api.research.effects.IResearchEffect; import com.minecolonies.api.research.util.ResearchState; @@ -107,7 +111,7 @@ public static Object visitorToObject(IVisitorData visitor) { map.put("saturation", visitor.getSaturation()); map.put("happiness", visitor.getCitizenHappinessHandler().getHappiness(visitor.getColony(), visitor)); map.put("skills", skillsToObject(visitor.getCitizenSkillHandler().getSkills())); - map.put("recruitCost", LuaConverter.stackToObject(visitor.getRecruitCost())); + map.put("recruitCost", LuaConverter.itemStackToObject(visitor.getRecruitCost())); return map; } @@ -349,7 +353,7 @@ public static Object builderResourcesToObject(IColony colony, BlockPos pos) { Map map = new HashMap<>(); ItemStack stack = resource.getItemStack().copy(); - map.put("item", LuaConverter.stackToObject(stack)); + map.put("item", LuaConverter.itemStackToObject(stack)); map.put("displayName", resource.getName()); map.put("available", resource.getAvailable()); map.put("delivering", resource.getAmountInDelivery()); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnderCellIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnderCellIntegration.java index cee6df8b1..b6e2dcf76 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnderCellIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnderCellIntegration.java @@ -14,7 +14,7 @@ protected EnderCellIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "enderCell"; + return "ender_cell"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnergyCellIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnergyCellIntegration.java index c437e31a6..043b29f81 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnergyCellIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/EnergyCellIntegration.java @@ -14,7 +14,7 @@ protected EnergyCellIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "energyCell"; + return "energy_cell"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/FurnatorIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/FurnatorIntegration.java index f1f7a5771..4f9f31400 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/FurnatorIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/FurnatorIntegration.java @@ -1,8 +1,8 @@ package de.srendi.advancedperipherals.common.addons.powah; import dan200.computercraft.api.lua.LuaFunction; -import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; @@ -50,6 +50,6 @@ public final Object getInventory() { if (stack.isEmpty()) { return null; } - return LuaConverter.stackToObject(stack); + return LuaConverter.itemStackToObject(stack); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/Integration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/Integration.java index dcd8e301b..6de92c792 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/Integration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/Integration.java @@ -1,8 +1,8 @@ package de.srendi.advancedperipherals.common.addons.powah; import de.srendi.advancedperipherals.common.addons.computercraft.integrations.IntegrationPeripheralProvider; -import owmii.powah.block.energycell.EnergyCellTile; import owmii.powah.block.ender.EnderCellTile; +import owmii.powah.block.energycell.EnergyCellTile; import owmii.powah.block.furnator.FurnatorTile; import owmii.powah.block.magmator.MagmatorTile; import owmii.powah.block.reactor.ReactorPartTile; diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/ReactorIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/ReactorIntegration.java index 150911521..3dcb1979c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/ReactorIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/ReactorIntegration.java @@ -1,8 +1,8 @@ package de.srendi.advancedperipherals.common.addons.powah; import dan200.computercraft.api.lua.LuaFunction; -import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.lib.peripherals.BlockEntityIntegrationPeripheral; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; @@ -16,7 +16,7 @@ protected ReactorIntegration(BlockEntity entity) { @Override @NotNull public String getType() { - return "uraniniteReactor"; + return "uraninite_reactor"; } @LuaFunction(mainThread = true) @@ -82,7 +82,7 @@ public final Object getInventoryUraninite() { if (stack.isEmpty()) { return null; } - return LuaConverter.stackToObject(stack); + return LuaConverter.itemStackToObject(stack); } @LuaFunction(mainThread = true) @@ -94,7 +94,7 @@ public final Object getInventoryRedstone() { if (stack.isEmpty()) { return null; } - return LuaConverter.stackToObject(stack); + return LuaConverter.itemStackToObject(stack); } @LuaFunction(mainThread = true) @@ -106,6 +106,6 @@ public final Object getInventoryCarbon() { if (stack.isEmpty()) { return null; } - return LuaConverter.stackToObject(stack); + return LuaConverter.itemStackToObject(stack); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/SolarPanelIntegration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/SolarPanelIntegration.java index 238ce5999..c921ae00a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/powah/SolarPanelIntegration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/powah/SolarPanelIntegration.java @@ -14,7 +14,7 @@ protected SolarPanelIntegration(BlockEntity entity) { @NotNull @Override public String getType() { - return "solarPanel"; + return "solar_panel"; } @LuaFunction(mainThread = true) diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java new file mode 100644 index 000000000..383918038 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSApi.java @@ -0,0 +1,508 @@ +package de.srendi.advancedperipherals.common.addons.refinedstorage; + +import com.refinedmods.refinedstorage.api.IRSAPI; +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; +import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; +import com.refinedmods.refinedstorage.api.network.INetwork; +import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; +import com.refinedmods.refinedstorage.api.network.node.INetworkNode; +import com.refinedmods.refinedstorage.api.storage.IStorage; +import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; +import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; +import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; +import com.refinedmods.refinedstorage.api.util.StackListEntry; +import com.refinedmods.refinedstorage.apiimpl.API; +import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; +import com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.blocks.blockentities.RSBridgeEntity; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; +import de.srendi.advancedperipherals.common.util.inventory.GenericFilter; +import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class RSApi { + + public static RSApi instance; + + private final IRSAPI api; + + public RSApi() { + api = API.instance(); + initiate(); + } + + private static INetworkNode read(CompoundTag tag, NetworkNode node) { + node.read(tag); + return node; + } + + public static ItemStack findItemFromStack(INetwork network, @Nullable ICraftingManager crafting, ItemStack item) { + return findItemFromFilter(network, crafting, ItemFilter.fromStack(item)); + } + + public static ItemStack findItemFromFilter(INetwork network, @Nullable ICraftingManager crafting, ItemFilter filter) { + for (StackListEntry temp : network.getItemStorageCache().getList().getStacks()) { + if (filter.test(temp.getStack())) + return temp.getStack().copy(); + } + + if (crafting == null) + return ItemStack.EMPTY; + + for (ICraftingPattern pattern : crafting.getPatterns()) { + for (ItemStack stack : pattern.getOutputs()) { + if (filter.test(stack)) + return stack.copy(); + } + } + + return ItemStack.EMPTY; + } + + public static FluidStack findFluidFromStack(INetwork network, @Nullable ICraftingManager crafting, FluidStack stack) { + return findFluidFromFilter(network, crafting, FluidFilter.fromStack(stack)); + } + + public static FluidStack findFluidFromFilter(INetwork network, @Nullable ICraftingManager crafting, FluidFilter filter) { + for (StackListEntry temp : network.getFluidStorageCache().getList().getStacks()) { + if (filter.test(temp.getStack())) + return temp.getStack().copy(); + } + + if (crafting == null) + return FluidStack.EMPTY; + + for (ICraftingPattern pattern : crafting.getPatterns()) { + if (pattern.getFluidOutputs().stream().anyMatch(filter::test)) + return pattern.getFluidOutputs().stream().filter(filter::test).findFirst().orElse(FluidStack.EMPTY).copy(); + } + + return FluidStack.EMPTY; + } + + /** + * Finds a pattern from filters. + * + * @param network The network to search patterns from. + * @param inputFilter The input filter to apply, can be null to ignore input filter. + * @param outputFilter The output filter to apply, can be null to ignore output filter. + * @return A Pair object containing the matched pattern and an error message if no pattern is found. + * The pattern can be null if no pattern is found. + * The error message is "NO_PATTERN_FOUND" if no pattern is found. + */ + public static Pair findPatternFromFilters(INetwork network, @Nullable GenericFilter inputFilter, @Nullable GenericFilter outputFilter) { + for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) { + if (pattern.getInputs().isEmpty()) + continue; + if (pattern.getOutputs().isEmpty()) + continue; + + boolean inputMatch = false; + boolean outputMatch = false; + + if (inputFilter != null) { + if (inputFilter instanceof ItemFilter itemInputFilter) { + outerLoop: + for (NonNullList input : pattern.getInputs()) { + for (ItemStack possibleInput : input) { + if (itemInputFilter.test(possibleInput)) { + inputMatch = true; + break outerLoop; + } + } + } + } else if(inputFilter instanceof FluidFilter itemFluidFilter) { + outerLoop: + for (NonNullList input : pattern.getFluidInputs()) { + for (FluidStack possibleInput : input) { + if (itemFluidFilter.test(possibleInput)) { + inputMatch = true; + break outerLoop; + } + } + } + } + } else { + inputMatch = true; + } + + if (outputFilter != null) { + if (outputFilter instanceof ItemFilter itemOutputFilter) { + for (ItemStack output : pattern.getOutputs()) { + if (itemOutputFilter.test(output)) { + outputMatch = true; + break; + } + } + } else if(outputFilter instanceof FluidFilter fluidOutputFilter) { + for (FluidStack output : pattern.getFluidOutputs()) { + if (fluidOutputFilter.test(output)) { + outputMatch = true; + break; + } + } + } + } else { + outputMatch = true; + } + + if (inputMatch && outputMatch) + return Pair.of(pattern, null); + } + + return Pair.of(null, "NO_PATTERN_FOUND"); + } + + public static Object listFluids(INetwork network) { + List fluids = new ArrayList<>(); + getFluids(network).forEach(item -> fluids.add(parseFluidStack(item, network))); + return fluids; + } + + public static Object listItems(INetwork network) { + List items = new ArrayList<>(); + getItems(network).forEach(item -> items.add(parseItemStack(item, network))); + return items; + } + + public static boolean isItemCraftable(INetwork network, ItemStack stack) { + return network.getCraftingManager().getPattern(stack) != null; + } + + public static boolean isFluidCraftable(INetwork network, FluidStack stack) { + return network.getCraftingManager().getPattern(stack) != null; + } + + public static long getMaxItemDiskStorage(INetwork network) { + long total = 0; + boolean creative = false; + for (IStorage store : network.getItemStorageCache().getStorages()) { + if (store instanceof IStorageDisk storageDisk) { + int cap = storageDisk.getCapacity(); + if (cap > 0) total += cap; + else creative = true; + } + } + return creative ? -1 : total; + } + + public static long getMaxFluidDiskStorage(INetwork network) { + long total = 0; + boolean creative = false; + for (IStorage store : network.getFluidStorageCache().getStorages()) { + if (store instanceof IStorageDisk storageDisk) { + int cap = storageDisk.getCapacity(); + if (cap > 0) total += cap; + else creative = true; + } + } + return creative ? -1 : total; + } + + public static long getUsedItemDiskStorage(INetwork network) { + long used = 0; + for (IStorage store : network.getItemStorageCache().getStorages()) { + if (store instanceof IStorageDisk storageDisk) { + used += storageDisk.getStored(); + } + } + return used; + } + + public static long getUsedFluidDiskStorage(INetwork network) { + long used = 0; + for (IStorage store : network.getFluidStorageCache().getStorages()) { + if (store instanceof IStorageDisk storageDisk) { + used += storageDisk.getStored(); + } + } + return used; + } + + public static long getMaxItemExternalStorage(INetwork network) { + long total = 0; + for (IStorage store : network.getItemStorageCache().getStorages()) { + if (store instanceof IExternalStorage externalStorage) { + total += externalStorage.getCapacity(); + } + } + return total; + } + + public static long getMaxFluidExternalStorage(INetwork network) { + long total = 0; + for (IStorage store : network.getFluidStorageCache().getStorages()) { + if (store instanceof IExternalStorage externalStorage) { + total += externalStorage.getCapacity(); + } + } + return total; + } + + public static long getUsedItemExternalStorage(INetwork network) { + long used = 0; + for (IStorage store : network.getItemStorageCache().getStorages()) { + if (store instanceof IExternalStorage externalStorage) { + used += externalStorage.getStored(); + } + } + return used; + } + + public static long getUsedFluidExternalStorage(INetwork network) { + long used = 0; + for (IStorage store : network.getFluidStorageCache().getStorages()) { + if (store instanceof IExternalStorage externalStorage) { + used += externalStorage.getStored(); + } + } + return used; + } + + public static Object getItem(INetwork network, ItemStack item) { + for (ItemStack itemStack : getItems(network)) { + if (itemStack.sameItem(item) && Objects.equals(itemStack.getTag(), item.getTag())) + return parseItemStack(itemStack, network); + } + return null; + } + + public static List getCraftableItems(INetwork network) { + IStorageCache cache = network.getItemStorageCache(); + Collection> craftableEntries = cache.getCraftablesList().getStacks(); + List result = new ArrayList<>(craftableEntries.size()); + + for (StackListEntry entry : craftableEntries) { + result.add(entry.getStack().copy()); + } + + return result; + } + + public static List getCraftableFluids(INetwork network) { + IStorageCache cache = network.getFluidStorageCache(); + Collection> craftableEntries = cache.getCraftablesList().getStacks(); + List result = new ArrayList<>(craftableEntries.size()); + + for (StackListEntry entry : craftableEntries) + result.add(entry.getStack().copy()); + + return result; + } + + public static List getItems(INetwork network) { + IStorageCache cache = network.getItemStorageCache(); + Collection> entries = cache.getList().getStacks(); + List result = new ArrayList<>(entries.size()); + + for (StackListEntry entry : entries) + result.add(entry.getStack().copy()); + + return result; + } + + public static List getFluids(INetwork network) { + IStorageCache cache = network.getFluidStorageCache(); + Collection> entries = cache.getList().getStacks(); + List result = new ArrayList<>(entries.size()); + + for (StackListEntry entry : entries) + result.add(entry.getStack().copy()); + + return result; + } + + public static List getPatterns(INetwork network) { + List patterns = new ArrayList<>(); + Collection craftingPatterns = network.getCraftingManager().getPatterns(); + + for (ICraftingPattern pattern : craftingPatterns) { + patterns.add(parsePattern(pattern, network)); + } + + return patterns; + } + + public static List getStorageDisks(INetwork network) { + List storageDisks = new ArrayList<>(); + + Collection collection = network.getNodeGraph().all(); + + for (INetworkNodeGraphEntry graphEntry : collection) { + INetworkNode node = graphEntry.getNode(); + if (node instanceof DiskDriveNetworkNode diskDrive) { + Arrays.stream(diskDrive.getFluidDisks()).filter(Objects::nonNull).forEach(disk -> storageDisks.add(parseStorageDisk(disk))); + Arrays.stream(diskDrive.getItemDisks()).filter(Objects::nonNull).forEach(disk -> storageDisks.add(parseStorageDisk(disk))); + } + } + + return storageDisks; + } + + public static List getDiskDrives(INetwork network) { + List diskDrives = new ArrayList<>(); + + for (INetworkNodeGraphEntry graphEntry : network.getNodeGraph().all()) { + INetworkNode node = graphEntry.getNode(); + if (node instanceof DiskDriveNetworkNode diskDrive) { + diskDrives.add(parseDiskDrive(diskDrive)); + } + } + + return diskDrives; + } + + public static List getCraftingTasks(INetwork network, RSBridgeEntity entity) { + List tasks = new ArrayList<>(); + + for (RSCraftJob task : entity.getJobs()) { + tasks.add(parseCraftingTask(task.getCraftingTask(), network)); + } + + return tasks; + } + + public static Object parseCraftingTask(ICraftingTask task, INetwork network) { + Map properties = new HashMap<>(); + + properties.put("id", task.getId()); + properties.put("pattern", parsePattern(task.getPattern(), network)); + properties.put("quantity", task.getQuantity()); + properties.put("completion", task.getCompletionPercentage()); + + return properties; + } + + public static Object parseStorageDisk(IStorageDisk disk) { + Map properties = new HashMap<>(); + + properties.put("used", disk.getStored()); + properties.put("capacity", disk.getCapacity()); + + return properties; + } + + public static Object parseDiskDrive(DiskDriveNetworkNode diskDrive) { + Map properties = new HashMap<>(); + + long total = 0; + long used = 0; + + List disks = new ArrayList<>(); + for (IStorageDisk disk : diskDrive.getFluidDisks()) { + if (disk == null) + continue; + total += disk.getCapacity(); + used += disk.getStored(); + + disks.add(parseStorageDisk(disk)); + } + for (IStorageDisk disk : diskDrive.getItemDisks()) { + if (disk == null) + continue; + total += disk.getCapacity(); + used += disk.getStored(); + + disks.add(parseStorageDisk(disk)); + } + + properties.put("used", used); + properties.put("total", total); + properties.put("drives", disks); + properties.put("mode", diskDrive.getWhitelistBlacklistMode()); + properties.put("redstone_mode", diskDrive.getRedstoneMode().toString()); + properties.put("access_type", diskDrive.getAccessType().toString()); + properties.put("position", LuaConverter.posToObject(diskDrive.getPos())); + properties.put("priority", diskDrive.getPriority()); + + return properties; + } + + public static Object parsePattern(ICraftingPattern pattern, INetwork network) { + if (pattern == null) + return null; + + Map map = new HashMap<>(); + map.put("outputs", pattern.getOutputs().stream().map(stack -> parseItemStack(stack.copy(), network)).toList()); + map.put("fluidOutputs", pattern.getFluidOutputs().stream().map(stack -> parseFluidStack(stack.copy(), network)).toList()); + + List>> inputs = pattern.getInputs().stream() + .map(singleInputList -> singleInputList.stream() + .map(stack -> parseItemStack(stack.copy(), network)) + .collect(Collectors.toList())) + .collect(Collectors.toList()); + + List>> fluidInputs = pattern.getInputs().stream() + .map(singleInputList -> singleInputList.stream() + .map(stack -> parseItemStack(stack.copy(), network)) + .collect(Collectors.toList())) + .collect(Collectors.toList()); + + List byproducts = new ArrayList<>(); + if (!pattern.isProcessing()) { + byproducts = pattern.getByproducts().stream() + .map(stack -> parseItemStack(stack.copy(), network)) + .collect(Collectors.toList()); + } + + map.put("fluidInputs", fluidInputs); + map.put("inputs", inputs); + map.put("byproducts", byproducts); + map.put("processing", pattern.isProcessing()); + Map container = new HashMap<>(); + map.put("name", pattern.getContainer().getName().getString()); + map.put("position", LuaConverter.posToObject(pattern.getContainer().getPosition())); + + map.put("container", container); + map.put("isValid", pattern.isValid()); + map.put("errorMessage", pattern.getErrorMessage() == null ? "" : pattern.getErrorMessage().getString()); + return map; + } + + public static Map parseItemStack(@Nullable ItemStack itemStack, INetwork network) { + if (itemStack == null || itemStack.isEmpty()) + return Collections.emptyMap(); + + Map map = LuaConverter.itemStackToObject(itemStack); + map.put("isCraftable", isItemCraftable(network, itemStack)); + + return map; + } + + public static Map parseFluidStack(@Nullable FluidStack fluidStack, INetwork network) { + if (fluidStack == null || fluidStack.isEmpty()) + return Collections.emptyMap(); + + Map map = LuaConverter.fluidStackToObject(fluidStack); + map.put("isCraftable", isFluidCraftable(network, fluidStack)); + return map; + } + + public void initiate() { + api.getNetworkNodeRegistry().add(new ResourceLocation(AdvancedPeripherals.MOD_ID, "rs_bridge"), (tag, world, pos) -> read(tag, new RSNode(world, pos))); + } + + public IRSAPI getApi() { + return api; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSCraftJob.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSCraftJob.java new file mode 100644 index 000000000..4461d7e22 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSCraftJob.java @@ -0,0 +1,191 @@ +package de.srendi.advancedperipherals.common.addons.refinedstorage; + +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; +import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; +import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; +import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; +import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; +import dan200.computercraft.api.peripheral.IComputerAccess; +import de.srendi.advancedperipherals.common.util.BasicCraftJob; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.common.util.StatusConstants; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.fluids.FluidStack; + +public class RSCraftJob extends BasicCraftJob { + + private final ICraftingManager craftingManager; + private final ItemStack itemToCraft; + private final FluidStack fluidToCraft; + + private ICalculationResult calculationResult; + private ICraftingTask craftingTask; + + public RSCraftJob(IComputerAccess computer, Level world, long amount, ItemStack itemToCraft, ICraftingManager calculationResult) { + super(computer, "rs", world, amount); + this.craftingManager = calculationResult; + this.itemToCraft = itemToCraft; + this.fluidToCraft = FluidStack.EMPTY; + } + + public RSCraftJob(IComputerAccess computer, Level world, long amount, FluidStack fluidToCraft, ICraftingManager calculationResult) { + super(computer, "rs", world, amount); + this.craftingManager = calculationResult; + this.fluidToCraft = fluidToCraft; + this.itemToCraft = ItemStack.EMPTY; + } + + @Override + protected boolean isJobDone() { + return craftingTask != null && craftingTask.getCompletionPercentage() == 100; + } + + @Override + protected boolean isJobCanceled() { + return craftingTask != null && craftingTask.getCompletionPercentage() != 100 && craftingManager.getTasks().stream().noneMatch(task -> task.getId() == this.craftingTask.getId()); + } + + @Override + public Object getParsedRequestedItem() { + return LuaConverter.itemStackToObject(itemToCraft, (int) amount); + } + + @Override + public long getElapsedTime() { + if (craftingTask == null) { + return -1; + } + return System.nanoTime() - craftingTask.getStartTime() * 1_000; + } + + @Override + public long getTotalItems() { + if (craftingTask == null || craftingTask.getRequested() == null) { + return -1; + } + ICraftingRequestInfo requestInfo = craftingTask.getRequested(); + + return requestInfo.getFluid() != null ? requestInfo.getFluid().getAmount() : requestInfo.getItem().getCount(); + } + + @Override + public long getItemProgress() { + return 0; + } + + @Override + public Object getEmittedItems() { + return null; + } + + @Override + public Object getUsedItems() { + return null; + } + + @Override + public Object getMissingItems() { + return null; + } + + @Override + public boolean hasMultiplePaths() { + return false; + } + + @Override + public Object getFinalOutput() { + return null; + } + + @Override + public boolean cancel() { + if (isJobDone() || isJobCanceled()) { + return false; + } + craftingManager.cancel(craftingTask.getId()); + return true; + } + + public ICraftingTask getCraftingTask() { + return craftingTask; + } + + @Override + protected void maybeCraft() { + if (startedCrafting || calculationNotSuccessful || calculationResult == null) { + return; + } + + CalculationResultType type = calculationResult.getType(); + + if (type == CalculationResultType.MISSING) { + fireEvent(true, StatusConstants.MISSING_ITEMS); + calculationNotSuccessful = true; + return; + } + + if (!calculationResult.isOk()) { + calculationNotSuccessful = true; + fireEvent(true, type.toString()); + return; + } + + craftingManager.start(calculationResult.getTask()); + this.craftingTask = calculationResult.getTask(); + setStartedCrafting(); + } + + @Override + protected void startCalculation() { + if (startedCalculation) { + return; + } + startedCalculation = true; + maybeCalculateFluid(); + maybeCalculateItem(); + } + + private void maybeCalculateItem() { + if (itemToCraft.isEmpty()) { + return; + } + + calculationResult = craftingManager.create(itemToCraft, (int) amount); + fireEvent(false, StatusConstants.CALCULATION_STARTED); + } + + private void maybeCalculateFluid() { + if (fluidToCraft.isEmpty()) { + return; + } + + if (craftingManager.getPattern(fluidToCraft) == null) { + fireEvent(true, StatusConstants.NOT_CRAFTABLE); + return; + } + + calculationResult = craftingManager.create(fluidToCraft, (int) amount); + fireEvent(false, StatusConstants.CALCULATION_STARTED); + } + + @Override + public void jobStateChanged() { + if (this.craftingTask == null) { + fireEvent(true, StatusConstants.UNKNOWN_ERROR); + return; + } + + if (isJobCanceled() && !isJobCanceled) { + fireEvent(false, StatusConstants.JOB_CANCELED); + setJobCanceled(); + return; + } + + if (isJobDone() && !isJobDone) { + fireEvent(true, StatusConstants.JOB_DONE); + setJobDone(); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java similarity index 81% rename from src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsFluidHandler.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java index f945fb8b6..a92b414ee 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSFluidHandler.java @@ -8,18 +8,18 @@ import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; -public class RsFluidHandler implements IStorageSystemFluidHandler { +public class RSFluidHandler implements IStorageSystemFluidHandler { @NotNull private final INetwork network; - public RsFluidHandler(@NotNull INetwork network) { + public RSFluidHandler(@NotNull INetwork network) { this.network = network; } @Override public int fill(FluidStack resource, FluidAction action) { - if(resource.isEmpty()) + if (resource.isEmpty()) return 0; return resource.getAmount() - network.insertFluid(resource, resource.getAmount(), action == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM).getAmount(); } @@ -27,8 +27,8 @@ public int fill(FluidStack resource, FluidAction action) { @NotNull @Override public FluidStack drain(FluidFilter filter, FluidAction simulate) { - FluidStack fluid = RefinedStorage.findFluidFromFilter(network, null, filter); - if(fluid == null) + FluidStack fluid = RSApi.findFluidFromFilter(network, null, filter); + if (fluid == null) return FluidStack.EMPTY; return network.extractFluid(fluid, filter.getCount(), IComparer.COMPARE_QUANTITY, simulate == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java similarity index 80% rename from src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsItemHandler.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java index a95035903..185944568 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RsItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSItemHandler.java @@ -11,14 +11,15 @@ /** * Used to transfer item between an inventory and the RS system. + * * @see de.srendi.advancedperipherals.common.addons.computercraft.peripheral.RsBridgePeripheral */ -public class RsItemHandler implements IStorageSystemItemHandler { +public class RSItemHandler implements IStorageSystemItemHandler { @NotNull private final INetwork network; - public RsItemHandler(@NotNull INetwork network) { + public RSItemHandler(@NotNull INetwork network) { this.network = network; } @@ -30,8 +31,9 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate @Override public ItemStack extractItem(ItemFilter filter, int count, boolean simulate) { - ItemStack item = RefinedStorage.findStackFromFilter(network, network.getCraftingManager(), filter); - AdvancedPeripherals.debug("Trying to extract item: " + item + " from filter: " + filter); + ItemStack item = RSApi.findItemFromFilter(network, network.getCraftingManager(), filter); + if (item == null) + AdvancedPeripherals.debug("Trying to extract item: " + item + " from filter: " + filter); if(item == null) return ItemStack.EMPTY; ItemStack extracted = network.extractItem(item, count, IComparer.COMPARE_NBT, simulate ? Action.SIMULATE : Action.PERFORM); diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorageNode.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSNode.java similarity index 88% rename from src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorageNode.java rename to src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSNode.java index 6c19489de..d80f191bb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorageNode.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RSNode.java @@ -10,9 +10,9 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -public class RefinedStorageNode extends NetworkNode { +public class RSNode extends NetworkNode { - public RefinedStorageNode(Level level, BlockPos pos) { + public RSNode(Level level, BlockPos pos) { super(level, pos); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorage.java b/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorage.java deleted file mode 100644 index 7f58105d6..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/refinedstorage/RefinedStorage.java +++ /dev/null @@ -1,289 +0,0 @@ -package de.srendi.advancedperipherals.common.addons.refinedstorage; - -import com.refinedmods.refinedstorage.api.IRSAPI; -import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; -import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; -import com.refinedmods.refinedstorage.api.network.INetwork; -import com.refinedmods.refinedstorage.api.network.node.INetworkNode; -import com.refinedmods.refinedstorage.api.storage.IStorage; -import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; -import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; -import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; -import com.refinedmods.refinedstorage.api.util.StackListEntry; -import com.refinedmods.refinedstorage.apiimpl.API; -import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; -import dan200.computercraft.shared.util.NBTUtil; -import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.util.LuaConverter; -import de.srendi.advancedperipherals.common.util.inventory.FluidFilter; -import de.srendi.advancedperipherals.common.util.inventory.ItemFilter; -import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.function.Supplier; -import java.util.stream.Stream; - -public class RefinedStorage { - - public static RefinedStorage instance; - - private final IRSAPI api; - - public RefinedStorage() { - api = API.instance(); - initiate(); - } - - private static INetworkNode read(CompoundTag tag, NetworkNode node) { - node.read(tag); - return node; - } - - public static ItemStack findStackFromStack(INetwork network, @Nullable ICraftingManager crafting, ItemStack item) { - return findStackFromFilter(network, crafting, ItemFilter.fromStack(item)); - } - - public static ItemStack findStackFromFilter(INetwork network, @Nullable ICraftingManager crafting, ItemFilter filter) { - for (StackListEntry temp : network.getItemStorageCache().getList().getStacks()) { - if (filter.test(temp.getStack())) - return temp.getStack().copy(); - } - - if (crafting == null) - return ItemStack.EMPTY; - - for (ICraftingPattern pattern : crafting.getPatterns()) { - for(ItemStack stack : pattern.getOutputs()) { - if (filter.test(stack)) - return stack.copy(); - } - } - - return ItemStack.EMPTY; - } - - public static FluidStack findFluidFromStack(INetwork network, @Nullable ICraftingManager crafting, FluidStack stack) { - return findFluidFromFilter(network, crafting, FluidFilter.fromStack(stack)); - } - - public static FluidStack findFluidFromFilter(INetwork network, @Nullable ICraftingManager crafting, FluidFilter filter) { - for (StackListEntry temp : network.getFluidStorageCache().getList().getStacks()) { - if (filter.test(temp.getStack())) - return temp.getStack().copy(); - } - - if (crafting == null) - return FluidStack.EMPTY; - - for (ICraftingPattern pattern : crafting.getPatterns()) { - if (pattern.getFluidOutputs().stream().anyMatch(filter::test)) - return pattern.getFluidOutputs().stream().filter(filter::test).findFirst().orElse(FluidStack.EMPTY).copy(); - } - - return FluidStack.EMPTY; - } - - public static Object listFluids(INetwork network) { - List fluids = new ArrayList<>(); - getFluids(network).forEach(item -> fluids.add(getObjectFromFluid(item, network))); - return fluids; - } - - public static Object listItems(INetwork network) { - List items = new ArrayList<>(); - getItems(network).forEach(item -> items.add(getObjectFromStack(item, network))); - return items; - } - - public static boolean isItemCraftable(INetwork network, ItemStack stack) { - return network.getCraftingManager().getPattern(stack) != null; - } - - public static boolean isFluidCraftable(INetwork network, FluidStack stack) { - return network.getCraftingManager().getPattern(stack) != null; - } - - public static long getMaxItemDiskStorage(INetwork network) { - long total = 0; - boolean creative = false; - for (IStorage store : network.getItemStorageCache().getStorages()) { - if (store instanceof IStorageDisk storageDisk) { - int cap = storageDisk.getCapacity(); - if (cap > 0) total += cap; - else creative = true; - } - } - return creative ? -1 : total; - } - - public static long getMaxFluidDiskStorage(INetwork network) { - long total = 0; - boolean creative = false; - for (IStorage store : network.getFluidStorageCache().getStorages()) { - if (store instanceof IStorageDisk storageDisk) { - int cap = storageDisk.getCapacity(); - if (cap > 0) total += cap; - else creative = true; - } - } - return creative ? -1 : total; - } - - public static long getMaxItemExternalStorage(INetwork network) { - long total = 0; - for (IStorage store : network.getItemStorageCache().getStorages()) { - if (store instanceof IExternalStorage externalStorage) { - total += externalStorage.getCapacity(); - } - } - return total; - } - - public static long getMaxFluidExternalStorage(INetwork network) { - long total = 0; - for (IStorage store : network.getFluidStorageCache().getStorages()) { - if (store instanceof IExternalStorage externalStorage) { - total += externalStorage.getCapacity(); - } - } - return total; - } - - public static Object getObjectFromPattern(ICraftingPattern pattern, INetwork network) { - if (pattern == null) return null; - Map map = new HashMap<>(); - List outputsList = pattern.getOutputs(); - List outputs = new ArrayList<>(); - for (ItemStack itemStack : outputsList) - outputs.add(getObjectFromStack(itemStack, network)); - - map.put("outputs", outputs); - - List> inputList = pattern.getInputs(); - List inputs = new ArrayList<>(); - for (List singleInputList : inputList) { - List inputs1 = new ArrayList<>(); - for (ItemStack stack : singleInputList) - inputs1.add(getObjectFromStack(stack, network)); - inputs.add(inputs1); - } - - List byproducts = new ArrayList<>(); - if (!pattern.isProcessing()) { - List byproductsList = pattern.getByproducts(); - for (ItemStack stack : byproductsList) - byproducts.add(getObjectFromStack(stack, network)); - } - - map.put("inputs", inputs); - map.put("outputs", outputs); - map.put("byproducts", byproducts); - map.put("processing", pattern.isProcessing()); - return map; - } - - public static Map getObjectFromStack(@Nullable ItemStack itemStack, INetwork network) { - if (itemStack == null) - return Collections.emptyMap(); - - Map map = new HashMap<>(); - CompoundTag nbt = itemStack.getTag(); - Supplier>> tags = () -> itemStack.getItem().builtInRegistryHolder().tags(); - map.put("fingerprint", ItemUtil.getFingerprint(itemStack)); - map.put("name", ItemUtil.getRegistryKey(itemStack.getItem()).toString()); - map.put("amount", itemStack.getCount()); - map.put("displayName", itemStack.getDisplayName().getString()); - map.put("isCraftable", isItemCraftable(network, itemStack)); - map.put("nbt", nbt == null ? null : NBTUtil.toLua(nbt)); - map.put("tags", tags.get().findAny().isEmpty() ? null : LuaConverter.tagsToList(tags)); - - return map; - } - - public static Map getObjectFromFluid(@Nullable FluidStack fluidStack, INetwork network) { - if (fluidStack == null) - return Collections.emptyMap(); - - Map map = new HashMap<>(); - Supplier>> tags = () -> fluidStack.getFluid().builtInRegistryHolder().tags(); - map.put("name", ForgeRegistries.FLUIDS.getKey(fluidStack.getFluid()).toString()); - map.put("amount", fluidStack.getAmount()); - map.put("displayName", fluidStack.getDisplayName().getString()); - map.put("isCraftable", isFluidCraftable(network, fluidStack)); - map.put("tags", tags.get().findAny().isEmpty() ? null : LuaConverter.tagsToList(tags)); - - return map; - } - - public static Object getItem(INetwork network, ItemStack item) { - for (ItemStack itemStack : getItems(network)) { - if (itemStack.sameItem(item) && Objects.equals(itemStack.getTag(), item.getTag())) - return getObjectFromStack(itemStack, network); - } - return null; - } - - public static List getCraftableItems(INetwork network) { - IStorageCache cache = network.getItemStorageCache(); - Collection> craftableEntries = cache.getCraftablesList().getStacks(); - List result = new ArrayList<>(craftableEntries.size()); - - for (StackListEntry entry : craftableEntries) { - result.add(entry.getStack().copy()); - } - - return result; - } - - public static List getCraftableFluids(INetwork network) { - IStorageCache cache = network.getFluidStorageCache(); - Collection> craftableEntries = cache.getCraftablesList().getStacks(); - List result = new ArrayList<>(craftableEntries.size()); - - for (StackListEntry entry : craftableEntries) - result.add(entry.getStack().copy()); - - return result; - } - - public static List getItems(INetwork network) { - IStorageCache cache = network.getItemStorageCache(); - Collection> entries = cache.getList().getStacks(); - List result = new ArrayList<>(entries.size()); - - for (StackListEntry entry : entries) - result.add(entry.getStack().copy()); - - return result; - } - - public static List getFluids(INetwork network) { - IStorageCache cache = network.getFluidStorageCache(); - Collection> entries = cache.getList().getStacks(); - List result = new ArrayList<>(entries.size()); - - for (StackListEntry entry : entries) - result.add(entry.getStack().copy()); - - return result; - } - - public void initiate() { - api.getNetworkNodeRegistry().add(new ResourceLocation(AdvancedPeripherals.MOD_ID, "rs_bridge"), (tag, world, pos) -> read(tag, new RefinedStorageNode(world, pos))); - } - - public IRSAPI getApi() { - return api; - } - -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/AutomataVSMountPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/AutomataVSMountPlugin.java new file mode 100644 index 000000000..543b673cc --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/AutomataVSMountPlugin.java @@ -0,0 +1,109 @@ +package de.srendi.advancedperipherals.common.addons.valkyrienskies; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperationContext; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.plugins.AutomataCorePlugin; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.lib.peripherals.AutomataCorePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.valkyrienskies.core.api.ships.ServerShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation.MOUNT_SHIP; + +public class AutomataVSMountPlugin extends AutomataCorePlugin { + + public AutomataVSMountPlugin(AutomataCorePeripheral automataCore) { + super(automataCore); + } + + @LuaFunction(mainThread = true) + public final boolean isOnShip() { + IPeripheralOwner owner = this.automataCore.getPeripheralOwner(); + return APAddons.isBlockOnShip(owner.getLevel(), owner.getPos()); + } + + @LuaFunction(mainThread = true) + public final MethodResult getCurrentShip() { + IPeripheralOwner owner = this.automataCore.getPeripheralOwner(); + ServerShip ship = (ServerShip) VSGameUtilsKt.getShipObjectManagingPos(owner.getLevel(), owner.getPos()); + if (ship == null) { + return MethodResult.of(); + } + Map data = LuaConverter.shipToObjectOnShip(ship, this.automataCore.getCenterPos()); + return MethodResult.of(data); + } + + @LuaFunction(mainThread = true) + public final MethodResult canMountToShip() { + List ships = this.getMountableShips(); + if (ships.size() == 0) { + return MethodResult.of(); + } + List shipNames = ships.stream().map(s -> s.getSlug()).collect(Collectors.toList()); + return MethodResult.of(shipNames); + } + + @LuaFunction(mainThread = true) + public final MethodResult mountToShip(IArguments args) throws LuaException { + String name = args.optString(0).orElse(null); + List ships = this.getMountableShips(); + if (ships.size() == 0) { + return MethodResult.of(false, "no mountable ship detected"); + } + ServerShip targetShip = null; + if (name == null) { + targetShip = ships.get(0); + } else { + for (ServerShip s : ships) { + if (s.getSlug().equals(name)) { + targetShip = s; + break; + } + } + } + if (targetShip == null) { + return MethodResult.of(false, "target ship not found"); + } + IPeripheralOwner owner = this.automataCore.getPeripheralOwner(); + Level level = owner.getLevel(); + Vec3 pos = this.getMountDetectPosition(); + Vector3d targetPos = targetShip.getWorldToShip().transformPosition(new Vector3d(pos.x, pos.y, pos.z)); + BlockPos newPosition = new BlockPos(targetPos.x, targetPos.y, targetPos.z); + return this.automataCore.withOperation(MOUNT_SHIP, new SingleOperationContext(1, 1), context -> { + boolean result = owner.move(level, newPosition); + if (!result) { + return MethodResult.of(false, "cannot mount to ship"); + } + return MethodResult.of(true); + }, context -> { + if (!owner.isMovementPossible(level, newPosition)) { + return MethodResult.of(false, "move forbidden"); + } + return null; + }); + } + + protected Vec3 getMountDetectPosition() { + IPeripheralOwner owner = this.automataCore.getPeripheralOwner(); + return owner.getCenterPos(); + } + + protected List getMountableShips() { + IPeripheralOwner owner = this.automataCore.getPeripheralOwner(); + return ValkyrienSkies.getNearbyShips((ServerLevel) owner.getLevel(), this.getMountDetectPosition(), 0.5); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/Integration.java b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/Integration.java new file mode 100644 index 000000000..b54a20c27 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/Integration.java @@ -0,0 +1,13 @@ +package de.srendi.advancedperipherals.common.addons.valkyrienskies; + +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.EnvironmentDetectorPeripheral; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.metaphysics.WeakAutomataCorePeripheral; + +public class Integration implements Runnable { + + @Override + public void run() { + EnvironmentDetectorPeripheral.addIntegrationPlugin(ShipScannerPlugin::new); + WeakAutomataCorePeripheral.addIntegrationPlugin(AutomataVSMountPlugin::new); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ShipScannerPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ShipScannerPlugin.java new file mode 100644 index 000000000..ee0786c76 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ShipScannerPlugin.java @@ -0,0 +1,61 @@ +package de.srendi.advancedperipherals.common.addons.valkyrienskies; + +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import de.srendi.advancedperipherals.common.addons.computercraft.operations.SphereOperationContext; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheralPlugin; +import de.srendi.advancedperipherals.lib.peripherals.IPeripheralOperation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.phys.Vec3; +import org.valkyrienskies.core.api.ships.ServerShip; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SphereOperation.SCAN_SHIPS; + +public class ShipScannerPlugin extends BasePeripheralPlugin { + public ShipScannerPlugin(IPeripheralOwner owner) { + super(owner); + } + + @Override + public IPeripheralOperation[] getOperations() { + return new IPeripheralOperation[]{SCAN_SHIPS}; + } + + @LuaFunction(mainThread = true) + public final MethodResult scanShips(int radius) throws LuaException { + return withOperation(SCAN_SHIPS, new SphereOperationContext(radius), context -> { + return context.getRadius() > SCAN_SHIPS.getMaxCostRadius() ? MethodResult.of(null, "Radius exceeds max value") : null; + }, context -> { + Vec3 pos = this.owner.getCenterPos(); + List ships = ValkyrienSkies.getNearbyShips((ServerLevel) this.owner.getLevel(), pos, context.getRadius()); + List> shipDatas = ships.stream().map(s -> LuaConverter.shipToObject(s, pos)).collect(Collectors.toList()); + return MethodResult.of(shipDatas); + }, null); + } + + @LuaFunction + public final MethodResult scanShipCost(int radius) { + int estimatedCost = estimateShipCost(radius); + if (estimatedCost < 0) { + return MethodResult.of(null, "Radius exceeds max value"); + } + return MethodResult.of(estimatedCost); + } + + private static int estimateShipCost(int radius) { + if (radius <= SCAN_SHIPS.getMaxFreeRadius()) { + return 0; + } + if (radius > SCAN_SHIPS.getMaxCostRadius()) { + return -1; + } + return SCAN_SHIPS.getCost(SphereOperationContext.of(radius)); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ValkyrienSkies.java b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ValkyrienSkies.java new file mode 100644 index 000000000..9e032a0eb --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/valkyrienskies/ValkyrienSkies.java @@ -0,0 +1,66 @@ +package de.srendi.advancedperipherals.common.addons.valkyrienskies; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3d; +import org.valkyrienskies.core.api.ships.ServerShip; +import org.valkyrienskies.core.api.ships.Ship; +import org.valkyrienskies.mod.common.VSGameUtilsKt; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public final class ValkyrienSkies { + private ValkyrienSkies() {} + + public static boolean isBlockOnShip(Level level, BlockPos pos) { + return VSGameUtilsKt.isBlockInShipyard(level, pos); + } + + public static Vec3 transformToWorldPos(Level level, BlockPos blockPos, Vec3 pos) { + Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, blockPos); + if (ship == null) { + return pos; + } + Vector3d newPos = ship.getShipToWorld().transformPosition(new Vector3d(pos.x, pos.y, pos.z)); + return new Vec3(newPos.x, newPos.y, newPos.z); + } + + public static Vec3 transformToWorldDir(Level level, BlockPos blockPos, Vec3 dir) { + Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, blockPos); + if (ship == null) { + return dir; + } + Vector3d newDir = ship.getShipToWorld().transformDirection(new Vector3d(dir.x, dir.y, dir.z)); + return new Vec3(newDir.x, newDir.y, newDir.z); + } + + public static void encodeShipInfo(Level level, BlockPos blockPos, Map data) { + Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, blockPos); + if (ship == null) { + return; + } + data.put("shipId", ship.getId()); + data.put("shipName", ship.getSlug()); + } + + public static List getNearbyShips(ServerLevel level, Vec3 pos, double radius) { + Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, new BlockPos(pos)); + if (ship != null) { + Vector3d newPos = ship.getShipToWorld().transformPosition(new Vector3d(pos.x, pos.y, pos.z)); + pos = new Vec3(newPos.x, newPos.y, newPos.z); + } + List shipPoses = VSGameUtilsKt.transformToNearbyShipsAndWorld(level, pos.x, pos.y, pos.z, radius); + List ships = new ArrayList<>(shipPoses.size()); + for (Vector3d p : shipPoses) { + ServerShip s = VSGameUtilsKt.getShipManagingPos(level, p.x, p.y, p.z); + if (ship == null || s.getId() != ship.getId()) { + ships.add(s); + } + } + return ships; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/PlayerDetectorBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/PlayerDetectorBlock.java index 5da7a86ff..2f1e6c9d6 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/PlayerDetectorBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/PlayerDetectorBlock.java @@ -4,7 +4,7 @@ import de.srendi.advancedperipherals.common.blocks.base.APBlockEntityBlock; import de.srendi.advancedperipherals.common.blocks.blockentities.PlayerDetectorEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -14,18 +14,17 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class PlayerDetectorBlock extends APBlockEntityBlock { public PlayerDetectorBlock() { - super(BlockEntityTypes.PLAYER_DETECTOR, true); + super(APBlockEntityTypes.PLAYER_DETECTOR, true); } - @Nullable + @NotNull @Override public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) { - return BlockEntityTypes.PLAYER_DETECTOR.get().create(pos, state); + return APBlockEntityTypes.PLAYER_DETECTOR.get().create(pos, state); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/RedstoneIntegratorBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/RedstoneIntegratorBlock.java index 32a3b183f..5d9475439 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/RedstoneIntegratorBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/RedstoneIntegratorBlock.java @@ -1,28 +1,30 @@ package de.srendi.advancedperipherals.common.blocks; +import dan200.computercraft.shared.util.RedstoneUtil; import de.srendi.advancedperipherals.common.blocks.base.BaseBlockEntityBlock; import de.srendi.advancedperipherals.common.blocks.blockentities.RedstoneIntegratorEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Material; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class RedstoneIntegratorBlock extends BaseBlockEntityBlock { public RedstoneIntegratorBlock() { - super(false, Properties.of(Material.METAL).isRedstoneConductor(Blocks::never)); + super(false, Properties.of(Material.METAL).isRedstoneConductor(APBlocks::never)); } - @Nullable + @NotNull @Override public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) { - return BlockEntityTypes.REDSTONE_INTEGRATOR.get().create(pos, state); + return APBlockEntityTypes.REDSTONE_INTEGRATOR.get().create(pos, state); } @Override @@ -33,8 +35,9 @@ public boolean isSignalSource(@NotNull BlockState blockState) { @Override public int getDirectSignal(@NotNull BlockState blockState, BlockGetter blockGetter, @NotNull BlockPos pos, @NotNull Direction side) { BlockEntity te = blockGetter.getBlockEntity(pos); - if (te instanceof RedstoneIntegratorEntity redstoneIntegratorTile) - return redstoneIntegratorTile.power[side.getOpposite().get3DDataValue()]; + if (te instanceof RedstoneIntegratorEntity redstoneIntegratorTile) { + return redstoneIntegratorTile.getOutput(side.getOpposite()); + } return 0; } @@ -42,4 +45,17 @@ public int getDirectSignal(@NotNull BlockState blockState, BlockGetter blockGett public int getSignal(@NotNull BlockState blockState, @NotNull BlockGetter blockGetter, @NotNull BlockPos pos, @NotNull Direction side) { return getDirectSignal(blockState, blockGetter, pos, side); } + + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighbor, BlockPos neighborPos, boolean moving) { + BlockEntity te = world.getBlockEntity(pos); + if (te instanceof RedstoneIntegratorEntity redstoneIntegratorTile) { + for (Direction direction : Direction.values()) { + if (pos.relative(direction).equals(neighborPos)) { + redstoneIntegratorTile.setInput(direction, RedstoneUtil.getRedstoneInput(world, neighborPos, direction)); + return; + } + } + } + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/APBlockEntityBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/APBlockEntityBlock.java index abbc0c374..5f26e6965 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/APBlockEntityBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/APBlockEntityBlock.java @@ -1,6 +1,5 @@ package de.srendi.advancedperipherals.common.blocks.base; -import de.srendi.advancedperipherals.common.blocks.blockentities.EnergyDetectorEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.entity.BlockEntity; @@ -33,11 +32,6 @@ public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState sta @Override public void onNeighborChange(BlockState state, LevelReader level, BlockPos pos, BlockPos neighbor) { super.onNeighborChange(state, level, pos, neighbor); - - BlockEntity blockEntity = level.getBlockEntity(pos); - - if(blockEntity instanceof EnergyDetectorEntity energyDetector) - energyDetector.invalidateStorages(); - + // BlockEntity blockEntity = level.getBlockEntity(pos); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlock.java index 3472e78ee..9e714707b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlock.java @@ -4,7 +4,11 @@ import net.minecraft.core.FrontAndTop; import net.minecraft.tags.TagKey; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlockEntityBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlockEntityBlock.java index a0aec0d0e..7a9fb99f7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlockEntityBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseBlockEntityBlock.java @@ -4,7 +4,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; -import net.minecraft.world.*; +import net.minecraft.world.Container; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -36,12 +40,18 @@ public BaseBlockEntityBlock(boolean belongToTickingEntity, Properties properties this.belongToTickingEntity = belongToTickingEntity; } + @NotNull + @Override + public abstract BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state); + @NotNull @Override public InteractionResult use(@NotNull BlockState state, Level levelIn, @NotNull BlockPos pos, @NotNull Player player, @NotNull InteractionHand handIn, @NotNull BlockHitResult hit) { if (levelIn.isClientSide) return InteractionResult.SUCCESS; BlockEntity tileEntity = levelIn.getBlockEntity(pos); - if (tileEntity != null && !(tileEntity instanceof IInventoryBlock)) return InteractionResult.PASS; + if (tileEntity != null && !(tileEntity instanceof IInventoryMenuBlock)) + return InteractionResult.PASS; + MenuProvider namedContainerProvider = this.getMenuProvider(state, levelIn, pos); if (namedContainerProvider != null) { if (!(player instanceof ServerPlayer serverPlayerEntity)) return InteractionResult.PASS; @@ -81,8 +91,6 @@ public BlockEntityTicker getTicker(Level level, @NotN }; } - - @Deprecated @Nullable @Override public MenuProvider getMenuProvider(@NotNull BlockState pState, Level pLevel, @NotNull BlockPos pPos) { @@ -91,7 +99,8 @@ public MenuProvider getMenuProvider(@NotNull BlockState pState, Level pLevel, @N return menuProvider; } - public @NotNull RenderShape getRenderShape(@NotNull BlockState state) { + @NotNull + public RenderShape getRenderShape(@NotNull BlockState state) { return RenderShape.MODEL; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseDetectorEntity.java new file mode 100644 index 000000000..0912220ab --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/BaseDetectorEntity.java @@ -0,0 +1,151 @@ +package de.srendi.advancedperipherals.common.blocks.base; + +import de.srendi.advancedperipherals.common.util.proxy.IStorageProxy; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @param The storage handle type + * @param The storage proxy type, must implements/extends both {@code } and {@link IStorageProxy} + * @param

The peripheral type, must extends {@link BasePeripheral} + */ +public abstract class BaseDetectorEntity> extends PeripheralBlockEntity

{ + + private static final String RATE_LIMIT_TAG = "RateLimit"; + + private final Capability capability; + // proxy that will forward X to the output but limit it to maxTransferRate + private final S proxy = createProxy(); + private volatile long transferRate = 0; + private LazyOptional inputStorageCap = LazyOptional.empty(); + private LazyOptional zeroStorageCap = LazyOptional.empty(); + + protected BaseDetectorEntity(BlockEntityType tileEntityType, BlockPos pos, BlockState state, Capability capability) { + super(tileEntityType, pos, state); + this.capability = capability; + } + + @NotNull + protected abstract S createProxy(); + + @NotNull + protected abstract T getZeroStorage(); + + @NotNull + protected S getStorageProxy() { + return this.proxy; + } + + /** + * @return the transfered amount of stuff in the last tick + */ + public long getTransferRate() { + return this.transferRate; + } + + /** + * @return the possible maximum transfered amount + */ + public long getMaxTransferRate() { + return this.proxy.getMaxTransferRate(); + } + + /** + * @return the max amount of stuff can be transfered in a tick + */ + public long getTransferRateLimit() { + return this.proxy.getTransferRate(); + } + + /** + * @param rate the max amount of stuff can be transfered in a tick + */ + public void setTransferRateLimit(long rate) { + if (this.proxy.getTransferRate() != rate) { + this.proxy.setTransferRate(rate); + this.setChanged(); + } + } + + /** + * @return the ID of last transfered stuff + */ + @Nullable + public String getLastTransferedId() { + return this.proxy.getLastTransferedId(); + } + + /** + * @return the ID of ready transfered stuff + */ + @Nullable + public String getReadyTransferId() { + return this.proxy.getReadyTransferId(); + } + + public Direction getInputDirection() { + return this.getBlockState().getValue(BaseBlock.ORIENTATION).front(); + } + + public Direction getOutputDirection() { + return this.getBlockState().getValue(BaseBlock.ORIENTATION).front().getOpposite(); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { + Direction inputDirection = this.getInputDirection(); + Direction outputDirection = this.getOutputDirection(); + if (cap == this.capability) { + if (direction == inputDirection) { + if (!this.inputStorageCap.isPresent()) { + this.inputStorageCap = LazyOptional.of(this::getStorageProxy); + } + return this.inputStorageCap.cast(); + } else if (direction == outputDirection) { + if (!this.zeroStorageCap.isPresent()) { + this.zeroStorageCap = LazyOptional.of(this::getZeroStorage); + } + return this.zeroStorageCap.cast(); + } + } + return super.getCapability(cap, direction); + } + + @Override + public void saveAdditional(@NotNull CompoundTag compound) { + super.saveAdditional(compound); + compound.putLong(RATE_LIMIT_TAG, this.getTransferRateLimit()); + } + + @Override + public void load(@NotNull CompoundTag nbt) { + this.proxy.setTransferRate(nbt.getLong(RATE_LIMIT_TAG)); + super.load(nbt); + } + + @Override + public void handleTick(Level level, BlockState state, BlockEntityType type) { + super.handleTick(level, state, type); + if (!level.isClientSide()) { + this.transferRate = this.proxy.getAndResetTransfered(); + } + } + + @NotNull + public LazyOptional getOutputStorage() { + Direction outputDirection = this.getOutputDirection(); + BlockEntity be = level.getBlockEntity(worldPosition.relative(outputDirection)); + return be == null ? LazyOptional.empty() : be.getCapability(this.capability, outputDirection.getOpposite()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryBlock.java index 3d118525b..5ca8c9ef6 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryBlock.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryBlock.java @@ -1,24 +1,10 @@ package de.srendi.advancedperipherals.common.blocks.base; -import de.srendi.advancedperipherals.common.container.base.BaseContainer; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.level.Level; - /** - * Used to assign a container to a TileEntity + * Used to assign an inventory storage to a block entity * - * @param The container related to this inventory - * @deprecated Will be merged with the APBlock in 0.9 */ - -@Deprecated(since = "0.7.16", forRemoval = true) -public interface IInventoryBlock { - - Component getDisplayName(); - - T createContainer(int id, Inventory playerInventory, BlockPos pos, Level world); +public interface IInventoryBlock { int getInvSize(); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryMenuBlock.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryMenuBlock.java new file mode 100644 index 000000000..1d028a8a4 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/IInventoryMenuBlock.java @@ -0,0 +1,19 @@ +package de.srendi.advancedperipherals.common.blocks.base; + +import de.srendi.advancedperipherals.common.container.base.BaseContainer; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.level.Level; + +/** + * Used to assign an inventory storage to a block entity with a proper container + * @param the container for that block entity + */ +public interface IInventoryMenuBlock extends IInventoryBlock { + + Component getDisplayName(); + + T createContainer(int id, Inventory playerInventory, BlockPos pos, Level world); + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java index 2b6d3ca8f..e62d578c7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PeripheralBlockEntity.java @@ -1,13 +1,15 @@ package de.srendi.advancedperipherals.common.blocks.base; import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.Capabilities; import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.util.CoordUtil; import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralTileEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.FrontAndTop; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -18,7 +20,9 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; @@ -34,61 +38,42 @@ import java.util.Collections; public abstract class PeripheralBlockEntity> extends BaseContainerBlockEntity implements WorldlyContainer, MenuProvider, IPeripheralTileEntity { - // TODO: move inventory logic to another tile entity! + private static final String PERIPHERAL_SETTINGS_KEY = "peripheralSettings"; - protected CompoundTag peripheralSettings; + protected CompoundTag peripheralSettings = new CompoundTag(); protected NonNullList items; - @Nullable - protected T peripheral = null; - private LazyOptional handler; - private LazyOptional fluidHandler; - private LazyOptional peripheralCap; + private LazyOptional handler = LazyOptional.empty(); + private LazyOptional fluidHandler = LazyOptional.empty(); + private LazyOptional peripheralCap = LazyOptional.empty(); - public PeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + protected PeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { super(tileEntityTypeIn, pos, state); - if (this instanceof IInventoryBlock inventoryBlock) { + if (this instanceof IInventoryBlock inventoryBlock) { items = NonNullList.withSize(inventoryBlock.getInvSize(), ItemStack.EMPTY); } else { items = NonNullList.withSize(0, ItemStack.EMPTY); } - peripheralSettings = new CompoundTag(); } @NotNull @Override - public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { if (cap == Capabilities.CAPABILITY_PERIPHERAL) { - if (peripheral == null) - // Perform later peripheral creation, because creating peripheral - // on init of tile entity cause some infinity loop, if peripheral - // are depend on tile entity data - this.peripheral = createPeripheral(); - if (peripheral.isEnabled()) { - if (peripheralCap == null) { - peripheralCap = LazyOptional.of(() -> peripheral); - } else if (!peripheralCap.isPresent()) { - // Recreate peripheral to allow CC: Tweaked correctly handle - // peripheral update logic, so new peripheral and old one will be - // different - peripheral = createPeripheral(); - peripheralCap = LazyOptional.of(() -> peripheral); + return this.getLazyPeripheral().cast(); + } else if (cap == ForgeCapabilities.ITEM_HANDLER) { + if (!remove && direction != null && this instanceof IInventoryBlock) { + if (!handler.isPresent()) { + handler = LazyOptional.of(() -> new SidedInvWrapper(this, Direction.NORTH)); } - return peripheralCap.cast(); - } else { - AdvancedPeripherals.debug(peripheral.getType() + " is disabled, you can enable it in the Configuration."); + return handler.cast(); + } + } else if (cap == ForgeCapabilities.FLUID_HANDLER) { + if (!remove && direction != null) { + if (!fluidHandler.isPresent()) { + fluidHandler = LazyOptional.of(() -> new FluidTank(0)); + } + return fluidHandler.cast(); } - } - - if (cap == ForgeCapabilities.ITEM_HANDLER && !remove && direction != null && this instanceof IInventoryBlock) { - if (handler == null || !handler.isPresent()) - handler = LazyOptional.of(() -> new SidedInvWrapper(this, Direction.NORTH)); - return handler.cast(); - } - - if (cap == ForgeCapabilities.FLUID_HANDLER && !remove && direction != null) { - if (fluidHandler == null || !fluidHandler.isPresent()) - fluidHandler = LazyOptional.of(() -> new FluidTank(0)); - return fluidHandler.cast(); } return super.getCapability(cap, direction); } @@ -96,21 +81,39 @@ public LazyOptional getCapability(@NotNull Capability cap, @Nullabl @Override public void invalidateCaps() { super.invalidateCaps(); - if (peripheralCap != null) - peripheralCap.invalidate(); - if (handler != null) - handler.invalidate(); - if (fluidHandler != null) - fluidHandler.invalidate(); + peripheralCap.invalidate(); + handler.invalidate(); + fluidHandler.invalidate(); } @NotNull protected abstract T createPeripheral(); public Iterable getConnectedComputers() { - if (peripheral == null) // just avoid some NPE in strange cases - return Collections.emptyList(); - return peripheral.getConnectedComputers(); + return this.getLazyPeripheral().map(BasePeripheral::getConnectedComputers).orElse(Collections.emptyList()); + } + + public LazyOptional getLazyPeripheral() { + // Perform later peripheral creation, because creating peripheral + // on init of tile entity cause some infinity loop, if peripheral + // are depend on tile entity data + if (!this.peripheralCap.isPresent()) { + // Recreate peripheral to allow CC: Tweaked correctly handle + // peripheral update logic, so new peripheral and old one will be + // different + final T peripheral = createPeripheral(); + if (!peripheral.isEnabled()) { + AdvancedPeripherals.debug(peripheral.getType() + " is disabled, you can enable it in the Configuration."); + return LazyOptional.empty(); + } + this.peripheralCap = LazyOptional.of(() -> peripheral); + } + return this.peripheralCap; + } + + @Nullable + public T getPeripheral() { + return this.getLazyPeripheral().orElse(null); } /*@Override @@ -122,7 +125,9 @@ public ITextComponent getDisplayName() { public void saveAdditional(@NotNull CompoundTag compound) { super.saveAdditional(compound); ContainerHelper.saveAllItems(compound, items); - if (!peripheralSettings.isEmpty()) compound.put(PERIPHERAL_SETTINGS_KEY, peripheralSettings); + if (!peripheralSettings.isEmpty()) { + compound.put(PERIPHERAL_SETTINGS_KEY, peripheralSettings); + } } @Override @@ -132,9 +137,10 @@ public void load(@NotNull CompoundTag compound) { super.load(compound); } + @NotNull @Override protected Component getDefaultName() { - return this instanceof IInventoryBlock inventoryBlock ? inventoryBlock.getDisplayName() : null; + return this instanceof IInventoryMenuBlock inventoryBlock ? inventoryBlock.getDisplayName() : null; } @Nullable @@ -143,13 +149,14 @@ public AbstractContainerMenu createMenu(int id, @NotNull Inventory inventory, @N return createMenu(id, inventory); } + @NotNull @Override protected AbstractContainerMenu createMenu(int id, @NotNull Inventory player) { - return this instanceof IInventoryBlock inventoryBlock ? inventoryBlock.createContainer(id, player, worldPosition, level) : null; + return this instanceof IInventoryMenuBlock inventoryBlock ? inventoryBlock.createContainer(id, player, worldPosition, level) : null; } @Override - public int[] getSlotsForFace(@NotNull Direction side) { + public int @NotNull [] getSlotsForFace(@NotNull Direction side) { return new int[]{0}; } @@ -222,7 +229,24 @@ public CompoundTag getPeripheralSettings() { @Override public void markSettingsChanged() { - setChanged(); + this.setChanged(); } -} + public void sendUpdate() { + this.setChanged(); + Level level = this.getLevel(); + if (level != null) { + level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 11); + } + } + + public ComputerSide getComputerSide(Direction direction) { + FrontAndTop orientation = getBlockState().getValue(BaseBlock.ORIENTATION); + return CoordUtil.getComputerSide(orientation, direction); + } + + @Override + public void handleTick(Level level, BlockState state, BlockEntityType type) { + this.getLazyPeripheral().ifPresent(BasePeripheral::update); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PoweredPeripheralBlockEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PoweredPeripheralBlockEntity.java index bace719d3..4178f0c5c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PoweredPeripheralBlockEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/base/PoweredPeripheralBlockEntity.java @@ -17,15 +17,10 @@ public abstract class PoweredPeripheralBlockEntity> extends PeripheralBlockEntity { - private final LazyOptional lazyEnergyStorage; + private LazyOptional lazyEnergyStorage = LazyOptional.empty(); - public PoweredPeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { + protected PoweredPeripheralBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { super(tileEntityTypeIn, pos, state); - if (APConfig.PERIPHERALS_CONFIG.enablePoweredPeripherals.get()) { - lazyEnergyStorage = LazyOptional.of(() -> new EnergyStorage(this.getMaxEnergyStored())); - } else { - lazyEnergyStorage = LazyOptional.empty(); - } } protected abstract int getMaxEnergyStored(); @@ -43,9 +38,14 @@ public void load(@NotNull CompoundTag compound) { } @Override - public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { - if (cap == ForgeCapabilities.ENERGY && lazyEnergyStorage.isPresent()) { - return lazyEnergyStorage.cast(); + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { + if (cap == ForgeCapabilities.ENERGY) { + if (APConfig.PERIPHERALS_CONFIG.enablePoweredPeripherals.get()) { + if (!lazyEnergyStorage.isPresent()) { + lazyEnergyStorage = LazyOptional.of(() -> new EnergyStorage(this.getMaxEnergyStored())); + } + return lazyEnergyStorage.cast(); + } } return super.getCapability(cap, direction); } @@ -55,5 +55,4 @@ public void invalidateCaps() { super.invalidateCaps(); this.lazyEnergyStorage.invalidate(); } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/BlockReaderEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/BlockReaderEntity.java index db48c0460..33e7b128f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/BlockReaderEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/BlockReaderEntity.java @@ -2,7 +2,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.BlockReaderPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; @@ -10,7 +10,7 @@ public class BlockReaderEntity extends PeripheralBlockEntity { public BlockReaderEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.BLOCK_READER.get(), pos, state); + super(APBlockEntityTypes.BLOCK_READER.get(), pos, state); } @NotNull diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java index 118611259..24e57b8d6 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ChatBoxEntity.java @@ -2,17 +2,15 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.ChatBoxPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; public class ChatBoxEntity extends PeripheralBlockEntity { + public ChatBoxEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.CHAT_BOX.get(), pos, state); + super(APBlockEntityTypes.CHAT_BOX.get(), pos, state); } @NotNull @@ -20,11 +18,4 @@ public ChatBoxEntity(BlockPos pos, BlockState state) { protected ChatBoxPeripheral createPeripheral() { return new ChatBoxPeripheral(this); } - - @Override - public void handleTick(Level level, BlockState state, BlockEntityType type) { - if (peripheral != null) { - peripheral.update(); - } - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ColonyIntegratorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ColonyIntegratorEntity.java index 8c6504791..27e9d5e1f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ColonyIntegratorEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/ColonyIntegratorEntity.java @@ -2,7 +2,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.ColonyPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; @@ -10,7 +10,7 @@ public class ColonyIntegratorEntity extends PeripheralBlockEntity { public ColonyIntegratorEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.COLONY_INTEGRATOR.get(), pos, state); + super(APBlockEntityTypes.COLONY_INTEGRATOR.get(), pos, state); } @NotNull diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/DistanceDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/DistanceDetectorEntity.java new file mode 100644 index 000000000..9af645790 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/DistanceDetectorEntity.java @@ -0,0 +1,131 @@ +package de.srendi.advancedperipherals.common.blocks.blockentities; + +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.DistanceDetectorPeripheral; +import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; +import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class DistanceDetectorEntity extends PeripheralBlockEntity { + + private volatile float maxRange = APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue(); + private float currentDistance = -1; + private volatile boolean showLaser = true; + private volatile boolean calculatePeriodically = false; + private volatile boolean ignoreTransparent = true; + private volatile DistanceDetectorPeripheral.DetectionType detectionType = DistanceDetectorPeripheral.DetectionType.BOTH; + + public DistanceDetectorEntity(BlockPos pos, BlockState state) { + super(APBlockEntityTypes.DISTANCE_DETECTOR.get(), pos, state); + } + + @NotNull + @Override + protected DistanceDetectorPeripheral createPeripheral() { + return new DistanceDetectorPeripheral(this); + } + + public float getMaxRange() { + return this.maxRange; + } + + public void setMaxRange(float maxRange) { + this.maxRange = Math.min(Math.max(maxRange, 0), APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue()); + } + + public float getCurrentDistance() { + return this.currentDistance; + } + + public void setCurrentDistance(float currentDistance) { + this.currentDistance = currentDistance; + } + + public boolean getShowLaser() { + return this.showLaser; + } + + public void setShowLaser(boolean showLaser) { + this.showLaser = showLaser; + } + + public boolean getCalculatePeriodically() { + return this.calculatePeriodically; + } + + public void setCalculatePeriodically(boolean calculatePeriodically) { + this.calculatePeriodically = calculatePeriodically; + } + + public boolean getIgnoreTransparent() { + return this.ignoreTransparent; + } + + public void setIgnoreTransparent(boolean ignoreTransparent) { + this.ignoreTransparent = ignoreTransparent; + } + + public DistanceDetectorPeripheral.DetectionType getDetectionType() { + return this.detectionType; + } + + public void setDetectionType(DistanceDetectorPeripheral.DetectionType detectionType) { + this.detectionType = detectionType; + } + + @Override + public AABB getRenderBoundingBox() { + float currentDistance = this.getCurrentDistance(); + if (currentDistance == -1) { + currentDistance = this.getMaxRange(); + } + currentDistance += 1.5f; + Direction direction = getBlockState().getValue(BaseBlock.ORIENTATION).front(); + Vec3 blockPos = Vec3.atCenterOf(this.getBlockPos()); + return new AABB(blockPos, blockPos.add(direction.getStepX() * currentDistance, direction.getStepY() * currentDistance, direction.getStepZ() * currentDistance)); + } + + @Override + public void load(@NotNull CompoundTag compound) { + this.setMaxRange(compound.getFloat("maxRange")); + this.setCurrentDistance(compound.getFloat("currentDistance")); + this.setShowLaser(compound.getBoolean("showLaser")); + this.setCalculatePeriodically(compound.getBoolean("calculatePeriodically")); + this.setIgnoreTransparent(compound.getBoolean("ignoreTransparent")); + this.setDetectionType(DistanceDetectorPeripheral.DetectionType.values()[compound.getByte("detectionType")]); + super.load(compound); + } + + @Override + public void saveAdditional(@NotNull CompoundTag compound) { + super.saveAdditional(compound); + compound.putFloat("maxRange", this.getMaxRange()); + compound.putFloat("currentDistance", this.getCurrentDistance()); + compound.putBoolean("showLaser", this.getShowLaser()); + compound.putBoolean("calculatePeriodically", this.getCalculatePeriodically()); + compound.putBoolean("ignoreTransparent", this.getIgnoreTransparent()); + compound.putByte("detectionType", (byte) this.getDetectionType().ordinal()); + } + + @Override + public CompoundTag getUpdateTag() { + CompoundTag compound = super.getUpdateTag(); + compound.putFloat("maxRange", this.getMaxRange()); + compound.putFloat("currentDistance", this.getCurrentDistance()); + compound.putBoolean("showLaser", this.getShowLaser()); + return compound; + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnergyDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnergyDetectorEntity.java index f8db556aa..fd825dc4f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnergyDetectorEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnergyDetectorEntity.java @@ -1,107 +1,40 @@ package de.srendi.advancedperipherals.common.blocks.blockentities; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.EnergyDetectorPeripheral; -import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; +import de.srendi.advancedperipherals.common.blocks.base.BaseDetectorEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; -import de.srendi.advancedperipherals.common.util.EnergyStorageProxy; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.util.proxy.EnergyStorageProxy; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.JigsawBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.EnergyStorage; import net.minecraftforge.energy.IEnergyStorage; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.Optional; +public class EnergyDetectorEntity extends BaseDetectorEntity { -public class EnergyDetectorEntity extends PeripheralBlockEntity { - - //a zero size, zero transfer energy storage to ensure that cables connect - private final EnergyStorage zeroStorage = new EnergyStorage(0, 0, 0); - public int transferRate = 0; - //storageProxy that will forward the energy to the output but limit it to maxTransferRate - public EnergyStorageProxy storageProxy = new EnergyStorageProxy(this, APConfig.PERIPHERALS_CONFIG.energyDetectorMaxFlow.get()); - LazyOptional energyStorageCap = LazyOptional.of(() -> storageProxy); - Direction energyInDirection = Direction.NORTH; - Direction energyOutDirection = Direction.SOUTH; - LazyOptional zeroStorageCap = LazyOptional.of(() -> zeroStorage); - @NotNull - private Optional outReceivingStorage = Optional.empty(); + private static final EnergyStorage ZERO_STORAGE = new EnergyStorage(0, 0, 0); public EnergyDetectorEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.ENERGY_DETECTOR.get(), pos, state); + super(APBlockEntityTypes.ENERGY_DETECTOR.get(), pos, state, ForgeCapabilities.ENERGY); } - @NotNull @Override + @NotNull protected EnergyDetectorPeripheral createPeripheral() { return new EnergyDetectorPeripheral(this); } - @NotNull - @Override - public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction direction) { - energyInDirection = getBlockState().getValue(JigsawBlock.ORIENTATION).front(); - energyOutDirection = getBlockState().getValue(JigsawBlock.ORIENTATION).front().getOpposite(); - if (cap == ForgeCapabilities.ENERGY) { - if (direction == energyInDirection) { - return energyStorageCap.cast(); - } else if (direction == energyOutDirection) { - return zeroStorageCap.cast(); - } - } - return super.getCapability(cap, direction); - } - @Override - public void saveAdditional(@NotNull CompoundTag compound) { - super.saveAdditional(compound); - compound.putInt("rateLimit", storageProxy.getMaxTransferRate()); - } - - @Override - public void handleTick(Level level, BlockState state, BlockEntityType type) { - if (!level.isClientSide) { - // this handles the rare edge case that receiveEnergy is called multiple times in one tick - transferRate = storageProxy.getTransferedInThisTick(); - storageProxy.resetTransferedInThisTick(); - } + @NotNull + protected EnergyStorageProxy createProxy() { + return new EnergyStorageProxy(this, APConfig.PERIPHERALS_CONFIG.energyDetectorMaxFlow.get()); } @Override - public void deserializeNBT(CompoundTag nbt) { - storageProxy.setMaxTransferRate(nbt.getInt("rateLimit")); - super.deserializeNBT(nbt); - } - - public void invalidateStorages() { - outReceivingStorage = Optional.empty(); - } - - // returns the cached output storage of the receiving block or refetches it if it has been invalidated @NotNull - public Optional getOutputStorage() { - // the documentation says that the value of the LazyOptional should be cached locally and invallidated using addListener - if (outReceivingStorage.isEmpty()) { - BlockEntity teOut = level.getBlockEntity(worldPosition.relative(energyOutDirection)); - if (teOut == null) { - return Optional.empty(); - } - LazyOptional lazyOptionalOutStorage = teOut.getCapability(ForgeCapabilities.ENERGY, energyOutDirection.getOpposite()); - outReceivingStorage = lazyOptionalOutStorage.resolve(); - lazyOptionalOutStorage.addListener(l -> { - outReceivingStorage = Optional.empty(); - }); - } - return outReceivingStorage; + protected IEnergyStorage getZeroStorage() { + return ZERO_STORAGE; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnvironmentDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnvironmentDetectorEntity.java index 64a4527cc..681ed938e 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnvironmentDetectorEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/EnvironmentDetectorEntity.java @@ -3,7 +3,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.EnvironmentDetectorPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PoweredPeripheralBlockEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; @@ -11,7 +11,7 @@ public class EnvironmentDetectorEntity extends PoweredPeripheralBlockEntity { public EnvironmentDetectorEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.ENVIRONMENT_DETECTOR.get(), pos, state); + super(APBlockEntityTypes.ENVIRONMENT_DETECTOR.get(), pos, state); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/FluidDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/FluidDetectorEntity.java new file mode 100644 index 000000000..82a9b7788 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/FluidDetectorEntity.java @@ -0,0 +1,40 @@ +package de.srendi.advancedperipherals.common.blocks.blockentities; + +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.FluidDetectorPeripheral; +import de.srendi.advancedperipherals.common.blocks.base.BaseDetectorEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.util.proxy.FluidStorageProxy; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.templates.FluidTank; +import org.jetbrains.annotations.NotNull; + +public class FluidDetectorEntity extends BaseDetectorEntity { + + private static final FluidTank ZERO_STORAGE = new FluidTank(0); + + public FluidDetectorEntity(BlockPos pos, BlockState state) { + super(APBlockEntityTypes.FLUID_DETECTOR.get(), pos, state, ForgeCapabilities.FLUID_HANDLER); + } + + @Override + @NotNull + protected FluidDetectorPeripheral createPeripheral() { + return new FluidDetectorPeripheral(this); + } + + @Override + @NotNull + protected FluidStorageProxy createProxy() { + return new FluidStorageProxy(this, APConfig.PERIPHERALS_CONFIG.fluidDetectorMaxFlow.get()); + } + + @Override + @NotNull + protected IFluidHandler getZeroStorage() { + return ZERO_STORAGE; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GasDetectorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GasDetectorEntity.java new file mode 100644 index 000000000..cb1cf6d2b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GasDetectorEntity.java @@ -0,0 +1,41 @@ +package de.srendi.advancedperipherals.common.blocks.blockentities; + +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.GasDetectorPeripheral; +import de.srendi.advancedperipherals.common.addons.mekanism.MekanismCapabilities; +import de.srendi.advancedperipherals.common.blocks.base.BaseDetectorEntity; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.util.proxy.GasStorageProxy; +import de.srendi.advancedperipherals.common.util.proxy.ZeroGasTank; +import mekanism.api.chemical.gas.IGasHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +public class GasDetectorEntity extends BaseDetectorEntity { + + // a zero size, zero transfer gas storage to ensure that cables connect + private static final IGasHandler ZERO_STORAGE = new ZeroGasTank(); + + public GasDetectorEntity(BlockPos pos, BlockState state) { + super(APBlockEntityTypes.GAS_DETECTOR.get(), pos, state, MekanismCapabilities.GAS_HANDLER); + } + + @Override + @NotNull + protected GasDetectorPeripheral createPeripheral() { + return new GasDetectorPeripheral(this); + } + + @Override + @NotNull + protected GasStorageProxy createProxy() { + return new GasStorageProxy(this, APConfig.PERIPHERALS_CONFIG.gasDetectorMaxFlow.get()); + } + + @Override + @NotNull + protected IGasHandler getZeroStorage() { + return ZERO_STORAGE; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GeoScannerEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GeoScannerEntity.java index 225541a4d..56eab8959 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GeoScannerEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/GeoScannerEntity.java @@ -3,7 +3,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.GeoScannerPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PoweredPeripheralBlockEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; @@ -11,7 +11,7 @@ public class GeoScannerEntity extends PoweredPeripheralBlockEntity { public GeoScannerEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.GEO_SCANNER.get(), pos, state); + super(APBlockEntityTypes.GEO_SCANNER.get(), pos, state); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/InventoryManagerEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/InventoryManagerEntity.java index b6dfde03f..afa24f11b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/InventoryManagerEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/InventoryManagerEntity.java @@ -1,11 +1,11 @@ package de.srendi.advancedperipherals.common.blocks.blockentities; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.InventoryManagerPeripheral; -import de.srendi.advancedperipherals.common.blocks.base.IInventoryBlock; +import de.srendi.advancedperipherals.common.blocks.base.IInventoryMenuBlock; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; import de.srendi.advancedperipherals.common.container.InventoryManagerContainer; import de.srendi.advancedperipherals.common.items.MemoryCardItem; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -16,17 +16,17 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.server.ServerLifecycleHooks; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import java.util.UUID; -public class InventoryManagerEntity extends PeripheralBlockEntity implements IInventoryBlock { +public class InventoryManagerEntity extends PeripheralBlockEntity implements IInventoryMenuBlock { private UUID owner = null; public InventoryManagerEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.INVENTORY_MANAGER.get(), pos, state); + super(APBlockEntityTypes.INVENTORY_MANAGER.get(), pos, state); } @NotNull @@ -75,7 +75,7 @@ public Component getDisplayName() { } @Override - public void load(CompoundTag data) { + public void load(@NotNull CompoundTag data) { if (data.contains("ownerId")) { this.owner = data.getUUID("ownerId"); } @@ -85,7 +85,7 @@ public void load(CompoundTag data) { } @Override - public void saveAdditional(CompoundTag data) { + public void saveAdditional(@NotNull CompoundTag data) { super.saveAdditional(data); if (this.owner != null) { data.putUUID("ownerId", this.owner); diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java index d9eb38a98..5479b6910 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/MeBridgeEntity.java @@ -1,17 +1,32 @@ package de.srendi.advancedperipherals.common.blocks.blockentities; -import appeng.api.networking.*; +import appeng.api.config.Actionable; +import appeng.api.networking.GridFlags; +import appeng.api.networking.GridHelper; +import appeng.api.networking.IGridNode; +import appeng.api.networking.IInWorldGridNodeHost; +import appeng.api.networking.IManagedGridNode; +import appeng.api.networking.crafting.ICraftingLink; +import appeng.api.networking.crafting.ICraftingRequester; import appeng.api.networking.crafting.ICraftingSimulationRequester; +import appeng.api.networking.energy.IEnergyService; import appeng.api.networking.security.IActionHost; import appeng.api.networking.security.IActionSource; +import appeng.api.stacks.AEItemKey; +import appeng.api.stacks.AEKey; +import appeng.api.storage.StorageHelper; import appeng.api.util.AECableType; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.CraftJob; -import de.srendi.advancedperipherals.common.addons.appliedenergistics.MeBridgeEntityListener; -import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MeBridgePeripheral; +import com.google.common.collect.ImmutableSet; +import de.srendi.advancedperipherals.common.addons.ae2.AEApi; +import de.srendi.advancedperipherals.common.addons.ae2.AECraftJob; +import de.srendi.advancedperipherals.common.addons.ae2.MEBridgeEntityListener; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MEBridgePeripheral; +import de.srendi.advancedperipherals.common.blocks.base.IInventoryBlock; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.util.BasicCraftJob; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; @@ -26,46 +41,49 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; -public class MeBridgeEntity extends PeripheralBlockEntity implements IActionSource, IActionHost, IInWorldGridNodeHost, ICraftingSimulationRequester { +public class MeBridgeEntity extends PeripheralBlockEntity implements IActionSource, IInWorldGridNodeHost, ICraftingSimulationRequester, IInventoryBlock, ICraftingRequester { - private final List jobs = new CopyOnWriteArrayList<>(); + private final List jobs = new CopyOnWriteArrayList<>(); private boolean initialized = false; - private final IManagedGridNode mainNode = GridHelper.createManagedNode(this, MeBridgeEntityListener.INSTANCE); + private final IManagedGridNode mainNode = GridHelper.createManagedNode(this, MEBridgeEntityListener.INSTANCE); public MeBridgeEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.ME_BRIDGE.get(), pos, state); + super(APBlockEntityTypes.ME_BRIDGE.get(), pos, state); } @NotNull @Override - protected MeBridgePeripheral createPeripheral() { - return new MeBridgePeripheral(this); + protected MEBridgePeripheral createPeripheral() { + return new MEBridgePeripheral(this); } @Override public void handleTick(Level level, BlockState state, BlockEntityType type) { - if (!this.level.isClientSide) { + super.handleTick(level, state, type); + if (!this.level.isClientSide()) { if (!initialized) { + MEBridgePeripheral peripheral = this.getPeripheral(); + if (peripheral == null) { + return; + } mainNode.setFlags(GridFlags.REQUIRE_CHANNEL); mainNode.setIdlePowerUsage(APConfig.PERIPHERALS_CONFIG.meConsumption.get()); - mainNode.setVisualRepresentation(new ItemStack(Blocks.ME_BRIDGE.get())); + mainNode.setVisualRepresentation(new ItemStack(APBlocks.ME_BRIDGE.get())); mainNode.setInWorldNode(true); mainNode.create(level, getBlockPos()); - //peripheral can be null if `getCapability` was not called before - if (peripheral == null) - peripheral = createPeripheral(); peripheral.setNode(mainNode); initialized = true; } // Try to start the job if the job calculation finished - jobs.forEach(CraftJob::maybeCraft); + jobs.forEach(BasicCraftJob::tick); - // Remove the job if the crafting started, we can't do anything with it anymore - jobs.removeIf(CraftJob::isCraftingStarted); + // Remove the job if the crafting calculation failed, we can't do anything with it anymore + jobs.removeIf(BasicCraftJob::canBePurged); } } @@ -126,7 +144,53 @@ public IActionSource getActionSource() { return this; } - public void addJob(CraftJob job) { + public void addJob(AECraftJob job) { jobs.add(job); } + + public List getJobs() { + return jobs; + } + + @Override + public int getInvSize() { + return 9; + } + + @Override + public void setItem(int index, @NotNull ItemStack stack) { + super.setItem(index, stack); + if (!initialized) + return; + + if (stack.isEmpty()) + return; + + IEnergyService energySrc = mainNode.getGrid().getEnergyService(); + int inserted = (int) StorageHelper.poweredInsert(energySrc, AEApi.getMonitor(getActionableNode()), AEItemKey.of(stack), stack.getCount(), this); + + if (inserted > 0) { + getItem(index).setCount(getItem(index).getCount() - inserted); + } + } + + @Override + public boolean canTakeItemThroughFace(int index, @NotNull ItemStack stack, @NotNull Direction direction) { + return false; + } + + @Override + public ImmutableSet getRequestedJobs() { + return jobs.stream().filter(BasicCraftJob::isCraftingStarted).map(AECraftJob::getJobLink).collect(Collectors.toCollection(ImmutableSet::of)); + } + + @Override + public long insertCraftedItems(ICraftingLink link, AEKey what, long amount, Actionable mode) { + return 0; + } + + @Override + public void jobStateChange(ICraftingLink link) { + jobs.stream().filter(BasicCraftJob::isCraftingStarted).filter((job) -> job.getJobLink().getCraftingID().equals(link.getCraftingID())).forEach(AECraftJob::jobStateChanged); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/NBTStorageEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/NBTStorageEntity.java index 707fec188..0b56fedc1 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/NBTStorageEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/NBTStorageEntity.java @@ -2,7 +2,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.NBTStoragePeripheral; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.block.state.BlockState; @@ -13,7 +13,7 @@ public class NBTStorageEntity extends PeripheralBlockEntity { - private Long lastConsumedMessage; - public PlayerDetectorEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.PLAYER_DETECTOR.get(), pos, state); - lastConsumedMessage = Events.getLastPlayerMessageID() - 1; + super(APBlockEntityTypes.PLAYER_DETECTOR.get(), pos, state); } @NotNull @@ -24,13 +17,4 @@ public PlayerDetectorEntity(BlockPos pos, BlockState state) { protected PlayerDetectorPeripheral createPeripheral() { return new PlayerDetectorPeripheral(this); } - - @Override - public void handleTick(Level level, BlockState state, BlockEntityType type) { - lastConsumedMessage = Events.traversePlayerMessages(lastConsumedMessage, message -> getConnectedComputers().forEach(computer -> { - if(message.eventName().equals("playerChangedDimension")) { - computer.queueEvent(message.eventName(), message.playerName(), message.fromDimension(), message.toDimension()); - } else computer.queueEvent(message.eventName(), message.playerName(), message.fromDimension()); - })); - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RsBridgeEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RSBridgeEntity.java similarity index 54% rename from src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RsBridgeEntity.java rename to src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RSBridgeEntity.java index e3bc4a364..d137b7812 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RsBridgeEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RSBridgeEntity.java @@ -1,5 +1,7 @@ package de.srendi.advancedperipherals.common.blocks.blockentities; +import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; +import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable; @@ -7,22 +9,29 @@ import dan200.computercraft.api.peripheral.IPeripheral; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.RsBridgePeripheral; -import de.srendi.advancedperipherals.common.addons.refinedstorage.RefinedStorageNode; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSCraftJob; +import de.srendi.advancedperipherals.common.addons.refinedstorage.RSNode; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; +import de.srendi.advancedperipherals.common.util.BasicCraftJob; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralTileEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL; -public class RsBridgeEntity extends NetworkNodeBlockEntity implements INetworkNodeProxy, IRedstoneConfigurable, IPeripheralTileEntity { +public class RSBridgeEntity extends NetworkNodeBlockEntity implements INetworkNodeProxy, IRedstoneConfigurable, IPeripheralTileEntity, ICraftingMonitorListener { private static final String PERIPHERAL_SETTINGS = "AP_SETTINGS"; //I have no clue what this does, but it works @@ -30,9 +39,11 @@ public class RsBridgeEntity extends NetworkNodeBlockEntity i protected CompoundTag peripheralSettings; protected RsBridgePeripheral peripheral = new RsBridgePeripheral(this); private LazyOptional peripheralCap; + private final List jobs = new CopyOnWriteArrayList<>(); + private boolean addedListener = false; - public RsBridgeEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.RS_BRIDGE.get(), pos, state, SPEC); + public RSBridgeEntity(BlockPos pos, BlockState state) { + super(APBlockEntityTypes.RS_BRIDGE.get(), pos, state, SPEC, RSNode.class); peripheralSettings = new CompoundTag(); } @@ -51,8 +62,35 @@ public LazyOptional getCapability(@NotNull Capability cap, @Nullabl return super.getCapability(cap, direction); } - public RefinedStorageNode createNode(Level level, BlockPos blockPos) { - return new RefinedStorageNode(level, blockPos); + @Override + public void handleTick(Level level, BlockState state, BlockEntityType type) { + if (getNode().getNetwork() != null) { + ICraftingManager manager = getNode().getNetwork().getCraftingManager(); + if (manager != null && !this.addedListener) { + manager.addListener(this); + this.addedListener = true; + } else if (manager == null && this.addedListener) { + this.addedListener = false; + } + } + + // Try to start the job if the job calculation finished + jobs.forEach(BasicCraftJob::tick); + + // Remove the job if the crafting calculation failed, we can't do anything with it anymore + jobs.removeIf(BasicCraftJob::canBePurged); + } + + public void addJob(RSCraftJob job) { + jobs.add(job); + } + + public List getJobs() { + return jobs; + } + + public RSNode createNode(Level level, BlockPos blockPos) { + return new RSNode(level, blockPos); } @Override @@ -77,4 +115,14 @@ public void markSettingsChanged() { setChanged(); } + @Override + public void onAttached() { + + } + + @Override + public void onChanged() { + // Not as perfect as we currently do it for our AE jobs. This is called for every job even if they aren't created from the bridge + jobs.stream().filter(BasicCraftJob::isCraftingStarted).forEach(BasicCraftJob::jobStateChanged); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RedstoneIntegratorEntity.java b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RedstoneIntegratorEntity.java index 1987a1bf0..459eb1fc1 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RedstoneIntegratorEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/common/blocks/blockentities/RedstoneIntegratorEntity.java @@ -1,26 +1,34 @@ package de.srendi.advancedperipherals.common.blocks.blockentities; +import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.shared.util.RedstoneUtil; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.RedstoneIntegratorPeripheral; import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity; -import de.srendi.advancedperipherals.common.setup.BlockEntityTypes; +import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import de.srendi.advancedperipherals.common.util.ServerWorker; +import de.srendi.advancedperipherals.common.util.SwarmEventDispatcher; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.RedStoneWireBlock; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; -import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; public class RedstoneIntegratorEntity extends PeripheralBlockEntity { + private static final String REDSTONE_EVENT_ID = "redstone_integrator"; - public int[] power = new int[Direction.values().length]; + private final int[] outputs = new int[Direction.values().length]; + private final AtomicInteger outputStatus = new AtomicInteger(0); + private final int[] outputing = new int[Direction.values().length]; + private final int[] inputs = new int[Direction.values().length]; public RedstoneIntegratorEntity(BlockPos pos, BlockState state) { - super(BlockEntityTypes.REDSTONE_INTEGRATOR.get(), pos, state); + super(APBlockEntityTypes.REDSTONE_INTEGRATOR.get(), pos, state); + for (int i = 0; i < outputing.length; i++) { + this.outputing[i] = -1; + } } @NotNull @@ -29,24 +37,40 @@ protected RedstoneIntegratorPeripheral createPeripheral() { return new RedstoneIntegratorPeripheral(this); } - public int getRedstoneInput(Direction direction) { - Objects.requireNonNull(level); - BlockPos neighbourPos = getBlockPos().relative(direction); - int power = level.getSignal(neighbourPos, direction); - if (power >= 15) return power; - - BlockState neighbourState = level.getBlockState(neighbourPos); - return neighbourState.getBlock() == Blocks.REDSTONE_WIRE ? Math.max(power, neighbourState.getValue(RedStoneWireBlock.POWER)) : power; + /** + * This method is safely to be called from multiple threads at any time. + */ + public int getInput(Direction direction) { + // no need to lock because JVM promise the int will never be half-updated + return this.inputs[direction.get3DDataValue()]; } - private void setRedstoneOutput(Direction direction, int power) { - int old = this.power[direction.get3DDataValue()]; - this.power[direction.get3DDataValue()] = power; - if (old != power) { - if (level != null) - RedstoneUtil.propagateRedstoneOutput(level, getBlockPos(), direction); + /** + * This method should only be called from main thread + */ + public void setInput(Direction direction, int input) { + if (this.inputs[direction.get3DDataValue()] == input) { + return; + } + this.inputs[direction.get3DDataValue()] = input; + ComputerSide side = this.getComputerSide(direction); + RedstoneIntegratorPeripheral peripheral = this.getPeripheral(); + if (peripheral != null) { + SwarmEventDispatcher.dispatch(REDSTONE_EVENT_ID, peripheral, side.getName()); + } + } - this.setChanged(); + private void updateRedstoneOutputs() { + if (this.level == null) { + return; + } + for (Direction direction : Direction.values()) { + int next = this.outputs[direction.get3DDataValue()]; + if (next != this.outputing[direction.get3DDataValue()]) { + RedstoneUtil.propagateRedstoneOutput(this.level, this.getBlockPos(), direction); + this.outputing[direction.get3DDataValue()] = next; + this.setChanged(); + } } } @@ -55,16 +79,43 @@ private void setRedstoneOutput(Direction direction, int power) { * See #384 * * @param direction Cardinal direction - * @param power The redstone power from 0 to 15 + * @param power The redstone power from 0 to 15 */ public void setOutput(Direction direction, int power) { - ServerWorker.add(() -> setRedstoneOutput(direction, power)); + power = Math.min(Math.max(power, 0), 15); + this.outputs[direction.get3DDataValue()] = power; + if (this.outputStatus.compareAndSet(0, 1)) { + ServerWorker.add(() -> { + this.outputStatus.set(0); + this.updateRedstoneOutputs(); + }); + } + } + + public int getOutput(Direction direction) { + // no need to lock because JVM promise the int will never be half-updated + return this.outputs[direction.get3DDataValue()]; + } + + private void initSignals() { + for (Direction direction : Direction.values()) { + this.setInput(direction, RedstoneUtil.getRedstoneInput(this.level, this.getBlockPos().relative(direction), direction)); + RedstoneUtil.propagateRedstoneOutput(this.level, this.getBlockPos(), direction); + this.outputing[direction.get3DDataValue()] = this.outputs[direction.get3DDataValue()]; + } + this.setChanged(); + } + + @Override + public void setLevel(Level level) { + super.setLevel(level); + ServerWorker.addToNextTick(this::initSignals); } @Override public void load(@NotNull CompoundTag compound) { for (Direction direction : Direction.values()) { - setRedstoneOutput(direction, compound.getInt(direction.name() + "Power")); + this.outputs[direction.get3DDataValue()] = compound.getInt(direction.getName() + "Power"); } super.load(compound); } @@ -72,10 +123,8 @@ public void load(@NotNull CompoundTag compound) { @Override public void saveAdditional(@NotNull CompoundTag compound) { super.saveAdditional(compound); - int i = 0; for (Direction direction : Direction.values()) { - compound.putInt(direction.name() + "Power", power[i]); - i++; + compound.putInt(direction.getName() + "Power", this.outputs[direction.get3DDataValue()]); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/commands/APCommands.java b/src/main/java/de/srendi/advancedperipherals/common/commands/APCommands.java index 858494f40..a8519c562 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/commands/APCommands.java +++ b/src/main/java/de/srendi/advancedperipherals/common/commands/APCommands.java @@ -4,7 +4,6 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.tree.LiteralCommandNode; - import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.core.computer.Environment; import dan200.computercraft.shared.command.UserLevel; @@ -12,11 +11,10 @@ import dan200.computercraft.shared.command.text.TableBuilder; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerContext; - import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.ChunkyPeripheral; +import de.srendi.advancedperipherals.common.util.ChunkManager; import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; - import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; @@ -46,8 +44,8 @@ public static void register(RegisterCommandsEvent event) { .executes(APCommands::safeExecute)) .build(); event.getDispatcher().register(Commands.literal(ROOT_LITERAL) - .then(Commands.literal("getHashItem").executes(context -> getHashItem(context.getSource()))) - .then(Commands.literal(FORCELOAD_LITERAL) + .then(Commands.literal("getHashItem") + .executes(context -> getHashItem(context.getSource()))).then(Commands.literal(FORCELOAD_LITERAL) .executes(context -> forceloadHelp(context.getSource())) .then(Commands.literal("help") .executes(context -> forceloadHelp(context.getSource()))) @@ -105,6 +103,8 @@ private static int forceloadDump(CommandSourceStack source) throws CommandSyntax ); } + ChunkManager manager = ChunkManager.get(source.getServer().overworld()); + source.sendSuccess(Component.literal("Forced " + manager.getForcedChunksCount() + " chunks"), true); table.display(source); return computers.length; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/APConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/APConfig.java index f19dbc4c2..651ccd789 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/APConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/APConfig.java @@ -1,19 +1,11 @@ package de.srendi.advancedperipherals.common.configuration; -import com.electronwill.nightconfig.core.file.CommentedFileConfig; import net.minecraftforge.fml.ModContainer; import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.config.ConfigFileTypeHandler; import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.loading.FMLPaths; - -import java.nio.file.Path; -import java.util.function.Function; public class APConfig extends ModConfig { - public static final ConfigFileHandler CONFIG_FILE_HANDLER = new ConfigFileHandler(); - public static final GeneralConfig GENERAL_CONFIG = new GeneralConfig(); public static final PeripheralsConfig PERIPHERALS_CONFIG = new PeripheralsConfig(); public static final MetaphysicsConfig METAPHYSICS_CONFIG = new MetaphysicsConfig(); @@ -24,37 +16,10 @@ public APConfig(IAPConfig config, ModContainer container) { } public static void register(ModLoadingContext context) { - //Creates the config folder - FMLPaths.getOrCreateGameRelativePath(FMLPaths.CONFIGDIR.get().resolve("Advancedperipherals"), "Advancedperipherals"); - ModContainer modContainer = context.getActiveContainer(); modContainer.addConfig(new APConfig(GENERAL_CONFIG, modContainer)); modContainer.addConfig(new APConfig(PERIPHERALS_CONFIG, modContainer)); modContainer.addConfig(new APConfig(METAPHYSICS_CONFIG, modContainer)); modContainer.addConfig(new APConfig(WORLD_CONFIG, modContainer)); } - - @Override - public ConfigFileTypeHandler getHandler() { - return CONFIG_FILE_HANDLER; - } - - public static class ConfigFileHandler extends ConfigFileTypeHandler { - - public static Path getPath(Path path) { - if (path.endsWith("serverconfig")) return FMLPaths.CONFIGDIR.get(); - - return path; - } - - @Override - public Function reader(Path configBasePath) { - return super.reader(getPath(configBasePath)); - } - - @Override - public void unload(Path configBasePath, ModConfig config) { - super.unload(getPath(configBasePath), config); - } - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/GeneralConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/GeneralConfig.java index 9ebf6a61d..8f07728e7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/GeneralConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/GeneralConfig.java @@ -33,7 +33,6 @@ public class GeneralConfig implements IAPConfig { configSpec = builder.build(); } - @Override public ForgeConfigSpec getConfigSpec() { return configSpec; @@ -46,6 +45,6 @@ public String getFileName() { @Override public ModConfig.Type getType() { - return ModConfig.Type.COMMON; + return ModConfig.Type.SERVER; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/MetaphysicsConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/MetaphysicsConfig.java index e45fdcbde..7a29fe96c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/MetaphysicsConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/MetaphysicsConfig.java @@ -47,6 +47,6 @@ public String getFileName() { @Override public ModConfig.Type getType() { - return ModConfig.Type.COMMON; + return ModConfig.Type.SERVER; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java index fa536e48e..066ededac 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java @@ -7,8 +7,8 @@ import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.config.ModConfig; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -30,12 +30,21 @@ public class PeripheralsConfig implements IAPConfig { public final ForgeConfigSpec.IntValue energyDetectorMaxFlow; public final ForgeConfigSpec.BooleanValue enableEnergyDetector; + // Fluid Detector + public final ForgeConfigSpec.IntValue fluidDetectorMaxFlow; + public final ForgeConfigSpec.BooleanValue enableFluidDetector; + + // Gas Detector + public final ForgeConfigSpec.IntValue gasDetectorMaxFlow; + public final ForgeConfigSpec.BooleanValue enableGasDetector; + // NBT Storage public final ForgeConfigSpec.IntValue nbtStorageMaxSize; public final ForgeConfigSpec.BooleanValue enableNBTStorage; // Chunky turtle public final ForgeConfigSpec.IntValue chunkLoadValidTime; + public final ForgeConfigSpec.IntValue chunkyTurtleRadius; public final ForgeConfigSpec.BooleanValue enableChunkyTurtle; @@ -61,8 +70,8 @@ public class PeripheralsConfig implements IAPConfig { // Environment Detector public final ForgeConfigSpec.BooleanValue enableEnvironmentDetector; - // AR Controller - public final ForgeConfigSpec.BooleanValue enableARGoggles; + // Smart glasses + public final ForgeConfigSpec.BooleanValue enableSmartGlasses; // Inventory Manager public final ForgeConfigSpec.BooleanValue enableInventoryManager; @@ -84,12 +93,21 @@ public class PeripheralsConfig implements IAPConfig { public final ForgeConfigSpec.IntValue compassAccurePlaceRadius; public final ForgeConfigSpec.IntValue compassAccurePlaceFreeRadius; + // Distance Detector + public final ForgeConfigSpec.BooleanValue enableDistanceDetector; + public final ForgeConfigSpec.DoubleValue distanceDetectorRange; + public final ForgeConfigSpec.IntValue distanceDetectorUpdateRate; + // Powered Peripherals public final ForgeConfigSpec.BooleanValue enablePoweredPeripherals; public final ForgeConfigSpec.BooleanValue disablePocketFuelConsumption; public final ForgeConfigSpec.IntValue poweredPeripheralMaxEnergyStorage; private final ForgeConfigSpec configSpec; + // Saddle turtle (it's tamed) + public final ForgeConfigSpec.BooleanValue enableSaddleTurtle; + public final ForgeConfigSpec.BooleanValue allowSaddleTurtleCapturePlayer; + private static final List chatBoxDefaultBannedCommands = Arrays.asList( "/execute", "/op", @@ -129,7 +147,17 @@ public PeripheralsConfig() { pop("Energy_Detector", builder); enableEnergyDetector = builder.comment("Enable the Energy Detector or not.").define("enableEnergyDetector", true); - energyDetectorMaxFlow = builder.comment("Defines the maximum energy flow of the energy detector.").defineInRange("energyDetectorMaxFlow", Integer.MAX_VALUE, 1, Integer.MAX_VALUE); + energyDetectorMaxFlow = builder.comment("Defines the maximum energy flow of the energy detector.").defineInRange("energyDetectorMaxFlow", Integer.MAX_VALUE, 0, Integer.MAX_VALUE); + + pop("Fluid_Detector", builder); + + enableFluidDetector = builder.comment("Enable the Fluid Detector or not.").define("enableFluidDetector", true); + fluidDetectorMaxFlow = builder.comment("Defines the maximum fluid flow of the fluid detector.").defineInRange("energyDetectorMaxFlow", Integer.MAX_VALUE, 0, Integer.MAX_VALUE); + + pop("Gas_Detector", builder); + + enableGasDetector = builder.comment("Enable the Gas Detector or not.").define("enableGasDetector", true); + gasDetectorMaxFlow = builder.comment("Defines the maximum gas flow of the gas detector.").defineInRange("gasDetectorMaxFlow", Integer.MAX_VALUE, 0, Integer.MAX_VALUE); pop("NBT_Storage", builder); @@ -168,7 +196,7 @@ public PeripheralsConfig() { pop("AR_Controller", builder); - enableARGoggles = builder.comment("Enable the AR goggles or not.").define("enableARGoggles", true); + enableSmartGlasses = builder.comment("Enable the smart glasses or not.").define("enableSmartGlasses", true); pop("Inventory_Manager", builder); @@ -196,6 +224,13 @@ public PeripheralsConfig() { compassAccurePlaceRadius = builder.comment("The maximum distance the compass can locate accurately with in each axis.").defineInRange("compassAccurePlaceRadius", 3, 0, 8); compassAccurePlaceFreeRadius = builder.comment("The free distance the compass can locate accurately with in each axis.").defineInRange("compassAccurePlaceFreeRadius", 1, 0, 4); + pop("Distance_Detector", builder); + + enableDistanceDetector = builder.comment("Enable the distance detector or not.").define("enableDistanceDetector", true); + distanceDetectorRange = builder.comment("Maximum range of the distance detector").defineInRange("distanceDetectorRange", 64D, 0D, Integer.MAX_VALUE); + distanceDetectorUpdateRate = builder.comment("Defines how often the distance detector updates it's distance if periodically updates are enabled. \n" + + "Periodically updates exists so we do not need to run \"getDistance\" on the main thread which eliminates the 1 tick yield of the lua function").defineInRange("maxUpdateRate", 2, 1, 100); + pop("Powered_Peripherals", builder); enablePoweredPeripherals = builder.comment("Enable RF storage for peripherals, that could use it").define("enablePoweredPeripherals", false); @@ -205,6 +240,11 @@ public PeripheralsConfig() { disablePocketFuelConsumption = builder.comment("If true, pockets will have infinite fuel").define("disablePocketFuelConsumption", true); + pop("Saddle_Turtle", builder); + + enableSaddleTurtle = builder.comment("Enable saddle turtle").define("enableSaddleTurtle", true); + allowSaddleTurtleCapturePlayer = builder.comment("Allow saddle turtle to capture player").define("allowSaddleTurtleCapturePlayer", true); + pop("Operations", builder); register(SingleOperation.values(), builder); @@ -228,7 +268,7 @@ public String getFileName() { @Override public ModConfig.Type getType() { - return ModConfig.Type.COMMON; + return ModConfig.Type.SERVER; } private List> parseChatBoxCommandFilters() { diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/WorldConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/WorldConfig.java index 8ba81c97c..9bc456e48 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/WorldConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/WorldConfig.java @@ -11,6 +11,7 @@ public class WorldConfig implements IAPConfig { public final ForgeConfigSpec.BooleanValue givePlayerBookOnJoin; public final ForgeConfigSpec.IntValue villagerStructureWeight; public final ForgeConfigSpec.BooleanValue enableWanderingTraderTrades; + public final ForgeConfigSpec.BooleanValue enableComputerScientistTrades; private final ForgeConfigSpec configSpec; public WorldConfig() { @@ -22,6 +23,7 @@ public WorldConfig() { givePlayerBookOnJoin = builder.comment("Gives the ap documentation to new players.").define("givePlayerBookOnJoin", true); villagerStructureWeight = builder.comment("The weight of the villager structures.").defineInRange("villagerStructureWeight", 10, 0, 16000); enableWanderingTraderTrades = builder.comment("Enable new wandering trader trades.").define("enableWanderingTraderTrades", true); + enableComputerScientistTrades = builder.comment("Enable computer scientist trades.").define("enableComputerScientistTrades", true); builder.pop(); configSpec = builder.build(); @@ -39,9 +41,6 @@ public String getFileName() { @Override public ModConfig.Type getType() { - return ModConfig.Type.COMMON; + return ModConfig.Type.SERVER; } - /* - [ - */ } diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerContainer.java b/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerContainer.java index 4ccc859cf..b4116aa2c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerContainer.java +++ b/src/main/java/de/srendi/advancedperipherals/common/container/InventoryManagerContainer.java @@ -3,8 +3,8 @@ import de.srendi.advancedperipherals.common.container.base.BaseContainer; import de.srendi.advancedperipherals.common.container.base.SlotCondition; import de.srendi.advancedperipherals.common.container.base.SlotInputHandler; -import de.srendi.advancedperipherals.common.setup.ContainerTypes; -import de.srendi.advancedperipherals.common.setup.Items; +import de.srendi.advancedperipherals.common.setup.APContainerTypes; +import de.srendi.advancedperipherals.common.setup.APItems; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -17,11 +17,11 @@ public class InventoryManagerContainer extends BaseContainer { public InventoryManagerContainer(int id, Inventory inventory, BlockPos pos, Level level) { - super(ContainerTypes.INVENTORY_MANAGER_CONTAINER.get(), id, inventory, pos, level); + super(APContainerTypes.INVENTORY_MANAGER_CONTAINER.get(), id, inventory, pos, level); layoutPlayerInventorySlots(7, 84); if (tileEntity != null) { tileEntity.getCapability(ForgeCapabilities.ITEM_HANDLER).ifPresent(handler -> { - addSlot(new SlotInputHandler(handler, 0, 79, 29, new SlotCondition().setNeededItem(Items.MEMORY_CARD.get()))); //Input + addSlot(new SlotInputHandler(handler, 0, 79, 29, new SlotCondition().setNeededItem(APItems.MEMORY_CARD.get()))); //Input }); } } @@ -44,7 +44,7 @@ public ItemStack quickMoveStack(@NotNull Player player, int index) { return ItemStack.EMPTY; } } else if (index <= 35) { - if (itemstack1.getItem().equals(Items.MEMORY_CARD.get())) { + if (itemstack1.getItem().equals(APItems.MEMORY_CARD.get())) { if (!this.moveItemStackTo(itemstack1, 36, 37, true)) { return ItemStack.EMPTY; } @@ -68,4 +68,5 @@ public ItemStack quickMoveStack(@NotNull Player player, int index) { return itemstack; } + } diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/SmartGlassesContainer.java b/src/main/java/de/srendi/advancedperipherals/common/container/SmartGlassesContainer.java new file mode 100644 index 000000000..fcecc6d1c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/container/SmartGlassesContainer.java @@ -0,0 +1,116 @@ +package de.srendi.advancedperipherals.common.container; + +import dan200.computercraft.client.gui.widgets.ComputerSidebar; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; +import dan200.computercraft.shared.network.container.ComputerContainerData; +import de.srendi.advancedperipherals.common.setup.APContainerTypes; +import de.srendi.advancedperipherals.common.smartglasses.SlotType; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesSlot; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +public class SmartGlassesContainer extends ContainerComputerBase { + public static final int BORDER = 8; + public static final int PLAYER_START_Y = 134; + public static final int PLAYER_START_X = ComputerSidebar.WIDTH + BORDER; + + public SmartGlassesContainer(int id, Predicate canUse, ServerComputer computer, Inventory playerInventory, IItemHandler inventory, ComputerContainerData data) { + super(APContainerTypes.SMART_GLASSES_CONTAINER.get(), id, canUse, ComputerFamily.ADVANCED, computer, data); + + /* + * Do player inventory before peripheral slots then quick move won't mixup + */ + + // Player hotbar + for (var x = 0; x < 9; x++) { + addSlot(new Slot(playerInventory, x, PLAYER_START_X + x * 18, PLAYER_START_Y + 3 * 18 + 5)); + } + + // Player inventory + for (var y = 0; y < 3; y++) { + for (var x = 0; x < 9; x++) { + addSlot(new Slot(playerInventory, x + y * 9 + 9, PLAYER_START_X + x * 18, PLAYER_START_Y + 1 + y * 18)); + } + } + + // Glasses Peripherals + addSlot(new SmartGlassesSlot(inventory, 0, 222, 148, SlotType.PERIPHERALS)); + addSlot(new SmartGlassesSlot(inventory, 1, 204, 166, SlotType.PERIPHERALS)); + addSlot(new SmartGlassesSlot(inventory, 2, 222, 166, SlotType.PERIPHERALS)); + addSlot(new SmartGlassesSlot(inventory, 3, 240, 166, SlotType.PERIPHERALS)); + addSlot(new SmartGlassesSlot(inventory, 4, 222, 184, SlotType.PERIPHERALS)); + + // Glasses Modules + addSlot(new SmartGlassesSlot(inventory, 5, 222, 148, SlotType.MODULES)); + addSlot(new SmartGlassesSlot(inventory, 6, 204, 166, SlotType.MODULES)); + addSlot(new SmartGlassesSlot(inventory, 7, 222, 166, SlotType.MODULES)); + addSlot(new SmartGlassesSlot(inventory, 8, 240, 166, SlotType.MODULES)); + addSlot(new SmartGlassesSlot(inventory, 9, 222, 184, SlotType.MODULES)); + addSlot(new SmartGlassesSlot(inventory, 10, 240, 184, SlotType.MODULES)); + + // Player inventory + for (var y = 0; y < 3; y++) { + for (var x = 0; x < 9; x++) { + addSlot(new Slot(playerInventory, x + y * 9 + 9, PLAYER_START_X + x * 18, PLAYER_START_Y + 1 + y * 18)); + } + } + + // Player hotbar + for (var x = 0; x < 9; x++) { + addSlot(new Slot(playerInventory, x, PLAYER_START_X + x * 18, PLAYER_START_Y + 3 * 18 + 5)); + } + + } + + public SmartGlassesContainer(int id, Predicate predicate, ServerComputer computer, ComputerContainerData data, Inventory player, ItemStack glasses) { + this(id, predicate, computer, player, glasses.getCapability(ForgeCapabilities.ITEM_HANDLER).orElseThrow(NullPointerException::new), data); + } + + @NotNull + @Override + public ItemStack quickMoveStack(@NotNull Player player, int index) { + ItemStack itemstack = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + if (slot.hasItem()) { + ItemStack itemstack1 = slot.getItem(); + itemstack = itemstack1.copy(); + if (index >= 36) { + if (!this.moveItemStackTo(itemstack1, 0, 36, true)) { + return ItemStack.EMPTY; + } + } else { + if (!this.moveItemStackTo(itemstack1, 36, 36 + 11, true)) { + return ItemStack.EMPTY; + } + } + + if (itemstack1.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + if (itemstack1.getCount() == itemstack.getCount()) { + return ItemStack.EMPTY; + } + + slot.onTake(player, itemstack1); + } + + return itemstack; + } + + @Override + public boolean stillValid(Player player) { + return true; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/base/SlotCondition.java b/src/main/java/de/srendi/advancedperipherals/common/container/base/SlotCondition.java index d1fae341c..1adcfcbc3 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/base/SlotCondition.java +++ b/src/main/java/de/srendi/advancedperipherals/common/container/base/SlotCondition.java @@ -12,9 +12,9 @@ */ public class SlotCondition { - public List> neededTags = new ArrayList<>(); + private List> neededTags = new ArrayList<>(); - public List neededItems = new ArrayList<>(); + private List neededItems = new ArrayList<>(); /** * Sets the valid tags for the item @@ -75,9 +75,9 @@ public boolean isValid(ItemStack stack) { if (stack.getTags().noneMatch(tag::equals)) valid = false; } } - if (!neededItems.isEmpty()) { - if (!neededItems.contains(stack.getItem())) valid = false; - } + if (!neededItems.isEmpty() && (!neededItems.contains(stack.getItem()))) + valid = false; + return valid; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/BlockLootTables.java b/src/main/java/de/srendi/advancedperipherals/common/data/BlockLootTables.java index 894a18ff3..f0c88c869 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/BlockLootTables.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/BlockLootTables.java @@ -1,6 +1,6 @@ package de.srendi.advancedperipherals.common.data; -import de.srendi.advancedperipherals.common.setup.Registration; +import de.srendi.advancedperipherals.common.setup.APRegistration; import net.minecraft.world.level.block.Block; import net.minecraftforge.registries.RegistryObject; import org.jetbrains.annotations.NotNull; @@ -9,7 +9,7 @@ public class BlockLootTables extends net.minecraft.data.loot.BlockLoot { @Override protected void addTables() { - Registration.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(registeredBlock -> { + APRegistration.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(registeredBlock -> { //Allow blocks to transfer their name to the dropped block when broken this.add(registeredBlock, (block) -> this.createNameableBlockEntityTable(block)); }); @@ -18,6 +18,6 @@ protected void addTables() { @NotNull @Override protected Iterable getKnownBlocks() { - return Registration.BLOCKS.getEntries().stream().map(RegistryObject::get)::iterator; + return APRegistration.BLOCKS.getEntries().stream().map(RegistryObject::get)::iterator; } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/BlockStatesAndModelsProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/BlockStatesAndModelsProvider.java index 05ca01c26..ae80747a0 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/BlockStatesAndModelsProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/BlockStatesAndModelsProvider.java @@ -2,16 +2,22 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; import net.minecraft.core.Direction; import net.minecraft.core.FrontAndTop; import net.minecraft.data.DataGenerator; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; -import net.minecraftforge.client.model.generators.*; +import net.minecraftforge.client.model.generators.BlockModelBuilder; +import net.minecraftforge.client.model.generators.BlockStateProvider; +import net.minecraftforge.client.model.generators.ConfiguredModel; +import net.minecraftforge.client.model.generators.ModelFile; +import net.minecraftforge.client.model.generators.ModelProvider; import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.registries.ForgeRegistries; +import java.util.Arrays; + public class BlockStatesAndModelsProvider extends BlockStateProvider { public BlockStatesAndModelsProvider(DataGenerator packOutput, ExistingFileHelper exFileHelper) { @@ -20,29 +26,41 @@ public BlockStatesAndModelsProvider(DataGenerator packOutput, ExistingFileHelper @Override protected void registerStatesAndModels() { - peripheralBlock(Blocks.ENVIRONMENT_DETECTOR.get(), "front"); - peripheralBlock(Blocks.CHAT_BOX.get(), "front"); - peripheralBlock(Blocks.PLAYER_DETECTOR.get(), "side", "front"); - peripheralBlock(Blocks.ME_BRIDGE.get(), "front"); - peripheralBlock(Blocks.RS_BRIDGE.get(), "front"); - peripheralBlock(Blocks.ENERGY_DETECTOR.get(), "front", "back"); - peripheralBlock(Blocks.PERIPHERAL_CASING.get()); - peripheralBlock(Blocks.INVENTORY_MANAGER.get(), "front"); - peripheralBlock(Blocks.REDSTONE_INTEGRATOR.get(), "front"); - peripheralBlock(Blocks.BLOCK_READER.get(), generateModel(Blocks.BLOCK_READER.get(), false, "north", "south", "east", "west", "up", "down")); - peripheralBlock(Blocks.GEO_SCANNER.get(), "front"); - peripheralBlock(Blocks.COLONY_INTEGRATOR.get(), generateModel(Blocks.COLONY_INTEGRATOR.get()) - .texture("particle", blockTexture(Blocks.COLONY_INTEGRATOR.get())) - .texture("up", blockTexture(net.minecraft.world.level.block.Blocks.OAK_LOG, "top")) - .texture("down", blockTexture(net.minecraft.world.level.block.Blocks.OAK_LOG, "top"))); - peripheralBlock(Blocks.NBT_STORAGE.get(), "front"); + // Define blocks with specific sides and orientations + peripheralBlock(APBlocks.ENVIRONMENT_DETECTOR.get(), "front", "top"); + peripheralBlock(APBlocks.CHAT_BOX.get(), "front", "top"); + peripheralBlock(APBlocks.ME_BRIDGE.get(), "front", "top"); + peripheralBlock(APBlocks.RS_BRIDGE.get(), "front", "top"); + peripheralBlock(APBlocks.ENERGY_DETECTOR.get(), "front", "back", "top", "east"); + peripheralBlock(APBlocks.FLUID_DETECTOR.get(), "front", "back", "top", "east"); + peripheralBlock(APBlocks.GAS_DETECTOR.get(), "front", "back", "top", "east"); + peripheralBlock(APBlocks.INVENTORY_MANAGER.get(), "front", "top"); + peripheralBlock(APBlocks.GEO_SCANNER.get(), "front", "top"); + peripheralBlock(APBlocks.COLONY_INTEGRATOR.get(), "front", "top"); + peripheralBlock(APBlocks.NBT_STORAGE.get(), "front", "top"); + + // Define blocks with custom model generation + peripheralBlock(APBlocks.PLAYER_DETECTOR.get(), generateModel(APBlocks.PLAYER_DETECTOR.get(), false, "side", "front", "top")); + peripheralBlock(APBlocks.REDSTONE_INTEGRATOR.get(), generateModel(APBlocks.REDSTONE_INTEGRATOR.get(), false, "side", "front", "top", "bottom")); + peripheralBlock(APBlocks.BLOCK_READER.get(), generateModel(APBlocks.BLOCK_READER.get(), false, "north", "south", "east", "west", "up", "down")); + peripheralBlock(APBlocks.DISTANCE_DETECTOR.get(), generateModel(APBlocks.DISTANCE_DETECTOR.get(), false, "north", "south", "east", "west", "up", "down")); + + // Define a simple block with all sides having the same texture + peripheralBlock(APBlocks.PERIPHERAL_CASING.get()); } + // Helper method to register block states and models with specific sides + private void peripheralBlock(Block block, String... sides) { + peripheralBlock(block, generateModel(block, true, sides)); + } + + // Helper method to register block states and models with a pre-generated model private void peripheralBlock(Block block, ModelFile file) { getVariantBuilder(block).forAllStates(state -> { ConfiguredModel.Builder builder = ConfiguredModel.builder().modelFile(file); FrontAndTop orientation = state.getValue(BaseBlock.ORIENTATION); - int x = 0, y; + int x = 0; + int y; if (orientation.top().getAxis() == Direction.Axis.Y) { y = (int) (orientation.front().toYRot() + 180) % 360; } else { @@ -55,10 +73,7 @@ private void peripheralBlock(Block block, ModelFile file) { }); } - private void peripheralBlock(Block block, String... sides) { - peripheralBlock(block, generateModel(block, true, sides)); - } - + // Helper method to generate a block model with specified sides and textures private BlockModelBuilder generateModel(Block block, boolean hasNormalSide, String... sides) { ResourceLocation particleTexture = blockTexture(block); BlockModelBuilder builder; @@ -67,32 +82,53 @@ private BlockModelBuilder generateModel(Block block, boolean hasNormalSide, Stri } else { builder = models().withExistingParent(name(block), mcLoc("block/cube_all")); } + for (String sideTexture : sides) { String side = sideTexture; - if (side.equals("side")) { - for (Direction direction : Direction.Plane.HORIZONTAL) - builder.texture(direction.toString(), blockTexture(block, sideTexture)); - } - if(side.equals("north")) - particleTexture = blockTexture(block, "north"); - if (side.equals("front")) { - side = "north"; - particleTexture = blockTexture(block, "front"); + switch (side) { + case "side": + for (Direction direction : Direction.Plane.HORIZONTAL) { + builder.texture(direction.toString(), blockTexture(block, sideTexture)); + } + break; + case "north": + particleTexture = blockTexture(block, side); + break; + case "front": + particleTexture = blockTexture(block, side); + side = "north"; + break; + case "top": + side = "up"; + break; + case "bottom": + side = "down"; + break; + case "back": + side = "south"; + break; + default: + break; } - if (side.equals("back")) side = "south"; - builder.texture(side, blockTexture(block, sideTexture)); + builder.texture(side, blockTexture(block, sideTexture)); + } + // Add default bottom texture if not specified + if (!Arrays.asList(sides).contains("down") && !Arrays.asList(sides).contains("bottom")) { + builder.texture("down", AdvancedPeripherals.getRL(ModelProvider.BLOCK_FOLDER + "/" + "bottom")); } builder.texture("particle", particleTexture); return builder; } + // Helper method to generate a simple block model private BlockModelBuilder generateModel(Block block) { return models().cubeAll(name(block), blockTexture(block)); } + // Helper methods for generating resource locations and block names private ResourceLocation blockTexture(Block block, String offset) { ResourceLocation name = key(block); return new ResourceLocation(name.getNamespace(), ModelProvider.BLOCK_FOLDER + "/" + name.getPath() + "_" + offset); @@ -105,5 +141,4 @@ private ResourceLocation key(Block block) { private String name(Block block) { return key(block).getPath(); } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/DataGenerators.java b/src/main/java/de/srendi/advancedperipherals/common/data/DataGenerators.java index e1f3f16a3..c7c8c015b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/DataGenerators.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/DataGenerators.java @@ -1,7 +1,7 @@ package de.srendi.advancedperipherals.common.data; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.setup.Registration; +import de.srendi.advancedperipherals.common.setup.APRegistration; import net.minecraft.data.DataGenerator; import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.data.event.GatherDataEvent; @@ -19,15 +19,14 @@ public static void genData(GatherDataEvent event) { DataGenerator generator = event.getGenerator(); ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); - generator.addProvider(event.includeServer(), new BlockTagsProvider(generator, existingFileHelper, Registration.BLOCKS)); + generator.addProvider(event.includeServer(), new BlockTagsProvider(generator, existingFileHelper, APRegistration.BLOCKS)); generator.addProvider(event.includeServer(), new RecipesProvider(generator)); generator.addProvider(event.includeServer(), new BlockLootTablesProvider(generator)); generator.addProvider(event.includeServer(), new TurtleUpgradesProvider(generator)); generator.addProvider(event.includeServer(), new PocketUpgradesProvider(generator)); generator.addProvider(event.includeServer(), new PoiTypeProvider(generator, existingFileHelper)); generator.addProvider(event.includeServer(), new BlockStatesAndModelsProvider(generator, existingFileHelper)); - + generator.addProvider(event.includeServer(), new ItemTagsProvider(generator, existingFileHelper)); generator.addProvider(event.includeClient(), new EnUsLanguageProvider(generator)); } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java index 22ada0834..832cf08be 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java @@ -2,10 +2,10 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.client.KeyBindings; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.setup.APItems; +import de.srendi.advancedperipherals.common.setup.APVillagers; import de.srendi.advancedperipherals.common.setup.CCRegistration; -import de.srendi.advancedperipherals.common.setup.Items; -import de.srendi.advancedperipherals.common.setup.Villagers; import net.minecraft.client.KeyMapping; import net.minecraft.data.DataGenerator; import net.minecraft.resources.ResourceLocation; @@ -33,58 +33,74 @@ protected void addTranslations() { addAdvancements(); addTooltips(); addKeybinds(); - addText(); - add(Villagers.COMPUTER_SCIENTIST, "Computer Scientist"); + addTexts(); + add(APVillagers.COMPUTER_SCIENTIST, "Computer Scientist"); add("advancedperipherals.name", AdvancedPeripherals.NAME); + add("curios.identifier.glasses", "Glasses"); add("itemGroup.advancedperipheralstab", AdvancedPeripherals.NAME); } private void addItems() { - addItem(Items.CHUNK_CONTROLLER, "Chunk Controller"); - addItem(Items.COMPUTER_TOOL, "Computer Tool"); - addItem(Items.WEAK_AUTOMATA_CORE, "Weak Automata Core"); - addItem(Items.HUSBANDRY_AUTOMATA_CORE, "Husbandry Automata Core"); - addItem(Items.END_AUTOMATA_CORE, "End Automata Core"); - addItem(Items.OVERPOWERED_WEAK_AUTOMATA_CORE, "Overpowered Weak Automata Core"); - addItem(Items.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE, "Overpowered Husbandry Automata Core"); - addItem(Items.OVERPOWERED_END_AUTOMATA_CORE, "Overpowered End Automata Core"); - addItem(Items.MEMORY_CARD, "Memory Card"); + addItem(APItems.CHUNK_CONTROLLER, "Chunk Controller"); + addItem(APItems.COMPUTER_TOOL, "Computer Tool"); + addItem(APItems.HOTKEY_MODULE, "Hotkey Module"); + addItem(APItems.MEMORY_CARD, "Memory Card"); + addItem(APItems.NIGHT_VISION_MODULE, "Night Vision Module"); + addItem(APItems.OVERLAY_MODULE, "Overlay Module"); + addItem(APItems.SMART_GLASSES, "Smart Glasses"); + addItem(APItems.SMART_GLASSES_INTERFACE, "Smart Glasses Interface"); + addItem(APItems.SMART_GLASSES_NETHERITE, "Netherite reinforced Smart Glasses"); + + addItem(APItems.END_AUTOMATA_CORE, "End Automata Core"); + addItem(APItems.HUSBANDRY_AUTOMATA_CORE, "Husbandry Automata Core"); + addItem(APItems.OVERPOWERED_END_AUTOMATA_CORE, "Overpowered End Automata Core"); + addItem(APItems.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE, "Overpowered Husbandry Automata Core"); + addItem(APItems.OVERPOWERED_WEAK_AUTOMATA_CORE, "Overpowered Weak Automata Core"); + addItem(APItems.WEAK_AUTOMATA_CORE, "Weak Automata Core"); + + addItem(APItems.CABLE_P2P_TUNNEL, "Cable P2P Tunnel"); } private void addBlocks() { - addBlock(Blocks.BLOCK_READER, "Block Reader"); - addBlock(Blocks.CHAT_BOX, "Chat Box"); - addBlock(Blocks.COLONY_INTEGRATOR, "Colony Integrator"); - addBlock(Blocks.ENERGY_DETECTOR, "Energy Detector"); - addBlock(Blocks.ENVIRONMENT_DETECTOR, "Environment Detector"); - addBlock(Blocks.GEO_SCANNER, "Geo Scanner"); - addBlock(Blocks.INVENTORY_MANAGER, "Inventory Manager"); - addBlock(Blocks.ME_BRIDGE, "ME Bridge"); - addBlock(Blocks.RS_BRIDGE, "RS Bridge"); - addBlock(Blocks.NBT_STORAGE, "NBT Storage"); - addBlock(Blocks.PERIPHERAL_CASING, "Peripheral Casing"); - addBlock(Blocks.PLAYER_DETECTOR, "Player Detector"); - addBlock(Blocks.REDSTONE_INTEGRATOR, "Redstone Integrator"); + addBlock(APBlocks.BLOCK_READER, "Block Reader"); + addBlock(APBlocks.CHAT_BOX, "Chat Box"); + addBlock(APBlocks.COLONY_INTEGRATOR, "Colony Integrator"); + addBlock(APBlocks.DISTANCE_DETECTOR, "Distance Detector"); + addBlock(APBlocks.ENERGY_DETECTOR, "Energy Detector"); + addBlock(APBlocks.ENVIRONMENT_DETECTOR, "Environment Detector"); + addBlock(APBlocks.FLUID_DETECTOR, "Fluid Detector"); + addBlock(APBlocks.GAS_DETECTOR, "Gas Detector"); + addBlock(APBlocks.GEO_SCANNER, "Geo Scanner"); + addBlock(APBlocks.INVENTORY_MANAGER, "Inventory Manager"); + addBlock(APBlocks.ME_BRIDGE, "ME Bridge"); + addBlock(APBlocks.NBT_STORAGE, "NBT Storage"); + addBlock(APBlocks.PERIPHERAL_CASING, "Peripheral Casing"); + addBlock(APBlocks.PLAYER_DETECTOR, "Player Detector"); + addBlock(APBlocks.REDSTONE_INTEGRATOR, "Redstone Integrator"); + addBlock(APBlocks.RS_BRIDGE, "RS Bridge"); } private void addTurtles() { - addTurtle(CCRegistration.ID.CHUNKY_TURTLE, "Chunky"); addTurtle(CCRegistration.ID.CHATTY_TURTLE, "Chatty"); + addTurtle(CCRegistration.ID.CHUNKY_TURTLE, "Chunky"); + addTurtle(CCRegistration.ID.COMPASS_TURTLE, "Compass"); addTurtle(CCRegistration.ID.ENVIRONMENT_TURTLE, "Environment"); - addTurtle(CCRegistration.ID.PLAYER_TURTLE, "Player Detector"); addTurtle(CCRegistration.ID.GEOSCANNER_TURTLE, "Geo"); - addTurtle(CCRegistration.ID.COMPASS_TURTLE, "Compass"); - addTurtle(CCRegistration.ID.WEAK_AUTOMATA, "Weak automata"); - addTurtle(CCRegistration.ID.HUSBANDRY_AUTOMATA, "Husbandry automata"); - addTurtle(CCRegistration.ID.END_AUTOMATA, "End automata"); - addTurtle(CCRegistration.ID.OP_WEAK_AUTOMATA, "Overpowered weak automata"); - addTurtle(CCRegistration.ID.OP_HUSBANDRY_AUTOMATA, "Overpowered husbandry automata"); - addTurtle(CCRegistration.ID.OP_END_AUTOMATA, "Overpowered end automata"); + addTurtle(CCRegistration.ID.PLAYER_TURTLE, "Player Detector"); + addTurtle(CCRegistration.ID.SADDLE_TURTLE, "Saddle"); + + addTurtle(CCRegistration.ID.END_AUTOMATA, "End Automata"); + addTurtle(CCRegistration.ID.HUSBANDRY_AUTOMATA, "Husbandry Automata"); + addTurtle(CCRegistration.ID.OP_END_AUTOMATA, "Overpowered End Automata"); + addTurtle(CCRegistration.ID.OP_HUSBANDRY_AUTOMATA, "Overpowered Husbandry Automata"); + addTurtle(CCRegistration.ID.OP_WEAK_AUTOMATA, "Overpowered Weak Automata"); + addTurtle(CCRegistration.ID.WEAK_AUTOMATA, "Weak Automata"); } private void addPockets() { - addPocket(CCRegistration.ID.COLONY_POCKET, "Colony"); addPocket(CCRegistration.ID.CHATTY_POCKET, "Chatty"); + addPocket(CCRegistration.ID.COLONY_POCKET, "Colony"); + addPocket(CCRegistration.ID.DISTANCE_POCKET, "Distance Detector"); addPocket(CCRegistration.ID.ENVIRONMENT_POCKET, "Environment"); addPocket(CCRegistration.ID.GEOSCANNER_POCKET, "Geo"); addPocket(CCRegistration.ID.PLAYER_POCKET, "Player Detector"); @@ -92,47 +108,55 @@ private void addPockets() { private void addAdvancements() { addAdvancement("root", AdvancedPeripherals.NAME, "Every journey starts with the first block"); - addAdvancement("weak_automata_core", "First automata core", "Does the afterlife exist in minecraft?"); - addAdvancement("end_automata_core", "End automata core", "If you can code gps-free position location with this, you're a powerful human being"); - addAdvancement("husbandry_automata_core", "Husbandry automata core", "Is this core gluten-free?"); - addAdvancement("overpowered_automata_core", "Overpowered automata core", "Can you handle so much power?"); + addAdvancement("base_toolkit", "Gentleman's set!", "Collect a redstone integrator, inventory manager and energy detector. How did you even play without this?"); addAdvancement("nbt_toolkit", "No secrets", "Collect a NBT storage and block reader. Now, all the world's secrets are open to you!"); addAdvancement("sense_toolkit", "The truth can't hide forever", "Collect a geo scanner and environmental detector. There are no limits for observability!"); + + addAdvancement("end_automata_core", "End Automata Core", "If you can code gps-free position location with this, you're a powerful human being"); + addAdvancement("husbandry_automata_core", "Husbandry Automata Core", "Is this core gluten-free?"); + addAdvancement("overpowered_automata_core", "Overpowered Automata Core", "Can you handle so much power?"); + addAdvancement("weak_automata_core", "First Automata Core", "Does the afterlife exist in minecraft?"); } private void addTooltips() { addTooltip("show_desc", "&b[&7%s&b] &7For Description"); - addTooltip("disabled", "&cThis item is disabled in the config, so you can craft it, but it'll not have any functionality."); - addTooltip(Items.COMPUTER_TOOL.get(), "&7This tool was made to tune our blocks. But for now, it's just a blue useless wrench."); - addTooltip(Blocks.ENERGY_DETECTOR.get(), "&7Can detect energy flow and acts as a resistor."); - addTooltip(Items.CHUNK_CONTROLLER.get(), "&7A crafting ingredient for the Chunky Turtle."); - addTooltip(Blocks.ENVIRONMENT_DETECTOR.get(), "&7This peripheral interacts with the minecraft world."); - addTooltip(Blocks.PLAYER_DETECTOR.get(), "&7This peripheral can be used to interact with players, but don't be a stalker."); - addTooltip(Blocks.RS_BRIDGE.get(), "&7The RS Bridge interacts with Refined Storage to manage your items."); - addTooltip(Blocks.ME_BRIDGE.get(), "&7The ME Bridge interacts with Applied Energistics to manage your items."); - addTooltip(Blocks.CHAT_BOX.get(), "&7Interacts with the ingame chat, can read and write messages."); - addTooltip(Blocks.PERIPHERAL_CASING.get(), "&7An empty hull without the love it deserves. Used as a crafting ingredient"); - addTooltip(Items.MEMORY_CARD.get(), "&7Can save the rights of a player to use it in an inventory manager."); + addTooltip("disabled", "&cThis item is disabled in config, so you can craft it, but it'll not have any functionality."); + + addTooltip(APBlocks.BLOCK_READER.get(), "&7Reads nbt data of blocks to interact with blocks which do not have computer support."); + addTooltip(APBlocks.CHAT_BOX.get(), "&7Interacts with the ingame chat, can read and write messages."); + addTooltip(APBlocks.COLONY_INTEGRATOR.get(), "&7Interacts with Minecolonies to read data about your colony and citizens."); + addTooltip(APBlocks.ENERGY_DETECTOR.get(), "&7Can detect energy flow and acts as a resistor."); + addTooltip(APBlocks.ENVIRONMENT_DETECTOR.get(), "&7This peripheral interacts with the minecraft world."); + addTooltip(APBlocks.GEO_SCANNER.get(), "&7Scans the area around it to find some shiny ores."); + addTooltip(APBlocks.INVENTORY_MANAGER.get(), "&7This block is able to send or receive specific items from a player inventory."); + addTooltip(APBlocks.ME_BRIDGE.get(), "&7The ME Bridge interacts with Applied Energistics to manage your items."); + addTooltip(APBlocks.NBT_STORAGE.get(), "&7Acts like a storage disk. Can store nbt based data."); + addTooltip(APBlocks.PERIPHERAL_CASING.get(), "&7An empty hull without the love it deserves. Used as crafting ingredient"); + addTooltip(APBlocks.PLAYER_DETECTOR.get(), "&7This peripheral can be used to interact with players, but don't be a stalker."); + addTooltip(APBlocks.REDSTONE_INTEGRATOR.get(), "&7This block is able to interact with redstone. Works exactly like the redstone api of an computer."); + addTooltip(APBlocks.RS_BRIDGE.get(), "&7The RS Bridge interacts with Refined Storage to manage your items."); + + addTooltip(APItems.CHUNK_CONTROLLER.get(), "&7A crafting ingredient for the Chunky Turtle."); + addTooltip(APItems.END_AUTOMATA_CORE.get(), "&7Upgrade for turtles, that allows basic interaction with the world and teleportation in one dimension."); + addTooltip(APItems.HUSBANDRY_AUTOMATA_CORE.get(), "&7Upgrade for turtles, that allows basic and advanced interactions with animals."); + addTooltip(APItems.OVERPOWERED_END_AUTOMATA_CORE.get(), "&7Improved version of the end automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); + addTooltip(APItems.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get(), "&7Improved version of the husbandry automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); + addTooltip(APItems.OVERPOWERED_WEAK_AUTOMATA_CORE.get(), "&7Improved version of the weak automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); + addTooltip(APItems.WEAK_AUTOMATA_CORE.get(), "&7Upgrade for turtles, which makes turtles more useful."); + + addTooltip(APItems.COMPUTER_TOOL.get(), "&7This tool was made to tune our blocks. But for now, it's just a blue useless wrench."); + addTooltip(APItems.MEMORY_CARD.get(), "&7Can save the rights of a player to use it in an inventory manager."); addTooltip("memory_card.bound", "&7Bound to &b%s&7."); - addTooltip(Blocks.INVENTORY_MANAGER.get(), "&7This block is able to send or receive specific items from a player inventory."); - addTooltip(Blocks.REDSTONE_INTEGRATOR.get(), "&7This block is able to interact with redstone. Works exactly like the redstone api of an computer."); - addTooltip(Blocks.BLOCK_READER.get(), "&7Reads nbt data of blocks to interact with blocks which do not have computer support."); - addTooltip(Blocks.GEO_SCANNER.get(), "&7Scans the area around it to find some shiny ores."); - addTooltip(Blocks.COLONY_INTEGRATOR.get(), "&7Interacts with Minecolonies to read data about your colony and citizens."); - addTooltip(Blocks.NBT_STORAGE.get(), "&7Acts like a storage disk. Can store nbt based data."); - addTooltip(Items.WEAK_AUTOMATA_CORE.get(), "&7Upgrade for turtles, which makes turtles more useful."); - addTooltip(Items.OVERPOWERED_WEAK_AUTOMATA_CORE.get(), "&7Improved version of the weak automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); - addTooltip(Items.HUSBANDRY_AUTOMATA_CORE.get(), "&7Upgrade for turtles, that allows basic and advanced interactions with animals."); - addTooltip(Items.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get(), "&7Improved version of the husbandry automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); - addTooltip(Items.END_AUTOMATA_CORE.get(), "&7Upgrade for turtles, that allows basic interaction with the world and teleportation in one dimension."); - addTooltip(Items.OVERPOWERED_END_AUTOMATA_CORE.get(), "&7Improved version of the end automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); - } - - private void addText() { - add("text." + AdvancedPeripherals.MOD_ID + ".removed_player", "Cleared the memory card"); - add("text." + AdvancedPeripherals.MOD_ID + ".added_player", "Added you to the memory card"); - add("text." + AdvancedPeripherals.MOD_ID + ".automata_core_feed_by_player", "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?"); + } + + private void addTexts() { + addText("removed_player", "Cleared the memory card"); + addText("added_player", "Added you to the memory card"); + addText("automata_core.feed_by_player", "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?"); + addText("smart_glasses.peripherals", "Peripherals"); + addText("smart_glasses.modules", "Modules"); + addText("saddle_turtle.dismount_hint", "Controlling %1$s. Press %2$s and %3$s to dismount."); } private void addKeybinds() { @@ -146,7 +170,11 @@ private void addAdvancement(@NotNull String advancement, @NotNull String name, @ } private void add(@NotNull Supplier key, @NotNull String name) { - add("entity.minecraft.villager." + AdvancedPeripherals.MOD_ID + "." + key.get().name().split(":")[1], name); + add(new ResourceLocation(key.get().name()).toLanguageKey("entity.minecraft.villager"), name); + } + + private void addText(String key, String value) { + add("text." + AdvancedPeripherals.MOD_ID + "." + key, value); } private void addTurtle(@NotNull ResourceLocation key, @NotNull String name) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/ItemTagsProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/ItemTagsProvider.java new file mode 100644 index 000000000..b3b9d4520 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/data/ItemTagsProvider.java @@ -0,0 +1,27 @@ +package de.srendi.advancedperipherals.common.data; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.addons.ae2.AE2Registries; +import de.srendi.advancedperipherals.common.setup.APItems; +import de.srendi.advancedperipherals.common.setup.APTags; +import net.minecraft.core.Registry; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.tags.TagsProvider; +import net.minecraft.world.item.Item; +import net.minecraftforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.Nullable; + +public class ItemTagsProvider extends TagsProvider { + + protected ItemTagsProvider(DataGenerator generator, @Nullable ExistingFileHelper existingFileHelper) { + super(generator, Registry.ITEM, AdvancedPeripherals.MOD_ID, existingFileHelper); + } + + @Override + protected void addTags() { + tag(APTags.Items.SMART_GLASSES) + .add(APItems.SMART_GLASSES.get()) + .add(APItems.SMART_GLASSES_NETHERITE.get()); + AE2Registries.registerTags(this::tag); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/PocketUpgradesProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/PocketUpgradesProvider.java index bb78f341b..a021dbee7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/PocketUpgradesProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/PocketUpgradesProvider.java @@ -2,7 +2,7 @@ import dan200.computercraft.api.pocket.PocketUpgradeDataProvider; import dan200.computercraft.api.pocket.PocketUpgradeSerialiser; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; import de.srendi.advancedperipherals.common.setup.CCRegistration; import net.minecraft.data.DataGenerator; import org.jetbrains.annotations.NotNull; @@ -17,10 +17,11 @@ public PocketUpgradesProvider(DataGenerator output) { @Override protected void addUpgrades(@NotNull Consumer>> addUpgrade) { - simpleWithCustomItem(CCRegistration.ID.CHATTY_POCKET, CCRegistration.CHAT_BOX_POCKET.get(), Blocks.CHAT_BOX.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.PLAYER_POCKET, CCRegistration.PLAYER_DETECTOR_POCKET.get(), Blocks.PLAYER_DETECTOR.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.ENVIRONMENT_POCKET, CCRegistration.ENVIRONMENT_POCKET.get(), Blocks.ENVIRONMENT_DETECTOR.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.GEOSCANNER_POCKET, CCRegistration.GEO_SCANNER_POCKET.get(), Blocks.GEO_SCANNER.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.COLONY_POCKET, CCRegistration.COLONY_POCKET.get(), Blocks.COLONY_INTEGRATOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.CHATTY_POCKET, CCRegistration.CHAT_BOX_POCKET.get(), APBlocks.CHAT_BOX.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.COLONY_POCKET, CCRegistration.COLONY_POCKET.get(), APBlocks.COLONY_INTEGRATOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.DISTANCE_POCKET, CCRegistration.DISTANCE_DETECTOR_POCKET.get(), APBlocks.DISTANCE_DETECTOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.ENVIRONMENT_POCKET, CCRegistration.ENVIRONMENT_POCKET.get(), APBlocks.ENVIRONMENT_DETECTOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.GEOSCANNER_POCKET, CCRegistration.GEO_SCANNER_POCKET.get(), APBlocks.GEO_SCANNER.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.PLAYER_POCKET, CCRegistration.PLAYER_DETECTOR_POCKET.get(), APBlocks.PLAYER_DETECTOR.get().asItem()).add(addUpgrade); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/PoiTypeProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/PoiTypeProvider.java index d3ca346a4..9549f1cc3 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/PoiTypeProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/PoiTypeProvider.java @@ -1,7 +1,7 @@ package de.srendi.advancedperipherals.common.data; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.setup.Registration; +import de.srendi.advancedperipherals.common.setup.APRegistration; import net.minecraft.data.DataGenerator; import net.minecraft.data.tags.PoiTypeTagsProvider; import net.minecraft.data.tags.TagsProvider; @@ -14,7 +14,6 @@ public class PoiTypeProvider extends PoiTypeTagsProvider { - public PoiTypeProvider(DataGenerator pGenerator, @Nullable ExistingFileHelper existingFileHelper) { super(pGenerator, AdvancedPeripherals.MOD_ID, existingFileHelper); } @@ -22,7 +21,7 @@ public PoiTypeProvider(DataGenerator pGenerator, @Nullable ExistingFileHelper ex @Override protected void addTags() { TagsProvider.TagAppender appender = tag(PoiTypeTags.ACQUIRABLE_JOB_SITE); - Registration.POI_TYPES.getEntries().stream().map(RegistryObject::getKey).forEach(appender::add); + APRegistration.POI_TYPES.getEntries().stream().map(RegistryObject::getKey).forEach(appender::add); } @NotNull diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/RecipesProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/RecipesProvider.java index d361c3f8a..fd6a1635b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/RecipesProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/RecipesProvider.java @@ -5,10 +5,15 @@ import com.refinedmods.refinedstorage.RSItems; import dan200.computercraft.shared.Registry; import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.setup.APItems; import de.srendi.advancedperipherals.common.util.RawValue; import net.minecraft.data.DataGenerator; -import net.minecraft.data.recipes.*; +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeProvider; +import net.minecraft.data.recipes.ShapedRecipeBuilder; +import net.minecraft.data.recipes.ShapelessRecipeBuilder; +import net.minecraft.data.recipes.UpgradeRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.ItemStack; @@ -28,16 +33,52 @@ public class RecipesProvider extends RecipeProvider implements IConditionBuilder { - private static final Block CASING = Blocks.PERIPHERAL_CASING.get(); + private static final Block CASING = APBlocks.PERIPHERAL_CASING.get(); private static final String HAS_ITEM = "has_item"; - public RecipesProvider(DataGenerator pGenerator) { - super(pGenerator); + public RecipesProvider(DataGenerator packOutput) { + super(packOutput); } @Override protected void buildCraftingRecipes(@NotNull Consumer consumer) { - ShapedRecipeBuilder.shaped(Blocks.CHAT_BOX.get()) + addShapeless(consumer); + addShaped(consumer); + addSmithing(consumer); + } + + private void addShapeless(@NotNull Consumer consumer) { + ShapelessRecipeBuilder.shapeless(APItems.OVERPOWERED_WEAK_AUTOMATA_CORE.get()) + .requires(APItems.WEAK_AUTOMATA_CORE.get()) + .requires(Items.NETHER_STAR) + .unlockedBy(HAS_ITEM, has(APItems.WEAK_AUTOMATA_CORE.get())) + .save(consumer); + + ShapelessRecipeBuilder.shapeless(APItems.OVERPOWERED_END_AUTOMATA_CORE.get()) + .requires(APItems.END_AUTOMATA_CORE.get()) + .requires(Items.NETHER_STAR) + .unlockedBy(HAS_ITEM, has(APItems.END_AUTOMATA_CORE.get())) + .save(consumer); + + ShapelessRecipeBuilder.shapeless(APItems.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get()) + .requires(APItems.HUSBANDRY_AUTOMATA_CORE.get()) + .requires(Items.NETHER_STAR) + .unlockedBy(HAS_ITEM, has(APItems.HUSBANDRY_AUTOMATA_CORE.get())) + .save(consumer); + } + + private void addShaped(@NotNull Consumer consumer) { + /*ShapedRecipeBuilder.shaped(APItems.AR_GOGGLES.get()) + .define('E', Tags.Items.ENDER_PEARLS) + .define('S', Tags.Items.RODS_WOODEN) + .define('G', Tags.Items.GLASS_BLACK) + .pattern("GSG") + .pattern(" E ") + .unlockedBy(HAS_ITEM, has(Items.STICK)) + .save(consumer); + */ + + ShapedRecipeBuilder.shaped(APBlocks.CHAT_BOX.get()) .define('P', ItemTags.LOGS) .define('A', CASING) .define('G', Tags.Items.INGOTS_GOLD) @@ -47,7 +88,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(de.srendi.advancedperipherals.common.setup.Items.CHUNK_CONTROLLER.get()) + ShapedRecipeBuilder.shaped(APItems.CHUNK_CONTROLLER.get()) .define('I', Tags.Items.INGOTS_IRON) .define('R', Tags.Items.DUSTS_REDSTONE) .define('A', Items.ENDER_EYE) @@ -57,7 +98,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(Items.RESPAWN_ANCHOR)) .save(consumer); - ShapedRecipeBuilder.shaped(de.srendi.advancedperipherals.common.setup.Items.COMPUTER_TOOL.get()) + ShapedRecipeBuilder.shaped(APItems.COMPUTER_TOOL.get()) .define('I', Tags.Items.INGOTS_IRON) .define('B', Items.BLUE_TERRACOTTA) .pattern("I I") @@ -66,7 +107,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(Items.BLUE_TERRACOTTA)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.ENERGY_DETECTOR.get()) + ShapedRecipeBuilder.shaped(APBlocks.ENERGY_DETECTOR.get()) .define('B', Tags.Items.STORAGE_BLOCKS_REDSTONE) .define('R', Items.REDSTONE_TORCH) .define('C', Items.COMPARATOR) @@ -78,7 +119,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.ENVIRONMENT_DETECTOR.get()) + ShapedRecipeBuilder.shaped(APBlocks.ENVIRONMENT_DETECTOR.get()) .define('W', ItemTags.WOOL) .define('S', ItemTags.SAPLINGS) .define('C', Tags.Items.CROPS) @@ -90,7 +131,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.INVENTORY_MANAGER.get()) + ShapedRecipeBuilder.shaped(APBlocks.INVENTORY_MANAGER.get()) .define('I', Tags.Items.INGOTS_IRON) .define('C', Tags.Items.CHESTS) .define('A', CASING) @@ -100,7 +141,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(de.srendi.advancedperipherals.common.setup.Items.MEMORY_CARD.get()) + ShapedRecipeBuilder.shaped(APItems.MEMORY_CARD.get()) .define('I', Tags.Items.INGOTS_IRON) .define('W', Tags.Items.GLASS_WHITE) .define('O', Items.OBSERVER) @@ -111,7 +152,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(Items.OBSERVER)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.PERIPHERAL_CASING.get()) + ShapedRecipeBuilder.shaped(APBlocks.PERIPHERAL_CASING.get()) .define('I', Tags.Items.INGOTS_IRON) .define('i', Items.IRON_BARS) .define('R', Tags.Items.STORAGE_BLOCKS_REDSTONE) @@ -121,7 +162,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(Items.REDSTONE_BLOCK)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.PLAYER_DETECTOR.get()) + ShapedRecipeBuilder.shaped(APBlocks.PLAYER_DETECTOR.get()) .define('S', Items.SMOOTH_STONE) .define('A', CASING) .define('R', Tags.Items.STORAGE_BLOCKS_REDSTONE) @@ -131,7 +172,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.REDSTONE_INTEGRATOR.get()) + ShapedRecipeBuilder.shaped(APBlocks.REDSTONE_INTEGRATOR.get()) .define('R', Tags.Items.STORAGE_BLOCKS_REDSTONE) .define('A', CASING) .define('C', Items.COMPARATOR) @@ -141,7 +182,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.BLOCK_READER.get()) + ShapedRecipeBuilder.shaped(APBlocks.BLOCK_READER.get()) .define('O', Items.OBSERVER) .define('I', Tags.Items.INGOTS_IRON) .define('M', Registry.ModBlocks.WIRED_MODEM_FULL.get()) @@ -153,7 +194,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.GEO_SCANNER.get()) + ShapedRecipeBuilder.shaped(APBlocks.GEO_SCANNER.get()) .define('O', Items.OBSERVER) .define('D', Tags.Items.GEMS_DIAMOND) .define('C', CASING) @@ -165,7 +206,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapedRecipeBuilder.shaped(Blocks.NBT_STORAGE.get()) + ShapedRecipeBuilder.shaped(APBlocks.NBT_STORAGE.get()) .define('C', Tags.Items.CHESTS) .define('A', CASING) .define('R', Tags.Items.STORAGE_BLOCKS_REDSTONE) @@ -181,7 +222,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) modLoaded("minecolonies") ) .addRecipe( - ShapedRecipeBuilder.shaped(Blocks.COLONY_INTEGRATOR.get()) + ShapedRecipeBuilder.shaped(APBlocks.COLONY_INTEGRATOR.get()) .define('O', ItemTags.LOGS) .define('A', CASING) .define('R', Ingredient.fromValues(Stream.of(new RawValue(new ResourceLocation("minecolonies", "blockminecoloniesrack"))))) @@ -196,7 +237,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) modLoaded("ae2") ) .addRecipe( - ShapedRecipeBuilder.shaped(Blocks.ME_BRIDGE.get()) + ShapedRecipeBuilder.shaped(APBlocks.ME_BRIDGE.get()) .define('F', AEBlocks.FLUIX_BLOCK.asItem()) .define('A', CASING) .define('I', AEBlocks.INTERFACE.asItem()) @@ -211,7 +252,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) modLoaded("refinedstorage") ) .addRecipe( - ShapedRecipeBuilder.shaped(Blocks.RS_BRIDGE.get()) + ShapedRecipeBuilder.shaped(APBlocks.RS_BRIDGE.get()) .define('Q', RSItems.QUARTZ_ENRICHED_IRON.get()) .define('A', CASING) .define('I', RSBlocks.INTERFACE.get()) @@ -221,7 +262,7 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING))::save ).build(consumer, new ResourceLocation(AdvancedPeripherals.MOD_ID, "rs_bridge")); - ShapedRecipeBuilder.shaped(de.srendi.advancedperipherals.common.setup.Items.WEAK_AUTOMATA_CORE.get()) + ShapedRecipeBuilder.shaped(APItems.WEAK_AUTOMATA_CORE.get()) .define('A', CASING) .define('R', Tags.Items.STORAGE_BLOCKS_REDSTONE) .define('S', Items.SOUL_LANTERN) @@ -233,23 +274,13 @@ protected void buildCraftingRecipes(@NotNull Consumer consumer) .unlockedBy(HAS_ITEM, has(CASING)) .save(consumer); - ShapelessRecipeBuilder.shapeless(de.srendi.advancedperipherals.common.setup.Items.OVERPOWERED_WEAK_AUTOMATA_CORE.get()) - .requires(de.srendi.advancedperipherals.common.setup.Items.WEAK_AUTOMATA_CORE.get()) - .requires(Items.NETHER_STAR) - .unlockedBy(HAS_ITEM, has(de.srendi.advancedperipherals.common.setup.Items.WEAK_AUTOMATA_CORE.get())) - .save(consumer); - - ShapelessRecipeBuilder.shapeless(de.srendi.advancedperipherals.common.setup.Items.OVERPOWERED_END_AUTOMATA_CORE.get()) - .requires(de.srendi.advancedperipherals.common.setup.Items.END_AUTOMATA_CORE.get()) - .requires(Items.NETHER_STAR) - .unlockedBy(HAS_ITEM, has(de.srendi.advancedperipherals.common.setup.Items.END_AUTOMATA_CORE.get())) - .save(consumer); + } - ShapelessRecipeBuilder.shapeless(de.srendi.advancedperipherals.common.setup.Items.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get()) - .requires(de.srendi.advancedperipherals.common.setup.Items.HUSBANDRY_AUTOMATA_CORE.get()) - .requires(Items.NETHER_STAR) - .unlockedBy(HAS_ITEM, has(de.srendi.advancedperipherals.common.setup.Items.HUSBANDRY_AUTOMATA_CORE.get())) - .save(consumer); + private void addSmithing(@NotNull Consumer consumer) { + UpgradeRecipeBuilder + .smithing(Ingredient.of(APItems.SMART_GLASSES.get()), Ingredient.of(Items.NETHERITE_INGOT), APItems.SMART_GLASSES_NETHERITE.get()) + .unlocks("has_item", has(Items.NETHERITE_INGOT)) + .save(consumer, new ResourceLocation(AdvancedPeripherals.MOD_ID, "armor/" + APItems.SMART_GLASSES_NETHERITE.getKey().location().getPath())); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java index 4a1ec409a..86d8e8bbe 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java @@ -2,9 +2,9 @@ import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider; import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.setup.APItems; import de.srendi.advancedperipherals.common.setup.CCRegistration; -import de.srendi.advancedperipherals.common.setup.Items; import net.minecraft.data.DataGenerator; import org.jetbrains.annotations.NotNull; @@ -18,18 +18,19 @@ public TurtleUpgradesProvider(DataGenerator generator) { @Override protected void addUpgrades(@NotNull Consumer>> addUpgrade) { - simpleWithCustomItem(CCRegistration.ID.CHATTY_TURTLE, CCRegistration.CHAT_BOX_TURTLE.get(), Blocks.CHAT_BOX.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.PLAYER_TURTLE, CCRegistration.PLAYER_DETECTOR_TURTLE.get(), Blocks.PLAYER_DETECTOR.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.ENVIRONMENT_TURTLE, CCRegistration.ENVIRONMENT_TURTLE.get(), Blocks.ENVIRONMENT_DETECTOR.get().asItem()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.CHUNKY_TURTLE, CCRegistration.CHUNKY_TURTLE.get(), Items.CHUNK_CONTROLLER.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.GEOSCANNER_TURTLE, CCRegistration.GEO_SCANNER_TURTLE.get(), Blocks.GEO_SCANNER.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.CHATTY_TURTLE, CCRegistration.CHAT_BOX_TURTLE.get(), APBlocks.CHAT_BOX.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.PLAYER_TURTLE, CCRegistration.PLAYER_DETECTOR_TURTLE.get(), APBlocks.PLAYER_DETECTOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.ENVIRONMENT_TURTLE, CCRegistration.ENVIRONMENT_TURTLE.get(), APBlocks.ENVIRONMENT_DETECTOR.get().asItem()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.CHUNKY_TURTLE, CCRegistration.CHUNKY_TURTLE.get(), APItems.CHUNK_CONTROLLER.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.GEOSCANNER_TURTLE, CCRegistration.GEO_SCANNER_TURTLE.get(), APBlocks.GEO_SCANNER.get().asItem()).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.COMPASS_TURTLE, CCRegistration.COMPASS_TURTLE.get(), net.minecraft.world.item.Items.COMPASS).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.WEAK_AUTOMATA, CCRegistration.WEAK_TURTLE.get(), Items.WEAK_AUTOMATA_CORE.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.END_AUTOMATA, CCRegistration.END_TURTLE.get(), Items.END_AUTOMATA_CORE.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.HUSBANDRY_AUTOMATA, CCRegistration.HUSBANDRY_TURTLE.get(), Items.HUSBANDRY_AUTOMATA_CORE.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.OP_WEAK_AUTOMATA, CCRegistration.OP_WEAK_TURTLE.get(), Items.OVERPOWERED_WEAK_AUTOMATA_CORE.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.OP_END_AUTOMATA, CCRegistration.OP_END_TURTLE.get(), Items.OVERPOWERED_END_AUTOMATA_CORE.get()).add(addUpgrade); - simpleWithCustomItem(CCRegistration.ID.OP_HUSBANDRY_AUTOMATA, CCRegistration.OP_HUSBANDRY_TURTLE.get(), Items.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.SADDLE_TURTLE, CCRegistration.SADDLE_TURTLE.get(), net.minecraft.world.item.Items.SADDLE).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.WEAK_AUTOMATA, CCRegistration.WEAK_TURTLE.get(), APItems.WEAK_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.END_AUTOMATA, CCRegistration.END_TURTLE.get(), APItems.END_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.HUSBANDRY_AUTOMATA, CCRegistration.HUSBANDRY_TURTLE.get(), APItems.HUSBANDRY_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.OP_WEAK_AUTOMATA, CCRegistration.OP_WEAK_TURTLE.get(), APItems.OVERPOWERED_WEAK_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.OP_END_AUTOMATA, CCRegistration.OP_END_TURTLE.get(), APItems.OVERPOWERED_END_AUTOMATA_CORE.get()).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.OP_HUSBANDRY_AUTOMATA, CCRegistration.OP_HUSBANDRY_TURTLE.get(), APItems.OVERPOWERED_HUSBANDRY_AUTOMATA_CORE.get()).add(addUpgrade); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleEnderPearl.java b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleEnderPearl.java new file mode 100644 index 000000000..911fb78f9 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleEnderPearl.java @@ -0,0 +1,215 @@ +package de.srendi.advancedperipherals.common.entity; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.setup.APEntities; +import de.srendi.advancedperipherals.common.util.ChunkManager; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrowableProjectile; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Consumer; + +public class TurtleEnderPearl extends ThrowableProjectile { + + private ITurtleAccess turtle = null; + private BlockPos spawnPos = null; + private Consumer callback = null; + private int life = 20; + private boolean changedDim = false; + + public TurtleEnderPearl(EntityType type, Level world) { + super(type, world); + this.noPhysics = true; + this.setNoGravity(true); + } + + public TurtleEnderPearl(ITurtleAccess turtle, @Nullable Direction direction) { + this(APEntities.TURTLE_ENDER_PEARL.get(), turtle.getLevel()); + this.turtle = turtle; + this.spawnPos = turtle.getPosition(); + this.setPos(Vec3.atCenterOf(this.spawnPos)); + if (direction == null) { + direction = turtle.getDirection(); + } + this.setDeltaMovement(Vec3.atLowerCornerOf(direction.getNormal()).scale(1 / 20.0)); + } + + @Nullable + public ITurtleAccess getTurtle() { + return turtle; + } + + public void setCallback(Consumer callback) { + this.callback = callback; + } + + @Nullable + private ServerComputer getServerComputer() { + if (this.turtle instanceof TurtleBrain turtle) { + return turtle.getOwner().createServerComputer(); + } + return null; + } + + @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } + + @Override + public void readAdditionalSaveData(CompoundTag storage) {} + + @Override + public void addAdditionalSaveData(CompoundTag storage) {} + + @Override + protected void defineSynchedData() {} + + @Override + public void tick() { + if (this.level.isClientSide) { + super.tick(); + return; + } + if (this.turtle == null) { + this.discard(); + return; + } + if (this.life < 0) { + this.life--; + // clean after 5s + if (this.life < -100) { + this.discard(); + return; + } + return; + } + if (this.life == 0) { + this.life = -1; + this.setDeltaMovement(Vec3.ZERO); + this.moveTo(Vec3.atCenterOf(this.blockPosition())); + AdvancedPeripherals.debug("Turtle Ender Pearl stabled: " + this.toString()); + if (this.callback != null) { + this.callback.accept(this); + } + return; + } + this.life--; + super.tick(); + } + + // TODO: the turtle ender pearl should have a fancy and 999w flash render + public static class Renderer extends EntityRenderer { + public Renderer(EntityRendererProvider.Context ctx) { + super(ctx); + } + + @Override + public boolean shouldRender(TurtleEnderPearl entity, Frustum view, double x, double y, double z) { + return entity.turtle != null && super.shouldRender(entity, view, x, y, z); + } + + @Override + public ResourceLocation getTextureLocation(TurtleEnderPearl entity) { + return null; + } + } + + @Override + public void remove(Entity.RemovalReason reason) { + super.remove(reason); + if (reason.shouldDestroy()) { + if (this.callback != null) { + this.callback.accept(null); + } + } + } + + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); + if (!(entity instanceof TurtleEnderPearl oldPearl)) { + return; + } + this.turtle = oldPearl.turtle; + this.callback = oldPearl.callback; + this.life = oldPearl.life + 20; + this.changedDim = true; + } + + @Override + public boolean canChangeDimensions() { + return !this.changedDim && super.canChangeDimensions(); + } + + @Override + public Entity changeDimension(ServerLevel newWorld) { + if (this.changedDim) { + return null; + } + Entity newEntity = super.changeDimension(newWorld); + this.changedDim = newEntity != null; + if (newEntity instanceof TurtleEnderPearl newPearl) { + AdvancedPeripherals.debug("Turtle Ender Pearl crossed to dimension " + newWorld.dimension().toString()); + newPearl.spawnPos = newPearl.blockPosition(); + ChunkManager.get(newWorld).addForceChunk(newWorld, newPearl.getUUID(), newPearl.chunkPosition()); + if (newWorld.dimension() == Level.END) { + newPearl.life = 0; + // do not spawn turtle on the obsidian platform + final int maxHeight = newWorld.getMaxBuildHeight(); + int lowestY = maxHeight; + for (; lowestY > newPearl.spawnPos.getY() + 2; lowestY--) { + if (!newWorld.getBlockState(newPearl.spawnPos.atY(lowestY - 1)).isAir()) { + break; + } + } + AdvancedPeripherals.debug("Turtle Ender Pearl lowest Y: " + lowestY); + for (int y = lowestY; y <= maxHeight; y++) { + BlockPos pos = newPearl.spawnPos.atY(y); + List pearlList = newWorld.getEntities(APEntities.TURTLE_ENDER_PEARL.get(), new AABB(pos), entity -> true); + if (pearlList.isEmpty()) { + AdvancedPeripherals.debug("Turtle Ender Pearl moved to " + pos); + newPearl.moveTo(Vec3.atCenterOf(pos)); + break; + } + } + } + } + return newEntity; + } + + @Override + protected void onHit(HitResult hit) { + if (hit.getType() == HitResult.Type.BLOCK) { + BlockHitResult blockHit = (BlockHitResult) hit; + if (this.spawnPos == null || !this.spawnPos.equals(blockHit.getBlockPos())) { + this.discard(); + } + } + } + + @Override + protected boolean canHitEntity(Entity entity) { + return false; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java new file mode 100644 index 000000000..340bd3cc1 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java @@ -0,0 +1,261 @@ +package de.srendi.advancedperipherals.common.entity; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.network.container.ComputerContainerData; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.turtle.items.TurtleItemFactory; +import de.srendi.advancedperipherals.common.network.toserver.SaddleTurtleControlPacket; +import de.srendi.advancedperipherals.common.setup.APEntities; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.HasCustomInventoryScreen; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.portal.PortalInfo; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; + +public class TurtleSeatEntity extends Entity implements HasCustomInventoryScreen { + + // TODO: better rendering + + private ITurtleAccess turtle = null; + private int life = 0; + + private boolean forwardKey = false; + private boolean backKey = false; + private boolean leftKey = false; + private boolean rightKey = false; + private boolean upKey = false; + private boolean downKey = false; + private boolean forwardKeyOld = false; + private boolean backKeyOld = false; + private boolean leftKeyOld = false; + private boolean rightKeyOld = false; + private boolean upKeyOld = false; + private boolean downKeyOld = false; + + public TurtleSeatEntity(EntityType type, Level world) { + super(type, world); + this.noPhysics = true; + } + + public TurtleSeatEntity(ITurtleAccess turtle) { + this(APEntities.TURTLE_SEAT.get(), turtle.getLevel()); + this.turtle = turtle; + } + + public void setTurtle(ITurtleAccess turtle) { + this.turtle = turtle; + } + + public ITurtleAccess getOwner() { + return turtle; + } + + @Nullable + private ServerComputer getServerComputer() { + Player player = this.getSelfAndPassengers().filter(e -> e instanceof Player).map(e -> (Player) e).findFirst().orElse(null); + if (player != null && this.turtle instanceof TurtleBrain turtle) { + TileTurtle tile = turtle.getOwner(); + if (tile.isUsable(player)) { + return tile.createServerComputer(); + } + } + return null; + } + + public void keepAlive() { + this.life = 2; + } + + public Vec3 getTurtlePos() { + BlockPos pos = this.turtle.getPosition(); + return Vec3.atCenterOf(pos); + } + + @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } + + @Override + public void readAdditionalSaveData(CompoundTag storage) {} + + @Override + public void addAdditionalSaveData(CompoundTag storage) {} + + @Override + protected void defineSynchedData() {} + + @Override + public void setPos(double x, double y, double z) { + super.setPos(x, y, z); + AABB bb = this.getBoundingBox(); + this.setBoundingBox(bb.move(new Vec3(x, y, z).subtract(bb.getCenter()))); + } + + @Override + protected void removePassenger(Entity entity) { + super.removePassenger(entity); + this.forwardKey = false; + this.backKey = false; + this.leftKey = false; + this.rightKey = false; + this.upKey = false; + this.downKey = false; + this.forwardKeyOld = false; + this.backKeyOld = false; + this.leftKeyOld = false; + this.rightKeyOld = false; + this.upKeyOld = false; + this.downKeyOld = false; + if (entity instanceof TamableAnimal tamed) { + tamed.setInSittingPose(false); + } + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity entity) { + return this.getTurtlePos().add(0, 0.4, 0); + } + + @Override + public Entity getControllingPassenger() { + return null; // this.getFirstPassenger(); + } + + @Override + public double getPassengersRidingOffset() { + return 0.05; + } + + @Override + public void tick() { + if (this.level.isClientSide) { + return; + } + this.life--; + if (this.life < 0) { + this.discard(); + return; + } + ServerComputer computer = this.getServerComputer(); + if (computer != null) { + if (this.forwardKey != this.forwardKeyOld) { + this.forwardKeyOld = this.forwardKey; + computer.queueEvent("saddle_control", new Object[]{"forward", this.forwardKey}); + } + if (this.backKey != this.backKeyOld) { + this.backKeyOld = this.backKey; + computer.queueEvent("saddle_control", new Object[]{"back", this.backKey}); + } + if (this.leftKey != this.leftKeyOld) { + this.leftKeyOld = this.leftKey; + computer.queueEvent("saddle_control", new Object[]{"left", this.leftKey}); + } + if (this.rightKey != this.rightKeyOld) { + this.rightKeyOld = this.rightKey; + computer.queueEvent("saddle_control", new Object[]{"right", this.rightKey}); + } + if (this.upKey != this.upKeyOld) { + this.upKeyOld = this.upKey; + computer.queueEvent("saddle_control", new Object[]{"up", this.upKey}); + } + if (this.downKey != this.downKeyOld) { + this.downKeyOld = this.downKey; + computer.queueEvent("saddle_control", new Object[]{"down", this.downKey}); + } + } + } + + public void handleSaddleTurtleControlPacket(SaddleTurtleControlPacket packet) { + this.forwardKey = packet.forward; + this.backKey = packet.back; + this.leftKey = packet.left; + this.rightKey = packet.right; + this.upKey = packet.up; + this.downKey = packet.down; + } + + @Override + public void openCustomInventoryScreen(Player player) { + if (!this.level.isClientSide && this.hasPassenger(player)) { + if (this.downKey) { + player.stopRiding(); + this.discard(); + return; + } + if (this.turtle instanceof TurtleBrain turtle) { + TileTurtle tile = turtle.getOwner(); + if (!tile.isUsable(player)) { + return; + } + ServerComputer computer = tile.createServerComputer(); + ItemStack stack = TurtleItemFactory.create(tile); + new ComputerContainerData(computer, stack).open(player, tile); + } + } + } + + public static class Renderer extends EntityRenderer { + public Renderer(EntityRendererProvider.Context ctx) { + super(ctx); + } + + @Override + public boolean shouldRender(TurtleSeatEntity a0, Frustum a1, double a2, double a3, double a4) { + return false; + } + + @Override + public ResourceLocation getTextureLocation(TurtleSeatEntity a0) { + return null; + } + } + + @Override + public boolean canChangeDimensions() { + return false; + } + + @Override + public PortalInfo findDimensionEntryPoint(ServerLevel newLevel) { + return new PortalInfo(this.getTurtlePos(), Vec3.ZERO, 0, 0); + } + + @Override + public boolean shouldBlockExplode(net.minecraft.world.level.Explosion a0, net.minecraft.world.level.BlockGetter a1, BlockPos a2, BlockState a3, float a4) { + return false; + } + + @Override + public boolean isIgnoringBlockTriggers() { + return true; + } + + @Override + public PushReaction getPistonPushReaction() { + return PushReaction.IGNORE; + } + + @Override + public void setDeltaMovement(Vec3 a0) {} +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/APBlockItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/APBlockItem.java index 296852eee..fbfc664f9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/APBlockItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/APBlockItem.java @@ -1,36 +1,21 @@ package de.srendi.advancedperipherals.common.items; import de.srendi.advancedperipherals.common.items.base.BaseBlockItem; -import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; -import net.minecraft.core.NonNullList; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; public class APBlockItem extends BaseBlockItem { - @Nullable - private final ResourceLocation turtleID; - @Nullable - private final ResourceLocation pocketID; private final Supplier enabledSup; - public APBlockItem(Block blockIn, Properties properties, @Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID, Supplier enabledSup) { + public APBlockItem(Block blockIn, Properties properties, Supplier enabledSup) { super(blockIn, properties); - this.turtleID = turtleID; - this.pocketID = pocketID; this.enabledSup = enabledSup; } - public APBlockItem(Block blockIn, @Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID, Supplier enabledSup) { + public APBlockItem(Block blockIn, Supplier enabledSup) { super(blockIn); - this.turtleID = turtleID; - this.pocketID = pocketID; this.enabledSup = enabledSup; } @@ -39,10 +24,4 @@ public boolean isEnabled() { return enabledSup.get(); } - @Override - public void fillItemCategory(@NotNull CreativeModeTab group, @NotNull NonNullList items) { - super.fillItemCategory(group, items); - if(allowedIn(group)) - ItemUtil.addComputerItemToTab(turtleID, pocketID, items); - } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/APItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/APItem.java index 04f5e9d8f..34ffcbeb5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/APItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/APItem.java @@ -1,35 +1,20 @@ package de.srendi.advancedperipherals.common.items; import de.srendi.advancedperipherals.common.items.base.BaseItem; -import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; -import net.minecraft.core.NonNullList; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; public class APItem extends BaseItem { - @Nullable - private final ResourceLocation turtleID; - @Nullable - private final ResourceLocation pocketID; private final Supplier enabledSup; - public APItem(Properties properties, @Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID, Supplier enabledSup) { + public APItem(Properties properties, Supplier enabledSup) { super(properties); - this.turtleID = turtleID; - this.pocketID = pocketID; this.enabledSup = enabledSup; } - public APItem(@Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID, Supplier enabledSup) { + public APItem(Supplier enabledSup) { super(); - this.turtleID = turtleID; - this.pocketID = pocketID; this.enabledSup = enabledSup; } @@ -38,11 +23,4 @@ public boolean isEnabled() { return enabledSup.get(); } - @Override - public void fillItemCategory(@NotNull CreativeModeTab group, @NotNull NonNullList items) { - super.fillItemCategory(group, items); - if(allowedIn(group)) - ItemUtil.addComputerItemToTab(turtleID, pocketID, items); - } - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesInterfaceItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesInterfaceItem.java new file mode 100644 index 000000000..abd6d27d3 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesInterfaceItem.java @@ -0,0 +1,71 @@ +package de.srendi.advancedperipherals.common.items; + +import dan200.computercraft.shared.network.container.ComputerContainerData; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.setup.APTags; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesMenuProvider; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.NotNull; + +public class SmartGlassesInterfaceItem extends BaseItem { + + public SmartGlassesInterfaceItem() { + super(new Properties().stacksTo(1)); + } + + @Override + public InteractionResultHolder use(@NotNull Level world, @NotNull Player player, InteractionHand hand) { + if (world.isClientSide) + return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand)); + + // In case this method gets executed by the smart glasses interface, we need to check if the glasses may be in the + // curio slot or on the head + ItemStack findGlasses = player.getItemBySlot(EquipmentSlot.HEAD); + if (!findGlasses.is(APTags.Items.SMART_GLASSES)) + if (APAddons.curiosLoaded) + findGlasses = APAddons.getCurioGlasses(player); + + if (!findGlasses.is(APTags.Items.SMART_GLASSES)) { + player.displayClientMessage(Component.translatable("item.advancedperipherals.smartglasses.dontwear"), false); + return super.use(world, player, hand); + } + + // The constructor of the ComputerContainerData in the lambda wants a final version of this var + ItemStack glasses = findGlasses; + + SmartGlassesItem smartGlasses = (SmartGlassesItem) glasses.getItem(); + + SmartGlassesComputer computer = smartGlasses.getOrCreateComputer((ServerLevel) world, player, player.getInventory(), glasses); + computer.turnOn(); + + LazyOptional itemHandler = glasses.getCapability(ForgeCapabilities.ITEM_HANDLER); + if (!itemHandler.isPresent() || itemHandler.resolve().isEmpty()) { + AdvancedPeripherals.debug("There was an issue with the item handler of the glasses while trying to open the gui"); + return super.use(world, player, hand); + } + NetworkHooks.openScreen((ServerPlayer) player, new SmartGlassesMenuProvider(computer, glasses, itemHandler.resolve().get()), bytes -> new ComputerContainerData(computer, glasses).toBytes(bytes)); + + return super.use(world, player, hand); + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesItem.java new file mode 100644 index 000000000..cb5c1a112 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/items/SmartGlassesItem.java @@ -0,0 +1,332 @@ +package de.srendi.advancedperipherals.common.items; + +import com.google.common.base.Objects; +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.filesystem.IWritableMount; +import dan200.computercraft.api.media.IMedia; +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.shared.PocketUpgrades; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ServerComputerRegistry; +import dan200.computercraft.shared.computer.core.ServerContext; +import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.network.container.ComputerContainerData; +import dan200.computercraft.shared.util.IDAssigner; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAPI; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesItemHandler; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesMenuProvider; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import net.minecraft.ChatFormatting; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Container; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.server.ServerLifecycleHooks; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public class SmartGlassesItem extends ArmorItem implements IComputerItem, IMedia { + + private static final String NBT_UPGRADE = "Upgrade"; + private static final String NBT_UPGRADE_INFO = "UpgradeInfo"; + public static final String NBT_LIGHT = "Light"; + public static final String NBT_ON = "On"; + + private static final String NBT_INSTANCE = "InstanceId"; + private static final String NBT_SESSION = "SessionId"; + + public SmartGlassesItem(ArmorMaterial material) { + super(material, EquipmentSlot.HEAD, new Properties().stacksTo(1).tab(AdvancedPeripherals.TAB)); + } + + @Nullable + @Override + public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) { + return new ICapabilityProvider() { + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (cap == ForgeCapabilities.ITEM_HANDLER) { + return LazyOptional.of(() -> { + SmartGlassesComputer computer = getServerComputer(ServerLifecycleHooks.getCurrentServer(), stack); + SmartGlassesItemHandler handler = new SmartGlassesItemHandler(stack, computer); + return handler; + }).cast(); + } + return LazyOptional.empty(); + } + }; + } + + private boolean tick(ItemStack stack, Level world, Entity entity, SmartGlassesComputer computer) { + computer.setLevel((ServerLevel) world); + if (entity != null) { + computer.setPosition(entity.blockPosition()); + } + + boolean changed = false; + + // Sync ID + int id = computer.getID(); + if (id != getComputerID(stack)) { + changed = true; + setComputerID(stack, id); + } + + // Sync label + String label = computer.getLabel(); + if (!Objects.equal(label, getLabel(stack))) { + changed = true; + setLabel(stack, label); + } + + boolean on = computer.isOn(); + if (on != isMarkedOn(stack)) { + changed = true; + stack.getOrCreateTag().putBoolean(NBT_ON, on); + } + + Entity computerEntity = computer.getEntity(); + if (computerEntity != entity) { + changed = true; + computer.setEntity(entity); + } + + ItemStack computerStack = computer.getStack(); + if (computerStack != stack) { + changed = true; + computer.setStack(stack); + } + + for (Map.Entry e : computer.getUpgrades().entrySet()) { + IPocketUpgrade upgrade = PocketUpgrades.instance().get(e.getKey().toString()); + if (upgrade != null) { + upgrade.update(computer, e.getValue()); + } + } + + return changed; + } + + @Override + public void inventoryTick(@NotNull ItemStack stack, @NotNull Level world, @NotNull Entity entity, int slotNum, boolean selected) { + LazyOptional optItemHandler = stack.getCapability(ForgeCapabilities.ITEM_HANDLER); + SmartGlassesItemHandler itemHandler = (SmartGlassesItemHandler) optItemHandler.orElse(null); + for (int slot = 0; slot < itemHandler.getSlots(); slot++) { + ItemStack itemStack = itemHandler.getStackInSlot(slot); + if (itemStack.getItem() instanceof IModuleItem iModuleItem) { + SmartGlassesAccess glassesAccess = null; + IModule module = null; + if (!world.isClientSide) { + SmartGlassesComputer computer = getOrCreateComputer((ServerLevel) world, entity, entity instanceof Player player ? player.getInventory() : null, stack); + module = computer.getModules().get(slot); + glassesAccess = computer.getSmartGlassesAccess(); + } + iModuleItem.inventoryTick(itemStack, world, entity, slot, selected, glassesAccess, module); + } + } + + if (world.isClientSide) { + return; + } + Container inventory = entity instanceof Player player ? player.getInventory() : null; + SmartGlassesComputer computer = getOrCreateComputer((ServerLevel) world, entity, inventory, stack); + computer.keepAlive(); + computer.setItemHandler(itemHandler); + + boolean changed = tick(stack, world, entity, computer); + if (changed && inventory != null) { + inventory.setChanged(); + } + } + + @Override + public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { + if (entity.level.isClientSide || entity.level.getServer() == null) { + return false; + } + + SmartGlassesComputer computer = getServerComputer(entity.level.getServer(), stack); + if (computer != null && tick(stack, entity.level, entity, computer)) { + entity.setItem(stack.copy()); + } + return false; + } + + @NotNull + @Override + public InteractionResultHolder use(Level world, Player player, @NotNull InteractionHand hand) { + ItemStack glasses = player.getItemInHand(hand); + + if (!world.isClientSide) { + SmartGlassesComputer computer = getOrCreateComputer((ServerLevel) world, player, player.getInventory(), glasses); + computer.turnOn(); + + LazyOptional itemHandler = glasses.getCapability(ForgeCapabilities.ITEM_HANDLER); + if (!itemHandler.isPresent() || itemHandler.resolve().isEmpty()) { + AdvancedPeripherals.debug("There was an issue with the item handler of the glasses while trying to open the gui"); + return InteractionResultHolder.sidedSuccess(player.getItemInHand(hand), world.isClientSide); + } + new ComputerContainerData(computer, glasses).open(player, new SmartGlassesMenuProvider(computer, glasses, itemHandler.resolve().get())); + } + return super.use(world, player, hand); + } + + public ItemStack create(int id, @Nullable String label) { + ItemStack result = new ItemStack(this); + if (id >= 0) { + result.getOrCreateTag().putInt(NBT_ID, id); + } + if (label != null) { + result.setHoverName(Component.literal(label)); + } + return result; + } + + @Override + public ComputerFamily getFamily() { + return ComputerFamily.ADVANCED; + } + + @Override + public ItemStack withFamily(ItemStack stack, ComputerFamily family) { + return create(getComputerID(stack), getLabel(stack)); + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @Nullable Level world, @NotNull List list, TooltipFlag flag) { + if (flag.isAdvanced() || getLabel(stack) == null) { + int id = getComputerID(stack); + if (id >= 0) { + list.add(Component.translatable("gui.computercraft.tooltip.computer_id", id).withStyle(ChatFormatting.GRAY)); + } + } + } + + @Override + public String getCreatorModId(ItemStack stack) { + return AdvancedPeripherals.MOD_ID; + } + + public SmartGlassesComputer getOrCreateComputer(ServerLevel level, Entity entity, @Nullable Container inventory, ItemStack stack) { + int sessionID = getSessionID(stack); + + ServerComputerRegistry registry = ServerContext.get(level.getServer()).registry(); + SmartGlassesComputer computer = (SmartGlassesComputer) registry.get(sessionID, getInstanceID(stack)); + if (computer == null) { + int computerID = getComputerID(stack); + if (computerID < 0) { + computerID = ComputerCraftAPI.createUniqueNumberedSaveDir(level, IDAssigner.COMPUTER); + setComputerID(stack, computerID); + } + + computer = new SmartGlassesComputer(level, getComputerID(stack), getLabel(stack), getFamily(), stack.getOrCreateTag().getCompound(SmartGlassesComputer.UPGRADE_DATAS_TAG)); + + setInstanceID(stack, computer.register()); + setSessionID(stack, registry.getSessionID()); + + computer.addAPI(new SmartGlassesAPI()); + + // Only turn on when initially creating the computer, rather than each tick. + if (isMarkedOn(stack) && entity instanceof Player) { + computer.turnOn(); + } + if (inventory != null) { + inventory.setChanged(); + } + } + computer.setLevel(level); + return computer; + } + + @Nullable + public static SmartGlassesComputer getServerComputer(MinecraftServer server, ItemStack stack) { + if (server == null) { + return null; + } + return (SmartGlassesComputer) ServerContext.get(server).registry().get(getSessionID(stack), getInstanceID(stack)); + } + + // IComputerItem implementation + private static void setComputerID(ItemStack stack, int computerID) { + stack.getOrCreateTag().putInt(NBT_ID, computerID); + } + + @Nullable + @Override + public String getLabel(ItemStack stack) { + return IComputerItem.super.getLabel(stack); + } + + @Override + public boolean setLabel(ItemStack stack, @Nullable String label) { + if (label != null) { + stack.setHoverName(Component.literal(label)); + } else { + stack.resetHoverName(); + } + return true; + } + + @Nullable + @Override + public IWritableMount createDataMount(@NotNull ItemStack stack, @NotNull Level level) { + int id = getComputerID(stack); + if (id >= 0) { + return ComputerCraftAPI.createSaveDirMount(level, "computer/" + id, ComputerCraft.computerSpaceLimit); + } + return null; + } + + public static int getInstanceID(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + return nbt != null && nbt.contains(NBT_INSTANCE) ? nbt.getInt(NBT_INSTANCE) : -1; + } + + private static void setInstanceID(ItemStack stack, int instanceID) { + stack.getOrCreateTag().putInt(NBT_INSTANCE, instanceID); + } + + private static int getSessionID(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + return nbt != null && nbt.contains(NBT_SESSION) ? nbt.getInt(NBT_SESSION) : -1; + } + + private static void setSessionID(ItemStack stack, int sessionID) { + stack.getOrCreateTag().putInt(NBT_SESSION, sessionID); + } + + private static boolean isMarkedOn(ItemStack stack) { + CompoundTag nbt = stack.getTag(); + return nbt != null && nbt.getBoolean(NBT_ON); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/WeakAutomataCore.java b/src/main/java/de/srendi/advancedperipherals/common/items/WeakAutomataCore.java index 12394d92d..45ea57ba5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/WeakAutomataCore.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/WeakAutomataCore.java @@ -1,12 +1,12 @@ package de.srendi.advancedperipherals.common.items; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.Items; +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.setup.APItems; import de.srendi.advancedperipherals.common.util.EnumColor; import de.srendi.advancedperipherals.lib.metaphysics.IFeedableAutomataCore; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; @@ -27,7 +27,7 @@ import java.util.Map; import java.util.Optional; -public class WeakAutomataCore extends APItem implements IFeedableAutomataCore { +public class WeakAutomataCore extends BaseItem implements IFeedableAutomataCore { private static final String CONSUMED_ENTITY_COUNT = "consumed_entity_count"; private static final String CONSUMED_ENTITY_NAME = "consumed_entity_name"; @@ -37,24 +37,25 @@ public class WeakAutomataCore extends APItem implements IFeedableAutomataCore { static { Map endSouls = new HashMap<>(); endSouls.put(ForgeRegistries.ENTITY_TYPES.getKey(EntityType.ENDERMAN).toString(), 10); - WeakAutomataCoreRecord endSoulRecord = new WeakAutomataCoreRecord(endSouls, Items.END_AUTOMATA_CORE.get()); + WeakAutomataCoreRecord endSoulRecord = new WeakAutomataCoreRecord(endSouls, APItems.END_AUTOMATA_CORE.get()); Map husbandrySouls = new HashMap<>(); husbandrySouls.put(ForgeRegistries.ENTITY_TYPES.getKey(EntityType.COW).toString(), 3); husbandrySouls.put(ForgeRegistries.ENTITY_TYPES.getKey(EntityType.SHEEP).toString(), 3); husbandrySouls.put(ForgeRegistries.ENTITY_TYPES.getKey(EntityType.CHICKEN).toString(), 3); - WeakAutomataCoreRecord husbandrySoulRecord = new WeakAutomataCoreRecord(husbandrySouls, Items.HUSBANDRY_AUTOMATA_CORE.get()); + WeakAutomataCoreRecord husbandrySoulRecord = new WeakAutomataCoreRecord(husbandrySouls, APItems.HUSBANDRY_AUTOMATA_CORE.get()); endSoulRecord.ingredients.keySet().forEach(entityType -> AUTOMATA_CORE_REGISTRY.put(entityType, endSoulRecord)); husbandrySoulRecord.ingredients.keySet().forEach(entityType -> AUTOMATA_CORE_REGISTRY.put(entityType, husbandrySoulRecord)); } - public WeakAutomataCore(Properties properties, @Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID) { - super(properties, turtleID, pocketID, APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore); + public WeakAutomataCore(Properties properties) { + super(properties); } - public WeakAutomataCore(@Nullable ResourceLocation turtleID, @Nullable ResourceLocation pocketID) { - super(turtleID, pocketID, APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore); + @Override + public boolean isEnabled() { + return APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore.get(); } @Override @@ -73,7 +74,7 @@ public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals); + + private static int index = 0; + + public static void init() { + registerServerToClient(SaddleTurtleInfoPacket.class, SaddleTurtleInfoPacket::decode); + registerServerToClient(ToastToClientPacket.class, ToastToClientPacket::decode); + registerServerToClient(RenderableObjectSyncPacket.class, RenderableObjectSyncPacket::decode); + registerServerToClient(RenderableObjectDeletePacket.class, RenderableObjectDeletePacket::decode); + registerServerToClient(RenderableObjectClearPacket.class, RenderableObjectClearPacket::decode); + registerServerToClient(RenderableObjectBulkSyncPacket.class, RenderableObjectBulkSyncPacket::decode); + registerServerToClient(OverlayModuleClientRequestPacket.class, OverlayModuleClientRequestPacket::decode); + + registerClientToServer(GlassesHotkeyPacket.class, GlassesHotkeyPacket::decode); + registerClientToServer(SaddleTurtleControlPacket.class, SaddleTurtleControlPacket::decode); + registerClientToServer(OverlayModuleClientInfoPacket.class, OverlayModuleClientInfoPacket::decode); + } + + public static void registerServerToClient(Class packet, Function decode) { + CHANNEL.registerMessage(index++, packet, IPacket::encode, decode, IPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); + } + + public static void registerClientToServer(Class packet, Function decode) { + CHANNEL.registerMessage(index++, packet, IPacket::encode, decode, IPacket::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); + } + + public static void sendToClient(Object packet, ServerPlayer player) { + CHANNEL.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); + } + + public static void sendToServer(Object packet) { + CHANNEL.sendToServer(packet); + } + + public static void sendTo(Object packet, ServerPlayer player) { + if (!(player instanceof FakePlayer)) { + CHANNEL.sendTo(packet, player.connection.getConnection(), NetworkDirection.PLAY_TO_CLIENT); + } + } + + public static void sendToAll(Object packet) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + server.getPlayerList().getPlayers().forEach(player -> sendTo(packet, player)); + } + + public static void sendToAllTracking(Object packet, Level world, BlockPos pos) { + if (world instanceof ServerLevel) { + ((ServerLevel) world).getChunkSource().chunkMap.getPlayers(new ChunkPos(pos), false).forEach(p -> sendTo(packet, p)); + } else { + CHANNEL.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunk(pos.getX() >> 4, pos.getZ() >> 4)), packet); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/network/base/IPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/base/IPacket.java similarity index 89% rename from src/main/java/de/srendi/advancedperipherals/network/base/IPacket.java rename to src/main/java/de/srendi/advancedperipherals/common/network/base/IPacket.java index 9a52059bb..1374f5bff 100644 --- a/src/main/java/de/srendi/advancedperipherals/network/base/IPacket.java +++ b/src/main/java/de/srendi/advancedperipherals/common/network/base/IPacket.java @@ -1,4 +1,4 @@ -package de.srendi.advancedperipherals.network.base; +package de.srendi.advancedperipherals.common.network.base; import net.minecraft.network.FriendlyByteBuf; import net.minecraftforge.network.NetworkEvent; diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/OverlayModuleClientRequestPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/OverlayModuleClientRequestPacket.java new file mode 100644 index 000000000..7051d3f49 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/OverlayModuleClientRequestPacket.java @@ -0,0 +1,36 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.addons.minecolonies.MineColonies; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.network.toserver.OverlayModuleClientInfoPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class OverlayModuleClientRequestPacket implements IPacket { + + public OverlayModuleClientRequestPacket() { + + } + + @Override + public void handle(NetworkEvent.Context context) { + Minecraft minecraft = Minecraft.getInstance(); + + int sizeX = minecraft.getWindow().getWidth(), sizeY = minecraft.getWindow().getHeight(); + double guiScale = minecraft.getWindow().getGuiScale(); + + APNetworking.sendToServer(new OverlayModuleClientInfoPacket(minecraft.player.getUUID(), sizeX, sizeY, guiScale)); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + + } + + public static OverlayModuleClientRequestPacket decode(FriendlyByteBuf buffer) { + return new OverlayModuleClientRequestPacket(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectBulkSyncPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectBulkSyncPacket.java new file mode 100644 index 000000000..d033c9eb2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectBulkSyncPacket.java @@ -0,0 +1,45 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectDecodeRegistry; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class RenderableObjectBulkSyncPacket implements IPacket { + + private final Collection objects; + + public RenderableObjectBulkSyncPacket(Collection objects) { + this.objects = objects; + } + + @Override + public void handle(NetworkEvent.Context context) { + OverlayObjectHolder.addOrUpdateObjects(objects); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(objects.size()); + for (RenderableObject object : objects) + object.encode(buffer); + } + + public static RenderableObjectBulkSyncPacket decode(FriendlyByteBuf buffer) { + int size = buffer.readInt(); + List objects = new ArrayList<>(); + + for (int i = 0; i < size; i++) { + int typeId = buffer.readInt(); + objects.add(ObjectDecodeRegistry.getObject(typeId, buffer)); + } + + return new RenderableObjectBulkSyncPacket(objects); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectClearPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectClearPacket.java new file mode 100644 index 000000000..72fd6590a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectClearPacket.java @@ -0,0 +1,27 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class RenderableObjectClearPacket implements IPacket { + + public RenderableObjectClearPacket() { + + } + + @Override + public void handle(NetworkEvent.Context context) { + OverlayObjectHolder.clear(); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + + } + + public static RenderableObjectClearPacket decode(FriendlyByteBuf buffer) { + return new RenderableObjectClearPacket(); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectDeletePacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectDeletePacket.java new file mode 100644 index 000000000..b1ef370a1 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectDeletePacket.java @@ -0,0 +1,29 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class RenderableObjectDeletePacket implements IPacket { + + private final int object; + + public RenderableObjectDeletePacket(int object) { + this.object = object; + } + + @Override + public void handle(NetworkEvent.Context context) { + OverlayObjectHolder.removeObject(object); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(object); + } + + public static RenderableObjectDeletePacket decode(FriendlyByteBuf buffer) { + return new RenderableObjectDeletePacket(buffer.readInt()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectSyncPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectSyncPacket.java new file mode 100644 index 000000000..fb2a1ba68 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/RenderableObjectSyncPacket.java @@ -0,0 +1,33 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.smartglasses.OverlayObjectHolder; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectDecodeRegistry; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class RenderableObjectSyncPacket implements IPacket { + + private final RenderableObject object; + + public RenderableObjectSyncPacket(RenderableObject object) { + this.object = object; + } + + @Override + public void handle(NetworkEvent.Context context) { + OverlayObjectHolder.addOrUpdateObject(object); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + object.encode(buffer); + } + + public static RenderableObjectSyncPacket decode(FriendlyByteBuf buffer) { + int id = buffer.readInt(); + RenderableObject decodedObject = ObjectDecodeRegistry.getObject(id, buffer); + return new RenderableObjectSyncPacket(decodedObject); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java new file mode 100644 index 000000000..7cb9e3cf9 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java @@ -0,0 +1,45 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fml.loading.FMLEnvironment; +import net.minecraftforge.network.NetworkEvent; + +import static de.srendi.advancedperipherals.client.ClientRegistry.SADDLE_TURTLE_OVERLAY; + +public class SaddleTurtleInfoPacket implements IPacket { + + private final int fuelLevel; + private final int fuelLimit; + private final int barColor; + + public SaddleTurtleInfoPacket(int fuelLevel, int fuelLimit, int barColor) { + this.fuelLevel = fuelLevel; + this.fuelLimit = fuelLimit; + this.barColor = barColor; + } + + @Override + public void handle(NetworkEvent.Context context) { + if (!FMLEnvironment.dist.isClient()) { + return; + } + SADDLE_TURTLE_OVERLAY.setFuelLevel(this.fuelLevel); + SADDLE_TURTLE_OVERLAY.setFuelLimit(this.fuelLimit); + SADDLE_TURTLE_OVERLAY.setBarColor(this.barColor); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(this.fuelLevel); + buffer.writeInt(this.fuelLimit); + buffer.writeInt(this.barColor); + } + + public static SaddleTurtleInfoPacket decode(FriendlyByteBuf buffer) { + int fuelLevel = buffer.readInt(); + int fuelLimit = buffer.readInt(); + int barColor = buffer.readInt(); + return new SaddleTurtleInfoPacket(fuelLevel, fuelLimit, barColor); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/network/toclient/ToastToClientPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/ToastToClientPacket.java similarity index 90% rename from src/main/java/de/srendi/advancedperipherals/network/toclient/ToastToClientPacket.java rename to src/main/java/de/srendi/advancedperipherals/common/network/toclient/ToastToClientPacket.java index e2a804eff..3536d9462 100644 --- a/src/main/java/de/srendi/advancedperipherals/network/toclient/ToastToClientPacket.java +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/ToastToClientPacket.java @@ -1,8 +1,8 @@ -package de.srendi.advancedperipherals.network.toclient; +package de.srendi.advancedperipherals.common.network.toclient; import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.network.base.IPacket; import de.srendi.advancedperipherals.common.util.ToastUtil; -import de.srendi.advancedperipherals.network.base.IPacket; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraftforge.fml.loading.FMLEnvironment; diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java new file mode 100644 index 000000000..c6f5506ed --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java @@ -0,0 +1,55 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.server.ServerLifecycleHooks; + +import java.util.UUID; + +public class GlassesHotkeyPacket implements IPacket { + + private final UUID player; + private final String keyBind; + private final int keyPressDuration; + + public GlassesHotkeyPacket(UUID player, String keyBind, int keyPressDuration) { + this.player = player; + this.keyBind = keyBind; + this.keyPressDuration = keyPressDuration; + } + + @Override + public void handle(NetworkEvent.Context context) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + + ServerPlayer serverPlayer = server.getPlayerList().getPlayer(player); + if (serverPlayer == null) + return; + + for (ItemStack stack : serverPlayer.getAllSlots()) { + if (stack.getItem() instanceof SmartGlassesItem) { + SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); + + if (computer != null) + computer.queueEvent("glassesKeyPressed", new Object[]{keyBind, keyPressDuration}); + } + } + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeUUID(player); + buffer.writeUtf(keyBind); + buffer.writeInt(keyPressDuration); + } + + public static GlassesHotkeyPacket decode(FriendlyByteBuf buffer) { + return new GlassesHotkeyPacket(buffer.readUUID(), buffer.readUtf(), buffer.readInt()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/OverlayModuleClientInfoPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/OverlayModuleClientInfoPacket.java new file mode 100644 index 000000000..5f9b33f26 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/OverlayModuleClientInfoPacket.java @@ -0,0 +1,63 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.server.ServerLifecycleHooks; + +import java.util.UUID; + +public class OverlayModuleClientInfoPacket implements IPacket { + + private final UUID player; + private final int screenWidth; + private final int screenHeight; + private final double guiScale; + + public OverlayModuleClientInfoPacket(UUID player, int screenWidth, int screenHeight, double guiScale) { + this.player = player; + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + this.guiScale = guiScale; + } + + @Override + public void handle(NetworkEvent.Context context) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + + ServerPlayer serverPlayer = server.getPlayerList().getPlayer(player); + if (serverPlayer == null) + return; + + for (ItemStack stack : serverPlayer.getAllSlots()) { + if (stack.getItem() instanceof SmartGlassesItem) { + SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); + + if (computer != null) { + OverlayModule module = computer.getModule(OverlayModule.class); + + if (module != null) + module.setScreenSizes(screenWidth, screenHeight, guiScale); + } + } + } + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeUUID(player); + buffer.writeInt(screenWidth); + buffer.writeInt(screenHeight); + buffer.writeDouble(guiScale); + } + + public static OverlayModuleClientInfoPacket decode(FriendlyByteBuf buffer) { + return new OverlayModuleClientInfoPacket(buffer.readUUID(), buffer.readInt(), buffer.readInt(), buffer.readDouble()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java new file mode 100644 index 000000000..e9fca5ba5 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java @@ -0,0 +1,77 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; + +public class SaddleTurtleControlPacket implements IPacket { + + public final boolean forward; + public final boolean back; + public final boolean left; + public final boolean right; + public final boolean up; + public final boolean down; + + private static final byte FORWARD_BIT = 1 << 0; + private static final byte BACK_BIT = 1 << 1; + private static final byte LEFT_BIT = 1 << 2; + private static final byte RIGHT_BIT = 1 << 3; + private static final byte UP_BIT = 1 << 4; + private static final byte DOWN_BIT = 1 << 5; + + public SaddleTurtleControlPacket(boolean forward, boolean back, boolean left, boolean right, boolean up, boolean down) { + this.forward = forward; + this.back = back; + this.left = left; + this.right = right; + this.up = up; + this.down = down; + } + + private SaddleTurtleControlPacket(byte bits) { + this((bits & FORWARD_BIT) != 0, (bits & BACK_BIT) != 0, (bits & LEFT_BIT) != 0, (bits & RIGHT_BIT) != 0, (bits & UP_BIT) != 0, (bits & DOWN_BIT) != 0); + } + + @Override + public void handle(NetworkEvent.Context context) { + ServerPlayer player = context.getSender(); + if (player != null && player.getRootVehicle() instanceof TurtleSeatEntity seat) { + seat.handleSaddleTurtleControlPacket(this); + } + } + + private byte encodeToBits() { + byte b = 0; + if (this.forward) { + b |= FORWARD_BIT; + } + if (this.back) { + b |= BACK_BIT; + } + if (this.left) { + b |= LEFT_BIT; + } + if (this.right) { + b |= RIGHT_BIT; + } + if (this.up) { + b |= UP_BIT; + } + if (this.down) { + b |= DOWN_BIT; + } + return b; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeByte(this.encodeToBits()); + } + + public static SaddleTurtleControlPacket decode(FriendlyByteBuf buffer) { + return new SaddleTurtleControlPacket(buffer.readByte()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APBlockEntityTypes.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APBlockEntityTypes.java new file mode 100644 index 000000000..16ace7696 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APBlockEntityTypes.java @@ -0,0 +1,44 @@ +package de.srendi.advancedperipherals.common.setup; + +import com.google.common.collect.Sets; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.blocks.blockentities.BlockReaderEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.ChatBoxEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.ColonyIntegratorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.DistanceDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.EnergyDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.EnvironmentDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.FluidDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.GasDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.GeoScannerEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.InventoryManagerEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.NBTStorageEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.PlayerDetectorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.RedstoneIntegratorEntity; +import de.srendi.advancedperipherals.common.blocks.blockentities.RSBridgeEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraftforge.registries.RegistryObject; + +public class APBlockEntityTypes { + + protected static void register() { + } + + public static final RegistryObject> BLOCK_READER = APRegistration.TILE_ENTITIES.register("block_reader", () -> new BlockEntityType<>(BlockReaderEntity::new, Sets.newHashSet(APBlocks.BLOCK_READER.get()), null)); + public static final RegistryObject> CHAT_BOX = APRegistration.TILE_ENTITIES.register("chat_box", () -> new BlockEntityType<>(ChatBoxEntity::new, Sets.newHashSet(APBlocks.CHAT_BOX.get()), null)); + public static final RegistryObject> COLONY_INTEGRATOR = APRegistration.TILE_ENTITIES.register("colony_integrator", () -> new BlockEntityType<>(ColonyIntegratorEntity::new, Sets.newHashSet(APBlocks.COLONY_INTEGRATOR.get()), null)); + public static final RegistryObject> DISTANCE_DETECTOR = APRegistration.TILE_ENTITIES.register("distance_detector", () -> new BlockEntityType<>(DistanceDetectorEntity::new, Sets.newHashSet(APBlocks.DISTANCE_DETECTOR.get()), null)); + public static final RegistryObject> ENERGY_DETECTOR = APRegistration.TILE_ENTITIES.register("energy_detector", () -> new BlockEntityType<>(EnergyDetectorEntity::new, Sets.newHashSet(APBlocks.ENERGY_DETECTOR.get()), null)); + public static final RegistryObject> ENVIRONMENT_DETECTOR = APRegistration.TILE_ENTITIES.register("environment_detector", () -> new BlockEntityType<>(EnvironmentDetectorEntity::new, Sets.newHashSet(APBlocks.ENVIRONMENT_DETECTOR.get()), null)); + public static final RegistryObject> FLUID_DETECTOR = APRegistration.TILE_ENTITIES.register("fluid_detector", () -> new BlockEntityType<>(FluidDetectorEntity::new, Sets.newHashSet(APBlocks.FLUID_DETECTOR.get()), null)); + public static final RegistryObject> GAS_DETECTOR = APAddons.mekanismLoaded ? APRegistration.TILE_ENTITIES.register("gas_detector", () -> new BlockEntityType<>(GasDetectorEntity::new, Sets.newHashSet(APBlocks.GAS_DETECTOR.get()), null)) : null; + public static final RegistryObject> GEO_SCANNER = APRegistration.TILE_ENTITIES.register("geo_scanner", () -> new BlockEntityType<>(GeoScannerEntity::new, Sets.newHashSet(APBlocks.GEO_SCANNER.get()), null)); + public static final RegistryObject> INVENTORY_MANAGER = APRegistration.TILE_ENTITIES.register("inventory_manager", () -> new BlockEntityType<>(InventoryManagerEntity::new, Sets.newHashSet(APBlocks.INVENTORY_MANAGER.get()), null)); + public static final RegistryObject> ME_BRIDGE = APAddons.appliedEnergisticsLoaded ? APRegistration.TILE_ENTITIES.register("me_bridge", () -> new BlockEntityType<>(MeBridgeEntity::new, Sets.newHashSet(APBlocks.ME_BRIDGE.get()), null)) : null; + public static final RegistryObject> NBT_STORAGE = APRegistration.TILE_ENTITIES.register("nbt_storage", () -> new BlockEntityType<>(NBTStorageEntity::new, Sets.newHashSet(APBlocks.NBT_STORAGE.get()), null)); + public static final RegistryObject> PLAYER_DETECTOR = APRegistration.TILE_ENTITIES.register("player_detector", () -> new BlockEntityType<>(PlayerDetectorEntity::new, Sets.newHashSet(APBlocks.PLAYER_DETECTOR.get()), null)); + public static final RegistryObject> REDSTONE_INTEGRATOR = APRegistration.TILE_ENTITIES.register("redstone_integrator", () -> new BlockEntityType<>(RedstoneIntegratorEntity::new, Sets.newHashSet(APBlocks.REDSTONE_INTEGRATOR.get()), null)); + public static final RegistryObject> RS_BRIDGE = APAddons.refinedStorageLoaded ? APRegistration.TILE_ENTITIES.register("rs_bridge", () -> new BlockEntityType<>(RSBridgeEntity::new, Sets.newHashSet(APBlocks.RS_BRIDGE.get()), null)) : null; + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APBlocks.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APBlocks.java new file mode 100644 index 000000000..1afa60e8b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APBlocks.java @@ -0,0 +1,56 @@ +package de.srendi.advancedperipherals.common.setup; + +import de.srendi.advancedperipherals.common.blocks.PlayerDetectorBlock; +import de.srendi.advancedperipherals.common.blocks.RedstoneIntegratorBlock; +import de.srendi.advancedperipherals.common.blocks.base.APBlockEntityBlock; +import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.items.APBlockItem; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.registries.RegistryObject; + +import java.util.function.Supplier; + +public class APBlocks { + + protected static void register() { + } + + public static final RegistryObject BLOCK_READER = register("block_reader", () -> new APBlockEntityBlock<>(APBlockEntityTypes.BLOCK_READER, true), () -> new APBlockItem(APBlocks.BLOCK_READER.get(), APConfig.PERIPHERALS_CONFIG.enableBlockReader)); + public static final RegistryObject CHAT_BOX = register("chat_box", () -> new APBlockEntityBlock<>(APBlockEntityTypes.CHAT_BOX, true), () -> new APBlockItem(APBlocks.CHAT_BOX.get(), APConfig.PERIPHERALS_CONFIG.enableChatBox)); + public static final RegistryObject COLONY_INTEGRATOR = register("colony_integrator", () -> new APBlockEntityBlock<>(APBlockEntityTypes.COLONY_INTEGRATOR, false), () -> new APBlockItem(APBlocks.COLONY_INTEGRATOR.get(), APConfig.PERIPHERALS_CONFIG.enableColonyIntegrator)); + public static final RegistryObject DISTANCE_DETECTOR = register("distance_detector", () -> new APBlockEntityBlock<>(APBlockEntityTypes.DISTANCE_DETECTOR, true), () -> new APBlockItem(APBlocks.DISTANCE_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enableNBTStorage)); + public static final RegistryObject ENERGY_DETECTOR = register("energy_detector", () -> new APBlockEntityBlock<>(APBlockEntityTypes.ENERGY_DETECTOR, true), () -> new APBlockItem(APBlocks.ENERGY_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enableEnergyDetector)); + public static final RegistryObject ENVIRONMENT_DETECTOR = register("environment_detector", () -> new APBlockEntityBlock<>(APBlockEntityTypes.ENVIRONMENT_DETECTOR, false), () -> new APBlockItem(APBlocks.ENVIRONMENT_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enableEnvironmentDetector)); + public static final RegistryObject FLUID_DETECTOR = register("fluid_detector", () -> new APBlockEntityBlock<>(APBlockEntityTypes.FLUID_DETECTOR, true), () -> new APBlockItem(APBlocks.FLUID_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enableFluidDetector)); + public static final RegistryObject GAS_DETECTOR = register("gas_detector", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("mekanism") ? APBlockEntityTypes.GAS_DETECTOR : null, true), () -> new APBlockItem(APBlocks.GAS_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enableGasDetector)); + public static final RegistryObject GEO_SCANNER = register("geo_scanner", () -> new APBlockEntityBlock<>(APBlockEntityTypes.GEO_SCANNER, false), () -> new APBlockItem(APBlocks.GEO_SCANNER.get(), APConfig.PERIPHERALS_CONFIG.enableGeoScanner)); + public static final RegistryObject INVENTORY_MANAGER = register("inventory_manager", () -> new APBlockEntityBlock<>(APBlockEntityTypes.INVENTORY_MANAGER, false), () -> new APBlockItem(APBlocks.INVENTORY_MANAGER.get(), APConfig.PERIPHERALS_CONFIG.enableInventoryManager)); + public static final RegistryObject ME_BRIDGE = register("me_bridge", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("ae2") ? APBlockEntityTypes.ME_BRIDGE : null, ModList.get().isLoaded("ae2")), () -> new APBlockItem(APBlocks.ME_BRIDGE.get(), APConfig.PERIPHERALS_CONFIG.enableMEBridge)); + public static final RegistryObject NBT_STORAGE = register("nbt_storage", () -> new APBlockEntityBlock<>(APBlockEntityTypes.NBT_STORAGE, false), () -> new APBlockItem(APBlocks.NBT_STORAGE.get(), APConfig.PERIPHERALS_CONFIG.enableNBTStorage)); + public static final RegistryObject PERIPHERAL_CASING = register("peripheral_casing", BaseBlock::new, () -> new APBlockItem(APBlocks.PERIPHERAL_CASING.get(), new Item.Properties().stacksTo(16), () -> true)); + public static final RegistryObject PLAYER_DETECTOR = register("player_detector", PlayerDetectorBlock::new, () -> new APBlockItem(APBlocks.PLAYER_DETECTOR.get(), APConfig.PERIPHERALS_CONFIG.enablePlayerDetector)); + public static final RegistryObject REDSTONE_INTEGRATOR = register("redstone_integrator", RedstoneIntegratorBlock::new, () -> new APBlockItem(APBlocks.REDSTONE_INTEGRATOR.get(), APConfig.PERIPHERALS_CONFIG.enableRedstoneIntegrator)); + public static final RegistryObject RS_BRIDGE = register("rs_bridge", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("refinedstorage") ? APBlockEntityTypes.RS_BRIDGE : null, false), () -> new APBlockItem(APBlocks.RS_BRIDGE.get(), APConfig.PERIPHERALS_CONFIG.enableRSBridge)); + + private static RegistryObject registerNoItem(String name, Supplier block) { + return APRegistration.BLOCKS.register(name, block); + } + + private static RegistryObject register(String name, Supplier block, Supplier blockItem) { + RegistryObject registryObject = registerNoItem(name, block); + APRegistration.ITEMS.register(name, blockItem); + return registryObject; + } + + public static boolean never(BlockState state, BlockGetter level, BlockPos pos) { + return false; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java new file mode 100644 index 000000000..b51d363b3 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java @@ -0,0 +1,28 @@ +package de.srendi.advancedperipherals.common.setup; + +import dan200.computercraft.shared.network.container.ComputerContainerData; +import dan200.computercraft.shared.network.container.ContainerData; +import de.srendi.advancedperipherals.common.container.InventoryManagerContainer; +import de.srendi.advancedperipherals.common.container.SmartGlassesContainer; +import net.minecraft.core.BlockPos; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.extensions.IForgeMenuType; +import net.minecraftforge.registries.RegistryObject; + +public class APContainerTypes { + + public static final RegistryObject> INVENTORY_MANAGER_CONTAINER = APRegistration.CONTAINER_TYPES.register("memory_card_container", () -> IForgeMenuType.create((windowId, inv, data) -> { + BlockPos pos = data.readBlockPos(); + Level level = inv.player.getCommandSenderWorld(); + return new InventoryManagerContainer(windowId, inv, pos, level); + })); + + public static final RegistryObject> SMART_GLASSES_CONTAINER = APRegistration.CONTAINER_TYPES.register("smart_glasses_container", () -> ContainerData.toType(ComputerContainerData::new, + (id, inv, data) -> new SmartGlassesContainer(id, player -> true, null, data, inv, data.displayStack()) + )); + + protected static void register() { + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java new file mode 100644 index 000000000..ee3f2bf8e --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java @@ -0,0 +1,40 @@ +package de.srendi.advancedperipherals.common.setup; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.entity.TurtleEnderPearl; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.RegistryObject; + +@Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) +public class APEntities { + + public static final RegistryObject> TURTLE_ENDER_PEARL = APRegistration.ENTITIES.register("turtle_ender_pearl", + () -> EntityType.Builder.of(TurtleEnderPearl::new, MobCategory.MISC) + .sized(0.5F, 0.5F) + .clientTrackingRange(4) + .updateInterval(4) + .fireImmune() + .build("turtle_ender_pearl")); + public static final RegistryObject> TURTLE_SEAT = APRegistration.ENTITIES.register("turtle_seat", + () -> EntityType.Builder.of(TurtleSeatEntity::new, MobCategory.MISC) + .sized(0.8F, 0.8F) + .clientTrackingRange(4) + .updateInterval(1) + .fireImmune() + .build("turtle_seat")); + + public static void register() { + } + + @SubscribeEvent + public static void livingRender(EntityRenderersEvent.RegisterRenderers event) { + event.registerEntityRenderer(TURTLE_ENDER_PEARL.get(), TurtleEnderPearl.Renderer::new); + event.registerEntityRenderer(TURTLE_SEAT.get(), TurtleSeatEntity.Renderer::new); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java new file mode 100644 index 000000000..57d45b1e3 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java @@ -0,0 +1,40 @@ +package de.srendi.advancedperipherals.common.setup; + +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.addons.ae2.AE2Registries; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.items.APItem; +import de.srendi.advancedperipherals.common.items.MemoryCardItem; +import de.srendi.advancedperipherals.common.items.SmartGlassesInterfaceItem; +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.items.WeakAutomataCore; +import de.srendi.advancedperipherals.common.items.base.SmartGlassesMaterials; +import de.srendi.advancedperipherals.common.smartglasses.modules.hotkey.HotkeyModuleItem; +import de.srendi.advancedperipherals.common.smartglasses.modules.nightvision.NightVisionModuleItem; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayGlassesItem; +import net.minecraft.world.item.Item; +import net.minecraftforge.registries.RegistryObject; + +public class APItems { + + public static final RegistryObject CABLE_P2P_TUNNEL = APAddons.appliedEnergisticsLoaded ? (RegistryObject) (RegistryObject) AE2Registries.CABLE_P2P_TUNNEL : null; + public static final RegistryObject CHUNK_CONTROLLER = APRegistration.ITEMS.register("chunk_controller", () -> new APItem(new Item.Properties().stacksTo(16), APConfig.PERIPHERALS_CONFIG.enableChunkyTurtle)); + public static final RegistryObject COMPUTER_TOOL = APRegistration.ITEMS.register("computer_tool", () -> new APItem(new Item.Properties().stacksTo(1), () -> true)); + public static final RegistryObject END_AUTOMATA_CORE = APRegistration.ITEMS.register("end_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableEndAutomataCore)); + public static final RegistryObject HOTKEY_MODULE = APRegistration.ITEMS.register("hotkey_module", HotkeyModuleItem::new); + public static final RegistryObject HUSBANDRY_AUTOMATA_CORE = APRegistration.ITEMS.register("husbandry_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableHusbandryAutomataCore)); + public static final RegistryObject MEMORY_CARD = APRegistration.ITEMS.register("memory_card", MemoryCardItem::new); + public static final RegistryObject NIGHT_VISION_MODULE = APRegistration.ITEMS.register("nightvision_module", NightVisionModuleItem::new); + public static final RegistryObject OVERLAY_MODULE = APRegistration.ITEMS.register("overlay_module", OverlayGlassesItem::new); + public static final RegistryObject OVERPOWERED_END_AUTOMATA_CORE = APRegistration.ITEMS.register("overpowered_end_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableEndAutomataCore)); + public static final RegistryObject OVERPOWERED_HUSBANDRY_AUTOMATA_CORE = APRegistration.ITEMS.register("overpowered_husbandry_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableHusbandryAutomataCore)); + public static final RegistryObject OVERPOWERED_WEAK_AUTOMATA_CORE = APRegistration.ITEMS.register("overpowered_weak_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore)); + public static final RegistryObject SMART_GLASSES = APRegistration.ITEMS.register("smart_glasses", () -> new SmartGlassesItem(SmartGlassesMaterials.CHAIN)); + public static final RegistryObject SMART_GLASSES_INTERFACE = APRegistration.ITEMS.register("smart_glasses_interface", SmartGlassesInterfaceItem::new); + public static final RegistryObject SMART_GLASSES_NETHERITE = APRegistration.ITEMS.register("smart_glasses_netherite", () -> new SmartGlassesItem(SmartGlassesMaterials.NETHERITE)); + public static final RegistryObject WEAK_AUTOMATA_CORE = APRegistration.ITEMS.register("weak_automata_core", () -> new WeakAutomataCore(new Item.Properties().stacksTo(1))); + + protected static void register() { + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/Registration.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APRegistration.java similarity index 83% rename from src/main/java/de/srendi/advancedperipherals/common/setup/Registration.java rename to src/main/java/de/srendi/advancedperipherals/common/setup/APRegistration.java index d80a33c6b..015f5ff0d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/Registration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APRegistration.java @@ -3,6 +3,7 @@ import dan200.computercraft.api.pocket.PocketUpgradeSerialiser; import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser; import de.srendi.advancedperipherals.AdvancedPeripherals; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.village.poi.PoiType; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.inventory.MenuType; @@ -14,10 +15,11 @@ import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; -public class Registration { +public class APRegistration { public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, AdvancedPeripherals.MOD_ID); public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, AdvancedPeripherals.MOD_ID); + public static final DeferredRegister> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, AdvancedPeripherals.MOD_ID); public static final DeferredRegister> TILE_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, AdvancedPeripherals.MOD_ID); public static final DeferredRegister> CONTAINER_TYPES = DeferredRegister.create(ForgeRegistries.MENU_TYPES, AdvancedPeripherals.MOD_ID); public static final DeferredRegister POI_TYPES = DeferredRegister.create(ForgeRegistries.POI_TYPES, AdvancedPeripherals.MOD_ID); @@ -29,6 +31,7 @@ public static void register() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); BLOCKS.register(modEventBus); ITEMS.register(modEventBus); + ENTITIES.register(modEventBus); TILE_ENTITIES.register(modEventBus); CONTAINER_TYPES.register(modEventBus); POI_TYPES.register(modEventBus); @@ -36,11 +39,13 @@ public static void register() { TURTLE_SERIALIZER.register(modEventBus); POCKET_SERIALIZER.register(modEventBus); - Blocks.register(); - BlockEntityTypes.register(); - Items.register(); - ContainerTypes.register(); - Villagers.register(); + APBlocks.register(); + APBlockEntityTypes.register(); + APItems.register(); + APEntities.register(); + APContainerTypes.register(); + APVillagers.register(); CCRegistration.register(); + APTags.Items.init(); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APTags.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APTags.java new file mode 100644 index 000000000..5b80a0f4b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APTags.java @@ -0,0 +1,24 @@ +package de.srendi.advancedperipherals.common.setup; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.NotNull; + +public class APTags { + + public static class Items { + + public static final TagKey SMART_GLASSES = tag("smart_glasses"); + + public static void init() { + + } + + private static TagKey tag(@NotNull String name) { + return TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(AdvancedPeripherals.MOD_ID, name)); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APVillagers.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APVillagers.java new file mode 100644 index 000000000..f0338f20c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APVillagers.java @@ -0,0 +1,20 @@ +package de.srendi.advancedperipherals.common.setup; + +import com.google.common.collect.ImmutableSet; +import dan200.computercraft.shared.Registry; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.entity.ai.village.poi.PoiType; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraftforge.registries.RegistryObject; + +public class APVillagers { + + public static final RegistryObject COMPUTER_SCIENTIST_POI = APRegistration.POI_TYPES.register("computer_scientist", () -> new PoiType(ImmutableSet.copyOf(Registry.ModBlocks.COMPUTER_ADVANCED.get().getStateDefinition().getPossibleStates()), 1, 1)); + + public static final RegistryObject COMPUTER_SCIENTIST = APRegistration.VILLAGER_PROFESSIONS.register("computer_scientist", () -> new VillagerProfession(AdvancedPeripherals.getRL("computer_scientist").toString(), holder -> holder.is(COMPUTER_SCIENTIST_POI.getKey()), holder -> holder.is(COMPUTER_SCIENTIST_POI.getKey()), ImmutableSet.of(), ImmutableSet.of(Registry.ModBlocks.COMPUTER_ADVANCED.get()), SoundEvents.VILLAGER_WORK_TOOLSMITH)); + + protected static void register() { + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/BlockEntityTypes.java b/src/main/java/de/srendi/advancedperipherals/common/setup/BlockEntityTypes.java deleted file mode 100644 index e215232e2..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/BlockEntityTypes.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.srendi.advancedperipherals.common.setup; - -import com.google.common.collect.Sets; -import de.srendi.advancedperipherals.common.blocks.blockentities.*; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.registries.RegistryObject; - -public class BlockEntityTypes { - - public static final RegistryObject> CHAT_BOX = Registration.TILE_ENTITIES.register("chat_box", () -> new BlockEntityType<>(ChatBoxEntity::new, Sets.newHashSet(Blocks.CHAT_BOX.get()), null)); - public static final RegistryObject> ENVIRONMENT_DETECTOR = Registration.TILE_ENTITIES.register("environment_detector", () -> new BlockEntityType<>(EnvironmentDetectorEntity::new, Sets.newHashSet(Blocks.ENVIRONMENT_DETECTOR.get()), null)); - public static final RegistryObject> PLAYER_DETECTOR = Registration.TILE_ENTITIES.register("player_detector", () -> new BlockEntityType<>(PlayerDetectorEntity::new, Sets.newHashSet(Blocks.PLAYER_DETECTOR.get()), null)); - public static final RegistryObject> ME_BRIDGE = ModList.get().isLoaded("ae2") ? Registration.TILE_ENTITIES.register("me_bridge", () -> new BlockEntityType<>(MeBridgeEntity::new, Sets.newHashSet(Blocks.ME_BRIDGE.get()), null)) : null; - public static final RegistryObject> RS_BRIDGE = ModList.get().isLoaded("refinedstorage") ? Registration.TILE_ENTITIES.register("rs_bridge", () -> new BlockEntityType<>(RsBridgeEntity::new, Sets.newHashSet(Blocks.RS_BRIDGE.get()), null)) : null; - public static final RegistryObject> ENERGY_DETECTOR = Registration.TILE_ENTITIES.register("energy_detector", () -> new BlockEntityType<>(EnergyDetectorEntity::new, Sets.newHashSet(Blocks.ENERGY_DETECTOR.get()), null)); - public static final RegistryObject> INVENTORY_MANAGER = Registration.TILE_ENTITIES.register("inventory_manager", () -> new BlockEntityType<>(InventoryManagerEntity::new, Sets.newHashSet(Blocks.INVENTORY_MANAGER.get()), null)); - public static final RegistryObject> REDSTONE_INTEGRATOR = Registration.TILE_ENTITIES.register("redstone_integrator", () -> new BlockEntityType<>(RedstoneIntegratorEntity::new, Sets.newHashSet(Blocks.REDSTONE_INTEGRATOR.get()), null)); - public static final RegistryObject> BLOCK_READER = Registration.TILE_ENTITIES.register("block_reader", () -> new BlockEntityType<>(BlockReaderEntity::new, Sets.newHashSet(Blocks.BLOCK_READER.get()), null)); - public static final RegistryObject> GEO_SCANNER = Registration.TILE_ENTITIES.register("geo_scanner", () -> new BlockEntityType<>(GeoScannerEntity::new, Sets.newHashSet(Blocks.GEO_SCANNER.get()), null)); - public static final RegistryObject> COLONY_INTEGRATOR = Registration.TILE_ENTITIES.register("colony_integrator", () -> new BlockEntityType<>(ColonyIntegratorEntity::new, Sets.newHashSet(Blocks.COLONY_INTEGRATOR.get()), null)); - public static final RegistryObject> NBT_STORAGE = Registration.TILE_ENTITIES.register("nbt_storage", () -> new BlockEntityType<>(NBTStorageEntity::new, Sets.newHashSet(Blocks.NBT_STORAGE.get()), null)); - - public static void register() { - } - -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/Blocks.java b/src/main/java/de/srendi/advancedperipherals/common/setup/Blocks.java deleted file mode 100644 index 238c2d939..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/Blocks.java +++ /dev/null @@ -1,53 +0,0 @@ -package de.srendi.advancedperipherals.common.setup; - -import de.srendi.advancedperipherals.common.blocks.PlayerDetectorBlock; -import de.srendi.advancedperipherals.common.blocks.RedstoneIntegratorBlock; -import de.srendi.advancedperipherals.common.blocks.base.APBlockEntityBlock; -import de.srendi.advancedperipherals.common.blocks.base.BaseBlock; -import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.items.APBlockItem; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.registries.RegistryObject; - -import java.util.function.Supplier; - -public class Blocks { - - public static final RegistryObject ENVIRONMENT_DETECTOR = register("environment_detector", () -> new APBlockEntityBlock<>(BlockEntityTypes.ENVIRONMENT_DETECTOR, false), () -> new APBlockItem(Blocks.ENVIRONMENT_DETECTOR.get(), CCRegistration.ID.ENVIRONMENT_TURTLE, CCRegistration.ID.ENVIRONMENT_POCKET, APConfig.PERIPHERALS_CONFIG.enableEnvironmentDetector::get)); - public static final RegistryObject CHAT_BOX = register("chat_box", () -> new APBlockEntityBlock<>(BlockEntityTypes.CHAT_BOX, true), () -> new APBlockItem(Blocks.CHAT_BOX.get(), CCRegistration.ID.CHATTY_TURTLE, CCRegistration.ID.CHATTY_POCKET, APConfig.PERIPHERALS_CONFIG.enableChatBox::get)); - public static final RegistryObject PLAYER_DETECTOR = register("player_detector", PlayerDetectorBlock::new, () -> new APBlockItem(Blocks.PLAYER_DETECTOR.get(), CCRegistration.ID.PLAYER_TURTLE, CCRegistration.ID.PLAYER_POCKET, APConfig.PERIPHERALS_CONFIG.enablePlayerDetector::get)); - public static final RegistryObject ME_BRIDGE = register("me_bridge", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("ae2") ? BlockEntityTypes.ME_BRIDGE : null, ModList.get().isLoaded("ae2")), () -> new APBlockItem(Blocks.ME_BRIDGE.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableMEBridge::get)); - public static final RegistryObject RS_BRIDGE = register("rs_bridge", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("refinedstorage") ? BlockEntityTypes.RS_BRIDGE : null, false), () -> new APBlockItem(Blocks.RS_BRIDGE.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableRSBridge::get)); - public static final RegistryObject ENERGY_DETECTOR = register("energy_detector", () -> new APBlockEntityBlock<>(BlockEntityTypes.ENERGY_DETECTOR, true), () -> new APBlockItem(Blocks.ENERGY_DETECTOR.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableEnergyDetector::get)); - public static final RegistryObject PERIPHERAL_CASING = register("peripheral_casing", BaseBlock::new, () -> new APBlockItem(Blocks.PERIPHERAL_CASING.get(), new Item.Properties().stacksTo(16), null, null, () -> true)); - public static final RegistryObject INVENTORY_MANAGER = register("inventory_manager", () -> new APBlockEntityBlock<>(BlockEntityTypes.INVENTORY_MANAGER, false), () -> new APBlockItem(Blocks.INVENTORY_MANAGER.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableInventoryManager::get)); - public static final RegistryObject REDSTONE_INTEGRATOR = register("redstone_integrator", RedstoneIntegratorBlock::new, () -> new APBlockItem(Blocks.REDSTONE_INTEGRATOR.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableRedstoneIntegrator::get)); - public static final RegistryObject BLOCK_READER = register("block_reader", () -> new APBlockEntityBlock<>(BlockEntityTypes.BLOCK_READER, true), () -> new APBlockItem(Blocks.BLOCK_READER.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableBlockReader::get)); - public static final RegistryObject GEO_SCANNER = register("geo_scanner", () -> new APBlockEntityBlock<>(BlockEntityTypes.GEO_SCANNER, false), () -> new APBlockItem(Blocks.GEO_SCANNER.get(), CCRegistration.ID.GEOSCANNER_TURTLE, CCRegistration.ID.GEOSCANNER_POCKET, APConfig.PERIPHERALS_CONFIG.enableGeoScanner::get)); - public static final RegistryObject COLONY_INTEGRATOR = register("colony_integrator", () -> new APBlockEntityBlock<>(ModList.get().isLoaded("minecolonies") ? BlockEntityTypes.COLONY_INTEGRATOR : null, false), () -> new APBlockItem(Blocks.COLONY_INTEGRATOR.get(), null, CCRegistration.ID.COLONY_POCKET, APConfig.PERIPHERALS_CONFIG.enableColonyIntegrator::get)); - public static final RegistryObject NBT_STORAGE = register("nbt_storage", () -> new APBlockEntityBlock<>(BlockEntityTypes.NBT_STORAGE, false), () -> new APBlockItem(Blocks.NBT_STORAGE.get(), null, null, APConfig.PERIPHERALS_CONFIG.enableNBTStorage::get)); - - public static void register() { - } - - private static RegistryObject registerNoItem(String name, Supplier block) { - return Registration.BLOCKS.register(name, block); - } - - private static RegistryObject register(String name, Supplier block, Supplier blockItem) { - RegistryObject registryObject = registerNoItem(name, block); - Registration.ITEMS.register(name, blockItem); - return registryObject; - } - - public static boolean never(BlockState state, BlockGetter level, BlockPos pos) { - return false; - } - -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java b/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java index 6bf5b1fd4..a72ff2f45 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java @@ -7,6 +7,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.integrations.IntegrationPeripheralProvider; import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketChatBoxUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketColonyIntegratorUpgrade; +import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketDistanceDetectorUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketEnvironmentUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketGeoScannerUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.pocket.PocketPlayerDetectorUpgrade; @@ -16,6 +17,7 @@ import de.srendi.advancedperipherals.common.addons.computercraft.turtles.TurtleEnvironmentDetectorUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.turtles.TurtleGeoScannerUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.turtles.TurtlePlayerDetectorUpgrade; +import de.srendi.advancedperipherals.common.addons.computercraft.turtles.TurtleSaddleUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.turtles.metaphysics.EndAutomata; import de.srendi.advancedperipherals.common.addons.computercraft.turtles.metaphysics.HusbandryAutomata; import de.srendi.advancedperipherals.common.addons.computercraft.turtles.metaphysics.OverpoweredEndAutomata; @@ -29,28 +31,30 @@ @Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class CCRegistration { - public static final RegistryObject> CHAT_BOX_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.CHATTY_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleChatBoxUpgrade::new)); - public static final RegistryObject> PLAYER_DETECTOR_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.PLAYER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtlePlayerDetectorUpgrade::new)); - public static final RegistryObject> ENVIRONMENT_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.ENVIRONMENT_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleEnvironmentDetectorUpgrade::new)); - public static final RegistryObject> CHUNKY_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.CHUNKY_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleChunkyUpgrade::new)); - public static final RegistryObject> GEO_SCANNER_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.GEOSCANNER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleGeoScannerUpgrade::new)); - public static final RegistryObject> COMPASS_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.COMPASS_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleCompassUpgrade::new)); - public static final RegistryObject> WEAK_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.WEAK_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(WeakAutomata::new)); - public static final RegistryObject> END_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.END_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(EndAutomata::new)); - public static final RegistryObject> HUSBANDRY_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.HUSBANDRY_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(HusbandryAutomata::new)); - public static final RegistryObject> OP_WEAK_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.OP_WEAK_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredWeakAutomata::new)); - public static final RegistryObject> OP_END_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.OP_END_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredEndAutomata::new)); - public static final RegistryObject> OP_HUSBANDRY_TURTLE = Registration.TURTLE_SERIALIZER.register(ID.OP_HUSBANDRY_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredHusbandryAutomata::new)); + public static final RegistryObject> CHAT_BOX_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.CHATTY_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleChatBoxUpgrade::new)); + public static final RegistryObject> CHUNKY_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.CHUNKY_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleChunkyUpgrade::new)); + public static final RegistryObject> COMPASS_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.COMPASS_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleCompassUpgrade::new)); + public static final RegistryObject> END_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.END_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(EndAutomata::new)); + public static final RegistryObject> ENVIRONMENT_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.ENVIRONMENT_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleEnvironmentDetectorUpgrade::new)); + public static final RegistryObject> GEO_SCANNER_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.GEOSCANNER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleGeoScannerUpgrade::new)); + public static final RegistryObject> HUSBANDRY_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.HUSBANDRY_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(HusbandryAutomata::new)); + public static final RegistryObject> OP_END_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.OP_END_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredEndAutomata::new)); + public static final RegistryObject> OP_HUSBANDRY_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.OP_HUSBANDRY_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredHusbandryAutomata::new)); + public static final RegistryObject> OP_WEAK_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.OP_WEAK_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(OverpoweredWeakAutomata::new)); + public static final RegistryObject> PLAYER_DETECTOR_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.PLAYER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtlePlayerDetectorUpgrade::new)); + public static final RegistryObject> SADDLE_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.SADDLE_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleSaddleUpgrade::new)); + public static final RegistryObject> WEAK_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.WEAK_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(WeakAutomata::new)); - public static final RegistryObject> CHAT_BOX_POCKET = Registration.POCKET_SERIALIZER.register(ID.CHATTY_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketChatBoxUpgrade::new)); - public static final RegistryObject> PLAYER_DETECTOR_POCKET = Registration.POCKET_SERIALIZER.register(ID.PLAYER_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketPlayerDetectorUpgrade::new)); - public static final RegistryObject> ENVIRONMENT_POCKET = Registration.POCKET_SERIALIZER.register(ID.ENVIRONMENT_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketEnvironmentUpgrade::new)); - public static final RegistryObject> GEO_SCANNER_POCKET = Registration.POCKET_SERIALIZER.register(ID.GEOSCANNER_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketGeoScannerUpgrade::new)); - public static final RegistryObject> COLONY_POCKET = Registration.POCKET_SERIALIZER.register(ID.COLONY_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketColonyIntegratorUpgrade::new)); + public static final RegistryObject> CHAT_BOX_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.CHATTY_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketChatBoxUpgrade::new)); + public static final RegistryObject> COLONY_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.COLONY_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketColonyIntegratorUpgrade::new)); + public static final RegistryObject> DISTANCE_DETECTOR_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.DISTANCE_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketDistanceDetectorUpgrade::new)); + public static final RegistryObject> ENVIRONMENT_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.ENVIRONMENT_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketEnvironmentUpgrade::new)); + public static final RegistryObject> GEO_SCANNER_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.GEOSCANNER_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketGeoScannerUpgrade::new)); + public static final RegistryObject> PLAYER_DETECTOR_POCKET = APRegistration.POCKET_SERIALIZER.register(ID.PLAYER_POCKET.getPath(), () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketPlayerDetectorUpgrade::new)); public static IntegrationPeripheralProvider integrationPeripheralProvider; - public static void register() { + protected static void register() { IntegrationPeripheralProvider.load(); integrationPeripheralProvider = new IntegrationPeripheralProvider(); ForgeComputerCraftAPI.registerPeripheralProvider(integrationPeripheralProvider); @@ -59,23 +63,25 @@ public static void register() { public static class ID { public static final ResourceLocation CHATTY_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "chatty_turtle"); - public static final ResourceLocation PLAYER_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "player_turtle"); - public static final ResourceLocation ENVIRONMENT_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "environment_turtle"); public static final ResourceLocation CHUNKY_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "chunky_turtle"); - public static final ResourceLocation GEOSCANNER_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "geoscanner_turtle"); public static final ResourceLocation COMPASS_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "compass_turtle"); - public static final ResourceLocation WEAK_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "weak_automata"); public static final ResourceLocation END_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "end_automata"); + public static final ResourceLocation ENVIRONMENT_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "environment_turtle"); + public static final ResourceLocation GEOSCANNER_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "geoscanner_turtle"); public static final ResourceLocation HUSBANDRY_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "husbandry_automata"); - public static final ResourceLocation OP_WEAK_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "overpowered_weak_automata"); public static final ResourceLocation OP_END_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "overpowered_end_automata"); public static final ResourceLocation OP_HUSBANDRY_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "overpowered_husbandry_automata"); + public static final ResourceLocation OP_WEAK_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "overpowered_weak_automata"); + public static final ResourceLocation PLAYER_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "player_turtle"); + public static final ResourceLocation SADDLE_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "saddle_turtle"); + public static final ResourceLocation WEAK_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "weak_automata"); public static final ResourceLocation CHATTY_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "chatty_pocket"); - public static final ResourceLocation PLAYER_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "player_pocket"); + public static final ResourceLocation COLONY_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "colony_pocket"); + public static final ResourceLocation DISTANCE_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "distance_pocket"); public static final ResourceLocation ENVIRONMENT_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "environment_pocket"); public static final ResourceLocation GEOSCANNER_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "geoscanner_pocket"); - public static final ResourceLocation COLONY_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "colony_pocket"); + public static final ResourceLocation PLAYER_POCKET = new ResourceLocation(AdvancedPeripherals.MOD_ID, "player_pocket"); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/ContainerTypes.java b/src/main/java/de/srendi/advancedperipherals/common/setup/ContainerTypes.java deleted file mode 100644 index 68ed5dc8c..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/ContainerTypes.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.srendi.advancedperipherals.common.setup; - -import de.srendi.advancedperipherals.common.container.InventoryManagerContainer; -import net.minecraft.core.BlockPos; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.level.Level; -import net.minecraftforge.common.extensions.IForgeMenuType; -import net.minecraftforge.registries.RegistryObject; - -public class ContainerTypes { - - public static final RegistryObject> INVENTORY_MANAGER_CONTAINER = Registration.CONTAINER_TYPES.register("memory_card_container", () -> IForgeMenuType.create((windowId, inv, data) -> { - BlockPos pos = data.readBlockPos(); - Level level = inv.player.getCommandSenderWorld(); - return new InventoryManagerContainer(windowId, inv, pos, level); - })); - - public static void register() { - } -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/Items.java b/src/main/java/de/srendi/advancedperipherals/common/setup/Items.java deleted file mode 100644 index 5cf12df13..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/Items.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.srendi.advancedperipherals.common.setup; - -import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.items.APItem; -import de.srendi.advancedperipherals.common.items.MemoryCardItem; -import de.srendi.advancedperipherals.common.items.WeakAutomataCore; -import net.minecraft.world.item.Item; -import net.minecraftforge.registries.RegistryObject; - -public class Items { - - public static final RegistryObject CHUNK_CONTROLLER = Registration.ITEMS.register("chunk_controller", () -> new APItem(new Item.Properties().stacksTo(16), CCRegistration.ID.CHUNKY_TURTLE, null, APConfig.PERIPHERALS_CONFIG.enableChunkyTurtle::get)); - public static final RegistryObject COMPUTER_TOOL = Registration.ITEMS.register("computer_tool", () -> new APItem(new Item.Properties().stacksTo(1), null, null, () -> true)); - public static final RegistryObject MEMORY_CARD = Registration.ITEMS.register("memory_card", MemoryCardItem::new); - public static final RegistryObject END_AUTOMATA_CORE = Registration.ITEMS.register("end_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), CCRegistration.ID.END_AUTOMATA, null, APConfig.METAPHYSICS_CONFIG.enableEndAutomataCore)); - public static final RegistryObject HUSBANDRY_AUTOMATA_CORE = Registration.ITEMS.register("husbandry_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), CCRegistration.ID.WEAK_AUTOMATA, null, APConfig.METAPHYSICS_CONFIG.enableHusbandryAutomataCore)); - public static final RegistryObject WEAK_AUTOMATA_CORE = Registration.ITEMS.register("weak_automata_core", () -> new WeakAutomataCore(new Item.Properties().stacksTo(1), CCRegistration.ID.WEAK_AUTOMATA, null)); - public static final RegistryObject OVERPOWERED_WEAK_AUTOMATA_CORE = Registration.ITEMS.register("overpowered_weak_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), CCRegistration.ID.OP_WEAK_AUTOMATA, null, APConfig.METAPHYSICS_CONFIG.enableWeakAutomataCore)); - public static final RegistryObject OVERPOWERED_END_AUTOMATA_CORE = Registration.ITEMS.register("overpowered_end_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), CCRegistration.ID.OP_END_AUTOMATA, null, APConfig.METAPHYSICS_CONFIG.enableEndAutomataCore)); - public static final RegistryObject OVERPOWERED_HUSBANDRY_AUTOMATA_CORE = Registration.ITEMS.register("overpowered_husbandry_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), CCRegistration.ID.OP_HUSBANDRY_AUTOMATA, null, APConfig.METAPHYSICS_CONFIG.enableHusbandryAutomataCore)); - - public static void register() { - } - -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/Villagers.java b/src/main/java/de/srendi/advancedperipherals/common/setup/Villagers.java deleted file mode 100644 index df00d9d8f..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/Villagers.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.srendi.advancedperipherals.common.setup; - -import com.google.common.collect.ImmutableSet; -import dan200.computercraft.shared.Registry; -import de.srendi.advancedperipherals.AdvancedPeripherals; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.entity.ai.village.poi.PoiType; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraftforge.registries.RegistryObject; - -public class Villagers { - - public static final RegistryObject COMPUTER_SCIENTIST_POI = Registration.POI_TYPES.register("computer_scientist", () -> new PoiType(ImmutableSet.copyOf(Registry.ModBlocks.COMPUTER_ADVANCED.get().getStateDefinition().getPossibleStates()), 1, 1)); - public static final RegistryObject COMPUTER_SCIENTIST = Registration.VILLAGER_PROFESSIONS.register("computer_scientist", () -> new VillagerProfession(AdvancedPeripherals.MOD_ID + ":computer_scientist", holder -> holder.is(COMPUTER_SCIENTIST_POI.getKey()), holder -> holder.is(COMPUTER_SCIENTIST_POI.getKey()), ImmutableSet.of(), ImmutableSet.of(Registry.ModBlocks.COMPUTER_ADVANCED.get()), SoundEvents.VILLAGER_WORK_TOOLSMITH)); - - public static void register() { - } - -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SlotType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SlotType.java new file mode 100644 index 000000000..f5498935a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SlotType.java @@ -0,0 +1,22 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import net.minecraft.network.chat.Component; + +public enum SlotType { + PERIPHERALS(Component.translatable("text.advancedperipherals.smart_glasses.peripherals")), + MODULES(Component.translatable("text.advancedperipherals.smart_glasses.modules")); + + private final Component name; + + SlotType(Component name) { + this.name = name; + } + + public Component getName() { + return name; + } + + public static SlotType defaultType() { + return PERIPHERALS; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAPI.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAPI.java new file mode 100644 index 000000000..04baafc24 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAPI.java @@ -0,0 +1,11 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.api.lua.ILuaAPI; + +public class SmartGlassesAPI implements ILuaAPI { + @Override + public String[] getNames() { + return new String[]{"smartglasses"}; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAccess.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAccess.java new file mode 100644 index 000000000..50420c042 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesAccess.java @@ -0,0 +1,67 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.pocket.IPocketAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class SmartGlassesAccess implements IPocketAccess { + + private final SmartGlassesComputer computer; + + public SmartGlassesAccess(SmartGlassesComputer computer) { + this.computer = computer; + } + + @Nullable + @Override + public Entity getEntity() { + return computer.getEntity(); + } + + @Override + public int getColour() { + return 0; + } + + @Override + public void setColour(int colour) { + } + + @Override + public int getLight() { + return 0; + } + + @Override + public void setLight(int colour) { + } + + @Override + public CompoundTag getUpgradeNBTData() { + return computer.getUpgradeNBTData(); + } + + @Override + public void updateUpgradeNBTData() { + computer.updateUpgradeNBTData(); + } + + @Override + public void invalidatePeripheral() { + computer.invalidatePeripheral(); + } + + @Override + public Map getUpgrades() { + return computer.getUpgrades(); + } + + public SmartGlassesComputer getComputer() { + return computer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java new file mode 100644 index 000000000..e76a5ee0c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java @@ -0,0 +1,264 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.core.computer.ComputerSide; +import dan200.computercraft.shared.PocketUpgrades; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.core.ServerComputer; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import de.srendi.advancedperipherals.common.smartglasses.modules.ModulePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +/** + * Basically just a {@link dan200.computercraft.shared.pocket.core.PocketServerComputer} but with some changes + */ +public class SmartGlassesComputer extends ServerComputer implements IPocketAccess { + + public static final String UPGRADE_DATAS_TAG = "UpgradeDatas"; + + @Nullable + private Entity entity; + private ItemStack stack = ItemStack.EMPTY; + private final SmartGlassesAccess smartGlassesAccess = new SmartGlassesAccess(this); + @Nullable + private SmartGlassesItemHandler itemHandler = null; + @NotNull + private final ModulePeripheral modulePeripheral; + private final CompoundTag upgradeDatas; + + private boolean peripheralOutdated = false; + private boolean isDirty = true; + + private Map upgrades = Collections.emptyMap(); + private final Map modules = new HashMap<>(); + + public SmartGlassesComputer(ServerLevel world, int computerID, @Nullable String label, ComputerFamily family, @NotNull CompoundTag upgradeDatas) { + super(world, computerID, label, family, 39, 13); + this.addAPI(new SmartGlassesAPI()); + this.modulePeripheral = new ModulePeripheral(this); + this.upgradeDatas = upgradeDatas; + this.setPeripheral(ComputerSide.BACK, this.modulePeripheral); + } + + @Nullable + @Override + public Entity getEntity() { + if (stack.isEmpty() || entity == null || !entity.isAlive()) { + return null; + } + + if (entity instanceof Player player) { + Inventory inventory = player.getInventory(); + if (inventory.contains(stack)) { + return player; + } + return null; + } + if (entity instanceof ItemEntity itemEntity) { + return itemEntity.getItem() == stack ? entity : null; + } + return null; + } + + @Override + public ServerLevel getLevel() { + return this.entity == null ? super.getLevel() : (ServerLevel) this.entity.getCommandSenderWorld(); + } + + @Override + public BlockPos getPosition() { + return this.entity == null ? super.getPosition() : new BlockPos(this.entity.getEyePosition()); + } + + @Override + public int getColour() { + return 0; + } + + @Override + public void setColour(int colour) { + // We don't have a color. + } + + public void setStack(ItemStack stack) { + this.stack = stack; + this.invalidatePeripheral(); + this.updateUpgradeNBTData(); + } + + public ItemStack getStack() { + return stack; + } + + @Override + public int getLight() { + return 0; + } + + @Override + public void setLight(int colour) { + } + + public void setItemHandler(@Nullable SmartGlassesItemHandler itemHandler) { + this.itemHandler = itemHandler; + } + + @Override + @NotNull + public CompoundTag getUpgradeNBTData() { + return this.upgradeDatas; + } + + public void setUpgradeData(@NotNull ComputerSide side, @NotNull ResourceLocation id, @NotNull CompoundTag data) { + data.putString("UpgradeSide", side.getName()); + this.upgradeDatas.put(id.toString(), data); + this.updateUpgradeNBTData(); + } + + public void removeUpgradeData(@NotNull ComputerSide side) { + for (String id : this.upgradeDatas.getAllKeys()) { + if (side.getName().equals(this.upgradeDatas.getCompound(id).getString("UpgradeSide"))) { + this.upgradeDatas.remove(id); + this.updateUpgradeNBTData(); + return; + } + } + } + + @Override + public void updateUpgradeNBTData() { + this.isDirty = true; + } + + @Override + public void invalidatePeripheral() { + this.peripheralOutdated = true; + } + + @Override + @NotNull + public Map getUpgrades() { + return this.upgrades; + } + + @Override + public void setPeripheral(ComputerSide side, IPeripheral peripheral) { + super.setPeripheral(side, peripheral); + } + + private void updatePeripheralsAndModules(SmartGlassesItemHandler itemHandler) { + Set upgradesIdSet = new HashSet<>(); + ImmutableMap.Builder upgradesBuilder = new ImmutableMap.Builder<>(); + for (int slot = 0; slot < SmartGlassesItemHandler.PERIPHERAL_SLOTS; slot++) { + ComputerSide side = SmartGlassesSlot.indexToSide(slot); + ItemStack peripheralItem = itemHandler.getStackInSlot(slot); + IPocketUpgrade upgrade = PocketUpgrades.instance().get(peripheralItem); + IPeripheral peripheral = upgrade != null ? upgrade.createPeripheral(smartGlassesAccess) : null; + setPeripheral(side, peripheral); + if (peripheral != null) { + ResourceLocation id = upgrade.getUpgradeID(); + if (upgradesIdSet.add(id)) { + upgradesBuilder.put(id, peripheral); + setUpgradeData(side, id, this.upgradeDatas.getCompound(id.toString())); + continue; + } + } + removeUpgradeData(side); + } + this.upgrades = upgradesBuilder.build(); + for (int slot = SmartGlassesItemHandler.PERIPHERAL_SLOTS; slot < SmartGlassesItemHandler.SLOTS; slot++) { + ItemStack peripheralItem = itemHandler.getStackInSlot(slot); + IModule oldModule = modules.get(slot); + if (!peripheralItem.isEmpty() && peripheralItem.getItem() instanceof IModuleItem module) { + IModule newModule = module.createModule(smartGlassesAccess); + if (oldModule != null && oldModule.getName().equals(newModule.getName())) { + continue; + } + modules.put(slot, newModule); + } else if (oldModule != null) { + oldModule.onUnequipped(smartGlassesAccess); + modules.remove(slot); + } + } + this.modulePeripheral.updateModules(); + setPeripheral(ComputerSide.BACK, null); + setPeripheral(ComputerSide.BACK, this.modulePeripheral); + if (this.entity instanceof Player player) { + player.getInventory().setChanged(); + } + } + + @Override + public void tickServer() { + super.tickServer(); + + boolean shouldUpdateInventory = this.peripheralOutdated || this.isDirty; + if (this.peripheralOutdated && this.itemHandler != null) { + this.peripheralOutdated = false; + this.updatePeripheralsAndModules(this.itemHandler); + } + if (this.isDirty) { + this.isDirty = false; + CompoundTag data = this.stack.getOrCreateTag(); + data.put(UPGRADE_DATAS_TAG, this.upgradeDatas.copy()); + } + if (shouldUpdateInventory && entity instanceof Player player) { + player.getInventory().setChanged(); + } + + this.modules.values().forEach(module -> { + module.tick(smartGlassesAccess); + }); + } + + public void setEntity(@Nullable Entity entity) { + if (this.entity == entity) { + return; + } + this.entity = entity; + if (entity == null) { + return; + } + this.setLevel((ServerLevel) this.entity.getCommandSenderWorld()); + this.setPosition(new BlockPos(this.entity.getEyePosition())); + } + + public Map getModules() { + return modules; + } + + @Nullable + public T getModule(Class module) { + return modules.values().stream().filter(module::isInstance).map(module::cast).findFirst().orElse(null); + } + + @Override + protected void onRemoved() { + super.onRemoved(); + } + + @NotNull + public SmartGlassesAccess getSmartGlassesAccess() { + return smartGlassesAccess; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesItemHandler.java new file mode 100644 index 000000000..d3b27fad6 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesItemHandler.java @@ -0,0 +1,173 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.shared.PocketUpgrades; +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import net.minecraft.core.NonNullList; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import javax.annotation.Nonnull; + +public class SmartGlassesItemHandler implements IItemHandlerModifiable { + + public static final int SLOTS = 11; + public static final int PERIPHERAL_SLOTS = 5; + + private final ItemStack glasses; + @Nullable + private final SmartGlassesComputer computer; + + public SmartGlassesItemHandler(ItemStack glasses, @Nullable SmartGlassesComputer computer) { + this.glasses = glasses; + this.computer = computer; + } + + public ItemStack getGlasses() { + return glasses; + } + + @Override + public int getSlots() { + return SLOTS; + } + + @Override + public int getSlotLimit(int slot) { + return 1; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + if (stack.getItem() instanceof SmartGlassesItem) { + return false; + } + List items = this.loadItems(); + if (slot < PERIPHERAL_SLOTS) { + IPocketUpgrade upgrade = PocketUpgrades.instance().get(stack); + if (upgrade == null) { + return false; + } + ResourceLocation id = upgrade.getUpgradeID(); + for (int i = 0; i < PERIPHERAL_SLOTS; i++) { + IPocketUpgrade u = PocketUpgrades.instance().get(items.get(i)); + if (u != null && u.getUpgradeID().equals(id)) { + return false; + } + } + return true; + } + Item item = stack.getItem(); + if (!(item instanceof IModuleItem module)) { + return false; + } + for (int i = PERIPHERAL_SLOTS; i < SLOTS; i++) { + if (items.get(i).getItem() == item) { + return false; + } + } + return true; + } + + @Override + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + if (stack.isEmpty()) { + return ItemStack.EMPTY; + } + if (!isItemValid(slot, stack)) { + return stack; + } + ItemStack existing = getStackInSlot(slot); + if (!existing.isEmpty()) { + return stack; + } + + int limit = getSlotLimit(slot); + if (limit <= 0) { + return stack; + } + + boolean reachedLimit = stack.getCount() > limit; + + if (!simulate) { + if (existing.isEmpty()) { + setStackInSlot(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack); + } else { + existing.grow(reachedLimit ? limit : stack.getCount()); + } + + setChanged(); + } + + return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - limit) : ItemStack.EMPTY; + } + + @Override + @Nonnull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) { + return ItemStack.EMPTY; + } + + ItemStack existing = getStackInSlot(slot); + if (existing.isEmpty()) { + return ItemStack.EMPTY; + } + + int toExtract = Math.min(amount, existing.getMaxStackSize()); + + if (existing.getCount() <= toExtract) { + if (simulate) { + return existing.copy(); + } + setStackInSlot(slot, ItemStack.EMPTY); + return existing; + } + + if (!simulate) { + setStackInSlot(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract)); + } + return ItemHandlerHelper.copyStackWithSize(existing, toExtract); + } + + @Override + public ItemStack getStackInSlot(int slot) { + return loadItems().get(slot); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + NonNullList items = loadItems(); + if (ItemStack.isSameItemSameTags(stack, items.get(slot))) { + return; + } + items.set(slot, stack); + saveItems(items); + setChanged(); + } + + public void setChanged() { + if (this.computer != null) { + this.computer.invalidatePeripheral(); + } + } + + public void saveItems(NonNullList items) { + ContainerHelper.saveAllItems(this.glasses.getOrCreateTag(), items); + } + + public NonNullList loadItems() { + NonNullList items = NonNullList.withSize(SLOTS, ItemStack.EMPTY); + ContainerHelper.loadAllItems(this.glasses.getOrCreateTag(), items); + return items; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesMenuProvider.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesMenuProvider.java new file mode 100644 index 000000000..bf1fb3b53 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesMenuProvider.java @@ -0,0 +1,43 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.shared.computer.core.ServerComputer; +import de.srendi.advancedperipherals.common.container.SmartGlassesContainer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; + +public class SmartGlassesMenuProvider implements MenuProvider { + private final ServerComputer computer; + private final Component name; + private final IItemHandler glassesContainer; + + public SmartGlassesMenuProvider(ServerComputer computer, ItemStack stack, IItemHandler glassesContainer) { + this.computer = computer; + name = stack.getHoverName(); + this.glassesContainer = glassesContainer; + } + + @NotNull + @Override + public Component getDisplayName() { + return name; + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int id, @NotNull Inventory inventory, @NotNull Player entity) { + return new SmartGlassesContainer(id, + p -> { + return true; + }, + computer, inventory, glassesContainer, null + ); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesSlot.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesSlot.java new file mode 100644 index 000000000..13f4d39ed --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesSlot.java @@ -0,0 +1,43 @@ +package de.srendi.advancedperipherals.common.smartglasses; + +import dan200.computercraft.core.computer.ComputerSide; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class SmartGlassesSlot extends SlotItemHandler { + + public final SlotType slotType; + private boolean isEnabled; + + public SmartGlassesSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition, SlotType slotType) { + super(itemHandler, index, xPosition, yPosition); + this.slotType = slotType; + this.isEnabled = slotType == SlotType.defaultType(); + } + + public void setEnabled(boolean enabled) { + isEnabled = enabled; + } + + @Override + public boolean isActive() { + return isEnabled; + } + + @Override + public int getMaxStackSize() { + return 1; + } + + public static ComputerSide indexToSide(int slot) { + return switch (slot) { + case 0 -> ComputerSide.TOP; + case 1 -> ComputerSide.LEFT; + case 2 -> ComputerSide.FRONT; + case 3 -> ComputerSide.RIGHT; + case 4 -> ComputerSide.BOTTOM; + default -> throw new IllegalArgumentException("slot must in range [0,4]"); + }; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModule.java new file mode 100644 index 000000000..57376e535 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModule.java @@ -0,0 +1,38 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules; + +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +public interface IModule { + + ResourceLocation getName(); + + /** + * Used to define the available functions of the module. This method only gets called once when indexing the modules + *

+ * Return null if the module does not have any functions + * + * @return an object containing lua functions {@link dan200.computercraft.api.lua.LuaFunction} + */ + @Nullable + IModuleFunctions getFunctions(SmartGlassesAccess smartGlassesAccess); + + /** + * Classic tick function. + *

+ * Implementations should check if the entity is not null since the glasses can still tick without belonging to an entity + * @param smartGlassesAccess Contains access to the entity, the computer, the level or the upgrades + */ + default void tick(SmartGlassesAccess smartGlassesAccess) {} + + default void onUnequipped(SmartGlassesAccess smartGlassesAccess) {} + + /** + * ErrorConstants class contains constants for error messages. This is used for easier error handling for users. + */ + class ErrorConstants { + public static final String ALREADY_EXISTS = "ID_ALREADY_EXISTS"; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java new file mode 100644 index 000000000..3656500eb --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java @@ -0,0 +1,13 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules; + +import de.srendi.advancedperipherals.lib.peripherals.IPeripheralPlugin; + +/** + * Used to define the available functions of the module. + * Functions can be defined by creating final public methods annotated with the @{@link dan200.computercraft.api.lua.LuaFunction} annotation + */ +public interface IModuleFunctions extends IPeripheralPlugin { + + IModuleFunctions EMPTY = new IModuleFunctions() {}; + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java new file mode 100644 index 000000000..bed3560a2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java @@ -0,0 +1,24 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules; + +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +public interface IModuleItem { + + IModule createModule(SmartGlassesAccess access); + + /** + * This method is called every tick the item is in the inventory of the smart glasses + * Runs on the client and server side + * + * @param access The access to the smart glasses - Null on the client side + * @param module The module - Null on the client side + */ + default void inventoryTick(ItemStack itemStack, Level level, Entity entity, int inventorySlot, boolean isCurrentItem, @Nullable SmartGlassesAccess access, @Nullable IModule module) { + + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheral.java new file mode 100644 index 000000000..14aef19d0 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheral.java @@ -0,0 +1,43 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules; + +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import org.jetbrains.annotations.NotNull; + +public class ModulePeripheral extends BasePeripheral { + + public static final String PERIPHERAL_TYPE = "smart_glasses"; + + public ModulePeripheral(SmartGlassesComputer computer) { + super(PERIPHERAL_TYPE, new ModulePeripheralOwner(computer)); + } + + public void updateModules() { + // We need to set the initialization to false so the dynamic peripheral re-builds the plugins + clearAllPlugins(); + + SmartGlassesComputer computer = getPeripheralOwner().getComputer(); + computer.getModules().values().forEach(module -> { + IModuleFunctions functions = module.getFunctions(computer.getSmartGlassesAccess()); + if (functions != null) { + addPlugin(functions); + } + }); + } + + @Override + public boolean isEnabled() { + return true; + } + + @LuaFunction(mainThread = true) + public final String[] getModules() { + return getPeripheralOwner().getComputer().getModules().values().stream().map(module -> module.getName().toString()).toArray(String[]::new); + } + + @LuaFunction(mainThread = true) + public final boolean hasModule(@NotNull String module) { + return getPeripheralOwner().getComputer().getModules().values().stream().anyMatch(m -> m.getName().toString().equals(module)); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheralOwner.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheralOwner.java new file mode 100644 index 000000000..f7353f1ef --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/ModulePeripheralOwner.java @@ -0,0 +1,152 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.core.computer.ComputerSide; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.BasePeripheralOwner; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.util.fakeplayer.APFakePlayer; +import de.srendi.advancedperipherals.lib.peripherals.IBasePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.FrontAndTop; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +import org.apache.commons.lang3.NotImplementedException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.stream.Stream; + +public class ModulePeripheralOwner extends BasePeripheralOwner { + + //TODO: Think about making our own smart glasses access so we don't have the not used stuff like the color or the light + // We would need to remove the pocket stuff from the SmartGlassesComputer + private final SmartGlassesComputer computer; + + public ModulePeripheralOwner(SmartGlassesComputer computer) { + this.computer = computer; + } + + @Nullable + @Override + public String getCustomName() { + return "smartglasses"; + } + + @Nullable + @Override + public Level getLevel() { + return computer.getEntity().getLevel(); + } + + @NotNull + @Override + public BlockPos getPos() { + return new BlockPos(computer.getEntity().getEyePosition()); + } + + @NotNull + @Override + public Vec3 getCenterPos() { + return computer.getEntity().getEyePosition(); + } + + @NotNull + @Override + public Direction getFacing() { + Vec3 dir = getDirection(); + return Direction.getNearest(dir.x, dir.y, dir.z); + } + + @NotNull + @Override + public FrontAndTop getOrientation() { + Vec3 up = computer.getEntity().getUpVector(1.0f); + return FrontAndTop.fromFrontAndTop(getFacing(), Direction.getNearest(up.x, up.y, up.z)); + } + + @NotNull + @Override + public Vec3 getDirection() { + return computer.getEntity().getLookAngle(); + } + + @NotNull + public SmartGlassesComputer getComputer() { + return computer; + } + + @Nullable + @Override + public Entity getHoldingEntity() { + return computer.getEntity(); + } + + @Nullable + @Override + public Player getOwner() { + Entity owner = computer.getEntity(); + return owner instanceof Player player ? player : null; + } + + @NotNull + @Override + public CompoundTag getDataStorage() { + return computer.getUpgradeNBTData(); + } + + @Override + public void markDataStorageDirty() { + computer.updateUpgradeNBTData(); + } + + @Override + public T withPlayer(APFakePlayer.Action function) { + throw new NotImplementedException(); + } + + @Override + public ItemStack getToolInMainHand() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack storeItem(ItemStack stored) { + throw new NotImplementedException(); + } + + @Override + public void destroyUpgrade() { + throw new NotImplementedException(); + } + + @Override + public boolean isMovementPossible(@NotNull Level level, @NotNull BlockPos pos) { + return false; + } + + @Override + public boolean move(@NotNull Level level, @NotNull BlockPos pos) { + return false; + } + + @Override + public T getConnectedPeripheral(Class type) { + IPeripheral foundPeripheral = Stream.of(ComputerSide.values()) + .map(side -> computer.getPeripheral(side)) + .filter(peripheral -> { + if (peripheral == null || type.isInstance(peripheral)) { + return false; + } + return peripheral instanceof IBasePeripheral basePeripheral ? basePeripheral.isEnabled() : true; + }) + .findFirst() + .orElse(null); + return (T) foundPeripheral; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModule.java new file mode 100644 index 000000000..c695a8334 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModule.java @@ -0,0 +1,21 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.hotkey; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; +import net.minecraft.resources.ResourceLocation; + +public class HotkeyModule implements IModule { + + @Override + public ResourceLocation getName() { + return AdvancedPeripherals.getRL("hotkey"); + } + + @Override + public IModuleFunctions getFunctions(SmartGlassesAccess smartGlassesAccess) { + return null; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java new file mode 100644 index 000000000..9dd8594a6 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java @@ -0,0 +1,58 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.hotkey; + +import de.srendi.advancedperipherals.client.KeyBindings; +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toserver.GlassesHotkeyPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import de.srendi.advancedperipherals.common.util.KeybindUtil; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +public class HotkeyModuleItem extends BaseItem implements IModuleItem { + + private static final String KEY_PRESS_DURATION_NBT = "KeyPressDuration"; + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public IModule createModule(SmartGlassesAccess access) { + return new HotkeyModule(); + } + + @Override + public void inventoryTick(@NotNull ItemStack stack, @NotNull Level level, @NotNull Entity entity, int slot, boolean isSelected) { + if (!level.isClientSide() || !(entity instanceof Player player)) + return; + + if (KeybindUtil.isKeyPressed(KeyBindings.GLASSES_HOTKEY_KEYBINDING)) { + // Add another 50ms to the duration, one tick + setKeyPressDuration(stack, getKeyPressDuration(stack) + 50); + } else if(getKeyPressDuration(stack) > 0) { + // If the key is not pressed, but the duration is greater than 0, we can assume that the key was pressed + // We can now post the event + + int duration = getKeyPressDuration(stack); + setKeyPressDuration(stack, 0); + + String keyBind = KeyBindings.GLASSES_HOTKEY_KEYBINDING.getKey().getName(); + APNetworking.sendToServer(new GlassesHotkeyPacket(player.getUUID(), keyBind, duration)); + } + } + + public static int getKeyPressDuration(ItemStack stack) { + return stack.copy().getOrCreateTag().getInt(KEY_PRESS_DURATION_NBT); + } + + public static void setKeyPressDuration(ItemStack stack, int keyPressDuration) { + stack.getOrCreateTag().putInt(KEY_PRESS_DURATION_NBT, keyPressDuration); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionFunctions.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionFunctions.java new file mode 100644 index 000000000..ef9458a9c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionFunctions.java @@ -0,0 +1,24 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.nightvision; + +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; + +public class NightVisionFunctions implements IModuleFunctions { + + private final NightVisionModule nightVisionModule; + + public NightVisionFunctions(NightVisionModule nightVisionModule) { + this.nightVisionModule = nightVisionModule; + } + + @LuaFunction + public final boolean isNightVisionEnabled() { + return nightVisionModule.isNightVisionEnabled(); + } + + @LuaFunction + public final void enableNightVision(boolean enable) { + nightVisionModule.enableNightVision(enable); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java new file mode 100644 index 000000000..f1333b273 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java @@ -0,0 +1,54 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.nightvision; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.Nullable; + +public class NightVisionModule implements IModule { + + public boolean nightVisionEnabled = true; + + public NightVisionModule() { + + } + + @Override + public ResourceLocation getName() { + return AdvancedPeripherals.getRL("night_vision"); + } + + @Override + @Nullable + public IModuleFunctions getFunctions(SmartGlassesAccess smartGlassesAccess) { + return new NightVisionFunctions(this); + } + + @Override + public void onUnequipped(SmartGlassesAccess smartGlassesAccess) { + if (smartGlassesAccess.getEntity() != null) { + if (smartGlassesAccess.getEntity() instanceof Player player) { + player.removeEffect(MobEffects.NIGHT_VISION); + } + } + + } + + /** + * isNightVisionEnabled is safety to be called concurrently + */ + public boolean isNightVisionEnabled() { + return nightVisionEnabled; + } + + /** + * enableNightVision is safety to be called concurrently + */ + public void enableNightVision(boolean enable) { + nightVisionEnabled = enable; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java new file mode 100644 index 000000000..44da3ee90 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java @@ -0,0 +1,41 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.nightvision; + +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +public class NightVisionModuleItem extends BaseItem implements IModuleItem { + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public IModule createModule(SmartGlassesAccess access) { + return new NightVisionModule(); + } + + @Override + public void inventoryTick(ItemStack itemStack, Level level, Entity entity, int inventorySlot, boolean isCurrentItem, @Nullable SmartGlassesAccess access, @Nullable IModule module) { + if (level.isClientSide() || !(entity instanceof Player player)) { + return; + } + + if (module instanceof NightVisionModule nightVisionModule) { + if (nightVisionModule.nightVisionEnabled) { + player.addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, 20 * 13 - 1 /* minus 1 tick then the client timing won't flash */)); + } else { + player.removeEffect(MobEffects.NIGHT_VISION); + } + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectDecodeRegistry.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectDecodeRegistry.java new file mode 100644 index 000000000..2406ca69b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectDecodeRegistry.java @@ -0,0 +1,25 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +public class ObjectDecodeRegistry { + + private static final Map> objectRegistry = new HashMap<>(); + + public static RenderableObject getObject(int id, FriendlyByteBuf buf) { + if (objectRegistry.containsKey(id)) { + return objectRegistry.get(id).apply(buf); + } + return null; + } + + public static void register(int id, Function function) { + objectRegistry.put(id, function); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectProperty.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectProperty.java new file mode 100644 index 000000000..a580e14a6 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/ObjectProperty.java @@ -0,0 +1,22 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.PropertyType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used to mark a field as a property. It is used for the properties of lua objects. + * Fields annotated with @ObjectProperty will be accessible in lua via the arguments/the filter table for the specific object. + * @see PropertyType + * @see OverlayObject + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface ObjectProperty { + + Class> type(); + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesFunctions.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesFunctions.java new file mode 100644 index 000000000..b9bd68184 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesFunctions.java @@ -0,0 +1,153 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BlockObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.BoxObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.SphereObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim.TorusObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.ItemObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.LineObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.RectangleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.TextObject; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; + +public class OverlayGlassesFunctions implements IModuleFunctions { + + private final OverlayModule overlayModule; + private final SmartGlassesAccess access; + + public OverlayGlassesFunctions(OverlayModule overlayModule) { + this.overlayModule = overlayModule; + this.access = overlayModule.access; + } + + @LuaFunction + public final MethodResult createRectangle(IArguments arguments) throws LuaException { + RectangleObject rectangle = new RectangleObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(rectangle); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createCircle(IArguments arguments) throws LuaException { + CircleObject circle = new CircleObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(circle); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createLine(IArguments arguments) throws LuaException { + LineObject rectangle = new LineObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(rectangle); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createText(IArguments arguments) throws LuaException { + TextObject circle = new TextObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(circle); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createItem(IArguments arguments) throws LuaException { + ItemObject item = new ItemObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(item); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createBlock(IArguments arguments) throws LuaException { + BlockObject block = new BlockObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(block); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createBox(IArguments arguments) throws LuaException { + BoxObject block = new BoxObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(block); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createSphere(IArguments arguments) throws LuaException { + SphereObject block = new SphereObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(block); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult createTorus(IArguments arguments) throws LuaException { + TorusObject block = new TorusObject(overlayModule, arguments); + RenderableObject object = overlayModule.addObject(block); + + return MethodResult.of(object, "SUCCESS"); + } + + @LuaFunction + public final MethodResult getObject(IArguments arguments) throws LuaException { + int id = arguments.getInt(0); + return MethodResult.of(overlayModule.getObjects().get(id)); + } + + @LuaFunction + public final MethodResult removeObject(int id) { + return MethodResult.of(overlayModule.removeObject(id)); + } + + @LuaFunction + public final MethodResult clear() { + return MethodResult.of(overlayModule.clear()); + } + + @LuaFunction + public final MethodResult getObjectsSize() { + return MethodResult.of(overlayModule.getObjects().size()); + } + + @LuaFunction + public final MethodResult getSize() { + return MethodResult.of(overlayModule.getScreenWidth(), overlayModule.getScreenHeight()); + } + + @LuaFunction + public final MethodResult getGuiScale() { + return MethodResult.of(overlayModule.getGuiScale()); + } + + @LuaFunction + public final MethodResult getCoords() { + Vec3 pos = access.getEntity().getEyePosition(); + return MethodResult.of(pos.x, pos.y, pos.z); + } + + @LuaFunction + public final MethodResult update() { + return MethodResult.of(overlayModule.bulkUpdate()); + } + + @LuaFunction + public final MethodResult autoUpdate(IArguments arguments) throws LuaException { + overlayModule.autoUpdate = arguments.optBoolean(0, !overlayModule.autoUpdate); + return MethodResult.of(overlayModule.autoUpdate); + } + + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java new file mode 100644 index 000000000..20a3bd78b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java @@ -0,0 +1,19 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; + +public class OverlayGlassesItem extends BaseItem implements IModuleItem { + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public IModule createModule(SmartGlassesAccess smartGlassesAccess) { + return new OverlayModule(smartGlassesAccess); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayModule.java new file mode 100644 index 000000000..d56776558 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayModule.java @@ -0,0 +1,179 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toclient.OverlayModuleClientRequestPacket; +import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectBulkSyncPacket; +import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectClearPacket; +import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectDeletePacket; +import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectSyncPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class OverlayModule implements IModule { + + public final ConcurrentHashMap objects = new ConcurrentHashMap<>(); + public final ConcurrentHashMap objectsToUpdate = new ConcurrentHashMap<>(); + public final SmartGlassesAccess access; + + public boolean autoUpdate = true; + private int idCounter = 0; + + private int screenWidth = 0; + private int screenHeight = 0; + private double guiScale = 1; + + public OverlayModule(SmartGlassesAccess access) { + this.access = access; + } + + @Override + public ResourceLocation getName() { + return AdvancedPeripherals.getRL("glasses"); + } + + @Override + public IModuleFunctions getFunctions(SmartGlassesAccess smartGlassesAccess) { + return new OverlayGlassesFunctions(this); + } + + @Override + public void tick(@NotNull SmartGlassesAccess smartGlassesAccess) { + + Entity entity = smartGlassesAccess.getEntity(); + if (entity instanceof ServerPlayer player && entity.getLevel().getGameTime() % 2 == 0) { + APNetworking.sendTo(new OverlayModuleClientRequestPacket(), player); + } + } + + public void setScreenSizes(int screenWidth, int screenHeight, double guiScale) { + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + this.guiScale = guiScale; + } + + public int getScreenWidth() { + return screenWidth; + } + + public int getScreenHeight() { + return screenHeight; + } + + public double getGuiScale() { + return guiScale; + } + + public SmartGlassesAccess getAccess() { + return access; + } + + public Map getObjects() { + return objects; + } + + /** + * Adds an object to the module. If the object already exists, it will return the object and stop proceeding + * + * @param object The object which should be added + * @return A pair of the object and a boolean. The boolean is true if the object was added successfully and false if not. + * The object is the object which was added or the object which already exists(When not successful). + */ + public RenderableObject addObject(RenderableObject object) { + int id = idCounter++; + object.setId(id); + if (autoUpdate) { + APNetworking.sendTo(new RenderableObjectSyncPacket(object), (ServerPlayer) access.getEntity()); + objects.put(id, object); + } else { + objectsToUpdate.put(id, object); + } + return object; + } + + /** + * Removes an object from the module if it exists and updates the client. + * + * @param id the object id + * @return true if the object existed and was removed, false if the object was not in the collection + */ + public boolean removeObject(int id) { + RenderableObject removed = objects.remove(id); + + if (removed != null) + APNetworking.sendTo(new RenderableObjectDeletePacket(id), (ServerPlayer) access.getEntity()); + + return removed != null; + } + + /** + * Removes all objects from the module + * + * @return the amount of objects cleared + */ + public int clear() { + int size = objects.size(); + objects.clear(); + idCounter = 0; + objectsToUpdate.clear(); + APNetworking.sendTo(new RenderableObjectClearPacket(), (ServerPlayer) access.getEntity()); + return size; + } + + /** + * Just sends a sync package to the client, this method should only be called from the setter lua functions from our objects + * + * @param object the object to sync to the player + */ + public void update(RenderableObject object) { + if (autoUpdate) { + APNetworking.sendTo(new RenderableObjectSyncPacket(object), (ServerPlayer) access.getEntity()); + return; + } + + objectsToUpdate.put(object.getId(), object); + } + + + public int bulkUpdate() { + int size = objectsToUpdate.size(); + int packetCount = (int) Math.ceil((double) size / 15000); + + // In some cases, if the user creates a lot of objects above 15k, the packet payload can be too big. + // We split up the packets for every 15k objects to prevent the payload limit from mc + for (int i = 0; i < packetCount; i++) { + List packetObjects = new ArrayList<>(); + int count = 0; + + for (RenderableObject object : objectsToUpdate.values()) { + packetObjects.add(object); + objects.put(object.getId(), object); + objectsToUpdate.remove(object.getId()); + count++; + + if (count >= 15000) { + break; // Ensure we don't exceed the packet size limit + } + } + + APNetworking.sendTo(new RenderableObjectBulkSyncPacket(packetObjects), + (ServerPlayer) access.getEntity() + ); + } + + return size; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayObject.java new file mode 100644 index 000000000..ec4be1bdb --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayObject.java @@ -0,0 +1,199 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.BooleanProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.PropertyType; +import de.srendi.advancedperipherals.common.util.StringUtil; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.logging.log4j.Level; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +public abstract class OverlayObject { + + @BooleanProperty + private boolean enabled = true; + + private int id; + private OverlayModule module; + private UUID player; + + public OverlayObject(OverlayModule module, IArguments arguments) { + this.module = module; + } + + /** + * For clientside initialization + */ + public OverlayObject(UUID player) { + this.player = player; + } + + public void setId(int id) { + this.id = id; + } + + @LuaFunction + public int getId() { + return id; + } + + public OverlayModule getModule() { + return module; + } + + public UUID getPlayer() { + return player; + } + + @LuaFunction + public final void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @LuaFunction + public final boolean isEnabled() { + return enabled; + } + + /** + * Maps properties from the provided arguments to the fields of this class. + *

+ * This method uses Java Reflection to map properties from IArguments to the fields of the classes. + * It only maps properties that have the annotation {@link ObjectProperty}. If a field does not have this annotation, + * a warning message is logged and the method returns. + *

+ * If a property is valid, its value is cast to the field type and set as the new value of the field. + * If a property is not valid, a warning message is logged and the method returns. + *

+ * If an error occurs during the mapping of properties, an exception message is logged and a LuaException is thrown. + * + * @param arguments the IArguments containing properties to be mapped + * @throws LuaException if an error occurs during the mapping of properties + * @see IArguments + * @see ObjectProperty + * @see PropertyType + */ + public void reflectivelyMapProperties(IArguments arguments) throws LuaException { + if (arguments.optTable(0).isEmpty()) + return; + + try { + Map properties = arguments.optTable(0).get().entrySet().stream() + .filter(entry -> entry.getKey() instanceof String) + .collect(Collectors.toMap(entry -> (String) entry.getKey(), Map.Entry::getValue)); + + Field[] allFields = FieldUtils.getAllFields(this.getClass()); + + for (Field field : allFields) { + if (properties.containsKey(field.getName())) { + var value = properties.get(field.getName()); + + Annotation[] fieldProperties = field.getAnnotations(); + ObjectProperty objectProperty = null; + Annotation propertyAnnotation = null; + + for (Annotation annotation : fieldProperties) { + objectProperty = annotation.annotationType().getAnnotation(ObjectProperty.class); + if (objectProperty != null) { + propertyAnnotation = annotation; + break; + } + } + + if (objectProperty == null) { + AdvancedPeripherals.debug("The field " + field.getName() + " has no ObjectProperty annotation and can't be changed.", Level.WARN); + return; + } + + PropertyType propertyType = PropertyType.of(objectProperty); + if (propertyType != null) { + value = castValueToFieldType(field, value); + if (propertyType.checkIsValid(value)) { + propertyType.init(propertyAnnotation); + value = propertyType.mapValue(value); + + // Make the field accessible + field.setAccessible(true); + + // Set the value of the field + field.set(this, castValueToFieldType(field, value)); + + } else { + AdvancedPeripherals.debug("The value " + value + " is not valid for the field " + field.getName() + ".", Level.WARN); + return; + } + } + } + } + } catch (LuaException | IllegalAccessException exception) { + AdvancedPeripherals.exception("An error occurred while mapping properties.", exception); + throw new LuaException("An error occurred while mapping properties."); + } + } + + /** + * Casts the given value to the type of the provided field. + * Can be overwritten if the desired casting is not supported. + * + * @param field the field object representing the type to cast to + * @param value the value to be casted + * @return the casted value + */ + public Object castValueToFieldType(Field field, Object value) { + Class fieldType = field.getType(); + + if (fieldType.isAssignableFrom(value.getClass())) { + return value; + } else if (fieldType.equals(Integer.TYPE)) { + return Double.valueOf(value.toString()).intValue(); + } else if (fieldType.equals(Double.TYPE)) { + return Double.valueOf(value.toString()); + } else if (fieldType.equals(Boolean.TYPE)) { + return Boolean.valueOf(value.toString()); + } else if (fieldType.equals(Long.TYPE)) { + return Long.valueOf(StringUtil.removeFloatingPoints(value.toString())); + } else if (fieldType.equals(Short.TYPE)) { + return Short.valueOf(StringUtil.removeFloatingPoints(value.toString())); + } else if (fieldType.equals(Byte.TYPE)) { + return Byte.valueOf(StringUtil.removeFloatingPoints(value.toString())); + } else if (fieldType.equals(Float.TYPE)) { + return Float.valueOf(value.toString()); + } else { + AdvancedPeripherals.debug("The field type " + fieldType.getName() + " is not supported for the value " + value + ".", Level.WARN); + } + return value; + } + + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(id); + Entity entity = module.getAccess().getEntity(); + if(entity instanceof Player player) { + buffer.writeBoolean(true); + buffer.writeUUID(player.getUUID()); + } else { + // Should theoretically never happen. But better safe than sorry + buffer.writeBoolean(false); + } + } + + @Override + public String toString() { + return "OverlayObject{" + + "enabled=" + enabled + + ", module=" + module + + ", player=" + player + + '}'; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/RenderableObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/RenderableObject.java new file mode 100644 index 000000000..ff92bbd70 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/RenderableObject.java @@ -0,0 +1,257 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FixedPointNumberProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FloatingNumberProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; +import java.util.function.Supplier; + +// TODO: generate setters/getters lua functions out of our FloatingNumberProperty fields +public class RenderableObject extends OverlayObject { + + @FloatingNumberProperty(min = 0, max = 1) + public float opacity = 1; + + @FixedPointNumberProperty(min = 0, max = Integer.MAX_VALUE) + public int color = 0xFFFFFF; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float x = 0; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float y = 0; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float z = 0; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float maxX = 0; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float maxY = 0; + + @FloatingNumberProperty(min = -32767, max = 32767) + public float maxZ = 0; + + @FloatingNumberProperty(min = 0, max = 360) + public float rotX = 0f; + + @FloatingNumberProperty(min = 0, max = 360) + public float rotY = 0f; + + @FloatingNumberProperty(min = 0, max = 360) + public float rotZ = 0f; + + public RenderableObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public RenderableObject(UUID player) { + super(player); + } + + @LuaFunction + public final float getOpacity() { + return opacity; + } + + @LuaFunction + public final void setOpacity(double opacity) { + this.opacity = (float) opacity; + getModule().update(this); + } + + @LuaFunction + public final int getColor() { + return color; + } + + @LuaFunction + public final void setColor(int color) { + this.color = color; + getModule().update(this); + } + + @LuaFunction + public final void setMaxX(double maxX) { + this.maxX = (float) maxX; + getModule().update(this); + } + + @LuaFunction + public final double getMaxX() { + return maxX; + } + + @LuaFunction + public final void setMaxY(double maxY) { + this.maxY = (float) maxY; + getModule().update(this); + } + + @LuaFunction + public final double getMaxY() { + return maxY; + } + + @LuaFunction + public final void setMaxZ(double maxZ) { + this.maxZ = (float) maxZ; + getModule().update(this); + } + + @LuaFunction + public final double getMaxZ() { + return maxZ; + } + + @LuaFunction + public final void setX(double x) { + this.x = (float) x; + getModule().update(this); + } + + @LuaFunction + public final double getX() { + return x; + } + + @LuaFunction + public final void setY(double y) { + this.y = (float) y; + getModule().update(this); + } + + @LuaFunction + public final double getY() { + return y; + } + + @LuaFunction + public final void setZ(double z) { + this.z = (float) z; + getModule().update(this); + } + + @LuaFunction + public final float getZ() { + return z; + } + + @LuaFunction + public final void setRotX(double xRot) { + this.rotX = (float) xRot; + getModule().update(this); + } + + @LuaFunction + public final double getRotX() { + return rotX; + } + + @LuaFunction + public final void setRotY(double yRot) { + this.rotY = (float) yRot; + getModule().update(this); + } + + @LuaFunction + public final double getRotY() { + return rotY; + } + + @LuaFunction + public final void setRotZ(double zRot) { + this.rotZ = (float) zRot; + getModule().update(this); + } + + @LuaFunction + public final double getRotZ() { + return rotZ; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + super.encode(buffer); + buffer.writeInt(color); + buffer.writeFloat(opacity); + + buffer.writeFloat(x); + buffer.writeFloat(y); + buffer.writeFloat(z); + buffer.writeFloat(maxX); + buffer.writeFloat(maxY); + buffer.writeFloat(maxZ); + buffer.writeFloat(rotX); + buffer.writeFloat(rotY); + buffer.writeFloat(rotZ); + } + + protected static Optional baseDecode(FriendlyByteBuf buffer, Function constructor) { + int objectId = buffer.readInt(); + boolean hasValidUUID = buffer.readBoolean(); + if (!hasValidUUID) { + AdvancedPeripherals.exception("Tried to decode a buffer for an OverlayObject but without a valid player as target.", new IllegalArgumentException()); + return Optional.empty(); + } + UUID player = buffer.readUUID(); + int color = buffer.readInt(); + float opacity = buffer.readFloat(); + + float x = buffer.readFloat(); + float y = buffer.readFloat(); + float z = buffer.readFloat(); + float maxX = buffer.readFloat(); + float maxY = buffer.readFloat(); + float maxZ = buffer.readFloat(); + float rotX = buffer.readFloat(); + float rotY = buffer.readFloat(); + float rotZ = buffer.readFloat(); + + T clientObject = constructor.apply(player); + clientObject.setId(objectId); + clientObject.color = color; + clientObject.opacity = opacity; + clientObject.x = x; + clientObject.y = y; + clientObject.z = z; + clientObject.maxX = maxX; + clientObject.maxY = maxY; + clientObject.maxZ = maxZ; + clientObject.rotX = rotX; + clientObject.rotY = rotY; + clientObject.rotZ = rotZ; + + return Optional.of(clientObject); + } + + public IObjectRenderer getRenderObject() { + return null; + } + + @Override + public String toString() { + return "RenderableObject{" + + "opacity=" + opacity + + ", color=" + color + + ", x=" + x + + ", y=" + y + + ", z=" + z + + ", sizeX=" + maxX + + ", sizeY=" + maxY + + ", sizeZ=" + maxZ + + '}'; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BlockObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BlockObject.java new file mode 100644 index 000000000..1f83c4c01 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BlockObject.java @@ -0,0 +1,75 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.threedim.BlockRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.StringProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class BlockObject extends ThreeDimensionalObject { + public static final int TYPE_ID = 5; + + private final IObjectRenderer renderer = new BlockRenderer(); + + @StringProperty + public String block = "minecraft:air"; + + public BlockObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public BlockObject(UUID player) { + super(player); + } + + @LuaFunction + public final void setBlock(String block) { + this.block = block; + getModule().update(this); + } + + @LuaFunction + public final String getBlock() { + return block; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeUtf(block); + } + + public static BlockObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, BlockObject::new); + if (optionalObject.isEmpty()) + return null; + + boolean disableDepthTest = buffer.readBoolean(); + boolean disableCulling = buffer.readBoolean(); + + String block = buffer.readUtf(); + + BlockObject clientObject = optionalObject.get(); + clientObject.disableDepthTest = disableDepthTest; + clientObject.disableCulling = disableCulling; + clientObject.block = block; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BoxObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BoxObject.java new file mode 100644 index 000000000..2743b57b2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/BoxObject.java @@ -0,0 +1,55 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.threedim.BoxRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class BoxObject extends ThreeDimensionalObject { + public static final int TYPE_ID = 4; + + private final IObjectRenderer renderer = new BoxRenderer(); + + public BoxObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public BoxObject(UUID player) { + super(player); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + } + + public static BoxObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, BoxObject::new); + if (optionalObject.isEmpty()) + return null; + + boolean disableDepthTest = buffer.readBoolean(); + boolean disableCulling = buffer.readBoolean();; + + BoxObject clientObject = optionalObject.get(); + clientObject.disableDepthTest = disableDepthTest; + clientObject.disableCulling = disableCulling; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/SphereObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/SphereObject.java new file mode 100644 index 000000000..6e93a6014 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/SphereObject.java @@ -0,0 +1,110 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.threedim.SphereRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FixedPointNumberProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FloatingNumberProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class SphereObject extends ThreeDimensionalObject { + public static final int TYPE_ID = 6; + + private final IObjectRenderer renderer = new SphereRenderer(); + + @FixedPointNumberProperty(min = 1, max = 1024) + public int sectors = 16; + + @FixedPointNumberProperty(min = 1, max = 1024) + public int stacks = 16; + + @FloatingNumberProperty(min = 0.001f, max = 128) + public float radius = 1; + + public SphereObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public SphereObject(UUID player) { + super(player); + } + + @LuaFunction + public final void setRadius(float radius) { + this.radius = radius; + getModule().update(this); + } + + @LuaFunction + public final float getRadius() { + return radius; + } + + @LuaFunction + public final void setSectors(int sectors) { + this.sectors = sectors; + getModule().update(this); + } + + @LuaFunction + public final int getSectors() { + return sectors; + } + + @LuaFunction + public final void setStacks(int stacks) { + this.stacks = stacks; + getModule().update(this); + } + + @LuaFunction + public final int getStacks() { + return stacks; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeInt(sectors); + buffer.writeInt(stacks); + buffer.writeFloat(radius); + } + + public static SphereObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, SphereObject::new); + if (optionalObject.isEmpty()) + return null; + + boolean disableDepthTest = buffer.readBoolean(); + boolean disableCulling = buffer.readBoolean(); + + int sectors = buffer.readInt(); + int stacks = buffer.readInt(); + float radius = buffer.readFloat(); + + SphereObject clientObject = optionalObject.get(); + clientObject.disableDepthTest = disableDepthTest; + clientObject.disableCulling = disableCulling; + clientObject.sectors = sectors; + clientObject.stacks = stacks; + clientObject.radius = radius; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/ThreeDimensionalObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/ThreeDimensionalObject.java new file mode 100644 index 000000000..71114bf45 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/ThreeDimensionalObject.java @@ -0,0 +1,60 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.BooleanProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FloatingNumberProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.UUID; + +public abstract class ThreeDimensionalObject extends RenderableObject { + + @BooleanProperty + public boolean disableDepthTest = false; + + @BooleanProperty + public boolean disableCulling = false; + + public ThreeDimensionalObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + } + + public ThreeDimensionalObject(UUID player) { + super(player); + } + + @LuaFunction + public final void setDepthTest(boolean depthTest) { + disableDepthTest = depthTest; + getModule().update(this); + } + + @LuaFunction + public final boolean getDepthTest() { + return disableDepthTest; + } + + @LuaFunction + public final void setCulling(boolean culling) { + disableCulling = culling; + getModule().update(this); + } + + @LuaFunction + public final boolean getCulling() { + return disableCulling; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + super.encode(buffer); + + buffer.writeBoolean(disableDepthTest); + buffer.writeBoolean(disableCulling); + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/TorusObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/TorusObject.java new file mode 100644 index 000000000..0bf411ab3 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/three_dim/TorusObject.java @@ -0,0 +1,127 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.three_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.threedim.TorusRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim.CircleObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FixedPointNumberProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FloatingNumberProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class TorusObject extends ThreeDimensionalObject { + public static final int TYPE_ID = 7; + + private final IObjectRenderer renderer = new TorusRenderer(); + + @FixedPointNumberProperty(min = 1, max = 1024) + public int sides = 32; + + @FixedPointNumberProperty(min = 1, max = 1024) + public int rings = 16; + + @FloatingNumberProperty(min = 0.001f, max = 128) + public float minorRadius = 0.1f; + + @FloatingNumberProperty(min = 0.001f, max = 128) + public float majorRadius = 0.5f; + + public TorusObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public TorusObject(UUID player) { + super(player); + } + + @LuaFunction + public final void setMinorRadius(float radius) { + this.minorRadius = radius; + getModule().update(this); + } + + @LuaFunction + public final float getMinorRadius() { + return minorRadius; + } + + @LuaFunction + public final void setMajorRadius(float radius) { + this.majorRadius = radius; + getModule().update(this); + } + + @LuaFunction + public final float getMajorRadius() { + return majorRadius; + } + + @LuaFunction + public final void setSides(int sides) { + this.sides = sides; + getModule().update(this); + } + + @LuaFunction + public final int getSides() { + return sides; + } + + @LuaFunction + public final void setRings(int rings) { + this.rings = rings; + getModule().update(this); + } + + @LuaFunction + public final int getRings() { + return rings; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeInt(sides); + buffer.writeInt(rings); + buffer.writeFloat(minorRadius); + buffer.writeFloat(majorRadius); + } + + public static TorusObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, TorusObject::new); + if (optionalObject.isEmpty()) + return null; + + boolean disableDepthTest = buffer.readBoolean(); + boolean disableCulling = buffer.readBoolean(); + + int sectors = buffer.readInt(); + int stacks = buffer.readInt(); + float minorRadius = buffer.readFloat(); + float majorRadius = buffer.readFloat(); + + TorusObject clientObject = optionalObject.get(); + clientObject.disableDepthTest = disableDepthTest; + clientObject.disableCulling = disableCulling; + clientObject.sides = sectors; + clientObject.rings = stacks; + clientObject.minorRadius = minorRadius; + clientObject.majorRadius = majorRadius; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/CircleObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/CircleObject.java new file mode 100644 index 000000000..6cabbd143 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/CircleObject.java @@ -0,0 +1,152 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.CircleRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.BooleanProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FixedPointNumberProperty; +import net.minecraft.network.FriendlyByteBuf; +import owmii.powah.lib.client.util.Render; + +import java.util.Optional; +import java.util.UUID; + +public class CircleObject extends RenderableObject { + public static final int TYPE_ID = 1; + + private final IObjectRenderer renderer = new CircleRenderer(); + + @FixedPointNumberProperty(min = -32767, max = 32767) + public int radius = 0; + + @BooleanProperty + public boolean filled = true; + + @BooleanProperty + public boolean pixelated = false; + + @FixedPointNumberProperty(min = 0, max = 32767) + public int borderWidth = 4; + + @FixedPointNumberProperty(min = 0, max = 100) + public int segments = 25; + + public CircleObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public CircleObject(UUID player) { + super(player); + } + + @LuaFunction + public int getRadius() { + return radius; + } + + @LuaFunction + public void setRadius(int radius) { + this.radius = radius; + getModule().update(this); + } + + @LuaFunction + public boolean isFilled() { + return filled; + } + + @LuaFunction + public void setFilled(boolean filled) { + this.filled = filled; + getModule().update(this); + } + + @LuaFunction + public boolean isPixelated() { + return pixelated; + } + + @LuaFunction + public void setPixelated(boolean pixelated) { + this.pixelated = pixelated; + getModule().update(this); + } + + @LuaFunction + public int getBorderWidth() { + return borderWidth; + } + + @LuaFunction + public void setBorderWidth(int borderWidth) { + this.borderWidth = borderWidth; + getModule().update(this); + } + + @LuaFunction + public int getSegments() { + return segments; + } + + @LuaFunction + public void setSegments(int segments) { + this.segments = segments; + getModule().update(this); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeInt(radius); + buffer.writeBoolean(filled); + buffer.writeBoolean(pixelated); + buffer.writeInt(borderWidth); + buffer.writeInt(segments); + } + + public static CircleObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, CircleObject::new); + if (optionalObject.isEmpty()) + return null; + + int radius = buffer.readInt(); + boolean filled = buffer.readBoolean(); + boolean pixelated = buffer.readBoolean(); + int borderWidth = buffer.readInt(); + int segments = buffer.readInt(); + + CircleObject clientObject = optionalObject.get(); + clientObject.radius = radius; + clientObject.filled = filled; + clientObject.pixelated = pixelated; + clientObject.borderWidth = borderWidth; + clientObject.segments = segments; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } + + @Override + public String toString() { + return "Circle{" + + "radius=" + radius + + ", opacity=" + opacity + + ", color=" + color + + ", x=" + x + + ", y=" + y + + ", maxX=" + maxX + + ", maxY=" + maxY + + '}'; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/ItemObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/ItemObject.java new file mode 100644 index 000000000..0c3a9ace4 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/ItemObject.java @@ -0,0 +1,78 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.ItemRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.StringProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class ItemObject extends RenderableObject { + public static final int TYPE_ID = 3; + + private final IObjectRenderer renderer = new ItemRenderer(); + + @StringProperty + public String item = "minecraft:air"; + + public ItemObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public ItemObject(UUID player) { + super(player); + } + + public void setItem(String item) { + this.item = item; + } + + public String getItem() { + return item; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeUtf(item); + } + + public static ItemObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, ItemObject::new); + if (optionalObject.isEmpty()) + return null; + + String item = buffer.readUtf(); + + ItemObject clientObject = optionalObject.get(); + clientObject.item = item; + + return clientObject; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } + + @Override + public String toString() { + return "ItemObject{" + + "item='" + item + '\'' + + ", opacity=" + opacity + + ", color=" + color + + ", x=" + x + + ", y=" + y + + ", maxX=" + maxX + + ", maxY=" + maxY + + '}'; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/LineObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/LineObject.java new file mode 100644 index 000000000..8589c8343 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/LineObject.java @@ -0,0 +1,97 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.LineRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.BooleanProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FixedPointNumberProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +/** + * Just a line + */ +public class LineObject extends RenderableObject { + public static final int TYPE_ID = 8; + + @BooleanProperty + public boolean pixelated = false; + + @FixedPointNumberProperty(min = 0, max = 32767) + public int pixelSize = 4; + + private final IObjectRenderer renderer = new LineRenderer(); + + public LineObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + /** + * constructor for the client side initialization + * + * @param player the target player + */ + public LineObject(UUID player) { + super(player); + } + + @LuaFunction + public void setPixelated(boolean pixelated) { + this.pixelated = pixelated; + getModule().update(this); + } + + @LuaFunction + public boolean isPixelated() { + return pixelated; + } + + @LuaFunction + public void setPixelSize(int pixelSize) { + this.pixelSize = pixelSize; + getModule().update(this); + } + + @LuaFunction + public int getPixelSize() { + return pixelSize; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeBoolean(pixelated); + buffer.writeInt(pixelSize); + } + + public static LineObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, LineObject::new); + if (optionalObject.isEmpty()) + return null; + + boolean pixelated = buffer.readBoolean(); + int pixelSize = buffer.readInt(); + + LineObject clientObject = optionalObject.get(); + + clientObject.pixelated = pixelated; + clientObject.pixelSize = pixelSize; + + return clientObject; + + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/RectangleObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/RectangleObject.java new file mode 100644 index 000000000..cd3af074f --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/RectangleObject.java @@ -0,0 +1,53 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.RectangleRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import net.minecraft.network.FriendlyByteBuf; +import org.w3c.dom.css.Rect; + +import java.util.Optional; +import java.util.UUID; + +/** + * Just a rectangle + */ +public class RectangleObject extends RenderableObject { + public static final int TYPE_ID = 0; + + private final IObjectRenderer renderer = new RectangleRenderer(); + + public RectangleObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + /** + * constructor for the client side initialization + * + * @param player the target player + */ + public RectangleObject(UUID player) { + super(player); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + } + + public static RectangleObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, RectangleObject::new); + return optionalObject.orElse(null); + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/TextObject.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/TextObject.java new file mode 100644 index 000000000..72da53f55 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/objects/two_dim/TextObject.java @@ -0,0 +1,124 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.two_dim; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.client.smartglasses.objects.IObjectRenderer; +import de.srendi.advancedperipherals.client.smartglasses.objects.twodim.TextRenderer; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.OverlayModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.objects.RenderableObject; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.BooleanProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.FloatingNumberProperty; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes.StringProperty; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.Optional; +import java.util.UUID; + +public class TextObject extends RenderableObject { + public static final int TYPE_ID = 2; + + private final IObjectRenderer renderer = new TextRenderer(); + + @StringProperty + public String content = ""; + + @FloatingNumberProperty(min = 0, max = 128) + public float fontSize = 1; + + @BooleanProperty + public boolean shadow = false; + + @BooleanProperty + public boolean center = false; + + public TextObject(OverlayModule module, IArguments arguments) throws LuaException { + super(module, arguments); + reflectivelyMapProperties(arguments); + } + + public TextObject(UUID player) { + super(player); + } + + @LuaFunction + public final void setContent(String content) { + this.content = content; + getModule().update(this); + } + + @LuaFunction + public final String getContent() { + return content; + } + + // For any reason, cc does not support float, only double. So we need to cast it here + @LuaFunction + public void setFontSize(double fontSize) { + this.fontSize = (float) fontSize; + getModule().update(this); + } + + @LuaFunction + public double getFontSize() { + return fontSize; + } + + @LuaFunction + public void setShadow(boolean shadow) { + this.shadow = shadow; + getModule().update(this); + } + + @LuaFunction + public boolean isShadow() { + return shadow; + } + + @LuaFunction + public void setCenter(boolean center) { + this.center = center; + getModule().update(this); + } + + @LuaFunction + public boolean isCenter() { + return center; + } + + @Override + public IObjectRenderer getRenderObject() { + return renderer; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(TYPE_ID); + super.encode(buffer); + buffer.writeUtf(content); + buffer.writeFloat(fontSize); + buffer.writeBoolean(shadow); + buffer.writeBoolean(center); + } + + public static TextObject decode(FriendlyByteBuf buffer) { + Optional optionalObject = RenderableObject.baseDecode(buffer, TextObject::new); + if (optionalObject.isEmpty()) + return null; + + String content = buffer.readUtf(); + float fontSize = buffer.readFloat(); + boolean shadow = buffer.readBoolean(); + boolean center = buffer.readBoolean(); + + TextObject clientObject = optionalObject.get(); + clientObject.content = content; + clientObject.fontSize = fontSize; + clientObject.shadow = shadow; + clientObject.center = center; + + return clientObject; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanProperty.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanProperty.java new file mode 100644 index 000000000..120461133 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanProperty.java @@ -0,0 +1,15 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@ObjectProperty(type = BooleanType.class) +public @interface BooleanProperty { + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanType.java new file mode 100644 index 000000000..1dfc36e8a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/BooleanType.java @@ -0,0 +1,20 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +public class BooleanType implements PropertyType { + + @Override + public boolean checkIsValid(Object type) { + return type instanceof Boolean; + } + + @Override + public Boolean mapValue(Object type) { + return (Boolean) type; + } + + @Override + public void init(Object property) { + // Nothing to init here, we don't have any filters for booleans + } +} + diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberProperty.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberProperty.java new file mode 100644 index 000000000..f4a05242a --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberProperty.java @@ -0,0 +1,18 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@ObjectProperty(type = FixedPointNumberType.class) +public @interface FixedPointNumberProperty { + + long min() default Long.MIN_VALUE; + long max() default Long.MAX_VALUE; + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberType.java new file mode 100644 index 000000000..2f84192c0 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FixedPointNumberType.java @@ -0,0 +1,31 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +public class FixedPointNumberType implements PropertyType { + + public long min; + public long max; + + @Override + public boolean checkIsValid(Object type) { + return type instanceof Long || type instanceof Integer || type instanceof Short || type instanceof Byte; + } + + @Override + public Number mapValue(Object type) { + if (type instanceof Long) + return Math.min(Math.max((long) type, min), max); + if (type instanceof Integer) + return Math.min(Math.max((int) type, (int) min), (int) max); + if (type instanceof Short) + return Math.min(Math.max((short) type, (short) min), (short) max); + return Math.min(Math.max((byte) type, (byte) min), (byte) max); + } + + @Override + public void init(Object property) { + FixedPointNumberProperty decimalProperty = (FixedPointNumberProperty) property; + min = decimalProperty.min(); + max = decimalProperty.max(); + } +} + diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberProperty.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberProperty.java new file mode 100644 index 000000000..bc7e66f3c --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberProperty.java @@ -0,0 +1,18 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@ObjectProperty(type = FloatingNumberType.class) +public @interface FloatingNumberProperty { + + float min() default Float.MIN_VALUE; + float max() default Float.MAX_VALUE; + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberType.java new file mode 100644 index 000000000..02c769b59 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/FloatingNumberType.java @@ -0,0 +1,25 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +public class FloatingNumberType implements PropertyType { + + public float min; + public float max; + + @Override + public boolean checkIsValid(Object type) { + return type instanceof Float || type instanceof Double; + } + + @Override + public Number mapValue(Object type) { + return Math.min(Math.max((float) type, min), max); + } + + @Override + public void init(Object property) { + FloatingNumberProperty decimalProperty = (FloatingNumberProperty) property; + min = decimalProperty.min(); + max = decimalProperty.max(); + } +} + diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/PropertyType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/PropertyType.java new file mode 100644 index 000000000..bd74b3bed --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/PropertyType.java @@ -0,0 +1,31 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectProperty; + +import java.lang.reflect.InvocationTargetException; + +/** + * This interface represents a property type. It is used to check if a value is valid for the property and to map the value to the correct type. + * + * @param the type of the property value + * @see ObjectProperty + */ +public interface PropertyType { + + boolean checkIsValid(Object type); + + T mapValue(Object type); + + static PropertyType of(ObjectProperty property) { + try { + return property.type().getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException exception) { + AdvancedPeripherals.exception("An error occurred while trying to create the property type", exception); + } + return null; + } + + void init(Object property); + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringProperty.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringProperty.java new file mode 100644 index 000000000..17be93d2b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringProperty.java @@ -0,0 +1,15 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +import de.srendi.advancedperipherals.common.smartglasses.modules.overlay.ObjectProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@ObjectProperty(type = StringType.class) +public @interface StringProperty { + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringType.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringType.java new file mode 100644 index 000000000..05f67a1f2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/propertytypes/StringType.java @@ -0,0 +1,20 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.overlay.propertytypes; + +public class StringType implements PropertyType { + + @Override + public boolean checkIsValid(Object type) { + return type instanceof String; + } + + @Override + public String mapValue(Object type) { + return (String) type; + } + + @Override + public void init(Object property) { + // Nothing to init here, we don't have any filters for strings + } +} + diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/BasicCraftJob.java b/src/main/java/de/srendi/advancedperipherals/common/util/BasicCraftJob.java new file mode 100644 index 000000000..227bdcffa --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/BasicCraftJob.java @@ -0,0 +1,206 @@ +package de.srendi.advancedperipherals.common.util; + +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.IComputerAccess; +import de.srendi.advancedperipherals.common.util.StatusConstants; +import net.minecraft.world.level.Level; + +import java.util.concurrent.atomic.AtomicLong; + +public abstract class BasicCraftJob { + + protected static final String EVENT = "_crafting"; + private static final int JOB_DONE_PURGE_TIME = 5 * 60 * 1000; + + public static final AtomicLong ID_SEQ = new AtomicLong(); + + protected final long id = ID_SEQ.incrementAndGet(); + protected final IComputerAccess computer; + protected final String eventName; + protected final long amount; + protected final Level world; + + protected boolean startedCrafting = false; + protected boolean startedCalculation = false; + protected boolean calculationNotSuccessful = false; + protected boolean errorOccurred = false; + protected boolean isJobDone = false; + protected long jobDoneTime = 0; + protected boolean isJobCanceled = false; + protected String debugMessage = null; + + public BasicCraftJob(IComputerAccess computer, String eventName, Level world, long amount) { + this.computer = computer; + this.eventName = eventName; + this.world = world; + this.amount = amount; + } + + @LuaFunction + public final long getId() { + return id; + } + + protected abstract boolean isJobDone(); + + @LuaFunction + public final boolean isDone() { + return isJobDone(); + } + + protected abstract boolean isJobCanceled(); + + @LuaFunction + public final boolean isCanceled() { + return isJobCanceled(); + } + + @LuaFunction + public final boolean isCraftingStarted() { + return startedCrafting; + } + + @LuaFunction + public final boolean isCalculationStarted() { + return startedCalculation; + } + + @LuaFunction + public final boolean isCalculationNotSuccessful() { + return calculationNotSuccessful; + } + + @LuaFunction + public final boolean hasErrorOccurred() { + return errorOccurred; + } + + @LuaFunction + public final String getDebugMessage() { + return debugMessage; + } + + @LuaFunction(value = "getRequestedItem") + public final Object getRequestedItemLua() { + return getParsedRequestedItem(); + } + + @LuaFunction(value = "getElapsedTime") + public final long getElapsedTimeLua() { + return getElapsedTime(); + } + + @LuaFunction(value = "getTotalItems") + public final long getTotalItemsLua() { + return getTotalItems(); + } + + @LuaFunction(value = "getItemProgress") + public final long getItemProgressLua() { + return getItemProgress(); + } + + @LuaFunction(value = "getEmittedItems") + public final Object getEmittedItemsLua() { + return getEmittedItems(); + } + + @LuaFunction(value = "getUsedItems") + public final Object getUsedItemsLua() { + return getUsedItems(); + } + + @LuaFunction(value = "getMissingItems") + public final Object getMissingItemsLua() { + return getMissingItems(); + } + + @LuaFunction(value = "hasMultiplePaths") + public final boolean hasMultiplePathsLua() { + return hasMultiplePaths(); + } + + @LuaFunction(value = "getFinalOutput") + public final Object getFinalOutputLua() { + return getFinalOutput(); + } + + @LuaFunction(value = "cancel") + public final boolean cancelLua() { + return cancel(); + } + + public abstract Object getParsedRequestedItem(); + + public abstract long getElapsedTime(); + + public abstract long getTotalItems(); + + public abstract long getItemProgress(); + + public abstract Object getEmittedItems(); + + public abstract Object getUsedItems(); + + public abstract Object getMissingItems(); + + public abstract boolean hasMultiplePaths(); + + public abstract Object getFinalOutput(); + + public abstract boolean cancel(); + + public Level getWorld() { + return world; + } + + public long getAmount() { + return amount; + } + + public boolean canBePurged() { + return calculationNotSuccessful || ((isJobDone || isJobCanceled) && jobDoneTime + JOB_DONE_PURGE_TIME < System.currentTimeMillis()); + } + + protected void fireNotConnected() { + fireEvent(true, StatusConstants.NOT_CONNECTED); + } + + public void setStartedCrafting() { + this.startedCrafting = true; + fireEvent(false, StatusConstants.CRAFTING_STARTED); + } + + public void setJobCanceled() { + this.isJobCanceled = true; + this.jobDoneTime = System.currentTimeMillis(); + } + + public void setJobDone() { + this.isJobDone = true; + this.jobDoneTime = System.currentTimeMillis(); + } + + protected void fireEvent(boolean error, StatusConstants message) { + this.computer.queueEvent(eventName + EVENT, error, this.id, message.toString()); + this.debugMessage = message.toString(); + this.errorOccurred = error; + } + + protected void fireEvent(boolean error, String message) { + this.computer.queueEvent(eventName + EVENT, error, this.id, message); + this.debugMessage = message; + this.errorOccurred = error; + } + + public final void tick() { + startCalculation(); + maybeCraft(); + } + + protected abstract void maybeCraft(); + + protected abstract void startCalculation(); + + public abstract void jobStateChanged(); +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java b/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java index 3b338284d..238b16943 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/ChunkManager.java @@ -20,7 +20,11 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; @Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID) public class ChunkManager extends SavedData { @@ -35,6 +39,10 @@ public ChunkManager() { super(); } + public static int getMaxLoadRadius() { + return APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + } + public static @NotNull ChunkManager get(@NotNull ServerLevel level) { return level.getDataStorage().computeIfAbsent(ChunkManager::load, ChunkManager::new, DATA_NAME); } @@ -77,6 +85,10 @@ private static boolean unforceChunk(UUID owner, ServerLevel level, ChunkPos pos) return ForgeChunkManager.forceChunk(level, AdvancedPeripherals.MOD_ID, owner, pos.x, pos.z, false, true); } + public synchronized int getForcedChunksCount() { + return this.forcedChunks.size(); + } + public synchronized boolean addForceChunk(ServerLevel level, UUID owner, ChunkPos pos) { AdvancedPeripherals.debug("Trying to load forced chunk cluster " + pos, Level.WARN); LoadChunkRecord oldRecord = forcedChunks.get(owner); @@ -87,7 +99,7 @@ public synchronized boolean addForceChunk(ServerLevel level, UUID owner, ChunkPo } unforceChunkRecord(owner, oldRecord, oldLevel); } - final int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + final int chunkRadius = getMaxLoadRadius(); forcedChunks.put(owner, new LoadChunkRecord(level.dimension().location().toString(), pos, chunkRadius)); setDirty(); boolean result = true; @@ -150,7 +162,7 @@ public synchronized void init() { initialized = true; AdvancedPeripherals.debug(String.format("Schedule chunk manager init, forcedChunks = %d", forcedChunks.size()), Level.WARN); - final int chunkRadius = APConfig.PERIPHERALS_CONFIG.chunkyTurtleRadius.get(); + final int chunkRadius = getMaxLoadRadius(); final Map levels = getServerLevels(); forcedChunks.forEach((uuid, value) -> { String dimensionName = value.getDimensionName(); diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/CoordUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/CoordUtil.java index 48ff704e0..389264ad0 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/CoordUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/CoordUtil.java @@ -9,6 +9,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,8 +28,8 @@ public class CoordUtil { * * @return If the player is in the {@code range} as well as in the {@code maxRange}, or {@code range} and {@code maxRange} are -1 */ - public static boolean isInRange(@Nullable BlockPos pos, @Nullable Level world, @Nullable Player player, int range, int maxRange) { - // There are rare cases where these are null. For example if a player detector pocket computer runs while not in a player inventory + public static boolean isInRange(@Nullable Vec3 pos, @Nullable Level world, @Nullable Player player, int range, int maxRange) { + // There are rare cases where these can be null. For example if a player detector pocket computer runs while not in a player inventory // Fixes https://github.com/SirEndii/AdvancedPeripherals/issues/356 if (pos == null || world == null || player == null) { return false; @@ -49,7 +50,7 @@ public static boolean isInRange(@Nullable BlockPos pos, @Nullable Level world, @ } // To fix issue #439 - private static boolean isPlayerInBlockRange(@NotNull BlockPos pos, @NotNull Level world, @NotNull Player player, double range) { + private static boolean isPlayerInBlockRange(@NotNull Vec3 pos, @NotNull Level world, @NotNull Player player, double range) { if (range != -1 && player.getLevel() != world) return false; @@ -59,13 +60,12 @@ private static boolean isPlayerInBlockRange(@NotNull BlockPos pos, @NotNull Leve ey = y; y = tmp; } - double bx = (double)(pos.getX() + 0.5), by = (double)(pos.getY() + 0.5), bz = (double)(pos.getZ() + 0.5); - return Math.abs(x - bx) <= range && Math.abs(z - bz) <= range && + return Math.abs(x - pos.x) <= range && Math.abs(z - pos.z) <= range && // check both feet position and eye position, and ensure it will work if player is higher than 2 blocks - ((y <= by && by <= ey) || Math.min(Math.abs(y - by), Math.abs(ey - by)) <= range); + ((y <= pos.y && pos.y <= ey) || Math.min(Math.abs(y - pos.y), Math.abs(ey - pos.y)) <= range); } - public static boolean isInRange(@Nullable BlockPos pos, @Nullable Level world, @Nullable Player player, int x, int y, int z, int maxRange) { + public static boolean isInRange(@Nullable Vec3 pos, @Nullable Level world, @Nullable Player player, int x, int y, int z, int maxRange) { if (pos == null || world == null || player == null) return false; @@ -76,7 +76,7 @@ public static boolean isInRange(@Nullable BlockPos pos, @Nullable Level world, @ return isPlayerInBlockRangeXYZ(pos, world, player, (double) x, (double) y, (double) z, maxRange); } - private static boolean isPlayerInBlockRangeXYZ(@NotNull BlockPos pos, @NotNull Level world, @NotNull Player player, double dx, double dy, double dz, int maxRange) { + private static boolean isPlayerInBlockRangeXYZ(@NotNull Vec3 pos, @NotNull Level world, @NotNull Player player, double dx, double dy, double dz, int maxRange) { if (maxRange != -1 && player.getLevel() != world) return false; @@ -86,40 +86,39 @@ private static boolean isPlayerInBlockRangeXYZ(@NotNull BlockPos pos, @NotNull L ey = y; y = tmp; } - double bx = (double)(pos.getX() + 0.5), by = (double)(pos.getY() + 0.5), bz = (double)(pos.getZ() + 0.5); - return Math.abs(x - bx) <= dx && Math.abs(z - bz) <= dz && - ((y <= by && by <= ey) || Math.min(Math.abs(y - by), Math.abs(ey - by)) <= dy); + return Math.abs(x - pos.x) <= dx && Math.abs(z - pos.z) <= dz && + ((y <= pos.y && pos.y <= ey) || Math.min(Math.abs(y - pos.y), Math.abs(ey - pos.y)) <= dy); } - public static boolean isInRange(@Nullable BlockPos blockPos, @Nullable Player player, @Nullable Level world, @NotNull BlockPos firstPos, @NotNull BlockPos secondPos, int maxRange) { - if (blockPos == null || world == null || player == null) + public static boolean isInRange(@Nullable Vec3 pos, @Nullable Player player, @Nullable Level world, @NotNull BlockPos firstPos, @NotNull BlockPos secondPos, int maxRange) { + if (pos == null || world == null || player == null) return false; - double i = Math.abs(player.getX() - blockPos.getX()); - double j = Math.abs(player.getZ() - blockPos.getZ()); + double x = Math.abs(player.getX() - pos.x); + double y = Math.abs(player.getY() - pos.y); + double z = Math.abs(player.getZ() - pos.z); // Check if the distance of the player is within the max range of the player detector // Use manhattan distance, not euclidean distance to keep same behavior than other `isInRange` functions - if (i + j > (maxRange != -1 ? maxRange : Integer.MAX_VALUE)) + if (maxRange != -1 && x + y + z > maxRange) return false; return world.getNearbyPlayers(TargetingConditions.forNonCombat(), null, new AABB(firstPos, secondPos)).contains(player); } public static Direction getDirection(FrontAndTop orientation, String computerSide) throws LuaException { - if (computerSide == null) { + if (computerSide == null) throw new LuaException("null is not a valid side"); - } computerSide = computerSide.toLowerCase(Locale.ROOT); Direction dir = Direction.byName(computerSide); if (dir != null) return dir; + Direction top = orientation.top(); Direction front = orientation.front(); final ComputerSide side = ComputerSide.valueOfInsensitive(computerSide); - if (side == null) { + if (side == null) throw new LuaException(computerSide + " is not a valid side"); - } if (front.getAxis() == Direction.Axis.Y) { return switch (side) { @@ -140,6 +139,42 @@ public static Direction getDirection(FrontAndTop orientation, String computerSid case LEFT -> front.getClockWise(); }; } + } + public static ComputerSide getComputerSide(FrontAndTop orientation, Direction direction) { + Direction top = orientation.top(); + Direction front = orientation.front(); + + if (direction == front) { + return ComputerSide.FRONT; + } + if (direction == front.getOpposite()) { + return ComputerSide.BACK; + } + if (front.getAxis() == Direction.Axis.Y) { + if (direction == top) { + return ComputerSide.TOP; + } + if (direction == top.getOpposite()) { + return ComputerSide.BOTTOM; + } + if (direction == top.getClockWise()) { + return ComputerSide.RIGHT; + } + if (direction == top.getCounterClockWise()) { + return ComputerSide.LEFT; + } + } + if (direction == front.getClockWise()) { + return ComputerSide.RIGHT; + } + if (direction == front.getCounterClockWise()) { + return ComputerSide.LEFT; + } + if (direction == Direction.UP) { + return ComputerSide.TOP; + } + return ComputerSide.BOTTOM; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/DataStorageUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/DataStorageUtil.java index 0499427cc..52585dbb4 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/DataStorageUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/DataStorageUtil.java @@ -1,14 +1,17 @@ package de.srendi.advancedperipherals.common.util; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; import de.srendi.advancedperipherals.lib.peripherals.IPeripheralTileEntity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import org.jetbrains.annotations.NotNull; public class DataStorageUtil { + private DataStorageUtil() {} public static CompoundTag getDataStorage(@NotNull ITurtleAccess access, @NotNull TurtleSide side) { return access.getUpgradeNBTData(side); @@ -18,8 +21,17 @@ public static CompoundTag getDataStorage(@NotNull IPeripheralTileEntity tileEnti return tileEntity.getPeripheralSettings(); } - public static CompoundTag getDataStorage(@NotNull IPocketAccess pocket) { - return pocket.getUpgradeNBTData(); + public static CompoundTag getDataStorage(@NotNull IPocketAccess pocket, @NotNull IPocketUpgrade upgrade) { + String id = upgrade.getUpgradeID().toString(); + CompoundTag datas = pocket.getUpgradeNBTData(); + Tag tag = datas.get(id); + if (tag instanceof CompoundTag data) { + return data; + } + CompoundTag data = new CompoundTag(); + datas.put(id, data); + pocket.updateUpgradeNBTData(); + return data; } /** diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/EnergyStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/EnergyStorageProxy.java deleted file mode 100644 index 81d7f4a00..000000000 --- a/src/main/java/de/srendi/advancedperipherals/common/util/EnergyStorageProxy.java +++ /dev/null @@ -1,76 +0,0 @@ -package de.srendi.advancedperipherals.common.util; - -import de.srendi.advancedperipherals.common.blocks.blockentities.EnergyDetectorEntity; -import net.minecraftforge.energy.IEnergyStorage; - -import java.util.Optional; - -public class EnergyStorageProxy implements IEnergyStorage { - - private final EnergyDetectorEntity energyDetectorTE; - private int maxTransferRate; - private int transferedInThisTick = 0; - - public EnergyStorageProxy(EnergyDetectorEntity energyDetectorTE, int maxTransferRate) { - this.energyDetectorTE = energyDetectorTE; - this.maxTransferRate = maxTransferRate; - } - - @Override - public boolean canReceive() { - return true; - } - - @Override - public int receiveEnergy(int maxReceive, boolean simulate) { - Optional out = energyDetectorTE.getOutputStorage(); - return out.map(outStorage -> { - int transferred = outStorage.receiveEnergy(Math.min(maxReceive, maxTransferRate), simulate); - if (!simulate) { - transferedInThisTick += transferred; - } - return transferred; - }).orElse(0); - } - - @Override - public int getEnergyStored() { - Optional out = energyDetectorTE.getOutputStorage(); - return out.map(IEnergyStorage::getEnergyStored).orElse(0); - } - - @Override - public int getMaxEnergyStored() { - Optional out = energyDetectorTE.getOutputStorage(); - return out.map(IEnergyStorage::getMaxEnergyStored).orElse(0); - } - - @Override - public boolean canExtract() { - return false; - } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) { - return 0; - } - - public int getMaxTransferRate() { - return maxTransferRate; - } - - public void setMaxTransferRate(int rate) { - maxTransferRate = rate; - } - - /** - * should be called on every tick - */ - public void resetTransferedInThisTick() { - transferedInThisTick = 0; - } - - public int getTransferedInThisTick() { - return transferedInThisTick; - } -} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java b/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java index 415b45b23..2e3a97e00 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java @@ -4,33 +4,37 @@ public enum EnumColor { - BLACK("\u00a70", "Black", "black", "&0"), - DARK_BLUE("\u00a71", "Blue", "blue", "&1"), - DARK_GREEN("\u00a72", "Green", "green", "&2"), - DARK_AQUA("\u00a73", "Cyan", "cyan", "&3"), - DARK_RED("\u00a74", "Dark Red", "dark_red", "&4"), - DARK_PURPLE("\u00a75", "Purple", "purple", "&5"), - GOLD("\u00a76", "Orange", "orange", "&6"), - GRAY("\u00a77", "Light Gray", "light_gray", "&7"), - DARK_GRAY("\u00a78", "Gray", "gray", "&8"), - BLUE("\u00a79", "Light Blue", "light_blue", "&9"), - GREEN("\u00a7a", "Lime", "lime", "&a"), - AQUA("\u00a7b", "Aqua", "aqua", "&b"), - RED("\u00a7c", "Red", "red", "&c"), - LIGHT_PURPLE("\u00a7d", "Magenta", "magenta", "&d"), - YELLOW("\u00a7e", "Yellow", "yellow", "&e"), - WHITE("\u00a7f", "White", "white", "&f"); + BLACK("\u00a70", "Black", "black", "&0", 0, new float[]{0f, 0f, 0f, 1f}), + DARK_BLUE("\u00a71", "Blue", "blue", "&1", 0xFF0000c9, new float[]{0f, 0f, 0.804f, 1f}), + DARK_GREEN("\u00a72", "Green", "green", "&2", 0xFF0c9400, new float[]{0.048f, 0.592f, 0f, 1f}), + DARK_AQUA("\u00a73", "Cyan", "cyan", "&3", 0xFF009494, new float[]{0f, 0.592f, 0.592f, 1f}), + DARK_RED("\u00a74", "Dark Red", "dark_red", "&4", 0xFF940000, new float[]{0.592f, 0f, 0f, 1f}), + DARK_PURPLE("\u00a75", "Purple", "purple", "&5", 0xFF510094, new float[]{0.324f, 0f, 0.592f, 1f}), + GOLD("\u00a76", "Orange", "orange", "&6", 0xFFb59700, new float[]{1f, 0.407f, 0f, 1f}), + GRAY("\u00a77", "Light Gray", "light_gray", "&7", 0xFF616161, new float[]{0.388f, 0.388f, 0.388f, 1f}), + DARK_GRAY("\u00a78", "Gray", "gray", "&8", 0xFF4a4a4a, new float[]{0.296f, 0.296f, 0.296f, 1f}), + BLUE("\u00a79", "Light Blue", "light_blue", "&9", 0xFF1919ff, new float[]{0.098f, 0.098f, 1f, 1f}), + GREEN("\u00a7a", "Lime", "lime", "&a", 0xFF00e02d, new float[]{0f, 0.878f, 0.176f, 1f}), + AQUA("\u00a7b", "Aqua", "aqua", "&b", 0xFF17ffe4, new float[]{0.090f, 1f, 0.894f, 1f}), + RED("\u00a7c", "Red", "red", "&c", 0xFFff1c1c, new float[]{1f, 0.109f, 0.109f, 1f}), + LIGHT_PURPLE("\u00a7d", "Magenta", "magenta", "&d", 0xFF7424ff, new float[]{0.454f, 0.141f, 1f, 1f}), + YELLOW("\u00a7e", "Yellow", "yellow", "&e", 0xFFc8ff00, new float[]{0.784f, 1f, 0f, 1f}), + WHITE("\u00a7f", "White", "white", "&f", 0xFFffffff, new float[]{1f, 1f, 1f, 1f}); private final String code; private final String name; private final String technicalName; private final String alternativeCode; + private final int hex; + private final float[] rgb; - EnumColor(String code, String name, String technicalName, String alternativeCode) { + EnumColor(String code, String name, String technicalName, String alternativeCode, int hex, float[] rgb) { this.code = code; this.name = name; this.technicalName = technicalName; this.alternativeCode = alternativeCode; + this.hex = hex; + this.rgb = rgb; } public static Component buildTextComponent(Component textComponent) { @@ -41,6 +45,10 @@ public static Component buildTextComponent(Component textComponent) { return Component.literal(text); } + public float[] getRgb() { + return rgb; + } + public String getCode() { return code; } @@ -52,4 +60,8 @@ public String getType() { public String getTechnicalName() { return technicalName; } + + public int getHex() { + return hex; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/HitResultUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/HitResultUtil.java new file mode 100644 index 000000000..6112dc4a7 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/HitResultUtil.java @@ -0,0 +1,238 @@ +package de.srendi.advancedperipherals.common.util; + +import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.BlockEntityPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.DistanceDetectorPeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySelector; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Predicate; + +public class HitResultUtil { + + /** + * This method is used to get the hit result of an entity from the start position of a block + * + * @param from the source position like a block + * @param to the target position/max position + * @param level the level + * @param shapeGetter the block collision shape getter + * @return the hit result. {@link BlockHitResult#miss(Vec3, Direction, BlockPos)} if nothing found + */ + @NotNull + public static HitResult getHitResult(Vec3 from, Vec3 to, Level level, ClipContext.ShapeGetter shapeGetter) { + return getHitResult(from, to, level, shapeGetter, null); + } + + /** + * This method is used to get the hit result of an entity from the start position of a block + * + * @param from the source position like a block + * @param to the target position/max position + * @param level the level + * @param shapeGetter the block collision shape getter + * @param source the source Entity/BlockPos that will be ignored, or an {@link IPeripheralOwner} to auto determine the source. + * @return the hit result. {@link BlockHitResult#miss(Vec3, Direction, BlockPos)} if nothing found + */ + @NotNull + public static HitResult getHitResult(Vec3 from, Vec3 to, Level level, ClipContext.ShapeGetter shapeGetter, Object source) { + if (source instanceof IPeripheralOwner owner) { + if (owner instanceof BlockEntityPeripheralOwner || owner instanceof TurtlePeripheralOwner) { + source = owner.getPos(); + } else { + source = owner.getHoldingEntity(); + } + } + EntityHitResult entityResult = getEntityHitResult(from, to, level, source instanceof Entity ? (Entity) source : null, source instanceof Predicate ? (Predicate) source : EntitySelector.NO_SPECTATORS); + BlockHitResult blockResult = getBlockHitResult(from, to, level, shapeGetter, source instanceof BlockPos ? (BlockPos) source : null); + + if (entityResult.getType() == HitResult.Type.MISS) { + if (blockResult.getType() == HitResult.Type.MISS) { + return BlockHitResult.miss(from, blockResult.getDirection(), new BlockPos(to)); + } + return blockResult; + } else if (blockResult.getType() == HitResult.Type.MISS) { + return entityResult; + } + + double blockDistance = from.distanceToSqr(blockResult.getLocation()); + double entityDistance = from.distanceToSqr(entityResult.getLocation()); + + return blockDistance < entityDistance ? blockResult : entityResult; + } + + /** + * This method is used to get the hit result of an entity from the start position of a block + * This could be used to find an entity from the eyes position of another entity but since + * this method uses one AABB made out of the two coordinates, this would also find any entities + * which are not located in the ray you might want. {@link DistanceDetectorPeripheral#getDistance()} + * + * @param from the source position like a block + * @param to the target position/max position + * @param level the world + * @return the entity hit result. An empty HitResult with {@link HitResult.Type#MISS} as type if nothing found + */ + @NotNull + public static EntityHitResult getEntityHitResult(Vec3 from, Vec3 to, Level level) { + return getEntityHitResult(from, to, level, null); + } + + /** + * This method is used to get the hit result of an entity from the start position of a block + * This could be used to find an entity from the eyes position of another entity but since + * this method uses one AABB made out of the two coordinates, this would also find any entities + * which are not located in the ray you might want. {@link DistanceDetectorPeripheral#getDistance()} + * + * @param from the source position like a block + * @param to the target position/max position + * @param level the world + * @param source the source Entity that will be ignored + * @return the entity hit result. An empty HitResult with {@link HitResult.Type#MISS} as type if nothing found + */ + @NotNull + public static EntityHitResult getEntityHitResult(Vec3 from, Vec3 to, Level level, Entity source) { + return getEntityHitResult(from, to, level, source, EntitySelector.NO_SPECTATORS); + } + + /** + * This method is used to get the hit result of an entity from the start position of a block + * This could be used to find an entity from the eyes position of another entity but since + * this method uses one AABB made out of the two coordinates, this would also find any entities + * which are not located in the ray you might want. {@link DistanceDetectorPeripheral#getDistance()} + * + * @param from the source position like a block + * @param to the target position/max position + * @param level the world + * @param source the source Entity that will be ignored + * @param entityFilter the entity filter + * @return the entity hit result. An empty HitResult with {@link HitResult.Type#MISS} as type if nothing found + */ + @NotNull + public static EntityHitResult getEntityHitResult(Vec3 from, Vec3 to, Level level, Entity source, Predicate entityFilter) { + AABB checkingBox = new AABB(to, from); + + List entities = level.getEntities(source, checkingBox, entityFilter); + + Entity nearestEntity = null; + Vec3 hitPos = null; + double nearestDist = 0; + + // Find the nearest entity + for (Entity entity : entities) { + Vec3 pos = entity.getBoundingBox().clip(from, to).orElse(null); + if (pos != null) { + double distance = from.distanceToSqr(pos); + if (nearestEntity == null || distance < nearestDist) { + nearestEntity = entity; + hitPos = pos; + nearestDist = distance; + } + } + } + + return nearestEntity == null ? EmptyEntityHitResult.INSTANCE : new EntityHitResult(nearestEntity, hitPos); + } + + /** + * This method is used to get the hit result of a block from the start position of a block + * + * @param from the source position + * @param to the target position/max position + * @param level the world + * @param shapeGetter the block collision shape getter + * @return the block hit result. {@link BlockHitResult#miss(Vec3, Direction, BlockPos)} if nothing found + */ + @NotNull + public static BlockHitResult getBlockHitResult(Vec3 from, Vec3 to, Level level, ClipContext.ShapeGetter shapeGetter) { + return getBlockHitResult(from, to, level, shapeGetter, null); + } + + /** + * This method is used to get the hit result of a block from the start position of a block + * + * @param from the source position + * @param to the target position/max position + * @param level the world + * @param shapeGetter the block collision shape getter + * @param source the source BlockPos that will be ignored + * @return the block hit result. {@link BlockHitResult#miss(Vec3, Direction, BlockPos)} if nothing found + */ + @NotNull + public static BlockHitResult getBlockHitResult(Vec3 from, Vec3 to, Level level, ClipContext.ShapeGetter shapeGetter, BlockPos source) { + return level.clip(new AdvancedClipContext(from, to, shapeGetter, ClipContext.Fluid.NONE, null, source)); + } + + public static class EmptyEntityHitResult extends EntityHitResult { + public static final EmptyEntityHitResult INSTANCE = new EmptyEntityHitResult(); + + /** + * The super constructor is a NotNull argument but since this result is empty, we'll just return null + */ + private EmptyEntityHitResult() { + super(null, null); + } + + @NotNull + @Override + public Type getType() { + return Type.MISS; + } + } + + /** + * A shape getter which ignores blocks which are not occluding like glass + */ + public static class IgnoreNoOccludedContext implements ClipContext.ShapeGetter { + public static final IgnoreNoOccludedContext INSTANCE = new IgnoreNoOccludedContext(); + + private IgnoreNoOccludedContext() {} + + @NotNull + @Override + public VoxelShape get(BlockState pState, @NotNull BlockGetter pBlock, @NotNull BlockPos pPos, @NotNull CollisionContext pCollisionContext) { + return !pState.canOcclude() ? Shapes.empty() : pState.getCollisionShape(pBlock, pPos, pCollisionContext); + } + } + + /** + * A clip context but with a custom shape getter. Used to define another shape getter for the block like {@link IgnoreNoOccludedContext} + */ + private static class AdvancedClipContext extends ClipContext { + + private final ShapeGetter blockShapeGetter; + private final BlockPos source; + + protected AdvancedClipContext(Vec3 from, Vec3 to, ShapeGetter blockShapeGetter, Fluid fluidShapeGetter, @Nullable Entity entity, BlockPos source) { + super(from, to, Block.COLLIDER, fluidShapeGetter, entity); + this.blockShapeGetter = blockShapeGetter; + this.source = source; + } + + @NotNull + @Override + public VoxelShape getBlockShape(@NotNull BlockState pBlockState, @NotNull BlockGetter pLevel, @NotNull BlockPos pPos) { + if (this.source != null && this.source.equals(pPos)) { + return Shapes.empty(); + } + return blockShapeGetter.get(pBlockState, pLevel, pPos, this.collisionContext); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java b/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java index 5bef952ad..aa9690e88 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java @@ -3,21 +3,40 @@ import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.shared.util.NBTUtil; import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.InventoryManagerPeripheral; +import de.srendi.advancedperipherals.common.util.inventory.FluidUtil; import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.tags.TagKey; import net.minecraft.util.StringRepresentable; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.scores.Team; import net.minecraftforge.common.IForgeShearable; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Quaterniondc; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.primitives.AABBic; +import org.valkyrienskies.core.api.ships.ServerShip; +import org.valkyrienskies.core.api.ships.properties.ShipInertiaData; +import org.valkyrienskies.core.api.ships.properties.ShipTransform; -import java.util.Collections; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,48 +45,144 @@ public class LuaConverter { - public static Map entityToLua(Entity entity) { - Map data = new HashMap<>(); - data.put("id", entity.getId()); - data.put("uuid", entity.getStringUUID()); - data.put("name", entity.getName().getString()); - data.put("tags", entity.getTags()); - data.put("canFreeze", entity.canFreeze()); - data.put("isGlowing", entity.isCurrentlyGlowing()); - data.put("isInWall", entity.isInWall()); - return data; + private static final CompoundTag EMPTY_TAG = new CompoundTag(); + private static final Map, List>> ENTITY_CONVERTERS = new HashMap<>(); + + /** + * registerEntityConverter register a converter for a type of entity. + * If an old converter exists, it will invoke the old one first before invoke the new converter. + * + * @param clazz The entity's class + * @param converter The {@link EntityConverter} + */ + public static void registerEntityConverter(Class clazz, EntityConverter converter) { + ENTITY_CONVERTERS.computeIfAbsent(clazz, (k) -> new ArrayList<>(1)).add(converter); } - public static Map livingEntityToLua(LivingEntity entity) { - Map data = entityToLua(entity); - data.put("health", entity.getHealth()); - data.put("maxHealth", entity.getMaxHealth()); - data.put("lastDamageSource", entity.getLastDamageSource() == null ? null : entity.getLastDamageSource().toString()); - return data; + // register default entity converters + static { + registerEntityConverter(Entity.class, (entity, data, ctx) -> { + data.put("id", entity.getId()); + data.put("uuid", entity.getStringUUID()); + if (entity.hasCustomName()) + data.put("customName", entity.getCustomName().getString()); + EntityType type = entity.getType(); + data.put("displayName", type.getDescription().getString()); + data.put("name", type.builtInRegistryHolder().key().location().toString()); + if (ctx.detailed()) { + data.put("type", type.getDescriptionId()); + data.put("category", type.getCategory().getName()); + data.put("canBurn", entity.fireImmune()); + data.put("canFreeze", entity.canFreeze()); + data.put("tags", entity.getTags()); + data.put("isGlowing", entity.isCurrentlyGlowing()); + data.put("isUnderWater", entity.isUnderWater()); + data.put("isInLava", entity.isInLava()); + data.put("isInWall", entity.isInWall()); + data.put("team", teamToLua(entity.getTeam())); + } + }); + registerEntityConverter(LivingEntity.class, (entity, data, ctx) -> { + data.put("baby", entity.isBaby()); + data.put("health", entity.getHealth()); + data.put("maxHealth", entity.getMaxHealth()); + if (ctx.detailed()) { + data.put("lastDamageSource", entity.getLastDamageSource() == null ? null : entity.getLastDamageSource().toString()); + Map effMap = new HashMap<>(); + entity.getActiveEffectsMap().forEach((key, value) -> { + effMap.put(key.getDescriptionId(), effectToLua(value)); + }); + data.put("effects", effMap); + } + }); + registerEntityConverter(Mob.class, (entity, data, ctx) -> { + data.put("aggressive", entity.isAggressive()); + }); + registerEntityConverter(Animal.class, (entity, data, ctx) -> { + data.put("inLove", entity.isInLove()); + if (ctx.detailed() && !ctx.itemInHand().isEmpty() && entity instanceof IForgeShearable shareable) { + data.put("shareable", shareable.isShearable(ctx.itemInHand(), entity.level, entity.blockPosition())); + } + }); + registerEntityConverter(Player.class, (entity, data, ctx) -> { + data.put("score", entity.getScore()); + data.put("luck", entity.getLuck()); + Inventory inv = entity.getInventory(); + data.put("handSlot", inv.selected); + if (ctx.detailed()) { + Map invMap = new HashMap<>(); + for (int slot = 0; slot < inv.getContainerSize(); slot++) { + ItemStack item = inv.getItem(slot); + if (!item.isEmpty()) { + invMap.put(slot, itemStackToObject(item)); + } + } + data.put("inventory", invMap); + } + }); + } + + @FunctionalInterface + public interface EntityConverter { + void entityToMap(T entity, Map data, Context ctx); + + record Context(boolean detailed, ItemStack itemInHand) {} } - public static Map animalToLua(Animal animal, ItemStack itemInHand) { - Map data = livingEntityToLua(animal); - data.put("baby", animal.isBaby()); - data.put("inLove", animal.isInLove()); - data.put("aggressive", animal.isAggressive()); - if (animal instanceof IForgeShearable shareable && !itemInHand.isEmpty()) { - data.put("shareable", shareable.isShearable(itemInHand, animal.level, animal.blockPosition())); + public static Map completeEntityToLua(Entity entity) { + return completeEntityToLua(entity, false); + } + + public static Map completeEntityToLua(Entity entity, boolean detailed) { + return completeEntityToLua(entity, ItemStack.EMPTY, detailed); + } + + public static Map completeEntityToLua(Entity entity, ItemStack itemInHand) { + return completeEntityToLua(entity, itemInHand, false); + } + + public static Map completeEntityToLua(Entity entity, ItemStack itemInHand, boolean detailed) { + if (entity == null) { + return null; + } + EntityConverter.Context ctx = new EntityConverter.Context(detailed, itemInHand); + Map data = new HashMap<>(); + for (Class entityClass = entity.getClass(); Entity.class.isAssignableFrom(entityClass); entityClass = entityClass.getSuperclass()) { + List> converters = ENTITY_CONVERTERS.get((Class) entityClass); + if (converters != null) { + for (EntityConverter converter : converters) { + ((EntityConverter) converter).entityToMap(entity, data, ctx); + } + } } return data; } - public static Map completeEntityToLua(Entity entity, ItemStack itemInHand) { - if (entity instanceof Animal animal) return animalToLua(animal, itemInHand); - if (entity instanceof LivingEntity livingEntity) return livingEntityToLua(livingEntity); - return entityToLua(entity); + public static Map completeEntityWithPositionToLua(Entity entity, BlockPos pos) { + return completeEntityWithPositionToLua(entity, pos, false); + } + + public static Map completeEntityWithPositionToLua(Entity entity, Vec3 pos) { + return completeEntityWithPositionToLua(entity, pos, false); + } + + public static Map completeEntityWithPositionToLua(Entity entity, BlockPos pos, boolean detailed) { + return completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos, detailed); } - public static Map completeEntityWithPositionToLua(Entity entity, ItemStack itemInHand, BlockPos pos) { - Map data = completeEntityToLua(entity, itemInHand); - data.put("x", entity.getX() - pos.getX()); - data.put("y", entity.getY() - pos.getY()); - data.put("z", entity.getZ() - pos.getZ()); + public static Map completeEntityWithPositionToLua(Entity entity, Vec3 pos, boolean detailed) { + return completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos, detailed); + } + + public static Map completeEntityWithPositionToLua(Entity entity, ItemStack itemInHand, BlockPos pos, boolean detailed) { + return completeEntityWithPositionToLua(entity, itemInHand, Vec3.atCenterOf(pos), detailed); + } + + public static Map completeEntityWithPositionToLua(Entity entity, ItemStack itemInHand, Vec3 pos, boolean detailed) { + Map data = completeEntityToLua(entity, itemInHand, detailed); + data.put("x", entity.getX() - pos.x); + data.put("y", entity.getY() - pos.y); + data.put("z", entity.getZ() - pos.z); return data; } @@ -90,8 +205,11 @@ public static Object stateToObject(Comparable blockStateValue) { } } + @Nullable public static Object posToObject(BlockPos pos) { - if (pos == null) return null; + if (pos == null) { + return null; + } Map map = new HashMap<>(3); map.put("x", pos.getX()); @@ -100,22 +218,47 @@ public static Object posToObject(BlockPos pos) { return map; } - public static Map stackToObject(@NotNull ItemStack stack) { - if (stack.isEmpty()) return new HashMap<>(); + @Nullable + public static Map itemStackToObject(@NotNull ItemStack stack) { + if (stack.isEmpty()) { + return null; + } Map map = itemToObject(stack.getItem()); - CompoundTag nbt = stack.copy().getOrCreateTag(); + CompoundTag nbt = stack.getTag(); + if (nbt == null) { + nbt = EMPTY_TAG; + } map.put("count", stack.getCount()); map.put("displayName", stack.getDisplayName().getString()); map.put("maxStackSize", stack.getMaxStackSize()); map.put("nbt", NBTUtil.toLua(nbt)); + map.put("nbtHash", NBTUtil.getNBTHash(nbt)); map.put("fingerprint", ItemUtil.getFingerprint(stack)); return map; } - public static Map stackToObject(@NotNull ItemStack itemStack, int amount) { + @Nullable + public static Map fluidStackToObject(@NotNull FluidStack stack) { + if (stack.isEmpty()) { + return null; + } + Map map = fluidToObject(stack.getFluid()); + CompoundTag nbt = stack.getTag(); + if (nbt == null) { + nbt = EMPTY_TAG; + } + map.put("count", stack.getAmount()); + map.put("displayName", stack.getDisplayName().getString()); + map.put("nbt", NBTUtil.toLua(nbt)); + map.put("nbtHash", NBTUtil.getNBTHash(nbt)); + map.put("fingerprint", FluidUtil.getFingerprint(stack)); + return map; + } + + public static Map itemStackToObject(@NotNull ItemStack itemStack, int amount) { ItemStack stack = itemStack.copy(); stack.setCount(amount); - return stackToObject(stack); + return itemStackToObject(stack); } /** @@ -126,10 +269,13 @@ public static Map stackToObject(@NotNull ItemStack itemStack, in * @return a Map containing proper item stack details * @see InventoryManagerPeripheral#getItems() */ + @Nullable public static Map stackToObjectWithSlot(@NotNull ItemStack stack, int slot) { - if (stack.isEmpty()) return new HashMap<>(); - Map map = stackToObject(stack); - map.put("slot", slot); + if (stack.isEmpty()) { + return null; + } + Map map = itemStackToObject(stack); + map.put("slot", slot + 1); return map; } @@ -140,8 +286,22 @@ public static Map itemToObject(@NotNull Item item) { return map; } + public static Map fluidToObject(@NotNull Fluid fluid) { + Map map = new HashMap<>(); + FluidType fluidType = fluid.getFluidType(); + map.put("tags", tagsToList(() -> fluid.builtInRegistryHolder().tags())); + map.put("name", FluidUtil.getRegistryKey(fluid).toString()); + map.put("density", fluidType.getDensity()); + map.put("lightLevel", fluidType.getLightLevel()); + map.put("temperature", fluidType.getTemperature()); + map.put("viscosity", fluidType.getViscosity()); + return map; + } + public static List tagsToList(@NotNull Supplier>> tags) { - if (tags.get().findAny().isEmpty()) return Collections.emptyList(); + // We use new ArrayList here instead of Collections.emptyList to prevent an issue with + // textutils.serialise. I just hope this does not lead to a memory leak + if (tags.get().findAny().isEmpty()) return new ArrayList<>(); return tags.get().map(LuaConverter::tagToString).toList(); } @@ -151,10 +311,12 @@ public static String tagToString(@NotNull TagKey tag) { // BlockPos tricks public static BlockPos convertToBlockPos(Map table) throws LuaException { - if (!table.containsKey("x") || !table.containsKey("y") || !table.containsKey("z")) - throw new LuaException("Table should be block position table"); - if (!(table.get("x") instanceof Number x) || !(table.get("y") instanceof Number y) || !(table.get("z") instanceof Number z)) - throw new LuaException("Table should be block position table"); + if (!table.containsKey("x") || !table.containsKey("y") || !table.containsKey("z")) { + throw new LuaException("Table should contains key 'x', 'y' and 'z'"); + } + if (!(table.get("x") instanceof Number x) || !(table.get("y") instanceof Number y) || !(table.get("z") instanceof Number z)) { + throw new LuaException("Position should be numbers"); + } return new BlockPos(x.intValue(), y.intValue(), z.intValue()); } @@ -162,4 +324,80 @@ public static BlockPos convertToBlockPos(BlockPos center, Map table) throw BlockPos relative = convertToBlockPos(table); return new BlockPos(center.getX() + relative.getX(), center.getY() + relative.getY(), center.getZ() + relative.getZ()); } + + public static Map effectToLua(MobEffectInstance effect) { + Map map = new HashMap<>(); + map.put("name", effect.getDescriptionId()); + map.put("duration", effect.getDuration()); + map.put("amplifier", effect.getAmplifier()); + return map; + } + + public static Map teamToLua(Team team) { + if (team == null) { + return null; + } + Map map = new HashMap<>(); + map.put("name", team.getName()); + map.put("color", team.getColor()); + return map; + } + + public static Map shipToObject(ServerShip ship) { + return shipToObject(ship, null); + } + + public static Map shipToObject(ServerShip ship, Vec3 pos) { + Map map = new HashMap<>(); + + map.put("id", ship.getId()); + map.put("slug", ship.getSlug()); + + ShipTransform tf = ship.getTransform(); + + Vector3dc shipPos = tf.getShipPositionInShipCoordinates(); + if (pos != null) { + Vector3dc worldPos = tf.getShipPositionInWorldCoordinates(); + map.put("x", worldPos.x() - pos.x); + map.put("y", worldPos.y() - pos.y); + map.put("z", worldPos.z() - pos.z); + } + Quaterniondc rot = tf.getShipToWorldRotation(); + final double rotX = rot.x(), rotY = rot.y(), rotZ = rot.z(), rotW = rot.w(); + map.put("rotate", Map.of("x", rotX, "y", rotY, "z", rotZ, "w", rotW)); + // Not really correct? + // map.put("pitch", Math.toDegrees(Math.asin(-2 * (rotX * rotZ - rotW * rotY)))); + // map.put("roll", Math.toDegrees(Math.atan2(2 * (rotX * rotY + rotW * rotZ), rotW * rotW + rotX * rotX - rotY * rotY - rotZ * rotZ))); + // map.put("yaw", Math.toDegrees(Math.atan2(2 * (rotY * rotZ + rotW * rotX), rotW * rotW - rotX * rotX - rotY * rotY + rotZ * rotZ))); + + AABBic box = ship.getShipAABB(); + if (box != null) { + map.put("size", Map.of("x", box.maxX() - box.minX(), "y", box.maxY() - box.minY(), "z", box.maxZ() - box.minZ())); + map.put("corner", Map.of("x", shipPos.x() - box.minX(), "y", shipPos.y() - box.minY(), "z", shipPos.z() - box.minZ())); + } + Vector3dc omega = ship.getOmega(); + map.put("omega", Map.of("x", omega.x(), "y", omega.y(), "z", omega.z())); + Vector3dc velocity = ship.getVelocity(); + map.put("isStatic", ship.isStatic()); + map.put("velocity", Map.of("x", velocity.x(), "y", velocity.y(), "z", velocity.z())); + + ShipInertiaData data = ship.getInertiaData(); + map.put("mass", data.getMass()); + Vector3d com = tf.getShipToWorld().transformPosition(data.getCenterOfMassInShipSpace(), new Vector3d()); + if (pos != null) { + map.put("centerOfMass", Map.of("x", com.x - pos.x, "y", com.y - pos.y, "z", com.z - pos.z)); + } + return map; + } + + public static Map shipToObjectOnShip(ServerShip ship, Vec3 pos) { + Map map = shipToObject(ship); + Vector3dc shipPos = ship.getTransform().getShipPositionInShipCoordinates(); + map.put("x", shipPos.x() - pos.x); + map.put("y", shipPos.y() - pos.y); + map.put("z", shipPos.z() - pos.z); + Vector3dc com = ship.getInertiaData().getCenterOfMassInShipSpace(); + map.put("centerOfMass", Map.of("x", com.x() - pos.x, "y", com.y() - pos.y, "z", com.z() - pos.z)); + return map; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/NBTUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/NBTUtil.java index b8bef9e45..bb6e37ebd 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/NBTUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/NBTUtil.java @@ -4,13 +4,26 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.configuration.APConfig; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.*; +import net.minecraft.core.Registry; +import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagParser; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; +import net.minecraftforge.server.ServerLifecycleHooks; import org.apache.logging.log4j.Level; import java.util.Map; public class NBTUtil { + private NBTUtil() {} public static Tag toDirectNBT(Object object) { // Mostly dan200.computercraft.shared.util toNBTTag method @@ -65,6 +78,18 @@ public static BlockPos blockPosFromNBT(CompoundTag nbt) { return new BlockPos(nbt.getInt("x"), nbt.getInt("y"), nbt.getInt("z")); } + public static Pair levelAndBlockPosFromNBT(CompoundTag nbt) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + ServerLevel level = server.getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(nbt.getString("dim")))); + return new Pair(level, blockPosFromNBT(nbt)); + } + + public static CompoundTag toNBT(net.minecraft.world.level.Level level, BlockPos pos) { + CompoundTag data = toNBT(pos); + data.putString("dim", level.dimension().location().toString()); + return data; + } + public static CompoundTag toNBT(ChunkPos pos) { CompoundTag data = new CompoundTag(); data.putInt("x", pos.x); diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java b/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java index 46398d900..376a2cacb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/Pair.java @@ -4,7 +4,7 @@ import java.util.function.Consumer; import java.util.function.Function; -public class Pair { +public final class Pair { private final T left; private final V right; @@ -42,12 +42,12 @@ public boolean rightPresent() { } public void ifRightPresent(Consumer consumer) { - if(rightPresent()) + if (rightPresent()) consumer.accept(right); } public void ifLeftPresent(Consumer consumer) { - if(leftPresent()) + if (leftPresent()) consumer.accept(left); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/RegistryUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/RegistryUtil.java new file mode 100644 index 000000000..e28937168 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/RegistryUtil.java @@ -0,0 +1,25 @@ +package de.srendi.advancedperipherals.common.util; + +import net.minecraft.ResourceLocationException; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; + +public class RegistryUtil { + + public static T getRegistryEntry(String name, IForgeRegistry forgeRegistry) { + ResourceLocation location; + try { + location = new ResourceLocation(name); + } catch (ResourceLocationException ex) { + location = null; + } + + T value; + if (location != null && forgeRegistry.containsKey(location) && (value = forgeRegistry.getValue(location)) != null) { + return value; + } else { + return null; + } + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/ScanUtils.java b/src/main/java/de/srendi/advancedperipherals/common/util/ScanUtils.java index 68a51bcd4..07194d1a7 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/ScanUtils.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/ScanUtils.java @@ -3,32 +3,31 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; import java.util.function.BiConsumer; public class ScanUtils { - public static void relativeTraverseBlocks(Level world, BlockPos center, int radius, BiConsumer consumer) { + public static void relativeTraverseBlocks(Level world, Vec3 center, double radius, BiConsumer consumer) { traverseBlocks(world, center, radius, consumer, true); } - public static void traverseBlocks(Level world, BlockPos center, int radius, BiConsumer consumer) { + public static void traverseBlocks(Level world, Vec3 center, double radius, BiConsumer consumer) { traverseBlocks(world, center, radius, consumer, false); } - public static void traverseBlocks(Level world, BlockPos center, int radius, BiConsumer consumer, boolean relativePosition) { - int x = center.getX(); - int y = center.getY(); - int z = center.getZ(); - for (int oX = x - radius; oX <= x + radius; oX++) { - for (int oY = y - radius; oY <= y + radius; oY++) { - for (int oZ = z - radius; oZ <= z + radius; oZ++) { + public static void traverseBlocks(Level world, Vec3 center, double radius, BiConsumer consumer, boolean relativePosition) { + final double x = center.x, y = center.y, z = center.z; + for (int oX = (int) (x - radius); oX <= (int) (x + radius); oX++) { + for (int oY = (int) (y - radius); oY <= (int) (y + radius); oY++) { + for (int oZ = (int) (z - radius); oZ <= (int) (z + radius); oZ++) { BlockPos subPos = new BlockPos(oX, oY, oZ); BlockState blockState = world.getBlockState(subPos); if (!blockState.isAir()) { if (relativePosition) { - consumer.accept(blockState, new BlockPos(oX - x, oY - y, oZ - z)); + consumer.accept(blockState, new Vec3(oX + 0.5 - center.x, oY + 0.5 - center.y, oZ + 0.5 - center.z)); } else { - consumer.accept(blockState, subPos); + consumer.accept(blockState, new Vec3(oX, oY, oZ)); } } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java b/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java index 884cbd5a2..cbde6790b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java @@ -12,9 +12,22 @@ public class ServerWorker { private static final Queue callQueue = new ConcurrentLinkedQueue<>(); + private static int tasksRan = 0; - public static void add(final Runnable call) { - callQueue.add(call); + /** + * This method will queue a task to current tick's end. + * If a task added during the end of a tick, the task will be delayed to the next tick; + */ + public static void add(final Runnable task) { + callQueue.add(task); + } + + /** + * Add to next tick will execute the task in next tick. + * It's an alias of ServerWorker.add(() -> ServerWorker.add(task)); + */ + public static void addToNextTick(final Runnable task) { + add(() -> add(task)); } @SubscribeEvent @@ -22,7 +35,8 @@ public static void serverTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.END) { while (!callQueue.isEmpty()) { final Runnable runnable = callQueue.poll(); - AdvancedPeripherals.debug("Running queued server worker call: " + runnable); + tasksRan++; + AdvancedPeripherals.debug("Running task #" + tasksRan + ". Running " + runnable.getClass()); runnable.run(); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/StatusConstants.java b/src/main/java/de/srendi/advancedperipherals/common/util/StatusConstants.java new file mode 100644 index 000000000..c697f5026 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/StatusConstants.java @@ -0,0 +1,49 @@ +package de.srendi.advancedperipherals.common.util; + +public enum StatusConstants { + + // Crafting Jobs + CALCULATION_STARTED, + CRAFTING_STARTED, + JOB_CANCELED, + JOB_DONE, + NOT_CRAFTABLE, + MISSING_ITEMS, // If there are missing items for a crafting recipe/job after the calculation is done + CPU_NOT_FOUND, + // Filters + EMPTY_FILTER, + FILTER_ITEM_NOT_FOUND, // Item could not be found in registry + FILTER_FLUID_NOT_FOUND, // Fluid could not be found in registry + FILTER_CHEMICAL_NOT_FOUND, // Chemical could not be found in registry + MISSING_FILTER, + NO_VALID_FLUID, // Fluid property of filter is not a string + NO_VALID_ITEM, // Item property of filter is not a string + NO_VALID_FROMSLOT, + NO_VALID_TOSLOT, + NO_VALID_NBT_HASH, + NO_VALID_NBT, + NO_VALID_FINGERPRINT, + NO_VALID_COUNT, + NO_VALID_FILTER_TYPE, + // Inventory, + INVENTORY_NOT_FOUND, + TARGET_NOT_FOUND, + ITEM_NOT_FOUND, // Debug message when an item couldn't be found in an/the target inventory + FLUID_NOT_FOUND, + CHEMICAL_NOT_FOUND, + // Misc + NOT_CONNECTED, + NOT_FOUND, // Generic not found state + ADDON_NOT_LOADED, + UNKNOWN_ERROR; + + public String withInfo(String extraInfo) { + return this + "_" + extraInfo; + } + + /*public String withInfo(APAddon addon) { + return this + "_" + addon.getModId(); + }*/ + + +} \ No newline at end of file diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/StringUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/StringUtil.java index f166eda25..c4a7ab396 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/StringUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/StringUtil.java @@ -31,4 +31,11 @@ public static String toHexString(byte[] bytes) { public static String convertAndToSectionMark(String str) { return str == null ? null : str.replaceAll("(?>>> events = new ConcurrentHashMap<>(); + private static final AtomicBoolean updated = new AtomicBoolean(); + + private SwarmEventDispatcher() {} + + /** + * {@code dispatch} will put periperal and event data into queue. + * The events will be fired together at the end of the tick. + * + * For example, if you invoke + *

+     * 
+     * dispatch("a_event", peripheral1, "random data1")
+     * dispatch("a_event", peripheral1, "data2")
+     * dispatch("a_event", peripheral2, "random data3")
+     * dispatch("another_event", peripheral1, "random data4")
+     * 
+     * 
+ * the events will be pushed at the end of the tick with form of + *
+     * 
+     * "a_event", {
+     *   ["peripheral1_name"] = {"random data1", "data2"},
+     *   ["peripheral2_name"] = {"random data3"},
+     * }
+     *
+     * "another_event", {
+     *   ["peripheral1_name"] = {"random data4"},
+     * }
+     * 
+     * 
+ */ + public static void dispatch(@NotNull String event, @NotNull BasePeripheral peripheral, Object data) { + boolean set = false; + ConcurrentMap>> computers = events.computeIfAbsent(event, (k) -> new ConcurrentHashMap<>()); + Iterable computerIter = peripheral.getConnectedComputers(); + for (IComputerAccess computer : computerIter) { + computers.computeIfAbsent(computer.getID(), (k) -> new ConcurrentHashMap<>()).compute(computer.getAttachmentName(), (name, datas) -> { + if (datas == null) { + datas = new HashSet<>(); + } + datas.add(data); + return datas; + }); + set = true; + } + if (set) { + updated.set(true); + } + } + + private static Map getComputers(MinecraftServer server) { + Map computers = new HashMap<>(); + ServerContext.get(server).registry().getComputers().forEach(computer -> computers.put(computer.getID(), computer)); + return computers; + } + + @SubscribeEvent + public static void serverTick(TickEvent.ServerTickEvent tickEvent) { + if (tickEvent.phase != TickEvent.Phase.END) { + return; + } + if (!updated.compareAndSet(true, false)) { + return; + } + Map computerMap = getComputers(tickEvent.getServer()); + events.forEach((event, computers) -> { + for (int id : computers.keySet()) { + ConcurrentMap> peripherals = computers.remove(id); + if (peripherals == null || peripherals.isEmpty()) { + continue; + } + ServerComputer computer = computerMap.get(id); + if (computer != null) { + computer.queueEvent(event, new Object[]{peripherals}); + } + } + }); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/TeleportUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/TeleportUtil.java new file mode 100644 index 000000000..24edd1379 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/TeleportUtil.java @@ -0,0 +1,41 @@ +package de.srendi.advancedperipherals.common.util; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; + +import java.util.ArrayList; +import java.util.List; + +public final class TeleportUtil { + private TeleportUtil() {} + + public static T teleportToWithPassengers(T entity, ServerLevel newLevel, Vec3 newPos) { + Vec3 oldPos = entity.position(); + List passengers = new ArrayList<>(entity.getPassengers()); + T newEntity; + if (entity instanceof ServerPlayer player) { + // TODO <1.20.1>: player will be reconstruct in 1.20.1 + player.teleportTo(newLevel, newPos.x, newPos.y, newPos.z, player.getYRot(), player.getXRot()); + newEntity = entity; + } else { + newEntity = (T) entity.getType().create(newLevel); + if (newEntity == null) { + return null; + } + entity.ejectPassengers(); + newEntity.restoreFrom(entity); + newEntity.moveTo(newPos.x, newPos.y, newPos.z, newEntity.getYRot(), newEntity.getXRot()); + newLevel.addDuringTeleport(newEntity); + entity.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); + } + for (Entity p : passengers) { + Entity newPassenger = teleportToWithPassengers(p, newLevel, p.position().subtract(oldPos).add(newPos)); + if (newPassenger != null) { + newPassenger.startRiding(newEntity, true); + } + } + return newEntity; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/APFakePlayer.java b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/APFakePlayer.java index a947a4c53..60d0c56c5 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/APFakePlayer.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/APFakePlayer.java @@ -2,6 +2,7 @@ import com.mojang.authlib.GameProfile; import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.util.HitResultUtil; import de.srendi.advancedperipherals.common.util.Pair; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -23,7 +24,6 @@ import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -32,7 +32,10 @@ import net.minecraft.world.level.block.StructureBlock; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.*; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.util.FakePlayer; @@ -42,10 +45,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; -import java.util.List; import java.util.UUID; -import java.util.function.Function; import java.util.function.Predicate; public class APFakePlayer extends FakePlayer { @@ -53,40 +53,36 @@ public class APFakePlayer extends FakePlayer { Highly inspired by https://github.com/SquidDev-CC/plethora/blob/minecraft-1.12/src/main/java/org/squiddev/plethora/gameplay/PlethoraFakePlayer.java */ public static final GameProfile PROFILE = new GameProfile(UUID.fromString("6e483f02-30db-4454-b612-3a167614b276"), "[" + AdvancedPeripherals.MOD_ID + "]"); - private static final Predicate collidablePredicate = EntitySelector.NO_SPECTATORS; - - private final WeakReference owner; - - private BlockPos digPosition; - private Block digBlock; + private static final Predicate DEFAULT_ENTITY_FILTER = EntitySelector.NO_SPECTATORS.and(LivingEntity.class::isInstance).and((entity) -> !entity.isPassenger()); + private BlockPos source = null; + private BlockPos digPosition = null; + private Block digBlock = null; private float currentDamage = 0; + private double reachRange = -1; public APFakePlayer(ServerLevel world, Entity owner, GameProfile profile) { super(world, profile != null && profile.isComplete() ? profile : PROFILE); if (owner != null) { setCustomName(owner.getName()); - this.owner = new WeakReference<>(owner); - } else { - this.owner = null; } } + public void setSourceBlock(BlockPos pos) { + this.source = pos; + } + @Override public void awardStat(@NotNull Stat stat) { MinecraftServer server = level.getServer(); if (server != null && getGameProfile() != PROFILE) { Player player = server.getPlayerList().getPlayer(getUUID()); - if (player != null) + if (player != null) { player.awardStat(stat); + } } } - @Override - public boolean canAttack(@NotNull LivingEntity livingEntity) { - return true; - } - @Override public void openTextEdit(@NotNull SignBlockEntity sign) { } @@ -101,7 +97,6 @@ public void playSound(@NotNull SoundEvent soundIn, float volume, float pitch) { } private void setState(Block block, BlockPos pos) { - if (digPosition != null) { gameMode.handleBlockBreakAction(digPosition, ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, Direction.EAST, 320, 1); } @@ -116,25 +111,25 @@ public float getEyeHeight(@NotNull Pose pose) { return 0; } - public static Function wrapActionWithRot(float yaw, float pitch, Function action) { + public static Action wrapActionWithRot(float yaw, float pitch, Action action) { return player -> player.doActionWithRot(yaw, pitch, action); } - public T doActionWithRot(float yaw, float pitch, Function action) { - final float oldRot = this.getYRot(); - this.setRot(oldRot + yaw, pitch); + public T doActionWithRot(float yaw, float pitch, Action action) { + final float yRot = this.getYRot(), xRot = this.getXRot(); + this.setRot(yRot + yaw, xRot + pitch); try { return action.apply(this); } finally { - this.setRot(oldRot, 0); + this.setRot(yRot, xRot); } } - public static Function wrapActionWithShiftKey(boolean shift, Function action) { + public static Action wrapActionWithShiftKey(boolean shift, Action action) { return player -> player.doActionWithShiftKey(shift, action); } - public T doActionWithShiftKey(boolean shift, Function action) { + public T doActionWithShiftKey(boolean shift, Action action) { boolean old = this.isShiftKeyDown(); this.setShiftKeyDown(shift); try { @@ -144,18 +139,38 @@ public T doActionWithShiftKey(boolean shift, Function actio } } - @Deprecated(forRemoval = true) - public Pair digBlock(Direction direction) { - return doActionWithRot(direction.toYRot() - this.getYRot(), direction == Direction.DOWN ? 90 : direction == Direction.UP ? -90 : 0, APFakePlayer::digBlock); + public static Action wrapActionWithReachRange(double range, Action action) { + return player -> player.doActionWithReachRange(range, action); + } + + public T doActionWithReachRange(double range, Action action) { + this.reachRange = range; + try { + return action.apply(this); + } finally { + this.reachRange = -1; + } + } + + public double getReachRange() { + AttributeInstance reachAttribute = this.getAttribute(ForgeMod.REACH_DISTANCE.get()); + if (reachAttribute == null) { + throw new IllegalArgumentException("How did this happened?"); + } + double range = reachAttribute.getValue(); + if (this.reachRange >= 0 && this.reachRange < range) { + range = this.reachRange; + } + return range; } public Pair digBlock() { Level world = getLevel(); HitResult hit = findHit(true, false); - if (hit.getType() == HitResult.Type.MISS) { + if (!(hit instanceof BlockHitResult blockHit) || hit.getType() == HitResult.Type.MISS) { return Pair.of(false, "Nothing to break"); } - BlockPos pos = new BlockPos(hit.getLocation()); + BlockPos pos = blockHit.getBlockPos(); BlockState state = world.getBlockState(pos); Block block = state.getBlock(); @@ -285,90 +300,39 @@ public InteractionResult use(boolean skipEntity, boolean skipBlock, @Nullable Pr } public HitResult findHit(boolean skipEntity, boolean skipBlock) { - return findHit(skipEntity, skipBlock, null); + return findHit(skipEntity, skipBlock, DEFAULT_ENTITY_FILTER); } @NotNull - public HitResult findHit(boolean skipEntity, boolean skipBlock, @Nullable Predicate entityFilter) { - AttributeInstance reachAttribute = getAttribute(ForgeMod.REACH_DISTANCE.get()); - if (reachAttribute == null) - throw new IllegalArgumentException("How did this happened?"); - - double range = reachAttribute.getValue(); - Vec3 origin = new Vec3(getX(), getY(), getZ()); - Vec3 look = getLookAngle(); + public HitResult findHit(boolean skipEntity, boolean skipBlock, @NotNull Predicate entityFilter) { + double range = this.getReachRange(); + Vec3 origin = new Vec3(this.getX(), this.getY(), this.getZ()); + Vec3 look = this.getLookAngle(); Vec3 target = new Vec3(origin.x + look.x * range, origin.y + look.y * range, origin.z + look.z * range); - ClipContext traceContext = new ClipContext(origin, target, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this); - Vec3 directionVec = traceContext.getFrom().subtract(traceContext.getTo()); - Direction traceDirection = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); - HitResult blockHit; + + BlockHitResult blockHit; if (skipBlock) { - blockHit = BlockHitResult.miss(traceContext.getTo(), traceDirection, new BlockPos(traceContext.getTo())); + Direction traceDirection = Direction.getNearest(look.x, look.y, look.z); + blockHit = BlockHitResult.miss(target, traceDirection, new BlockPos(target)); } else { - blockHit = BlockGetter.traverseBlocks(traceContext.getFrom(), traceContext.getTo(), traceContext, (rayTraceContext, blockPos) -> { - if (level.isEmptyBlock(blockPos) || blockPos.equals(blockPosition())) { - return null; - } - return new BlockHitResult(new Vec3(blockPos.getX(), blockPos.getY(), blockPos.getZ()), traceDirection, blockPos, false); - }, rayTraceContext -> BlockHitResult.miss(rayTraceContext.getTo(), traceDirection, new BlockPos(rayTraceContext.getTo()))); + blockHit = HitResultUtil.getBlockHitResult(origin, target, level, ClipContext.Block.OUTLINE, this.source); } - if (skipEntity) + if (skipEntity) { return blockHit; - - List entities = level.getEntities(this, getBoundingBox().expandTowards(look.x * range, look.y * range, look.z * range).inflate(1), collidablePredicate); - - LivingEntity closestEntity = null; - Vec3 closestVec = null; - double closestDistance = blockHit.getType() == HitResult.Type.MISS ? range * range : distanceToSqr(blockHit.getLocation()); - for (Entity entityHit : entities) { - if (!(entityHit instanceof LivingEntity entity)) { - continue; - } - // TODO: maybe let entityFilter returns the priority of the entity, instead of only returns the closest one. - if (entityFilter != null && !entityFilter.test(entity)) { - continue; - } - - // Removed a lot logic here to make Automata cores interact like a player. - // However, the results for some edge cases may change. Need more review and tests. - - // Hit vehicle before passenger - if (entity.isPassenger()) { - continue; - } - - AABB box = entity.getBoundingBox(); - Vec3 clipVec; - if (box.contains(origin)) { - clipVec = origin; - } else { - clipVec = box.clip(origin, target).orElse(null); - if (clipVec == null) { - continue; - } - } - double distance = origin.distanceToSqr(clipVec); - // Ignore small enough distance - if (distance <= 1e-6) { - distance = 0; - } - if (distance > closestDistance) { - continue; - } - if (distance == closestDistance && closestEntity != null) { - // Hit larger entity before smaller - if (closestEntity.getBoundingBox().getSize() >= box.getSize()) { - continue; - } - } - closestEntity = entity; - closestVec = clipVec; - closestDistance = distance; } - if (closestEntity != null) { - return new EntityHitResult(closestEntity, closestVec); + + // TODO: maybe let entityFilter returns the priority of the entity, instead of only returns the closest one. + EntityHitResult entityHit = HitResultUtil.getEntityHitResult(origin, target, level, this, entityFilter); + if (entityHit.getType() == HitResult.Type.ENTITY) { + return entityHit; } + return blockHit; } + + @FunctionalInterface + public interface Action { + T apply(APFakePlayer player); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java index fff168b9f..aa9b0b86e 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java @@ -3,19 +3,21 @@ import com.mojang.authlib.GameProfile; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.shared.util.WorldUtil; +import de.srendi.advancedperipherals.common.addons.APAddons; +import de.srendi.advancedperipherals.common.addons.valkyrienskies.ValkyrienSkies; +import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.InvWrapper; import java.util.WeakHashMap; -import java.util.function.Function; public final class FakePlayerProviderTurtle { @@ -32,22 +34,32 @@ public static APFakePlayer getPlayer(ITurtleAccess turtle, GameProfile profile) } public static void load(APFakePlayer player, ITurtleAccess turtle) { - Direction direction = turtle.getDirection(); - player.setLevel((ServerLevel) turtle.getLevel()); - // Player position - BlockPos position = turtle.getPosition(); - player.moveTo(position.getX() + 0.5, position.getY() + 0.5, position.getZ() + 0.5, direction.toYRot(), 0); + ServerLevel level = (ServerLevel) turtle.getLevel(); + player.setLevel(level); + + BlockPos pos = turtle.getPosition(); + player.setSourceBlock(pos); + + Vec3 direction = Vec3.atLowerCornerOf(turtle.getDirection().getNormal()); + Vec3 position = Vec3.atCenterOf(pos); + if (APAddons.vs2Loaded) { + position = ValkyrienSkies.transformToWorldPos(level, pos, position); + direction = ValkyrienSkies.transformToWorldDir(level, pos, direction); + } + player.setPosRaw(position.x, position.y, position.z); + player.lookAt(EntityAnchorArgument.Anchor.FEET, position.add(direction)); + // Player inventory Inventory playerInventory = player.getInventory(); playerInventory.selected = 0; // Copy primary items into player inventory and empty the rest - IItemHandler turtleInventory = turtle.getItemHandler(); - int size = turtleInventory.getSlots(); + Container turtleInventory = turtle.getInventory(); + int size = turtleInventory.getContainerSize(); int largerSize = playerInventory.getContainerSize(); playerInventory.selected = turtle.getSelectedSlot(); for (int i = 0; i < size; i++) { - playerInventory.setItem(i, turtleInventory.getStackInSlot(i)); + playerInventory.setItem(i, turtleInventory.getItem(i)); } for (int i = size; i < largerSize; i++) { playerInventory.setItem(i, ItemStack.EMPTY); @@ -71,19 +83,19 @@ public static void unload(APFakePlayer player, ITurtleAccess turtle) { } // Copy primary items into turtle inventory and then insert/drop the rest - IItemHandlerModifiable turtleInventory = turtle.getItemHandler(); - int size = turtleInventory.getSlots(); + Container turtleInventory = turtle.getInventory(); + int size = turtleInventory.getContainerSize(); int largerSize = playerInventory.getContainerSize(); playerInventory.selected = turtle.getSelectedSlot(); for (int i = 0; i < size; i++) { - turtleInventory.setStackInSlot(i, playerInventory.getItem(i)); + turtleInventory.setItem(i, playerInventory.getItem(i)); playerInventory.setItem(i, ItemStack.EMPTY); } for (int i = size; i < largerSize; i++) { ItemStack remaining = playerInventory.getItem(i); if (!remaining.isEmpty()) { - remaining = ItemHandlerHelper.insertItem(turtleInventory, remaining, false); + remaining = ItemHandlerHelper.insertItem(new InvWrapper(turtleInventory), remaining, false); if (!remaining.isEmpty()) { BlockPos position = turtle.getPosition(); WorldUtil.dropItemStack(remaining, turtle.getLevel(), position, turtle.getDirection().getOpposite()); @@ -94,8 +106,7 @@ public static void unload(APFakePlayer player, ITurtleAccess turtle) { } } - - public static T withPlayer(ITurtleAccess turtle, Function function) { + public static T withPlayer(ITurtleAccess turtle, APFakePlayer.Action function) { APFakePlayer player = getPlayer(turtle, turtle.getOwningPlayer()); load(player, turtle); T result = function.apply(player); diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java index 393fac7da..ede9e9efb 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidFilter.java @@ -1,10 +1,13 @@ package de.srendi.advancedperipherals.common.util.inventory; +import appeng.api.stacks.AEFluidKey; +import appeng.api.stacks.GenericStack; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.core.apis.TableHelper; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.NBTUtil; import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.RegistryUtil; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -17,11 +20,12 @@ import java.util.Map; -public class FluidFilter { +public class FluidFilter extends GenericFilter { private Fluid fluid = Fluids.EMPTY; private TagKey tag = null; private CompoundTag nbt = null; + private String nbtHash = null; private int count = 1000; private String fingerprint = ""; @@ -38,13 +42,20 @@ public static Pair parse(Map item) { String name = TableHelper.getStringField(item, "name"); if (name.startsWith("#")) { fluidFilter.tag = TagKey.create(Registry.FLUID_REGISTRY, new ResourceLocation(name.substring(1))); - } else if ((fluidFilter.fluid = ItemUtil.getRegistryEntry(name, ForgeRegistries.FLUIDS)) == null) { + } else if ((fluidFilter.fluid = RegistryUtil.getRegistryEntry(name, ForgeRegistries.FLUIDS)) == null) { return Pair.of(null, "FLUID_NOT_FOUND"); } } catch (LuaException luaException) { return Pair.of(null, "NO_VALID_FLUID"); } } + if (item.containsKey("nbtHash")) { + try { + fluidFilter.nbtHash = TableHelper.getStringField(item, "nbtHash"); + } catch (LuaException luaException) { + return Pair.of(null, "NO_VALID_NBT_HASH"); + } + } if (item.containsKey("nbt")) { try { fluidFilter.nbt = NBTUtil.fromText(TableHelper.getStringField(item, "nbt")); @@ -83,7 +94,7 @@ public static FluidFilter empty() { } public boolean isEmpty() { - return fingerprint.isEmpty() && fluid == Fluids.EMPTY && tag == null && nbt == null; + return fingerprint.isEmpty() && fluid == Fluids.EMPTY && tag == null && nbt == null && nbtHash == null; } public FluidStack toFluidStack() { @@ -97,6 +108,14 @@ public FluidFilter setCount(int count) { return this; } + @Override + public boolean testAE(GenericStack genericStack) { + if (genericStack.what() instanceof AEFluidKey aeFluidKey) { + return test(aeFluidKey.toStack(1)); + } + return false; + } + public boolean test(FluidStack stack) { if (!fingerprint.isEmpty()) { String testFingerprint = FluidUtil.getFingerprint(stack); @@ -112,6 +131,9 @@ public boolean test(FluidStack stack) { if (nbt != null && !stack.getOrCreateTag().equals(nbt)) { return false; } + if (nbtHash != null && !dan200.computercraft.shared.util.NBTUtil.getNBTHash(stack.getOrCreateTag()).equals(nbtHash)) { + return false; + } return true; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java index a3d8cdec6..f6fcbae85 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/FluidUtil.java @@ -3,11 +3,11 @@ import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; -import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; import de.srendi.advancedperipherals.common.util.CoordUtil; import de.srendi.advancedperipherals.common.util.StringUtil; import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -23,13 +23,11 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Objects; public class FluidUtil { - private FluidUtil() { - } + private FluidUtil() {} @Nullable public static IFluidHandler extractHandler(@Nullable Object object) { @@ -76,16 +74,16 @@ public static IFluidHandler getHandlerFromName(@NotNull IComputerAccess access, @NotNull public static String getFingerprint(@NotNull FluidStack stack) { - String fingerprint = stack.getOrCreateTag() + getRegistryKey(stack).toString() + stack.getDisplayName().getString(); - try { - byte[] bytesOfHash = fingerprint.getBytes(StandardCharsets.UTF_8); - MessageDigest md = MessageDigest.getInstance("MD5"); - return StringUtil.toHexString(md.digest(bytesOfHash)); - } catch (NoSuchAlgorithmException ex) { - AdvancedPeripherals.debug("Could not parse fingerprint.", org.apache.logging.log4j.Level.ERROR); - ex.printStackTrace(); + MessageDigest md = ItemUtil.getMessageDigest("MD5"); + if (md == null) { + return ""; + } + CompoundTag tag = stack.getTag(); + md.update(getRegistryKey(stack).toString().getBytes(StandardCharsets.UTF_8)); + if (tag != null && !tag.isEmpty()) { + md.update(tag.getAsString().getBytes(StandardCharsets.UTF_8)); } - return ""; + return StringUtil.toHexString(md.digest()); } public static ResourceLocation getRegistryKey(Fluid fluid) { @@ -93,6 +91,6 @@ public static ResourceLocation getRegistryKey(Fluid fluid) { } public static ResourceLocation getRegistryKey(FluidStack fluid) { - return ForgeRegistries.FLUIDS.getKey(fluid.copy().getFluid()); + return ForgeRegistries.FLUIDS.getKey(fluid.getFluid()); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java new file mode 100644 index 000000000..df8484325 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/GenericFilter.java @@ -0,0 +1,77 @@ +package de.srendi.advancedperipherals.common.util.inventory; + +import appeng.api.stacks.GenericStack; +import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.RegistryUtil; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.Map; + +public abstract class GenericFilter { + + /** + * Try to parse a raw filter table to any existing filter type. Could be a fluid filter, an item filter, maybe something else + * in the future. + *

+ * If the function can't find a valid type for the given name/resource location, it will return an empty filter with + * a proper error message. + * + * @param rawFilter The raw filter, which is a map of strings and objects + * @return A pair of the parsed filter and an error message, if there is one + */ + public static Pair, String> parseGeneric(Map rawFilter) { + // TODO: Add chemical filter support + + if (!rawFilter.containsKey("name")) { + if (rawFilter.containsKey("type") && rawFilter.get("type") instanceof String type) { + switch (type) { + case "item": + return ItemFilter.parse(rawFilter); + case "fluid": + return FluidFilter.parse(rawFilter); + } + } + // If the filter does not contain a name or a type, which should never happen, but players are players, we will just + // give the ItemFilter the task to parse the filter + return ItemFilter.parse(rawFilter); + } + String name = rawFilter.get("name").toString(); + + // Let's check in which registry this thing is + if (RegistryUtil.getRegistryEntry(name, ForgeRegistries.ITEMS) != null) { + return ItemFilter.parse(rawFilter); + } else if (RegistryUtil.getRegistryEntry(name, ForgeRegistries.FLUIDS) != null) { + return FluidFilter.parse(rawFilter); + } else { + // If the name is in neither of the registries, we will just return an empty filter + return Pair.of(empty(), "NO_VALID_FILTER_TYPE"); + } + } + + public abstract boolean isEmpty(); + + // AE2 stuff + public abstract boolean testAE(GenericStack genericStack); + + public abstract boolean test(T toTest); + + public static GenericFilter empty() { + return new GenericFilter<>() { + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean testAE(GenericStack genericStack) { + return false; + } + + @Override + public boolean test(Object toTest) { + return false; + } + }; + } + +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java index f86f1e487..9cc76fbee 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemFluidHandler.java @@ -11,7 +11,7 @@ public interface IStorageSystemFluidHandler extends IFluidHandler { * Uses a filter to find the right item. The amount should never be greater than 64 * stack sizes greater than 64. * - * @param filter The parsed filter + * @param filter The parsed filter * @param simulate Should this action be simulated * @return extracted from the slot, must be empty if nothing can be extracted. The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. */ diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java index f5b161f6a..63ae60a16 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemItemHandler.java @@ -11,6 +11,7 @@ public interface IStorageSystemItemHandler extends IItemHandler { * Uses a filter to find the right item. The amount should never be greater than 64 * stack sizes greater than 64. * + * @param filter The parsed filter * @param filter The parsed filter * @param count The amount to extract * @param simulate Should this action be simulated diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemPeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemPeripheral.java new file mode 100644 index 000000000..e567e39d3 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/IStorageSystemPeripheral.java @@ -0,0 +1,157 @@ +package de.srendi.advancedperipherals.common.util.inventory; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.ILuaCallback; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.peripheral.IComputerAccess; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.MEBridgePeripheral; +import de.srendi.advancedperipherals.common.util.ServerWorker; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; + +/** + * Implementation for common storage peripheral functions. Used for AE2 {@link MEBridgePeripheral} + * and RS {@link de.srendi.advancedperipherals.common.addons.computercraft.peripheral.RsBridgePeripheral} + *

+ * This ensures that these both bridges use the same methods. This makes it easier to support both in the same script + * In case there is a new mod which adds new ways to store and craft items, this ensures that the new peripheral + * has the same functions as the other ones + *

+ * Implementation needs to override {@link dan200.computercraft.api.lua.LuaFunction} + */ +public interface IStorageSystemPeripheral { + + boolean isConnected(); + + MethodResult isOnline(); + + MethodResult getItem(IArguments arguments) throws LuaException; + + MethodResult getFluid(IArguments arguments) throws LuaException; + + MethodResult getChemical(IArguments arguments) throws LuaException; + + MethodResult getItems(IArguments arguments) throws LuaException; + + MethodResult getFluids(IArguments arguments) throws LuaException; + + MethodResult getChemicals(IArguments arguments) throws LuaException; + + MethodResult getCraftableItems(IArguments arguments) throws LuaException; + + MethodResult getCraftableFluids(IArguments arguments) throws LuaException; + + MethodResult getCraftableChemicals(IArguments arguments) throws LuaException; + + MethodResult getCells(); + + MethodResult getDrives(); + + MethodResult importItem(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult exportItem(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult importFluid(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult exportFluid(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult importChemical(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult exportChemical(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult getStoredEnergy(); + + MethodResult getEnergyCapacity(); + + MethodResult getEnergyUsage(); + + MethodResult getAverageEnergyInput(); + + MethodResult getTotalExternalItemStorage(); + + MethodResult getTotalExternalFluidStorage(); + + MethodResult getTotalExternalChemicalStorage(); + + MethodResult getTotalItemStorage(); + + MethodResult getTotalFluidStorage(); + + MethodResult getTotalChemicalStorage(); + + MethodResult getUsedExternalItemStorage(); + + MethodResult getUsedExternalFluidStorage(); + + MethodResult getUsedExternalChemicalStorage(); + + MethodResult getUsedItemStorage(); + + MethodResult getUsedFluidStorage(); + + MethodResult getUsedChemicalStorage(); + + MethodResult getAvailableExternalItemStorage(); + + MethodResult getAvailableExternalFluidStorage(); + + MethodResult getAvailableExternalChemicalStorage(); + + MethodResult getAvailableItemStorage(); + + MethodResult getAvailableFluidStorage(); + + MethodResult getAvailableChemicalStorage(); + + MethodResult getCraftingTasks(); + + // A function to get our BasicCraftJob object with the id + MethodResult getCraftingTask(int id); + + MethodResult cancelCraftingTasks(IArguments arguments) throws LuaException; + + MethodResult craftItem(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult craftFluid(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult craftChemical(IComputerAccess computer, IArguments arguments) throws LuaException; + + MethodResult isCraftable(IArguments arguments) throws LuaException; + + MethodResult isCrafting(IArguments arguments) throws LuaException; + + MethodResult getPatterns(IArguments arguments) throws LuaException; + + // TODO: In 1.20.1 we should use the mainThread descriptor instead + @Deprecated(forRemoval = true, since = "1.20.1") + class CraftJobCallback implements ILuaCallback { + public static final String EVENT_ID = "_bridge_craft_requested"; + private static final AtomicInteger ID_SEQ = new AtomicInteger(); + + public final MethodResult pull = MethodResult.pullEvent(EVENT_ID, this); + private final int id = ID_SEQ.incrementAndGet(); + private volatile MethodResult result; + + public CraftJobCallback(IComputerAccess computer, Supplier worker) { + ServerWorker.add(() -> { + this.result = worker.get(); + computer.queueEvent(EVENT_ID, this.id); + }); + } + + @NotNull + @Override + public MethodResult resume(Object[] datas) { + if (!(datas[0] instanceof String event) || !(datas[1] instanceof Number taskId)) { + return this.pull; + } + if (!event.equals(EVENT_ID) || taskId.intValue() != this.id) { + return this.pull; + } + return this.result; + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java index f8a8074cf..41caa4db4 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemFilter.java @@ -1,10 +1,13 @@ package de.srendi.advancedperipherals.common.util.inventory; +import appeng.api.stacks.AEItemKey; +import appeng.api.stacks.GenericStack; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.core.apis.TableHelper; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.NBTUtil; import de.srendi.advancedperipherals.common.util.Pair; +import de.srendi.advancedperipherals.common.util.RegistryUtil; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -17,11 +20,12 @@ import java.util.Map; -public class ItemFilter { +public class ItemFilter extends GenericFilter { private Item item = Items.AIR; private TagKey tag = null; private CompoundTag nbt = null; + private String nbtHash = null; private int count = 64; private String fingerprint = ""; public int fromSlot = -1; @@ -40,13 +44,20 @@ public static Pair parse(Map item) { String name = TableHelper.getStringField(item, "name"); if (name.startsWith("#")) { itemFilter.tag = TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(name.substring(1))); - } else if ((itemFilter.item = ItemUtil.getRegistryEntry(name, ForgeRegistries.ITEMS)) == null) { + } else if ((itemFilter.item = RegistryUtil.getRegistryEntry(name, ForgeRegistries.ITEMS)) == null) { return Pair.of(null, "ITEM_NOT_FOUND"); } } catch (LuaException luaException) { return Pair.of(null, "NO_VALID_ITEM"); } } + if (item.containsKey("nbtHash")) { + try { + itemFilter.nbtHash = TableHelper.getStringField(item, "nbtHash"); + } catch (LuaException luaException) { + return Pair.of(null, "NO_VALID_NBT_HASH"); + } + } if (item.containsKey("nbt")) { try { itemFilter.nbt = NBTUtil.fromText(TableHelper.getStringField(item, "nbt")); @@ -67,14 +78,14 @@ public static Pair parse(Map item) { } if (item.containsKey("fromSlot")) { try { - itemFilter.fromSlot = TableHelper.getIntField(item, "fromSlot"); + itemFilter.fromSlot = TableHelper.getIntField(item, "fromSlot") - 1; } catch (LuaException luaException) { return Pair.of(null, "NO_VALID_FROMSLOT"); } } if (item.containsKey("toSlot")) { try { - itemFilter.toSlot = TableHelper.getIntField(item, "toSlot"); + itemFilter.toSlot = TableHelper.getIntField(item, "toSlot") - 1; } catch (LuaException luaException) { return Pair.of(null, "NO_VALID_TOSLOT"); } @@ -103,7 +114,7 @@ public static ItemFilter empty() { } public boolean isEmpty() { - return fingerprint.isEmpty() && item == Items.AIR && tag == null && nbt == null; + return fingerprint.isEmpty() && item == Items.AIR && tag == null && nbt == null && nbtHash == null; } public ItemStack toItemStack() { @@ -112,12 +123,19 @@ public ItemStack toItemStack() { return result; } + @Override + public boolean testAE(GenericStack genericStack) { + if (genericStack.what() instanceof AEItemKey aeItemKey) { + return test(aeItemKey.toStack()); + } + return false; + } + public boolean test(ItemStack stack) { if (!fingerprint.isEmpty()) { String testFingerprint = ItemUtil.getFingerprint(stack); return fingerprint.equals(testFingerprint); } - if (item != Items.AIR && !stack.is(item)) { return false; } @@ -127,6 +145,9 @@ public boolean test(ItemStack stack) { if (nbt != null && !stack.getOrCreateTag().equals(nbt)) { return false; } + if (nbtHash != null && !dan200.computercraft.shared.util.NBTUtil.getNBTHash(stack.getOrCreateTag()).equals(nbtHash)) { + return false; + } return true; } @@ -150,12 +171,17 @@ public Tag getNbt() { return nbt; } + public String getNbtHash() { + return nbtHash; + } + @Override public String toString() { return "ItemFilter{" + "item=" + ItemUtil.getRegistryKey(item) + ", tag=" + tag + ", nbt=" + nbt + + ", nbtHash=" + nbtHash + ", count=" + count + ", fingerprint='" + fingerprint + '\'' + ", fromSlot=" + fromSlot + diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemUtil.java b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemUtil.java index 665283d73..87f47ae77 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemUtil.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/inventory/ItemUtil.java @@ -3,14 +3,12 @@ import dan200.computercraft.shared.Registry; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.util.StringUtil; -import net.minecraft.ResourceLocationException; -import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.IForgeRegistry; import org.apache.logging.log4j.Level; import java.nio.charset.StandardCharsets; @@ -27,21 +25,14 @@ public class ItemUtil { public static final Item POCKET_NORMAL = Registry.ModItems.POCKET_COMPUTER_NORMAL.get(); public static final Item POCKET_ADVANCED = Registry.ModItems.POCKET_COMPUTER_ADVANCED.get(); - private ItemUtil() { - } + private ItemUtil() {} - public static T getRegistryEntry(String name, IForgeRegistry forgeRegistry) { - ResourceLocation location; + static MessageDigest getMessageDigest(String algorithm) { try { - location = new ResourceLocation(name); - } catch (ResourceLocationException ex) { - location = null; - } - - T value; - if (location != null && forgeRegistry.containsKey(location) && (value = forgeRegistry.getValue(location)) != null) { - return value; - } else { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + AdvancedPeripherals.debug("Could not generate fingerprint.", Level.ERROR); + ex.printStackTrace(); return null; } } @@ -53,16 +44,16 @@ public static T getRegistryEntry(String name, IForgeRegistry forgeRegistr * @return A generated MD5 hash from the item stack */ public static String getFingerprint(ItemStack stack) { - String fingerprint = stack.getOrCreateTag() + getRegistryKey(stack).toString() + stack.getDisplayName().getString(); - try { - byte[] bytesOfHash = fingerprint.getBytes(StandardCharsets.UTF_8); - MessageDigest md = MessageDigest.getInstance("MD5"); - return StringUtil.toHexString(md.digest(bytesOfHash)); - } catch (NoSuchAlgorithmException ex) { - AdvancedPeripherals.debug("Could not parse fingerprint.", Level.ERROR); - ex.printStackTrace(); + MessageDigest md = getMessageDigest("MD5"); + if (md == null) { + return ""; + } + CompoundTag tag = stack.getTag(); + md.update(getRegistryKey(stack).toString().getBytes(StandardCharsets.UTF_8)); + if (tag != null && !tag.isEmpty()) { + md.update(tag.getAsString().getBytes(StandardCharsets.UTF_8)); } - return ""; + return StringUtil.toHexString(md.digest()); } public static ItemStack makeTurtle(Item turtle, String upgrade) { @@ -87,22 +78,11 @@ public static List getItemsFromItemHandler(IItemHandler handler) { return items; } - public static void addComputerItemToTab(ResourceLocation turtleID, ResourceLocation pocketID, NonNullList items) { - if (turtleID != null) { - items.add(makeTurtle(TURTLE_ADVANCED, turtleID.toString())); - items.add(makeTurtle(TURTLE_NORMAL, turtleID.toString())); - } - if (pocketID != null) { - items.add(makePocket(POCKET_ADVANCED, pocketID.toString())); - items.add(makePocket(POCKET_NORMAL, pocketID.toString())); - } - } - public static ResourceLocation getRegistryKey(Item item) { return ForgeRegistries.ITEMS.getKey(item); } public static ResourceLocation getRegistryKey(ItemStack item) { - return ForgeRegistries.ITEMS.getKey(item.copy().getItem()); + return ForgeRegistries.ITEMS.getKey(item.getItem()); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/AbstractStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/AbstractStorageProxy.java new file mode 100644 index 000000000..b8e007c37 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/AbstractStorageProxy.java @@ -0,0 +1,42 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +public abstract class AbstractStorageProxy implements IStorageProxy { + private final long maxTransferRate; + private volatile long transferRate; + private long transfered = 0; + + protected AbstractStorageProxy(long maxTransferRate) { + this.maxTransferRate = maxTransferRate; + this.transferRate = maxTransferRate; + } + + @Override + public long getMaxTransferRate() { + return this.maxTransferRate; + } + + @Override + public long getTransferRate() { + return this.transferRate; + } + + @Override + public void setTransferRate(long rate) { + this.transferRate = Math.min(rate, this.maxTransferRate); + } + + protected void resetStatus() { + this.transfered = 0; + } + + @Override + public long getAndResetTransfered() { + long transfered = this.transfered; + this.resetStatus(); + return transfered; + } + + protected void onTransfered(long amount) { + this.transfered += amount; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/EnergyStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/EnergyStorageProxy.java new file mode 100644 index 000000000..de4481be4 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/EnergyStorageProxy.java @@ -0,0 +1,74 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +import de.srendi.advancedperipherals.common.blocks.blockentities.EnergyDetectorEntity; +import net.minecraftforge.energy.IEnergyStorage; + +public class EnergyStorageProxy extends AbstractStorageProxy implements IEnergyStorage { + + private final EnergyDetectorEntity energyDetectorTE; + private boolean lastTransfered = false; + private boolean wasReady = false; + private volatile boolean ready = false; + + public EnergyStorageProxy(EnergyDetectorEntity energyDetectorTE, int maxTransferRate) { + super(maxTransferRate); + this.energyDetectorTE = energyDetectorTE; + } + + @Override + public boolean canReceive() { + return true; + } + + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + return energyDetectorTE.getOutputStorage().map(outStorage -> { + int transferred = outStorage.receiveEnergy((int) Math.min(maxReceive, this.getTransferRate()), simulate); + if (!simulate) { + this.wasReady = true; + if (transferred > 0) { + this.lastTransfered = true; + this.onTransfered(transferred); + } + } + return transferred; + }).orElse(0); + } + + @Override + public String getLastTransferedId() { + return this.lastTransfered ? "forge:energy" : null; + } + + @Override + public String getReadyTransferId() { + return this.ready ? "forge:energy" : null; + } + + @Override + protected void resetStatus() { + super.resetStatus(); + this.ready = this.wasReady; + this.wasReady = false; + } + + @Override + public int getEnergyStored() { + return energyDetectorTE.getOutputStorage().map(IEnergyStorage::getEnergyStored).orElse(0); + } + + @Override + public int getMaxEnergyStored() { + return energyDetectorTE.getOutputStorage().map(IEnergyStorage::getMaxEnergyStored).orElse(0); + } + + @Override + public boolean canExtract() { + return false; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + return 0; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/FluidStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/FluidStorageProxy.java new file mode 100644 index 000000000..ceccd2bcc --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/FluidStorageProxy.java @@ -0,0 +1,85 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +import de.srendi.advancedperipherals.common.blocks.blockentities.FluidDetectorEntity; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.NotNull; + +public class FluidStorageProxy extends AbstractStorageProxy implements IFluidHandler { + + private final FluidDetectorEntity fluidDetectorEntity; + private ResourceLocation lastTransfered = null; + private ResourceLocation wasReady = null; + private volatile ResourceLocation ready = null; + + public FluidStorageProxy(FluidDetectorEntity fluidDetectorEntity, int maxTransferRate) { + super(maxTransferRate); + this.fluidDetectorEntity = fluidDetectorEntity; + } + + @Override + public int getTanks() { + return 1; + } + + @Override + public @NotNull FluidStack getFluidInTank(int tank) { + return fluidDetectorEntity.getOutputStorage().map(outStorage -> outStorage.getFluidInTank(tank)).orElse(FluidStack.EMPTY); + } + + @Override + public int getTankCapacity(int tank) { + return fluidDetectorEntity.getOutputStorage().map(outStorage -> outStorage.getTankCapacity(tank)).orElse(0); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return fluidDetectorEntity.getOutputStorage().map(outStorage -> outStorage.isFluidValid(tank, stack)).orElse(false); + } + + @Override + public int fill(FluidStack resource, IFluidHandler.FluidAction action) { + return fluidDetectorEntity.getOutputStorage().map(outStorage -> { + FluidStack transferring = resource.copy(); + transferring.setAmount((int) Math.min(resource.getAmount(), this.getTransferRate())); + int transferred = outStorage.fill(transferring, action); + if (!action.simulate()) { + this.wasReady = ForgeRegistries.FLUIDS.getKey(resource.getFluid()); + if (transferred > 0) { + this.onTransfered(transferred); + this.lastTransfered = this.wasReady; + } + } + return transferred; + }).orElse(0); + } + + @Override + public String getLastTransferedId() { + return this.lastTransfered == null ? null : this.lastTransfered.toString(); + } + + @Override + public String getReadyTransferId() { + return this.ready == null ? null : this.ready.toString(); + } + + @Override + protected void resetStatus() { + super.resetStatus(); + this.ready = this.wasReady; + this.wasReady = null; + } + + @Override + public @NotNull FluidStack drain(int maxDrain, IFluidHandler.FluidAction action) { + return FluidStack.EMPTY; + } + + @Override + public @NotNull FluidStack drain(FluidStack resource, IFluidHandler.FluidAction action) { + return FluidStack.EMPTY; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/GasStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/GasStorageProxy.java new file mode 100644 index 000000000..d2cf8f544 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/GasStorageProxy.java @@ -0,0 +1,95 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +import de.srendi.advancedperipherals.common.blocks.blockentities.GasDetectorEntity; +import mekanism.api.Action; +import mekanism.api.chemical.gas.GasStack; +import mekanism.api.chemical.gas.IGasHandler; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +public class GasStorageProxy extends AbstractStorageProxy implements IGasHandler { + + private final GasDetectorEntity gasDetectorEntity; + private ResourceLocation lastTransfered = null; + private ResourceLocation wasReady = null; + private volatile ResourceLocation ready = null; + + public GasStorageProxy(GasDetectorEntity gasDetectorEntity, int maxTransferRate) { + super(maxTransferRate); + this.gasDetectorEntity = gasDetectorEntity; + } + + @Override + public int getTanks() { + return 1; + } + + @NotNull + @Override + public GasStack getChemicalInTank(int tank) { + return gasDetectorEntity.getOutputStorage().map(outStorage -> outStorage.getChemicalInTank(tank)).orElse(GasStack.EMPTY); + } + + @Override + public void setChemicalInTank(int tank, @NotNull GasStack stack) { + gasDetectorEntity.getOutputStorage().ifPresent(outStorage -> outStorage.setChemicalInTank(tank, stack)); + } + + @Override + public long getTankCapacity(int tank) { + return gasDetectorEntity.getOutputStorage().map(outStorage -> outStorage.getTankCapacity(tank)).orElse(0L); + } + + @Override + public boolean isValid(int tank, @NotNull GasStack stack) { + return gasDetectorEntity.getOutputStorage().map(outStorage -> outStorage.isValid(tank, stack)).orElse(false); + } + + @NotNull + @Override + public GasStack insertChemical(@NotNull GasStack stack, @NotNull Action action) { + return gasDetectorEntity.getOutputStorage().map(outStorage -> { + GasStack transferring = stack.copy(); + transferring.setAmount(Math.min(stack.getAmount(), this.getTransferRate())); + GasStack left = outStorage.insertChemical(transferring, action); + if (!action.simulate()) { + this.wasReady = stack.getTypeRegistryName(); + long transferred = transferring.getAmount() - left.getAmount(); + if (transferred > 0) { + this.onTransfered(transferred); + this.lastTransfered = this.wasReady; + } + } + return left; + }).orElse(GasStack.EMPTY); + } + + @Override + public String getLastTransferedId() { + return this.lastTransfered == null ? null : this.lastTransfered.toString(); + } + + @Override + public String getReadyTransferId() { + return this.ready == null ? null : this.ready.toString(); + } + + @Override + protected void resetStatus() { + super.resetStatus(); + this.ready = this.wasReady; + this.wasReady = null; + } + + @NotNull + @Override + public GasStack insertChemical(int tank, @NotNull GasStack stack, @NotNull Action action) { + return insertChemical(stack, action); + } + + @NotNull + @Override + public GasStack extractChemical(int tank, long amount, @NotNull Action action) { + return GasStack.EMPTY; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/IStorageProxy.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/IStorageProxy.java new file mode 100644 index 000000000..59ddee014 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/IStorageProxy.java @@ -0,0 +1,19 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +import org.jetbrains.annotations.Nullable; + +public interface IStorageProxy { + long getMaxTransferRate(); + + long getTransferRate(); + + void setTransferRate(long rate); + + long getAndResetTransfered(); + + @Nullable + String getLastTransferedId(); + + @Nullable + String getReadyTransferId(); +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/proxy/ZeroGasTank.java b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/ZeroGasTank.java new file mode 100644 index 000000000..bc92925f6 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/util/proxy/ZeroGasTank.java @@ -0,0 +1,47 @@ +package de.srendi.advancedperipherals.common.util.proxy; + +import mekanism.api.Action; +import mekanism.api.chemical.gas.GasStack; +import mekanism.api.chemical.gas.IGasHandler; +import org.jetbrains.annotations.NotNull; + +public class ZeroGasTank implements IGasHandler { + + @Override + public int getTanks() { + return 0; + } + + @NotNull + @Override + public GasStack getChemicalInTank(int tank) { + return GasStack.EMPTY; + } + + @Override + public void setChemicalInTank(int tank, GasStack stack) { + + } + + @Override + public long getTankCapacity(int tank) { + return 0; + } + + @Override + public boolean isValid(int tank, @NotNull GasStack stack) { + return false; + } + + @NotNull + @Override + public GasStack insertChemical(int tank, @NotNull GasStack stack, @NotNull Action action) { + return GasStack.EMPTY; + } + + @NotNull + @Override + public GasStack extractChemical(int tank, long amount, @NotNull Action action) { + return GasStack.EMPTY; + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/village/VillageStructures.java b/src/main/java/de/srendi/advancedperipherals/common/village/VillageStructures.java index d88dd5f0b..2716741e8 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/village/VillageStructures.java +++ b/src/main/java/de/srendi/advancedperipherals/common/village/VillageStructures.java @@ -5,7 +5,11 @@ import de.srendi.advancedperipherals.common.configuration.APConfig; import net.minecraft.core.Registry; import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.worldgen.*; +import net.minecraft.data.worldgen.DesertVillagePools; +import net.minecraft.data.worldgen.PlainVillagePools; +import net.minecraft.data.worldgen.SavannaVillagePools; +import net.minecraft.data.worldgen.SnowyVillagePools; +import net.minecraft.data.worldgen.TaigaVillagePools; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement; diff --git a/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrade.java b/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrade.java index 37509a075..ce91b0037 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrade.java +++ b/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrade.java @@ -115,10 +115,10 @@ private TradeBuilder(WandererTradesEvent event, ItemStack stack, Type type, int * This one is for normal villagers with any type of{@link ItemLike}. * {@link net.minecraft.world.item.Item} or {@link net.minecraft.world.level.block.Block} as example. * - * @param event this should be executed in an event - pass the villager trade event here - * @param itemLike the item for trade - * @param type the trade type - * @param emeraldAmount the emerald amount of the trade + * @param event this should be executed in an event - pass the villager trade event here + * @param itemLike the item for trade + * @param type the trade type + * @param emeraldAmount the emerald amount of the trade * @param professionLevel the profession level of the villager. 1 to 5 * @return a builder instance */ @@ -130,10 +130,10 @@ public static TradeBuilder createTrade(VillagerTradesEvent event, ItemLike itemL * Creates a new TradeBuilder instance. Can be used to create villager trades for normal villagers * This one is for normal villagers with item stacks * - * @param event this should be executed in an event - pass the villager trade event here - * @param itemStack the item for trade - * @param type the trade type - * @param emeraldAmount the emerald amount of the trade + * @param event this should be executed in an event - pass the villager trade event here + * @param itemStack the item for trade + * @param type the trade type + * @param emeraldAmount the emerald amount of the trade * @param professionLevel the profession level of the villager. 1 to 5 * @return a builder instance */ @@ -146,10 +146,10 @@ public static TradeBuilder createTrade(VillagerTradesEvent event, ItemStack item * This one is for wandering traders with any type of{@link ItemLike}. * {@link net.minecraft.world.item.Item} or {@link net.minecraft.world.level.block.Block} as example. * - * @param event this should be executed in an event - pass the villager trade event here - * @param itemLike the item for trade - * @param type the trade type - * @param emeraldAmount the emerald amount of the trade + * @param event this should be executed in an event - pass the villager trade event here + * @param itemLike the item for trade + * @param type the trade type + * @param emeraldAmount the emerald amount of the trade * @param professionLevel the profession level of the villager. 1 to 5 * @return a builder instance */ @@ -161,10 +161,10 @@ public static TradeBuilder createTrade(WandererTradesEvent event, ItemLike itemL * Creates a new TradeBuilder instance. Can be used to create villager trades for wandering traders. * This one is for normal villagers with item stacks * - * @param event this should be executed in an event - pass the villager trade event here - * @param itemStack the item for trade - * @param type the trade type - * @param emeraldAmount the emerald amount of the trade + * @param event this should be executed in an event - pass the villager trade event here + * @param itemStack the item for trade + * @param type the trade type + * @param emeraldAmount the emerald amount of the trade * @param professionLevel the profession level of the villager. 1 to 5 * @return a builder instance */ @@ -213,10 +213,10 @@ public TradeBuilder setXp(int xp) { */ public void build() { VillagerTrade trade = new VillagerTrade(type, emeraldAmount, itemAmount, maxUses, xp, item, itemStack); - if(wandererEvent != null) { - if(professionLevel == 1) + if (wandererEvent != null) { + if (professionLevel == 1) wandererEvent.getGenericTrades().add(trade); - if(professionLevel == 2) + if (professionLevel == 2) wandererEvent.getRareTrades().add(trade); return; } diff --git a/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrades.java b/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrades.java index c53d97ab9..29819f5dc 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrades.java +++ b/src/main/java/de/srendi/advancedperipherals/common/village/VillagerTrades.java @@ -3,10 +3,10 @@ import dan200.computercraft.shared.Registry; import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.configuration.APConfig; -import de.srendi.advancedperipherals.common.setup.Blocks; +import de.srendi.advancedperipherals.common.setup.APBlocks; +import de.srendi.advancedperipherals.common.setup.APItems; +import de.srendi.advancedperipherals.common.setup.APVillagers; import de.srendi.advancedperipherals.common.setup.CCRegistration; -import de.srendi.advancedperipherals.common.setup.Items; -import de.srendi.advancedperipherals.common.setup.Villagers; import de.srendi.advancedperipherals.common.util.inventory.ItemUtil; import net.minecraftforge.event.village.VillagerTradesEvent; import net.minecraftforge.event.village.WandererTradesEvent; @@ -21,7 +21,7 @@ public class VillagerTrades { @SubscribeEvent public static void registerWanderingTrade(WandererTradesEvent event) { if (APConfig.WORLD_CONFIG.enableWanderingTraderTrades.get()) { - TradeBuilder.createTrade(event, Blocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 1) + TradeBuilder.createTrade(event, APBlocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 1) .setMaxUses(8) .build(); TradeBuilder.createTrade(event, Registry.ModBlocks.TURTLE_ADVANCED.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 1) @@ -32,24 +32,27 @@ public static void registerWanderingTrade(WandererTradesEvent event) { @SubscribeEvent public static void registerVillagerTrades(VillagerTradesEvent event) { - if (event.getType() == Villagers.COMPUTER_SCIENTIST.get()) { + if (event.getType() == APVillagers.COMPUTER_SCIENTIST.get()) { + if (!APConfig.WORLD_CONFIG.enableComputerScientistTrades.get()) { + return; + } - TradeBuilder.createTrade(event, Blocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 1) + TradeBuilder.createTrade(event, APBlocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 1) .setXp(1) .build(); - TradeBuilder.createTrade(event, Blocks.CHAT_BOX.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 1) + TradeBuilder.createTrade(event, APBlocks.CHAT_BOX.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 1) .build(); TradeBuilder.createTrade(event, Registry.ModBlocks.MONITOR_NORMAL.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 1) .setItemAmount(2) .build(); - TradeBuilder.createTrade(event, Blocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 1, 1) + TradeBuilder.createTrade(event, APBlocks.PERIPHERAL_CASING.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 1, 1) .setMaxUses(5) .build(); - TradeBuilder.createTrade(event, Blocks.INVENTORY_MANAGER.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 2) + TradeBuilder.createTrade(event, APBlocks.INVENTORY_MANAGER.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 2) .setXp(4) .build(); - TradeBuilder.createTrade(event, Blocks.REDSTONE_INTEGRATOR.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 2) + TradeBuilder.createTrade(event, APBlocks.REDSTONE_INTEGRATOR.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 2, 2) .setXp(3) .build(); TradeBuilder.createTrade(event, Registry.ModBlocks.COMPUTER_ADVANCED.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 3, 2) @@ -64,11 +67,11 @@ public static void registerVillagerTrades(VillagerTradesEvent event) { .setMaxUses(4) .setXp(7) .build(); - TradeBuilder.createTrade(event, Items.CHUNK_CONTROLLER.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 5, 3) + TradeBuilder.createTrade(event, APItems.CHUNK_CONTROLLER.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 5, 3) .setMaxUses(6) .setXp(8) .build(); - TradeBuilder.createTrade(event, Items.COMPUTER_TOOL.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 3) + TradeBuilder.createTrade(event, APItems.COMPUTER_TOOL.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 1, 3) .setMaxUses(1) .setXp(16) .build(); @@ -77,25 +80,25 @@ public static void registerVillagerTrades(VillagerTradesEvent event) { .setItemAmount(4) .build(); - TradeBuilder.createTrade(event, Blocks.ENERGY_DETECTOR.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 4, 4) + TradeBuilder.createTrade(event, APBlocks.ENERGY_DETECTOR.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 4, 4) .setXp(6) .build(); TradeBuilder.createTrade(event, Registry.ModBlocks.COMPUTER_ADVANCED.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 4, 4) .setXp(5) .setMaxUses(3) .build(); - TradeBuilder.createTrade(event, Items.MEMORY_CARD.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 2, 4) + TradeBuilder.createTrade(event, APItems.MEMORY_CARD.get(), VillagerTrade.Type.EMERALD_FOR_ITEM, 2, 4) .setXp(4) .build(); TradeBuilder.createTrade(event, ItemUtil.makeTurtle(ItemUtil.TURTLE_ADVANCED, CCRegistration.ID.CHUNKY_TURTLE.toString()), VillagerTrade.Type.ITEM_FOR_EMERALD, 8, 4) .setXp(7) .build(); - TradeBuilder.createTrade(event, Items.CHUNK_CONTROLLER.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 6, 4) + TradeBuilder.createTrade(event, APItems.CHUNK_CONTROLLER.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 6, 4) .setMaxUses(6) .setXp(6) .build(); - TradeBuilder.createTrade(event, Blocks.ME_BRIDGE.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 4, 5) + TradeBuilder.createTrade(event, APBlocks.ME_BRIDGE.get(), VillagerTrade.Type.ITEM_FOR_EMERALD, 4, 5) .setItemAmount(2) .setXp(4) .build(); diff --git a/src/main/java/de/srendi/advancedperipherals/lib/metaphysics/IFeedableAutomataCore.java b/src/main/java/de/srendi/advancedperipherals/lib/metaphysics/IFeedableAutomataCore.java index 6c3534300..c8a4586ab 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/metaphysics/IFeedableAutomataCore.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/metaphysics/IFeedableAutomataCore.java @@ -1,3 +1,4 @@ package de.srendi.advancedperipherals.lib.metaphysics; -public interface IFeedableAutomataCore {} +public interface IFeedableAutomataCore { +} diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/AutomataCorePeripheral.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/AutomataCorePeripheral.java index 6327b87f6..4c38ed502 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/AutomataCorePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/AutomataCorePeripheral.java @@ -4,6 +4,7 @@ import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleSide; +import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperation; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperationContext; import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; @@ -11,17 +12,18 @@ import de.srendi.advancedperipherals.lib.metaphysics.IAutomataCoreTier; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; + import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; public abstract class AutomataCorePeripheral extends BasePeripheral { - - public static final String ATTR_STORING_TOOL_DURABILITY = "storingToolDurability"; - private final IAutomataCoreTier tier; private final Map attributes = new HashMap<>(); + protected boolean destroyed = false; protected AutomataCorePeripheral(String type, ITurtleAccess turtle, TurtleSide side, IAutomataCoreTier tier) { super(type, new TurtlePeripheralOwner(turtle, side)); @@ -30,6 +32,11 @@ protected AutomataCorePeripheral(String type, ITurtleAccess turtle, TurtleSide s this.tier = tier; } + @Override + public Set getAdditionalTypes() { + return Collections.singleton("automata"); + } + public void addRotationCycle() { addRotationCycle(1); } @@ -84,4 +91,25 @@ public void setAttribute(String attribute) { public Direction validateSide(String direction) throws LuaException { return super.validateSide(direction); } + + public boolean isDestroyed() { + return this.destroyed; + } + + public boolean canActiveOverpower() { + return false; + } + + public abstract double getBreakChance(); + + public boolean afterOverpowerAction() { + if (isDestroyed() || !canActiveOverpower()) { + return false; + } + if (AdvancedPeripherals.RANDOM.nextDouble() <= getBreakChance()) { + this.destroyed = true; + owner.destroyUpgrade(); + } + return true; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheral.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheral.java index 09694d948..78ded5854 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheral.java @@ -1,23 +1,37 @@ package de.srendi.advancedperipherals.lib.peripherals; -import dan200.computercraft.api.lua.*; +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IDynamicPeripheral; import dan200.computercraft.api.peripheral.IPeripheral; +import de.srendi.advancedperipherals.common.addons.APAddons; import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; import de.srendi.advancedperipherals.common.addons.computercraft.owner.OperationAbility; import de.srendi.advancedperipherals.common.addons.computercraft.owner.PeripheralOwnerAbility; +import de.srendi.advancedperipherals.common.addons.valkyrienskies.ValkyrienSkies; import de.srendi.advancedperipherals.common.util.CoordUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; +import net.minecraft.world.phys.Vec3; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; import java.util.function.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class BasePeripheral implements IBasePeripheral, IDynamicPeripheral { @@ -26,7 +40,7 @@ public abstract class BasePeripheral implements IBas protected final O owner; protected final List pluggedMethods = new ArrayList<>(); protected boolean initialized = false; - protected List plugins = null; + protected final List plugins = new LinkedList<>(); protected String[] methodNames = new String[0]; protected BasePeripheral(String type, O owner) { @@ -34,32 +48,41 @@ protected BasePeripheral(String type, O owner) { this.owner = owner; } + protected void clearAllPlugins() { + this.initialized = false; + plugins.clear(); + } + protected void buildPlugins() { - if (!initialized) { - initialized = true; - this.pluggedMethods.clear(); - if (plugins != null) plugins.forEach(plugin -> { - if (plugin.isSuitable(this)) - pluggedMethods.addAll(plugin.getMethods()); - }); - owner.getAbilities().forEach(ability -> { - if (ability instanceof IPeripheralPlugin peripheralPlugin) - pluggedMethods.addAll(peripheralPlugin.getMethods()); - }); - this.methodNames = pluggedMethods.stream().map(BoundMethod::getName).toArray(String[]::new); + if (this.initialized) { + return; } + this.initialized = true; + this.pluggedMethods.clear(); + this.plugins.forEach(plugin -> { + if (plugin.isSuitable(this)) { + this.pluggedMethods.addAll(plugin.getMethods()); + } + }); + owner.getAbilities().forEach(ability -> { + if (ability instanceof IPeripheralPlugin peripheralPlugin) { + this.pluggedMethods.addAll(peripheralPlugin.getMethods()); + } + }); + this.methodNames = this.pluggedMethods.stream().map(BoundMethod::getName).toArray(String[]::new); } protected void addPlugin(@NotNull IPeripheralPlugin plugin) { - if (plugins == null) plugins = new LinkedList<>(); - plugins.add(plugin); + this.plugins.add(plugin); IPeripheralOperation[] operations = plugin.getOperations(); if (operations != null) { OperationAbility operationAbility = owner.getAbility(PeripheralOwnerAbility.OPERATION); - if (operationAbility == null) + if (operationAbility == null) { throw new IllegalArgumentException("This is not possible to attach plugin with operations to not operationable owner"); - for (IPeripheralOperation operation : operations) + } + for (IPeripheralOperation operation : operations) { operationAbility.registerOperation(operation); + } } } @@ -116,14 +139,34 @@ public final Map getConfiguration() { return getPeripheralConfiguration(); } - protected BlockPos getPos() { + public BlockPos getPos() { return owner.getPos(); } - protected Level getLevel() { + public Vec3 getCenterPos() { + return owner.getCenterPos(); + } + + public Level getLevel() { return owner.getLevel(); } + public boolean isOnShip() { + return APAddons.isBlockOnShip(owner.getLevel(), owner.getPos()); + } + + public Vec3 getPhysicsPos() { + Vec3 pos = this.getCenterPos(); + if (!APAddons.vs2Loaded) { + return pos; + } + return ValkyrienSkies.transformToWorldPos(owner.getLevel(), owner.getPos(), pos); + } + + public final BlockPos getPhysicsBlockPos() { + return new BlockPos(this.getPhysicsPos()); + } + protected Direction validateSide(String direction) throws LuaException { return CoordUtil.getDirection(owner.getOrientation(), direction); } @@ -131,16 +174,13 @@ protected Direction validateSide(String direction) throws LuaException { @Override @NotNull public String @NotNull [] getMethodNames() { - if (!initialized) - buildPlugins(); + buildPlugins(); return methodNames; } @Override @NotNull public MethodResult callMethod(@NotNull IComputerAccess access, @NotNull ILuaContext context, int index, @NotNull IArguments arguments) throws LuaException { - if (!initialized) - buildPlugins(); return pluggedMethods.get(index).apply(access, context, arguments); } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheralPlugin.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheralPlugin.java new file mode 100644 index 000000000..1fc8b319f --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/BasePeripheralPlugin.java @@ -0,0 +1,33 @@ +package de.srendi.advancedperipherals.lib.peripherals; + +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.MethodResult; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.IPeripheralOwner; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.OperationAbility; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.PeripheralOwnerAbility; +import org.jetbrains.annotations.Nullable; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public abstract class BasePeripheralPlugin implements IPeripheralPlugin { + protected final IPeripheralOwner owner; + + public BasePeripheralPlugin(IPeripheralOwner owner) { + this.owner = owner; + } + + public IPeripheralOwner getPeripheralOwner() { + return this.owner; + } + + protected MethodResult withOperation(IPeripheralOperation operation, T context, @Nullable IPeripheralCheck check, IPeripheralFunction method, @Nullable Consumer successCallback) throws LuaException { + return withOperation(operation, context, check, method, successCallback, null); + } + + protected MethodResult withOperation(IPeripheralOperation operation, T context, @Nullable IPeripheralCheck check, IPeripheralFunction method, @Nullable Consumer successCallback, @Nullable BiConsumer failCallback) throws LuaException { + OperationAbility operationAbility = this.owner.getAbility(PeripheralOwnerAbility.OPERATION); + if (operationAbility == null) throw new IllegalArgumentException("This shouldn't happen at all"); + return operationAbility.performOperation(operation, context, check, method, successCallback, failCallback); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java index 8fd524d0c..c97099586 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/DisabledPeripheral.java @@ -1,17 +1,18 @@ package de.srendi.advancedperipherals.lib.peripherals; import dan200.computercraft.api.pocket.IPocketAccess; +import dan200.computercraft.api.pocket.IPocketUpgrade; import de.srendi.advancedperipherals.common.addons.computercraft.owner.PocketPeripheralOwner; public class DisabledPeripheral extends BasePeripheral { - public static final DisabledPeripheral INSTANCE = new DisabledPeripheral("disabledPeripheral", null); + public static final DisabledPeripheral INSTANCE = new DisabledPeripheral("disabledPeripheral", null, null); - private DisabledPeripheral(String type, IPocketAccess access) { - super(type, new PocketPeripheralOwner(access)); + private DisabledPeripheral(String type, IPocketAccess access, IPocketUpgrade upgrade) { + super(type, new PocketPeripheralOwner(access, upgrade)); } @Override public boolean isEnabled() { - return true; + return false; } } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IBasePeripheral.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IBasePeripheral.java index 8836997dc..2bdd8fadc 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IBasePeripheral.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IBasePeripheral.java @@ -9,5 +9,13 @@ public interface IBasePeripheral extends IPeripheral Iterable getConnectedComputers(); + default void queueEvent(String event, Object... args) { + for (IComputerAccess computer : getConnectedComputers()) { + computer.queueEvent(event, args); + } + } + T getPeripheralOwner(); + + default void update() {} } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IPeripheralTileEntity.java b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IPeripheralTileEntity.java index 47c526faa..cc3caa796 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IPeripheralTileEntity.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/peripherals/IPeripheralTileEntity.java @@ -11,8 +11,5 @@ public interface IPeripheralTileEntity { void markSettingsChanged(); - default void handleTick(Level level, BlockState state, BlockEntityType type) { - - } - + default void handleTick(Level level, BlockState state, BlockEntityType type) {} } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java b/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java index 291a333de..ea6e01fdd 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/pocket/BasePocketUpgrade.java @@ -28,4 +28,12 @@ public IPeripheral createPeripheral(@NotNull IPocketAccess access) { if (!peripheral.isEnabled()) return DisabledPeripheral.INSTANCE; return peripheral; } + + @Override + public void update(@NotNull IPocketAccess access, @Nullable IPeripheral peripheral) { + super.update(access, peripheral); + if (peripheral instanceof IBasePeripheral basePeripheral) { + basePeripheral.update(); + } + } } diff --git a/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java b/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java index 2f06c5944..9171dc811 100644 --- a/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java +++ b/src/main/java/de/srendi/advancedperipherals/lib/turtle/PeripheralTurtleUpgrade.java @@ -47,4 +47,12 @@ public boolean isItemSuitable(@NotNull ItemStack stack) { } return super.isItemSuitable(stack); } + + @Override + public void update(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { + super.update(turtle, side); + if (!turtle.getLevel().isClientSide() && turtle.getPeripheral(side) instanceof IBasePeripheral basePeripheral) { + basePeripheral.update(); + } + } } diff --git a/src/main/java/de/srendi/advancedperipherals/network/APNetworking.java b/src/main/java/de/srendi/advancedperipherals/network/APNetworking.java deleted file mode 100644 index f1064f26e..000000000 --- a/src/main/java/de/srendi/advancedperipherals/network/APNetworking.java +++ /dev/null @@ -1,75 +0,0 @@ -package de.srendi.advancedperipherals.network; - -import de.srendi.advancedperipherals.AdvancedPeripherals; -import de.srendi.advancedperipherals.network.base.IPacket; -import de.srendi.advancedperipherals.network.toclient.ToastToClientPacket; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.network.simple.SimpleChannel; - -import java.util.Optional; -import java.util.function.Function; - -public class APNetworking { - private static final String PROTOCOL_VERSION = ModLoadingContext.get().getActiveContainer().getModInfo().getVersion().toString(); - private static final SimpleChannel NETWORK_CHANNEL = NetworkRegistry.newSimpleChannel(new ResourceLocation(AdvancedPeripherals.MOD_ID, "main_channel"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals); - private static int id = 0; - - public static void init() { - registerServerToClient(ToastToClientPacket.class, ToastToClientPacket::decode); - } - - public static void registerServerToClient(Class packet, Function decode) { - NETWORK_CHANNEL.registerMessage(id++, packet, IPacket::encode, decode, IPacket::handle, Optional.of(NetworkDirection.PLAY_TO_CLIENT)); - } - - public static void registerClientToServer(Class packet, Function decode) { - NETWORK_CHANNEL.registerMessage(id++, packet, IPacket::encode, decode, IPacket::handle, Optional.of(NetworkDirection.PLAY_TO_SERVER)); - } - - /** - * Sends a packet to the server.

- * Must be called Client side. - */ - public static void sendToServer(Object msg) { - NETWORK_CHANNEL.sendToServer(msg); - } - - /** - * Send a packet to a specific player.

- * Must be called Server side. - */ - public static void sendTo(Object msg, ServerPlayer player) { - if (!(player instanceof FakePlayer)) { - NETWORK_CHANNEL.send(PacketDistributor.PLAYER.with(() -> player), msg); - } - } - - public static void sendPacketToAll(Object packet) { - NETWORK_CHANNEL.send(PacketDistributor.ALL.noArg(), packet); - } - - public static ClientboundBlockEntityDataPacket createTEUpdatePacket(BlockEntity tile) { - return ClientboundBlockEntityDataPacket.create(tile); - } - - public static void sendToAllAround(Object mes, ResourceKey dim, BlockPos pos, int radius) { - NETWORK_CHANNEL.send(PacketDistributor.NEAR.with(() -> new PacketDistributor.TargetPoint(pos.getX(), pos.getY(), pos.getZ(), radius, dim)), mes); - } - - public static void sendToAllInWorld(Object mes, ServerLevel world) { - NETWORK_CHANNEL.send(PacketDistributor.DIMENSION.with(world::dimension), mes); - } -} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index be93663b7..ceffd3bc5 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -2,3 +2,6 @@ public net.minecraft.world.level.block.entity.BeaconBlockEntity f_58652_ public net.minecraft.world.level.block.entity.BeaconBlockEntity f_58653_ public-f net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool f_210559_ # rawTemplates public-f net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool f_210560_ # templates +protected net.minecraft.world.level.ClipContext f_45686_ # collisionContext +public net.minecraft.world.level.block.entity.BeaconBlockEntity f_58650_ # levels +public net.minecraft.world.phys.shapes.VoxelShape m_83294_(Lnet/minecraft/core/Direction;)Lnet/minecraft/world/phys/shapes/VoxelShape; # calculateFace \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 33142efab..5ff034ed1 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,7 +1,7 @@ modLoader = "javafml" loaderVersion = "[${loader_version},)" -license = "All rights reserved" -issueTrackerURL = "https://github.com/Seniorendi/AdvancedPeripherals/issues" +license = "Apache-2.0" +issueTrackerURL = "https://github.com/IntelligenceModding/AdvancedPeripherals/issues" logoFile = "pack.png" [[mods]] modId = "${mod_id}" @@ -29,7 +29,7 @@ side = "BOTH" modId = "computercraft" mandatory = true versionRange = "[${cc_version},)" -ordering = "NONE" +ordering = "AFTER" side = "BOTH" [[dependencies.${mod_id}]] modId = "curios" diff --git a/src/main/resources/assets/advancedperipherals/models/item/ar_goggles.json b/src/main/resources/assets/advancedperipherals/models/item/ar_goggles.json deleted file mode 100644 index 8cedf86ab..000000000 --- a/src/main/resources/assets/advancedperipherals/models/item/ar_goggles.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "advancedperipherals:item/ar_goggles" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/cable_p2p_tunnel.json b/src/main/resources/assets/advancedperipherals/models/item/cable_p2p_tunnel.json new file mode 100644 index 000000000..334ded781 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/cable_p2p_tunnel.json @@ -0,0 +1,6 @@ +{ + "parent": "ae2:item/p2p_tunnel_base", + "textures": { + "type": "computercraft:block/wired_modem_face" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/distance_detector.json b/src/main/resources/assets/advancedperipherals/models/item/distance_detector.json new file mode 100644 index 000000000..a082e96e2 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/distance_detector.json @@ -0,0 +1,3 @@ +{ + "parent": "advancedperipherals:block/distance_detector" +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/fluid_detector.json b/src/main/resources/assets/advancedperipherals/models/item/fluid_detector.json new file mode 100644 index 000000000..1b807b14c --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/fluid_detector.json @@ -0,0 +1,3 @@ +{ + "parent": "advancedperipherals:block/fluid_detector" +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/gas_detector.json b/src/main/resources/assets/advancedperipherals/models/item/gas_detector.json new file mode 100644 index 000000000..ccfae0e7e --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/gas_detector.json @@ -0,0 +1,3 @@ +{ + "parent": "advancedperipherals:block/gas_detector" +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/glasses_interface.json b/src/main/resources/assets/advancedperipherals/models/item/glasses_interface.json new file mode 100644 index 000000000..9360dcabb --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/glasses_interface.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/glasses_interface" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/hotkey_module.json b/src/main/resources/assets/advancedperipherals/models/item/hotkey_module.json new file mode 100644 index 000000000..32d09adea --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/hotkey_module.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/hotkey_module" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/memory_card.json b/src/main/resources/assets/advancedperipherals/models/item/memory_card.json index 0579cb7a6..c39681fc7 100644 --- a/src/main/resources/assets/advancedperipherals/models/item/memory_card.json +++ b/src/main/resources/assets/advancedperipherals/models/item/memory_card.json @@ -1,6 +1,14 @@ { - "parent": "item/generated", + "parent": "minecraft:item/generated", "textures": { "layer0": "advancedperipherals:item/memory_card" - } + }, + "overrides": [ + { + "predicate": { + "advancedperipherals:bounded": 1 + }, + "model": "advancedperipherals:item/memory_card_bounded" + } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/memory_card_bounded.json b/src/main/resources/assets/advancedperipherals/models/item/memory_card_bounded.json new file mode 100644 index 000000000..cf7733990 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/memory_card_bounded.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/memory_card_bounded" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/nightvision_module.json b/src/main/resources/assets/advancedperipherals/models/item/nightvision_module.json new file mode 100644 index 000000000..5a3622d06 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/nightvision_module.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/nightvision_module" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/overlay_module.json b/src/main/resources/assets/advancedperipherals/models/item/overlay_module.json new file mode 100644 index 000000000..1cd0fb85d --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/overlay_module.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/overlay_module" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/smart_glasses.json b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses.json new file mode 100644 index 000000000..bc29777ce --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/smart_glasses" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_interface.json b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_interface.json new file mode 100644 index 000000000..f833bbd1a --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_interface.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/smart_glasses_interface" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_netherite.json b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_netherite.json new file mode 100644 index 000000000..cf1262ab3 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/smart_glasses_netherite.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "advancedperipherals:item/smart_glasses_netherite" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/models/part/p2p/p2p_tunnel_cable.json b/src/main/resources/assets/advancedperipherals/models/part/p2p/p2p_tunnel_cable.json new file mode 100644 index 000000000..6baaf6042 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/part/p2p/p2p_tunnel_cable.json @@ -0,0 +1,6 @@ +{ + "parent": "ae2:part/p2p/p2p_tunnel_base", + "textures": { + "type": "computercraft:block/wired_modem_face" + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/ar_controller.png b/src/main/resources/assets/advancedperipherals/textures/block/ar_controller.png deleted file mode 100644 index 2fe546d82..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/ar_controller.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/ar_controller_front.png b/src/main/resources/assets/advancedperipherals/textures/block/ar_controller_front.png deleted file mode 100644 index a12c37923..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/ar_controller_front.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_down.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_down.png index c42740fa5..4e039835c 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_down.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_down.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_east.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_east.png index a6d3a2147..b2fac00a7 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_east.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_east.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png index b7d47a1c5..7a6bc401d 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png.mcmeta new file mode 100644 index 000000000..3d932eea7 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_north.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_south.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_south.png index b7963a0f9..f832cce92 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_south.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_south.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_up.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_up.png index 753304160..300540c6e 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_up.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_up.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_west.png b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_west.png index 7dc2aa101..3523ec91e 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/block_reader_west.png and b/src/main/resources/assets/advancedperipherals/textures/block/block_reader_west.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/bottom.png b/src/main/resources/assets/advancedperipherals/textures/block/bottom.png new file mode 100644 index 000000000..604ecb267 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/bottom.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/chat_box.png b/src/main/resources/assets/advancedperipherals/textures/block/chat_box.png index 1fc9a3ce9..134492be4 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/chat_box.png and b/src/main/resources/assets/advancedperipherals/textures/block/chat_box.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png index 0eca0ed3c..39868fc90 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/chat_box_top.png b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_top.png new file mode 100644 index 000000000..093f9a493 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/chat_box_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator.png b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator.png index e2e6b3ecd..eec100570 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator.png and b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png new file mode 100644 index 000000000..408810795 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png.mcmeta new file mode 100644 index 000000000..09eaec921 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 4 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_top.png b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_top.png new file mode 100644 index 000000000..3791355cb Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/colony_integrator_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_down.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_down.png new file mode 100644 index 000000000..cae832bbb Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_down.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_east.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_east.png new file mode 100644 index 000000000..d6d901d72 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_east.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_north.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_north.png new file mode 100644 index 000000000..0c3c26a82 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_north.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_south.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_south.png new file mode 100644 index 000000000..871968172 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_south.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_up.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_up.png new file mode 100644 index 000000000..13e0a0008 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_up.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_west.png b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_west.png new file mode 100644 index 000000000..bd82f778a Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/distance_detector_west.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector.png b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector.png index 3d23b2e88..5b994935b 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector.png and b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_back.png b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_back.png index 231a2e1e5..044eef38b 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_back.png and b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_back.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png new file mode 100644 index 000000000..f1609811f Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_east.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_front.png b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_front.png index eed36711f..b08e24afc 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_top.png b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_top.png new file mode 100644 index 000000000..a0c133c96 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/energy_detector_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector.png b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector.png index 3fc5af452..3f9a235c7 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector.png and b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png index 9b8a97a4f..2d3a1748a 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png.mcmeta new file mode 100644 index 000000000..09eaec921 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 4 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_top.png b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_top.png new file mode 100644 index 000000000..12bc33d06 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/environment_detector_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector.png b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector.png new file mode 100644 index 000000000..11e2eff13 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_back.png b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_back.png new file mode 100644 index 000000000..35fa025c6 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_back.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png new file mode 100644 index 000000000..61d6701eb Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_east.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_front.png b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_front.png new file mode 100644 index 000000000..071da91ff Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_top.png b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_top.png new file mode 100644 index 000000000..0b69a78a4 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/fluid_detector_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector.png b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector.png new file mode 100644 index 000000000..f7ae0047a Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_back.png b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_back.png new file mode 100644 index 000000000..e1b8d3304 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_back.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png new file mode 100644 index 000000000..106e4b829 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_east.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_front.png b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_front.png new file mode 100644 index 000000000..fb82941be Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_top.png b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_top.png new file mode 100644 index 000000000..10e66c3f9 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/gas_detector_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner.png b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner.png index c3be1ef20..6c37614cb 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner.png and b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png index 6252d7513..51c005da3 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png.mcmeta new file mode 100644 index 000000000..d6331b7cf --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": true, + "frametime": 4 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_top.png b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_top.png new file mode 100644 index 000000000..c4e38cc3b Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/geo_scanner_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager.png b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager.png index f928023f2..e4d76f393 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager.png and b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_front.png b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_front.png index 9d26f1f0e..932fbf477 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_top.png b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_top.png new file mode 100644 index 000000000..f6c8a30b2 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/inventory_manager_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge.png b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge.png index aad32c54b..0f33f12f0 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge.png and b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png index d9ee04417..72745ec1b 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_top.png b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_top.png new file mode 100644 index 000000000..cdc50a6a8 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/me_bridge_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage.png b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage.png index fb9f580b9..339272ef8 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage.png and b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png index e84078a3c..ebd09c27a 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_top.png b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_top.png new file mode 100644 index 000000000..78f6c6d3a Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/nbt_storage_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/peripheral_casing.png b/src/main/resources/assets/advancedperipherals/textures/block/peripheral_casing.png index 20aa776ea..258a10387 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/peripheral_casing.png and b/src/main/resources/assets/advancedperipherals/textures/block/peripheral_casing.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/player_detector.png b/src/main/resources/assets/advancedperipherals/textures/block/player_detector.png deleted file mode 100644 index 0ee0bb55b..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/player_detector.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/player_detector_front.png b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_front.png index a2ee80d43..cb29846f2 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/player_detector_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/player_detector_side.png b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_side.png index 19dc3a6e8..adb368100 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/player_detector_side.png and b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_side.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/player_detector_top.png b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_top.png new file mode 100644 index 000000000..e2cb43a5d Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/player_detector_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator.png b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator.png deleted file mode 100644 index f3c6599cc..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_bottom.png b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_bottom.png new file mode 100644 index 000000000..9401704ad Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_bottom.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png index 8458ee4c2..a5ab834f7 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_side.png b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_side.png new file mode 100644 index 000000000..dee7029f0 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_side.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_top.png b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_top.png new file mode 100644 index 000000000..4d3238964 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/redstone_integrator_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge.png b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge.png index e1b45deb4..1018593f5 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge.png and b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png index 45b15f398..e94fa1d59 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png and b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png.mcmeta b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png.mcmeta new file mode 100644 index 000000000..9559c00e4 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_front.png.mcmeta @@ -0,0 +1,6 @@ +{ + "animation": { + "interpolate": false, + "frametime": 2 + } +} diff --git a/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_top.png b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_top.png new file mode 100644 index 000000000..38c98a90f Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/block/rs_bridge_top.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/entity/villager/profession/computer_scientist.png b/src/main/resources/assets/advancedperipherals/textures/entity/villager/profession/computer_scientist.png index c42e1afbe..732775fc5 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/entity/villager/profession/computer_scientist.png and b/src/main/resources/assets/advancedperipherals/textures/entity/villager/profession/computer_scientist.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/entity/zombie_villager/profession/computer_scientist.png b/src/main/resources/assets/advancedperipherals/textures/entity/zombie_villager/profession/computer_scientist.png index d5e7a619c..e1acca553 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/entity/zombie_villager/profession/computer_scientist.png and b/src/main/resources/assets/advancedperipherals/textures/entity/zombie_villager/profession/computer_scientist.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/gui/corners_glasses.png b/src/main/resources/assets/advancedperipherals/textures/gui/corners_glasses.png new file mode 100644 index 000000000..18cf12823 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/gui/corners_glasses.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/gui/inventory_manager_gui.png b/src/main/resources/assets/advancedperipherals/textures/gui/inventory_manager_gui.png index dffcdff01..89175818d 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/gui/inventory_manager_gui.png and b/src/main/resources/assets/advancedperipherals/textures/gui/inventory_manager_gui.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/gui/smart_glasses_gui.png b/src/main/resources/assets/advancedperipherals/textures/gui/smart_glasses_gui.png new file mode 100644 index 000000000..7606b08a6 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/gui/smart_glasses_gui.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/ar_goggles.png b/src/main/resources/assets/advancedperipherals/textures/item/ar_goggles.png deleted file mode 100644 index 2fc985a12..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/ar_goggles.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/book.png b/src/main/resources/assets/advancedperipherals/textures/item/book.png index 6d5971d6d..bf4aae4be 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/book.png and b/src/main/resources/assets/advancedperipherals/textures/item/book.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/chunk_controller.png b/src/main/resources/assets/advancedperipherals/textures/item/chunk_controller.png index 11577536f..618db58d5 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/chunk_controller.png and b/src/main/resources/assets/advancedperipherals/textures/item/chunk_controller.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/computer_tool.png b/src/main/resources/assets/advancedperipherals/textures/item/computer_tool.png index 6e5491733..ecfe966c9 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/computer_tool.png and b/src/main/resources/assets/advancedperipherals/textures/item/computer_tool.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/empty_glasses_slot.png b/src/main/resources/assets/advancedperipherals/textures/item/empty_glasses_slot.png deleted file mode 100644 index 2f5d24e17..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/empty_glasses_slot.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/hotkey_module.png b/src/main/resources/assets/advancedperipherals/textures/item/hotkey_module.png new file mode 100644 index 000000000..e186c67f7 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/hotkey_module.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/memory_card.png b/src/main/resources/assets/advancedperipherals/textures/item/memory_card.png index 6da07f35e..5bd876fe5 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/memory_card.png and b/src/main/resources/assets/advancedperipherals/textures/item/memory_card.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/memory_card_bounded.png b/src/main/resources/assets/advancedperipherals/textures/item/memory_card_bounded.png new file mode 100644 index 000000000..df68ddf90 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/memory_card_bounded.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/base_gear.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/base_gear.png index 062ce0b12..a12585f2b 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/base_gear.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/base_gear.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire.png index f93c7193c..38b4ee20a 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_green.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_green.png index 10531427a..5e20e64b7 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_green.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_green.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_purple.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_purple.png index 824e63d55..3fdccd14d 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_purple.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/big_fire_purple.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire.png index 65690e8d4..8986741f1 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_green.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_green.png index ee4af9c9b..d5c2475e6 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_green.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_green.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_purple.png b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_purple.png index 97d2f2da2..5492c65e8 100644 Binary files a/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_purple.png and b/src/main/resources/assets/advancedperipherals/textures/item/metaphysics/fire_purple.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/nightvision_module.png b/src/main/resources/assets/advancedperipherals/textures/item/nightvision_module.png new file mode 100644 index 000000000..a550b780b Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/nightvision_module.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/overlay_module.png b/src/main/resources/assets/advancedperipherals/textures/item/overlay_module.png new file mode 100644 index 000000000..1af92e401 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/overlay_module.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses.png b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses.png new file mode 100644 index 000000000..3f7d76870 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_interface.png b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_interface.png new file mode 100644 index 000000000..d17ddf30c Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_interface.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_netherite.png b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_netherite.png new file mode 100644 index 000000000..631d797d9 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/smart_glasses_netherite.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/models/ar_goggles.png b/src/main/resources/assets/advancedperipherals/textures/models/ar_goggles.png deleted file mode 100644 index 5ec507c48..000000000 Binary files a/src/main/resources/assets/advancedperipherals/textures/models/ar_goggles.png and /dev/null differ diff --git a/src/main/resources/assets/advancedperipherals/textures/models/armor/netherite_glasses_layer_1.png b/src/main/resources/assets/advancedperipherals/textures/models/armor/netherite_glasses_layer_1.png new file mode 100644 index 000000000..c2aa67e3f Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/models/armor/netherite_glasses_layer_1.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/models/armor/smart_glasses_layer_1.png b/src/main/resources/assets/advancedperipherals/textures/models/armor/smart_glasses_layer_1.png new file mode 100644 index 000000000..c9bb9ddbe Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/models/armor/smart_glasses_layer_1.png differ diff --git a/src/main/resources/assets/advancedperipherals/textures/slot/empty_glasses_slot.png b/src/main/resources/assets/advancedperipherals/textures/slot/empty_glasses_slot.png new file mode 100644 index 000000000..df1718853 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/slot/empty_glasses_slot.png differ diff --git a/src/main/resources/data/advancedperipherals/loot_tables/chest/scientist_common.json b/src/main/resources/data/advancedperipherals/loot_tables/chest/scientist_common.json new file mode 100644 index 000000000..8f7871296 --- /dev/null +++ b/src/main/resources/data/advancedperipherals/loot_tables/chest/scientist_common.json @@ -0,0 +1,133 @@ +{ + "type": "minecraft:chest", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "minecraft:diamond" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "advancedperipherals:weak_automata_core" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "advancedperipherals:peripheral_casing", + "weight": 5 + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 5.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "minecraft:iron_ingot", + "weight": 5 + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "minecraft:gold_ingot" + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "minecraft:bread", + "weight": 10 + }, + { + "type": "minecraft:item", + "name": "minecraft:iron_pickaxe", + "weight": 5 + }, + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + } + ], + "name": "minecraft:coal" + }, + { + "type": "minecraft:item", + "name": "minecraft:iron_shovel", + "weight": 5 + } + ], + "rolls": { + "type": "minecraft:uniform", + "max": 8.0, + "min": 3.0 + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/advancedperipherals/structures/villages/scientist_taiga.nbt b/src/main/resources/data/advancedperipherals/structures/villages/scientist_taiga.nbt index fff19535b..f154b6eb9 100644 Binary files a/src/main/resources/data/advancedperipherals/structures/villages/scientist_taiga.nbt and b/src/main/resources/data/advancedperipherals/structures/villages/scientist_taiga.nbt differ diff --git a/src/main/resources/data/computercraft/lua/rom/programs/flat.lua b/src/main/resources/data/computercraft/lua/rom/programs/flat.lua new file mode 100644 index 000000000..05956edff --- /dev/null +++ b/src/main/resources/data/computercraft/lua/rom/programs/flat.lua @@ -0,0 +1 @@ +print("The earth is flat, at least in minecraft!") \ No newline at end of file diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 1c0067a65..4cf3c0150 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,7 +1,6 @@ { "pack": { "description": "Advanced peripherals resources", - "pack_format": 8, - "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." + "pack_format": 10 } } diff --git a/src/testMod/java/de/srendi/advancedperipherals/gametest/TestGameTests.java b/src/testMod/java/de/srendi/advancedperipherals/gametest/TestGameTests.java new file mode 100644 index 000000000..11a9bc84e --- /dev/null +++ b/src/testMod/java/de/srendi/advancedperipherals/gametest/TestGameTests.java @@ -0,0 +1,17 @@ +package de.srendi.advancedperipherals.gametest; + +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.gametest.PrefixGameTestTemplate; + +@GameTestHolder("advancedperipheralstest") +public class TestGameTests { + + @PrefixGameTestTemplate(false) + @GameTest(templateNamespace = "advancedperipheralstest") + public static void envDetectorTest(GameTestHelper helper) { + helper.succeed(); + } + +}