├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── changelog.txt ├── deploy.sh ├── docs ├── .vuepress │ ├── components │ │ ├── Foo │ │ │ └── Bar.vue │ │ ├── OtherComponent.vue │ │ └── demo-component.vue │ ├── config.js │ ├── enhanceApp.js │ ├── public │ │ └── logo.png │ └── styles │ │ ├── index.styl │ │ └── palette.styl ├── guide │ ├── README.md │ ├── assets │ │ ├── images │ │ │ ├── automation_chunks.png │ │ │ ├── automation_delays.png │ │ │ ├── automation_logic_gates.png │ │ │ ├── logofull.png │ │ │ ├── logofull1.png │ │ │ ├── original │ │ │ │ ├── logofull.png │ │ │ │ └── logofull1.png │ │ │ ├── service_block_icon.png │ │ │ ├── service_block_screen.png │ │ │ ├── service_developer_tools.png │ │ │ ├── state_block_icon.png │ │ │ ├── state_block_screen.png │ │ │ └── state_developer_tools.png │ │ └── videos │ │ │ ├── automation_example01.mp4 │ │ │ ├── service_block_example01.mp4 │ │ │ ├── state_block_example01.mp4 │ │ │ ├── state_block_example02.mp4 │ │ │ ├── state_block_example03.mp4 │ │ │ └── state_block_example04.mp4 │ ├── building-automations.md │ ├── configuration.md │ ├── faq.md │ ├── installation.md │ ├── service-block.md │ └── state-block.md └── index.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── package-lock.json ├── package.json └── src └── main ├── java └── com │ └── codestian │ └── homeassistantmc │ ├── HomeAssistantMC.java │ ├── block │ ├── ServiceBlock.java │ └── StateBlock.java │ ├── client │ └── gui │ │ ├── ServiceScreen.java │ │ └── StateScreen.java │ ├── commands │ └── Command.java │ ├── config │ ├── Config.java │ └── WebSocketConfig.java │ ├── event │ └── ServerEvent.java │ ├── init │ ├── ModBlocks.java │ ├── ModItems.java │ └── ModTileEntities.java │ ├── network │ ├── Network.java │ └── message │ │ ├── OpenServiceHandler.java │ │ ├── OpenServiceScreen.java │ │ ├── OpenStateHandler.java │ │ ├── OpenStateScreen.java │ │ ├── UpdateServiceBlockData.java │ │ └── UpdateStateBlockData.java │ ├── te │ ├── ServiceTileEntity.java │ └── StateTileEntity.java │ ├── websocket │ └── WebSocket.java │ └── worldsaveddata │ └── EntityData.java └── resources ├── META-INF └── mods.toml ├── assets └── homeassistantmc │ ├── blockstates │ ├── service_block.json │ └── state_block.json │ ├── lang │ └── en_us.json │ ├── models │ ├── block │ │ ├── service_block.json │ │ ├── state_block_off.json │ │ └── state_block_on.json │ └── item │ │ ├── service_block.json │ │ └── state_block.json │ └── textures │ └── blocks │ ├── service_block_side.png │ ├── service_block_top.png │ ├── state_block_side_off.png │ ├── state_block_side_on.png │ └── state_block_top.png ├── logo.png └── pack.mcmeta /.gitattributes: -------------------------------------------------------------------------------- 1 | # Disable autocrlf on generated files, they always generate with LF 2 | # Add any extra files or paths here to make git stop saying they 3 | # are changed when only line endings change. 4 | src/generated/**/.cache/cache text eol=lf 5 | src/generated/**/*.json text eol=lf 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: codestian 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | 24 | # docs 25 | /node_modules 26 | .DS_Store 27 | docs/.vuepress/.temp/ 28 | docs/.vuepress/.cache/ 29 | docs/.vuepress/dist 30 | 31 | # Files from Forge MDK 32 | forge*changelog.txt 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Codestian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo of HomeAssistantMC](https://i.imgur.com/9SMxBA5.png) 2 | 3 | HomeAssistantMC is a Minecraft mod that integrates Home Assistant to Minecraft, allowing retrieval of entity states and calling of services. This allows you to build and execute automations entirely ingame. 4 | 5 | ## Documentation 6 | Setup, configure and learn how to use HomeAssistantMC on the [documentation site](https://codestian.github.io/HomeAssistantMC/). 7 | 8 | ## Project Setup 9 | 10 | To build HomeAssistantMC from source code, clone the repository and open a Java IDE (IntelliJ recommended). Generate the run configurations with either `gradlew genEclipseRuns` (Eclipse) or `gradlew genIntellijRuns` (IntelliJ). Run `gradlew build` to generate the .jar file. 11 | 12 | For the documentation site, run `npm install` followed by `npm run dev`. The site is built with Vuepress written in markdown format. -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url = 'https://maven.minecraftforge.net' } 4 | mavenCentral() 5 | } 6 | dependencies { 7 | classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true 8 | } 9 | } 10 | 11 | plugins { 12 | // Shadow jar includes our libraries into our final jar 13 | id 'com.github.johnrengelman.shadow' version '6.1.0' 14 | } 15 | 16 | apply plugin: 'net.minecraftforge.gradle' 17 | apply plugin: 'eclipse' 18 | apply plugin: 'maven-publish' 19 | 20 | version = '1.0.0' 21 | group = 'com.codestian.homeassistantmc' 22 | archivesBaseName = 'homeassistantmc' 23 | 24 | java.toolchain.languageVersion = JavaLanguageVersion.of(8) 25 | 26 | println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) 27 | minecraft { 28 | mappings channel: 'official', version: '1.16.5' 29 | runs { 30 | client { 31 | workingDirectory project.file('run') 32 | property 'forge.logging.markers', 'REGISTRIES' 33 | property 'forge.logging.console.level', 'debug' 34 | mods { 35 | homeassistantmc { 36 | source sourceSets.main 37 | } 38 | } 39 | } 40 | 41 | server { 42 | workingDirectory project.file('run') 43 | property 'forge.logging.markers', 'REGISTRIES' 44 | property 'forge.logging.console.level', 'debug' 45 | mods { 46 | homeassistantmc { 47 | source sourceSets.main 48 | } 49 | } 50 | } 51 | 52 | data { 53 | workingDirectory project.file('run') 54 | property 'forge.logging.markers', 'REGISTRIES' 55 | property 'forge.logging.console.level', 'debug' 56 | args '--mod', 'examplemod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') 57 | mods { 58 | homeassistantmc { 59 | source sourceSets.main 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | sourceSets.main.resources { srcDir 'src/generated/resources' } 67 | 68 | dependencies { 69 | minecraft 'net.minecraftforge:forge:1.16.5-36.1.16' 70 | shadow implementation(group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.5.2') 71 | shadow implementation(group: 'org.yaml', name: 'snakeyaml', version: '1.28') 72 | } 73 | 74 | jar { 75 | manifest { 76 | attributes([ 77 | "Specification-Title": "homeassistantmc", 78 | "Specification-Vendor": "codestian", 79 | "Specification-Version": "1", // We are version 1 of ourselves 80 | "Implementation-Title": project.name, 81 | "Implementation-Version": "${version}", 82 | "Implementation-Vendor" :"codestian", 83 | "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") 84 | ]) 85 | } 86 | } 87 | 88 | shadowJar { 89 | classifier '' 90 | 91 | configurations = [project.configurations.shadow] 92 | relocate('org.java-websocket', 'com.codestian.homeassistantmc.repackage.org.java-websocket') 93 | relocate('org.yaml', 'com.codestian.homeassistantmc.repackage.org.yaml') 94 | manifest.attributes(jar.manifest.getAttributes()) 95 | } 96 | reobf { 97 | // We want the output of the following tasks to be reobfuscated 98 | // More info at "https://github.com/MinecraftForge/MinecraftForge/blob/b6ce4fb066eb886a305f0678649c33d6f8ba4f76/mdk/build.gradle#L157-L161" 99 | shadowJar {} 100 | } 101 | 102 | jar.finalizedBy('reobfJar') 103 | 104 | publishing { 105 | publications { 106 | mavenJava(MavenPublication) { 107 | artifact jar 108 | } 109 | } 110 | repositories { 111 | maven { 112 | url "file:///${project.projectDir}/mcmodsrepo" 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | Build: 1.16.5-36.1.16 - Fri Apr 30 17:59:06 GMT 2021 2 | trikzon: 3 | Add barrels and barrels/wooden block and item tag (#7676) 4 | 5 | ========= 6 | Build: 1.16.5-36.1.15 - Fri Apr 30 17:52:19 GMT 2021 7 | knightminer4: 8 | Fix shears not properly breaking tripwire (MC-129055) (#7718) 9 | 10 | ========= 11 | Build: 1.16.5-36.1.14 - Fri Apr 30 17:42:34 GMT 2021 12 | cpw: 13 | try gradleVersion 14 | 15 | cpw: 16 | trim? 17 | 18 | cpw: 19 | toString? 20 | 21 | cpw: 22 | fiddle 23 | 24 | cpw: 25 | split ? 26 | 27 | cpw: 28 | try better? 29 | 30 | cpw: 31 | with 32 | 33 | cpw: 34 | debug 35 | 36 | cpw: 37 | debug 38 | 39 | cpw: 40 | debug 41 | 42 | cpw: 43 | debug 44 | 45 | cpw: 46 | tokenize 47 | 48 | cpw: 49 | map 50 | 51 | cpw: 52 | trims 53 | 54 | cpw: 55 | tidy 56 | 57 | cpw: 58 | try passing in env 59 | 60 | cpw: 61 | try passing in env 62 | 63 | s8johost: 64 | Fix Line endings in tooltips not handled properly in multiplayer screen Closes #7738 (#7739) 65 | 66 | ========= 67 | Build: 1.16.5-36.1.13 - Fri Apr 23 20:28:12 GMT 2021 68 | github: 69 | Fix cats, phantoms and pillagers saying they're at BlockPos.ZERO during LivingSpawnEvent.CheckSpawn (#7722) 70 | 71 | ========= 72 | Build: 1.16.5-36.1.12 - Fri Apr 23 05:59:08 GMT 2021 73 | xfacthd: 74 | Pass BlockPos to BlockParticleData used for "fall impact" particle (#7705) 75 | 76 | matthrewp: 77 | [1.16] Add missing Multipart Blockstate Builder feature: Nested condition groups (#7677) 78 | 79 | ========= 80 | Build: 1.16.5-36.1.10 - Fri Apr 23 05:52:41 GMT 2021 81 | sciwhiz12: 82 | Check version ranges of optional dependencies when present (#7710) 83 | 84 | If an optional dependency is present, but it does not conform to the version range, 85 | it will now error out in the same fashion as missing required dependencies, instead 86 | of a more cryptic error down the line due to a missing method/class/field/etc. 87 | 88 | Implements and closes #7696 89 | 90 | ========= 91 | Build: 1.16.5-36.1.9 - Fri Apr 23 05:45:51 GMT 2021 92 | diesieben07: 93 | Fix ClientVisualization crashing on systems without monitors (#7719) 94 | 95 | ========= 96 | Build: 1.16.5-36.1.8 - Fri Apr 23 05:34:56 GMT 2021 97 | atkarimarton: 98 | Fix Furnace Minecarts going faster then vanilla (#7725) 99 | 100 | ========= 101 | Build: 1.16.5-36.1.7 - Fri Apr 23 05:28:36 GMT 2021 102 | ateranimavis: 103 | Update for Forge's new maven (#7723) 104 | 105 | ========= 106 | Build: 1.16.5-36.1.6 - Sun Apr 18 15:47:08 GMT 2021 107 | cpw: 108 | A bloody quote FFS 109 | 110 | Signed-off-by: cpw 111 | 112 | cpw: 113 | Update for new maven 114 | 115 | Signed-off-by: cpw 116 | 117 | ========= 118 | Build: 1.16.5-36.1.4 - Fri Apr 02 18:31:07 GMT 2021 119 | cpw: 120 | Fix broken java9hacks for j16 handling.. 121 | 122 | Signed-off-by: cpw 123 | 124 | ========= 125 | Build: 1.16.5-36.1.3 - Tue Mar 30 01:05:30 GMT 2021 126 | SizableShrimp: 127 | Add generic EntityTeleportEvent (#7694) 128 | 129 | ========= 130 | Build: 1.16.5-36.1.2 - Mon Mar 22 06:24:40 GMT 2021 131 | covers1624: 132 | Restore SS version, fixes findFieldInstanceChecks 133 | 134 | ========= 135 | Build: 1.16.5-36.1.1 - Wed Mar 17 17:04:46 GMT 2021 136 | diesieben07: 137 | Fix sign textures being stitched onto every texture atlas (#7690) 138 | 139 | ========= 140 | Build: 1.16.5-36.1.0 - Mon Mar 15 22:11:58 GMT 2021 141 | lexmanos: 142 | Fix AT order, missed exec line and bump for RB. 143 | 144 | ========= 145 | Build: 1.16.5-36.0.63 - Mon Mar 15 21:08:56 GMT 2021 146 | diesieben07: 147 | Fix wrong eye height when entity size changes (esp. baby animals) (#7628) 148 | 149 | ========= 150 | Build: 1.16.5-36.0.62 - Mon Mar 15 21:02:36 GMT 2021 151 | diesieben07: 152 | Allow ITeleporter to override the vanilla teleport sound (#7682) 153 | 154 | ========= 155 | Build: 1.16.5-36.0.61 - Mon Mar 15 20:20:21 GMT 2021 156 | SizableShrimp: 157 | Fix datapack exception related to EnumArgument with siblings (#7686) 158 | 159 | Invalid enum constants are now properly thrown as a CommandSyntaxException 160 | 161 | ========= 162 | Build: 1.16.5-36.0.60 - Mon Mar 15 19:29:01 GMT 2021 163 | 42383791+kaydogz: 164 | Add support for custom WoodTypes (#7623) 165 | 166 | ========= 167 | Build: 1.16.5-36.0.59 - Mon Mar 15 19:19:16 GMT 2021 168 | lexmanos: 169 | Use JGit instead of GrGit now that jcenter is going away. 170 | Update missed mapped name in MDK. 171 | 172 | ========= 173 | Build: 1.16.5-36.0.58 - Sat Mar 13 19:07:24 GMT 2021 174 | diesieben07: 175 | Fix incorrectly replaced SRG names 176 | 177 | gigaherz: 178 | Fix yet another copypasta. 179 | 180 | gigaherz: 181 | Bump nashorn wrapper version. 182 | 183 | ========= 184 | Build: 1.16.5-36.0.55 - Fri Mar 12 18:51:48 GMT 2021 185 | ateranimavis: 186 | Fix potential Deadlock when using custom Item entities. (#7532) 187 | 188 | Be careful when adding Entities during Chunk Load (#7519) 189 | 190 | ========= 191 | Build: 1.16.5-36.0.54 - Fri Mar 12 02:04:32 GMT 2021 192 | gigaherz: 193 | Fix copypasta. 194 | 195 | ========= 196 | Build: 1.16.5-36.0.53 - Fri Mar 12 00:11:22 GMT 2021 197 | curle: 198 | Automatically fix some issues with configurations deemed invalid for simple reasons (#7671) 199 | 200 | ========= 201 | Build: 1.16.5-36.0.52 - Thu Mar 11 20:59:54 GMT 2021 202 | gigaherz: 203 | Introduce a new feature that lets mods know if optional mods and optional network channels are present in the remote. 204 | Allow connections from forge versions that don't have the vanilla splitter. 205 | 206 | gigaherz: 207 | Bulk update license year, and use replacement variable so that the current year is always used. 208 | 209 | gigaherz: 210 | Bump SpecialSource 211 | 212 | gigaherz: 213 | Add coremod that injects bouncer methods to work around name conflicts with official names. 214 | Fixes a binary break. 215 | 216 | ========= 217 | Build: 1.16.5-36.0.48 - Tue Mar 09 22:22:20 GMT 2021 218 | lexmanos: 219 | Update to FG4, and Gradle 6.8. 220 | 221 | lexmanos: 222 | Regenerate patches with relative headers. This should lower conflicts in future PRs. 223 | Convert Forge to use Official mappings. 224 | Mojang released their obfuscation mappings but we have not used them up until now due to wanting to get their license to be more explicitly permissive. 225 | It is clear that their intent is to allow us to use their names for developing mods like this. 226 | See the full wording, and our interpretation here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md 227 | 228 | ========= 229 | Build: 1.16.5-36.0.46 - Thu Mar 04 20:15:10 GMT 2021 230 | diesieben07: 231 | Support splitting vanilla packets that are too large on forge<->forge connections (#7485) 232 | 233 | Currently only for SUpdateRecipesPacket and STagsListPacket that blow up with huge datapacks 234 | 235 | ========= 236 | Build: 1.16.5-36.0.45 - Wed Mar 03 20:50:47 GMT 2021 237 | pupnewfster: 238 | Fix a few places where the vanilla method was being called instead of the forge one (#7535) 239 | 240 | Cleanup javadocs references slightly, fix a couple spots not using the proper forge hooks, and remove a couple unneeded patches 241 | Update deprecation comment on isAir 242 | 243 | ========= 244 | Build: 1.16.5-36.0.44 - Wed Mar 03 05:29:04 GMT 2021 245 | usfirepilot123: 246 | Add Opacity to ForgeHooksClient#renderMainMenu (#7660) 247 | 248 | ========= 249 | Build: 1.16.5-36.0.43 - Thu Feb 25 02:37:09 GMT 2021 250 | oriondevelopment: 251 | Add support for caching of configuration values. (#7608) 252 | 253 | ========= 254 | Build: 1.16.5-36.0.42 - Tue Feb 16 02:43:01 GMT 2021 255 | kovac1066: 256 | Added entity attribute setup and creation events 257 | 258 | ========= 259 | Build: 1.16.5-36.0.41 - Tue Feb 16 01:28:51 GMT 2021 260 | knightminer4: 261 | Fix updateItemStackNBT not properly being called (#7646) 262 | 263 | Re-added ItemStack delegate redirect transformer 264 | 265 | ========= 266 | Build: 1.16.5-36.0.40 - Tue Feb 16 01:08:21 GMT 2021 267 | pupnewfster: 268 | Fix a few FluidUtil issues that were causing DispenseFluidContainer to not function properly (#7422) 269 | 270 | ========= 271 | Build: 1.16.5-36.0.39 - Tue Feb 16 00:49:27 GMT 2021 272 | daemonumbra: 273 | Fixed Configs not correcting when hot-loaded from changes on disk (#7427) 274 | 275 | ichttt: 276 | Add a way to specify a custom background texture with namespaces in the Creative GUI. (#7404) 277 | 278 | ========= 279 | Build: 1.16.5-36.0.37 - Tue Feb 16 00:39:15 GMT 2021 280 | xzk0701: 281 | Reduce default logging markers in the MDK. Modders can re-enable these for better debugging. (#7432) 282 | 283 | Modders PLEASE read your damn log, and fix the errors we point out. Spamming modpacks with stack traces is just lazy programming. 284 | 285 | ========= 286 | Build: 1.16.5-36.0.36 - Tue Feb 16 00:19:30 GMT 2021 287 | sciwhiz12: 288 | Deprecate Forge's setdimension command, vanilla execute command can do this now. (#7459) 289 | 290 | ========= 291 | Build: 1.16.5-36.0.35 - Mon Feb 15 23:38:35 GMT 2021 292 | spb.max2: 293 | Fix ItemTextureQuadConverter.convertTexture generating wrong quads, fixes #7620 (#7650) 294 | 295 | ========= 296 | Build: 1.16.5-36.0.34 - Mon Feb 15 23:22:40 GMT 2021 297 | florian: 298 | Added MultipartBakedModel.getModelData(). (#7595) 299 | 300 | This allows custom IBakedModel implementations to use the IModelData provided by their IBakedModel.getModelData() when used in the context of a multipart model. 301 | 302 | ========= 303 | Build: 1.16.5-36.0.33 - Mon Feb 15 23:15:50 GMT 2021 304 | cyborgmas18: 305 | fix global cache not being a block render type (#7648) 306 | 307 | ========= 308 | Build: 1.16.5-36.0.32 - Mon Feb 15 22:52:15 GMT 2021 309 | 35673674+alcatrazescapee: 310 | Allow mods to use additional custom LootParameter when querying existing loot tables (#7515) 311 | 312 | ========= 313 | Build: 1.16.5-36.0.31 - Mon Feb 15 21:40:16 GMT 2021 314 | github: 315 | Add ForgeHooks.canEntitySpawn to Cat, Phantom, and Patrol spawners. (#7569) 316 | 317 | ========= 318 | Build: 1.16.5-36.0.30 - Mon Feb 15 21:26:11 GMT 2021 319 | dev: 320 | Fix/Replace player visibility event (#7573) 321 | 322 | ========= 323 | Build: 1.16.5-36.0.29 - Mon Feb 15 21:16:26 GMT 2021 324 | ateranimavis: 325 | Fix: Clear the last error from glfwInit to prevent vanilla from throwing an exception later in the chain when glfw errors. (#7587) 326 | 327 | ========= 328 | Build: 1.16.5-36.0.28 - Mon Feb 15 20:56:51 GMT 2021 329 | 55965249+seymourimadeit: 330 | Fix MC-181464 persisting for modded shields (#7602) 331 | 332 | ========= 333 | Build: 1.16.5-36.0.27 - Mon Feb 15 20:11:46 GMT 2021 334 | malte0811: 335 | FIx race condition in LazyOptional (#7611) 336 | 337 | ========= 338 | Build: 1.16.5-36.0.26 - Mon Feb 15 03:16:02 GMT 2021 339 | xfacthd: 340 | [1.16.5] Fix shaders breaking almost every overlay that uses textures, fixes #7575 (#7624) 341 | 342 | ========= 343 | Build: 1.16.5-36.0.25 - Mon Feb 15 03:10:24 GMT 2021 344 | 40846040+telepathicgrunt: 345 | Disable syncing of Feature and Biome registries (#7639) 346 | 347 | ========= 348 | Build: 1.16.5-36.0.24 - Mon Feb 15 03:04:46 GMT 2021 349 | drullkus: 350 | Add IExtensibleEnum to GrassColorModifier (#7641) 351 | 352 | ========= 353 | Build: 1.16.5-36.0.23 - Mon Feb 15 02:36:26 GMT 2021 354 | github: 355 | Log stacktraces in NettyPacketEncoder. (#7654) 356 | 357 | ========= 358 | Build: 1.16.5-36.0.22 - Wed Feb 10 19:05:16 GMT 2021 359 | xfacthd: 360 | Lower logging level for datafixer warning to debug (#7636) 361 | 362 | ========= 363 | Build: 1.16.5-36.0.21 - Tue Feb 09 22:19:29 GMT 2021 364 | pupnewfster: 365 | Reintroduce forge's chunk manager to allow mods to force chunks with either a block position or entity (UUID) "owner" and have them properly persist between restarts (#7642) 366 | 367 | ========= 368 | Build: 1.16.5-36.0.20 - Tue Feb 09 21:28:24 GMT 2021 369 | pupnewfster: 370 | Fix two places where querying an object for the new "valid" capability from a capability invalidation listener could cause the object to return the old invalid capability. (#7643) 371 | 372 | ========= 373 | Build: 1.16.5-36.0.19 - Tue Feb 09 21:21:44 GMT 2021 374 | cyborgmas18: 375 | Fix config spec in cases of enum class discrepancies (#7635) 376 | 377 | ========= 378 | Build: 1.16.5-36.0.18 - Tue Feb 09 21:06:36 GMT 2021 379 | diesieben07: 380 | Fix onBlockAdded being called twice for ItemEntity placing non-TE blocks (#7607) 381 | 382 | ========= 383 | Build: 1.16.5-36.0.17 - Tue Feb 09 21:00:57 GMT 2021 384 | due: 385 | Prevent NullPointerException when adding new loot pool. (#7605) 386 | 387 | ========= 388 | Build: 1.16.5-36.0.16 - Tue Feb 09 20:53:48 GMT 2021 389 | brandon4261: 390 | Added generic multi part entity API (#7554) 391 | 392 | ========= 393 | Build: 1.16.5-36.0.15 - Sun Feb 07 03:41:41 GMT 2021 394 | cyborgmas18: 395 | Fix IAngerable entities crashing when reading nbt on client (#7618) 396 | 397 | ========= 398 | Build: 1.16.5-36.0.14 - Tue Feb 02 20:28:08 GMT 2021 399 | thesilkminer: 400 | [1.16.x] Add loot table ID in Global Loot Modifiers (#7428) 401 | 402 | thesilkminer: 403 | [1.16.x] Add loot table ID in Global Loot Modifiers (#7428) 404 | 405 | ========= 406 | Build: 1.16.5-36.0.13 - Sat Jan 30 02:07:17 GMT 2021 407 | pupnewfster: 408 | Add a block tag to allow mods to blacklist blocks endermen should not be able to place blocks on top of, similar to how vanilla hardcodes against them being able to place things on bedrock (#7548) 409 | 410 | ========= 411 | Build: 1.16.5-36.0.12 - Sat Jan 30 02:01:35 GMT 2021 412 | 7419378+hellfirepvp: 413 | Fix translucent model parts of MultiLayerModels rendering as missing models due to differing rendertypes when rendering block model (#7579) 414 | 415 | Signed-off-by: HellFirePvP <7419378+HellFirePvP@users.noreply.github.com> 416 | 417 | ========= 418 | Build: 1.16.5-36.0.11 - Sat Jan 30 01:35:10 GMT 2021 419 | pupnewfster: 420 | Fix existing file tag provider support looking in the wrong folder for custom tag types (#7576) 421 | 422 | ========= 423 | Build: 1.16.5-36.0.10 - Thu Jan 28 21:07:30 GMT 2021 424 | cyborgmas18: 425 | Propery re-encode registries (#7629) 426 | 427 | ========= 428 | Build: 1.16.5-36.0.9 - Thu Jan 28 01:23:13 GMT 2021 429 | cyborgmas18: 430 | Properly encode registries. (#7626) 431 | 432 | ========= 433 | Build: 1.16.5-36.0.8 - Thu Jan 28 00:00:43 GMT 2021 434 | cyborgmas18: 435 | Inject vanilla dimensions inside worlds missing them (#7599) 436 | 437 | ========= 438 | Build: 1.16.5-36.0.7 - Wed Jan 27 00:32:53 GMT 2021 439 | lexmanos: 440 | Update Coremods, ASM, and include standalone Nashorn to load on J15. 441 | 442 | lexmanos: 443 | Introduce a new field_to_instanceof transformer to reduce some simple patches. 444 | 445 | ========= 446 | Build: 1.16.5-36.0.4 - Tue Jan 26 02:53:10 GMT 2021 447 | lexmanos: 448 | Fix broken build. 449 | 450 | dev: 451 | Add modded biomes to overworld biome list (#7360) 452 | 453 | ========= 454 | Build: 1.16.5-36.0.2 - Tue Jan 26 02:25:10 GMT 2021 455 | lexmanos: 456 | Fix dynamic registries not getting ids assigned correctly from old worlds in specific unordered value insertions. Closes #7586 457 | 458 | ========= 459 | Build: 1.16.5-36.0.1 - Sun Jan 17 21:05:36 GMT 2021 460 | knightminer4: 461 | Optionally add a milk fluid to the vanilla bucket (#7294) 462 | 463 | Fixes the previous broken code that was supposed to make mod registered milk returned by the vanilla bucket by allowing mods to enable a milk fluid. 464 | 465 | ========= 466 | Build: 1.16.5-36.0.0 - Fri Jan 15 19:42:24 GMT 2021 467 | lexmanos: 468 | 1.16.5 Initial Update. 469 | 470 | ========= 471 | Build: 1.16.4-35.1.37 - Thu Jan 14 23:58:35 GMT 2021 472 | lexmanos: 473 | Update Coremods, ASM, and include standalone Nashorn to load on J15. 474 | 475 | ========= 476 | Build: 1.16.4-35.1.36 - Thu Jan 07 20:24:49 GMT 2021 477 | ian.rehwinkel: 478 | Added IWeatherParticleRenderHandler to allow a mod to take control over weather particles and sounds. (#7522) 479 | 480 | ========= 481 | Build: 1.16.4-35.1.35 - Thu Jan 07 20:16:03 GMT 2021 482 | covers1624: 483 | Allow Chunk loading Tickets to opt-into forcing chunk ticks. (#7525) 484 | 485 | ========= 486 | Build: 1.16.4-35.1.34 - Thu Jan 07 20:10:18 GMT 2021 487 | malte0811: 488 | Fix crash when mods add goals to skeleton horses (MC-206338) (#7509) 489 | 490 | ========= 491 | Build: 1.16.4-35.1.33 - Thu Jan 07 20:03:59 GMT 2021 492 | diesieben07: 493 | Set WM_CLASS and WM_INSTANCE_NAME for early progress window (#7534) 494 | 495 | ========= 496 | Build: 1.16.4-35.1.32 - Wed Jan 06 03:17:35 GMT 2021 497 | 35673674+alcatrazescapee: 498 | Make UnboundedMapCodec more lenient in decoding dimensions. Fixes MC-197860 (#7527) 499 | 500 | ========= 501 | Build: 1.16.4-35.1.31 - Tue Jan 05 19:59:52 GMT 2021 502 | lexmanos: 503 | Prevent NPE and deprecated MissingMappings.getMappings function. Closes #6252 504 | 505 | lexmanos: 506 | Fix FML's Config Sync packet not allowing same length filenames in encoder and decoder. Closes #7584 507 | 508 | ========= 509 | Build: 1.16.4-35.1.29 - Sun Jan 03 11:02:59 GMT 2021 510 | lexmanos: 511 | Fix entities not correctly being able to be ridden under water. 512 | 513 | ========= 514 | Build: 1.16.4-35.1.28 - Mon Dec 28 21:56:51 GMT 2020 515 | git: 516 | Fix crash when beehive is broken by fake player (#7566) 517 | 518 | ========= 519 | Build: 1.16.4-35.1.27 - Mon Dec 28 21:46:04 GMT 2020 520 | 35673674+alcatrazescapee: 521 | Add supplier variant to `AbstractBlock.Properties#lootFrom` (#7563) 522 | 523 | ========= 524 | Build: 1.16.4-35.1.26 - Mon Dec 28 21:40:18 GMT 2020 525 | diesieben07: 526 | Fix missing serializers when deserializing global loot modifiers (#7561) 527 | 528 | diesieben07: 529 | Fix ModFileResourcePack.getAllResourceLocations ignoring resourceNamespace. (#7562) 530 | 531 | Fixes #7405 532 | 533 | ========= 534 | Build: 1.16.4-35.1.24 - Mon Dec 28 21:34:39 GMT 2020 535 | diesieben07: 536 | Fix VanillaConnectionNetworkFilter sending out invalid entity properties packets without an entity ID (#7560) 537 | 538 | ========= 539 | Build: 1.16.4-35.1.23 - Mon Dec 28 21:17:01 GMT 2020 540 | richard: 541 | Make shear interactions extend to subclasses (#7544) 542 | 543 | ========= 544 | Build: 1.16.4-35.1.22 - Mon Dec 28 21:09:38 GMT 2020 545 | sciwhiz12: 546 | Add a SoundType subclass that uses suppliers (#7538) 547 | 548 | ========= 549 | Build: 1.16.4-35.1.21 - Mon Dec 28 21:03:56 GMT 2020 550 | sciwhiz12: 551 | Fix compound ingredient in shapeless recipes (#7537) Fixes #7530 552 | 553 | ========= 554 | Build: 1.16.4-35.1.20 - Mon Dec 28 20:19:04 GMT 2020 555 | matthrewp: 556 | Fix modded PointOfInterestType's not populating blockstate map when registered (#7503) 557 | 558 | 35673674+alcatrazescapee: 559 | Fix potential NPE in ForgeHooks.onItemPlaceIntoWorld when passing in null player. (#7505) 560 | 561 | ========= 562 | Build: 1.16.4-35.1.18 - Mon Dec 28 20:13:15 GMT 2020 563 | 48399898+poopoodice: 564 | Add new LivingConversionEvent to control mobs turning into other mobs. (#7386) 565 | 566 | ========= 567 | Build: 1.16.4-35.1.17 - Mon Dec 28 20:01:42 GMT 2020 568 | knightminer4: 569 | Add ItemAttributeModifierEvent (#7484) 570 | 571 | ========= 572 | Build: 1.16.4-35.1.16 - Mon Dec 28 19:54:38 GMT 2020 573 | bward7864: 574 | Fix RightClickBlock ALLOW not being implemented (#7426) 575 | 576 | ========= 577 | Build: 1.16.4-35.1.15 - Sat Dec 26 19:39:35 GMT 2020 578 | lexmanos: 579 | Make mod data packs able to be disabled. It'll break things, but that's on you. Closes #6776 580 | 581 | lexmanos: 582 | Quiet down errors related to modders not changing their update urls from the default. 583 | 584 | ========= 585 | Build: 1.16.4-35.1.13 - Sat Dec 12 17:34:07 GMT 2020 586 | tterrag: 587 | Add generated resource tracking to ExistingFileHelper 588 | 589 | ========= 590 | Build: 1.16.4-35.1.12 - Fri Dec 11 02:39:41 GMT 2020 591 | tterrag: 592 | Fix BlockStateProvider item models not knowing about block models 593 | 594 | Add tests for this case 595 | 596 | ========= 597 | Build: 1.16.4-35.1.11 - Tue Dec 08 19:54:40 GMT 2020 598 | richard: 599 | Override invalidateCaps instead of remove for vanilla TE capability invalidation (#7536) 600 | 601 | Properly invalidate patched in vanilla TE caps in invalidateCaps instead of remove so that they get invalidated on chunk unload 602 | 603 | ========= 604 | Build: 1.16.4-35.1.10 - Sat Dec 05 20:07:14 GMT 2020 605 | richard: 606 | Make TEs invalidate capabilities when the chunk they are in unloads (#7529) 607 | 608 | Fixed LazyOptional potentially notifying invalidation listeners multiple times. 609 | 610 | ========= 611 | Build: 1.16.4-35.1.9 - Sat Dec 05 20:01:00 GMT 2020 612 | cordonfreeman: 613 | Fixed entity navigation to stop entities spinning - MC-94054 (#7520) 614 | 615 | ========= 616 | Build: 1.16.4-35.1.8 - Sat Dec 05 19:52:56 GMT 2020 617 | 20846147+unbekannt1998: 618 | Fix wrong function call in BlockStateProvider::horizontalFaceBlock (#7514) 619 | 620 | ========= 621 | Build: 1.16.4-35.1.7 - Sun Nov 29 02:11:08 GMT 2020 622 | tterrag: 623 | Fix datagen order of multipart conditions being unstable 624 | 625 | ========= 626 | Build: 1.16.4-35.1.6 - Sat Nov 28 02:56:55 GMT 2020 627 | 35673674+alcatrazescapee: 628 | Fix forge config option for default world type not applying unless you change the default world type (#7521) 629 | 630 | ========= 631 | Build: 1.16.4-35.1.5 - Fri Nov 27 23:57:23 GMT 2020 632 | gigaherz: 633 | Implement feature for mods to define new world types (#7448) 634 | 635 | * Mods can now register world types via a new forge registry, and optionally register a settings screen to tweak them. 636 | * The default world type for dedicated servers and singleplayer world creation is configurable via forge's common config. 637 | 638 | ========= 639 | Build: 1.16.4-35.1.4 - Tue Nov 24 17:14:21 GMT 2020 640 | csh2001331: 641 | Fix dimType not encode to registries (#7513) 642 | 643 | ========= 644 | Build: 1.16.4-35.1.3 - Mon Nov 23 03:45:21 GMT 2020 645 | richard: 646 | Add support for referencing forge's resources and specifying existing mods to data generators (#7456) 647 | 648 | ========= 649 | Build: 1.16.4-35.1.2 - Sun Nov 22 22:01:29 GMT 2020 650 | cpw: 651 | Fix #6692 652 | 653 | Thanks @AterAnimAvis for help and suggestions 654 | 655 | Signed-off-by: cpw 656 | 657 | ========= 658 | Build: 1.16.4-35.1.1 - Sat Nov 21 19:57:45 GMT 2020 659 | cyborgmas18: 660 | Fix translucent blocks not rendering properly when moved by pistons on fabulous (#7441) 661 | 662 | ========= 663 | Build: 1.16.4-35.1.0 - Fri Nov 20 20:54:30 GMT 2020 664 | lexmanos: 665 | Bump version for RB. 666 | 667 | ========= 668 | Build: 1.16.4-35.0.22 - Fri Nov 20 18:24:46 GMT 2020 669 | 35673674+alcatrazescapee: 670 | Fix MC-194811 - Removing structures causes chunk save errors. 671 | 672 | diesieben07: 673 | Fix food bar not rendering when non-living entities are mounted (#7446) 674 | 675 | ========= 676 | Build: 1.16.4-35.0.20 - Fri Nov 20 18:18:37 GMT 2020 677 | diesieben07: 678 | Fix concurrency issue in StartupMessageManager (#7483) 679 | 680 | ========= 681 | Build: 1.16.4-35.0.19 - Fri Nov 20 18:11:25 GMT 2020 682 | 35673674+alcatrazescapee: 683 | Fix forge registry types that have private constructors (BlockStateProviderType, BlockPlacerType, FoliagePlacerType, TreeDecoratorType) (#7482) 684 | 685 | ========= 686 | Build: 1.16.4-35.0.18 - Sun Nov 15 16:08:55 GMT 2020 687 | cpw: 688 | Fix problem where the absence of forge and MC in later loading triggered a weird crash. 689 | 690 | Signed-off-by: cpw 691 | 692 | ========= 693 | Build: 1.16.4-35.0.17 - Sat Nov 14 01:41:38 GMT 2020 694 | cpw: 695 | Fix NPE problem when modid is mismatched. 696 | 697 | Signed-off-by: cpw 698 | 699 | ========= 700 | Build: 1.16.4-35.0.16 - Sat Nov 14 00:18:29 GMT 2020 701 | cpw: 702 | Return the processed modlist data to the upstream system, not the raw unprocessed data. Should resolve the problem 703 | that mixin complains about missing info when it's in a "crashed" situation. 704 | 705 | Signed-off-by: cpw 706 | 707 | ========= 708 | Build: 1.16.4-35.0.15 - Wed Nov 11 09:09:45 GMT 2020 709 | cyborgmas18: 710 | Fix dims on servers not loading the first run (#7445) 711 | 712 | ========= 713 | Build: 1.16.4-35.0.14 - Tue Nov 10 20:24:33 GMT 2020 714 | diesieben07: 715 | Allow for custom argument types by filtering them on vanilla connections (#7463) 716 | 717 | ========= 718 | Build: 1.16.4-35.0.13 - Tue Nov 10 20:13:34 GMT 2020 719 | bward7864: 720 | Add Player context to AnvilUpdateEvent (#7442) 721 | 722 | ========= 723 | Build: 1.16.4-35.0.12 - Tue Nov 10 20:02:33 GMT 2020 724 | git: 725 | Don't overwrite PlayerAdvancement's player with a fake one (#7454) 726 | 727 | If a FakePlayer is constructed with the same UUID/GameProfile as a 728 | currently active player, the player object within PlayerAdvancement is 729 | set to the fake player. 730 | 731 | As fake players cannot receive advancements (see grantCriterion), this 732 | prevents the actual player from receiving any advancements until they 733 | change dimension/relog. 734 | 735 | ========= 736 | Build: 1.16.4-35.0.11 - Tue Nov 10 19:46:01 GMT 2020 737 | curle: 738 | Add BannerBlock.forColor to SAS to fix banner.toItem() on servers. 739 | 740 | ========= 741 | Build: 1.16.4-35.0.10 - Tue Nov 10 19:36:40 GMT 2020 742 | boy132: 743 | Call Harvest check event even if the block doesn't require any tool (#7414) 744 | 745 | ========= 746 | Build: 1.16.4-35.0.9 - Tue Nov 10 19:25:26 GMT 2020 747 | lexmanos: 748 | Use linked collections to stabilize order when adding new registry entries. 749 | 750 | xfacthd: 751 | Render local player when the renderViewEntity is not the local player (#7216) 752 | 753 | ========= 754 | Build: 1.16.4-35.0.7 - Sun Nov 08 04:12:02 GMT 2020 755 | cpw: 756 | Some help in ExtensionPoint regarding DISPLAYTEST. Let's improve those tick rates! 757 | 758 | Signed-off-by: cpw 759 | 760 | ========= 761 | Build: 1.16.4-35.0.6 - Sun Nov 08 03:30:37 GMT 2020 762 | cpw: 763 | Handle erroring during early mod construction phases, and actually report that into the error UI 764 | by doing armslength exception handling and propagation. 765 | 766 | Signed-off-by: cpw 767 | 768 | ========= 769 | Build: 1.16.4-35.0.5 - Sun Nov 08 01:48:22 GMT 2020 770 | cpw: 771 | Support backwards loading 1.16.3 mods in 1.16.4, because we are able to do that. Tweak loading a bit to be smarter about dependency errors of various kinds. 772 | 773 | Signed-off-by: cpw 774 | 775 | ========= 776 | Build: 1.16.4-35.0.4 - Sat Nov 07 20:10:44 GMT 2020 777 | gigaherz: 778 | Add FluidStack codec, and a test mod that verifies its behaviour matches the existing write/read logic. 779 | Add missing license headers. 780 | 781 | ========= 782 | Build: 1.16.4-35.0.3 - Sat Nov 07 02:11:47 GMT 2020 783 | cpw: 784 | Update event bus version (should be 3.0.5) 785 | 786 | Tweak MDK to automatically populate recommended values for things like forge version, loader version and minecraft version. 787 | 788 | Signed-off-by: cpw 789 | 790 | ========= 791 | Build: 1.16.4-35.0.2 - Wed Nov 04 00:07:58 GMT 2020 792 | diesieben07: 793 | Workaround for modded attributes on vanilla entities logging warnings on vanilla clients 794 | 795 | Switch to a handler-based approach per packet class, simplify patch, add some docs 796 | 797 | Add license header and docs 798 | 799 | Switch to a network handler based approach 800 | 801 | Switch to a network handler based approach 802 | 803 | revert build gradle change 804 | 805 | Simplify Packet patch 806 | 807 | Add license header to IForgePacket 808 | 809 | Revert ForgeHooks changes 810 | 811 | Less hacky and more generic way to filter packets for vanilla connections 812 | 813 | _Actually_ Order SAS. 814 | It's early 815 | 816 | Order SAS 817 | 818 | simplify vanilla connection check 819 | 820 | Remove unneeded import change 821 | 822 | ========= 823 | Build: 1.16.4-35.0.1 - Mon Nov 02 19:57:45 GMT 2020 824 | cpw: 825 | Fix early sorting bug that meant the file deduping was causing an error, to, well, not cause it, so we can get to an error screen. 826 | 827 | Signed-off-by: cpw 828 | 829 | ========= 830 | Build: 1.16.4-35.0.0 - Mon Nov 02 19:15:50 GMT 2020 831 | lexmanos: 832 | 1.16.4 Initial Update 833 | 834 | ========= 835 | Build: 1.16.3-34.1.42 - Mon Nov 02 04:30:53 GMT 2020 836 | lexmanos: 837 | Fix Biomes not properly copying over ids loaded from the save to the new Dynamic Registry. 838 | 839 | ========= 840 | Build: 1.16.3-34.1.41 - Mon Nov 02 01:09:57 GMT 2020 841 | gigaherz: 842 | Introduce custom loader additions to the model data generators. (#7450) 843 | 844 | Currently implemented loaders: 845 | * OBJ 846 | * Composite 847 | * Multi-layer 848 | * Item layers (vanilla item/generated but with fullbright texture support) 849 | * Bucket 850 | * Separate Perspective 851 | 852 | ========= 853 | Build: 1.16.3-34.1.40 - Mon Nov 02 00:52:12 GMT 2020 854 | cpw: 855 | actually rollback on error in registry events. 856 | 857 | Signed-off-by: cpw 858 | 859 | ========= 860 | Build: 1.16.3-34.1.39 - Sun Nov 01 22:09:32 GMT 2020 861 | cpw: 862 | Update modlauncher. fixes #7452 863 | 864 | Signed-off-by: cpw 865 | 866 | cpw: 867 | Return client resources even if no data pack found on server. Closes #6225 (Pull request) 868 | 869 | Signed-off-by: cpw 870 | 871 | tobias.hotz: 872 | Auto-detect ansi support for log4j2 873 | 874 | move to fml.loading subpackage 875 | 876 | Add license header 877 | 878 | cpw: 879 | Fix config parse failure causing crash in building exception message. fixes #7438 880 | 881 | Signed-off-by: cpw 882 | 883 | ========= 884 | Build: 1.16.3-34.1.35 - Thu Oct 29 17:09:31 GMT 2020 885 | malte0811: 886 | Fix (NonNull)Lazy.Concurrent using a global lock (#7403) 887 | 888 | * Fix Lazy.Concurrent using a global lock, thus preventing multiple threads from resolving independent Lazy's at the same time 889 | * Use Lazy with an added null check to implement NonNullLazy 890 | 891 | ========= 892 | Build: 1.16.3-34.1.34 - Thu Oct 29 00:12:09 GMT 2020 893 | gigaherz: 894 | Update forge mappings to 20201028-1.16.3 (#7435) 895 | 896 | ========= 897 | Build: 1.16.3-34.1.33 - Tue Oct 27 16:01:02 GMT 2020 898 | 35673674+alcatrazescapee: 899 | Fix breaking changes from the Biome rename PR #7434 (#7439) 900 | 901 | ========= 902 | Build: 1.16.3-34.1.32 - Mon Oct 26 23:52:47 GMT 2020 903 | sciwhiz12: 904 | Reimplement nametag distance attribute, fix attribute translation keys (#7387) 905 | 906 | ========= 907 | Build: 1.16.3-34.1.31 - Mon Oct 26 22:07:02 GMT 2020 908 | 35673674+alcatrazescapee: 909 | Fix data pack biomes failing to load in SingleBiomeProvider (#7434) 910 | 911 | ========= 912 | Build: 1.16.3-34.1.30 - Mon Oct 26 22:00:28 GMT 2020 913 | cpw: 914 | Add in proper handling of equals and hashcode for modjar urls. Fixes very slow loading on windows. 915 | 916 | Signed-off-by: cpw 917 | 918 | ========= 919 | Build: 1.16.3-34.1.29 - Mon Oct 26 12:51:24 GMT 2020 920 | cpw: 921 | Force 8.0.5 ML 922 | 923 | Signed-off-by: cpw 924 | 925 | ========= 926 | Build: 1.16.3-34.1.28 - Mon Oct 26 11:32:40 GMT 2020 927 | cpw: 928 | Restore FingerprintViolationEvent with appropriate THIS IS F*CKING DEAD DELET WARNINGS. 929 | Also, notify in UI if using legacy JDK without capability to read out security data from mod jars. 930 | 931 | Signed-off-by: cpw 932 | 933 | ========= 934 | Build: 1.16.3-34.1.27 - Mon Oct 26 02:27:48 GMT 2020 935 | cpw: 936 | Rollback registries to vanilla state if something happens during loading, so subsequent activities can still run and not generate false reports.. 937 | 938 | Signed-off-by: cpw 939 | 940 | cpw: 941 | Add signature reporting for mods, using new signature capture from ModLauncher. Need to figure out 942 | how to reflect Minecraft's JAR signatures into here. 943 | 944 | Signed-off-by: cpw 945 | 946 | ========= 947 | Build: 1.16.3-34.1.25 - Tue Oct 20 19:32:40 GMT 2020 948 | lexmanos: 949 | Fix mcp_snapshot mapping issue causing unneeded patches. Closes #7424 950 | 951 | ========= 952 | Build: 1.16.3-34.1.24 - Tue Oct 20 11:26:03 GMT 2020 953 | gigaherz: 954 | Fix resource leak in the OBJ loader. 955 | 956 | ========= 957 | Build: 1.16.3-34.1.23 - Fri Oct 16 19:10:02 GMT 2020 958 | djbake101: 959 | Fix issue with ITeleporter allowing easier use of vanilla logic. (#7317) 960 | 961 | ========= 962 | Build: 1.16.3-34.1.22 - Thu Oct 15 19:49:26 GMT 2020 963 | richard: 964 | Adds tag support for Enchantments, Potions, and TileEntityTypes (#7379) 965 | 966 | ========= 967 | Build: 1.16.3-34.1.21 - Thu Oct 15 19:43:33 GMT 2020 968 | lexmanos: 969 | Resuscitate BiomeDictionary using RegistryKeys instead of biome references. 970 | 971 | ========= 972 | Build: 1.16.3-34.1.20 - Thu Oct 15 17:15:15 GMT 2020 973 | finntheraider: 974 | Add event for player changing game mode (#7355) 975 | 976 | ========= 977 | Build: 1.16.3-34.1.19 - Mon Oct 12 18:11:22 GMT 2020 978 | cpw: 979 | Fix RCON multipacket responses not actually understanding UTF8. 980 | 981 | Signed-off-by: cpw 982 | 983 | ========= 984 | Build: 1.16.3-34.1.18 - Mon Oct 12 01:49:09 GMT 2020 985 | cpw: 986 | Fix RCON not sending newlines in output for multiline. Fixes https://bugs.mojang.com/browse/MC-7569, a very old bug that is really annoying if you use RCON. 987 | 988 | Signed-off-by: cpw 989 | 990 | ========= 991 | Build: 1.16.3-34.1.17 - Sat Oct 10 16:45:26 GMT 2020 992 | championash5357: 993 | Fix Texture Presence String (#7408) 994 | 995 | ========= 996 | Build: 1.16.3-34.1.16 - Fri Oct 09 19:57:26 GMT 2020 997 | lexmanos: 998 | Fix typo causing potential error in vine growth. Closes #7406 999 | Sort missing registry dumps by name, making it easier to read. 1000 | 1001 | ========= 1002 | Build: 1.16.3-34.1.15 - Fri Oct 09 13:58:36 GMT 2020 1003 | gigaherz: 1004 | Fixed conditional advancement loading when using the "advancements" array. 1005 | Added automatic generation of conditional advancements from the criteria in the conditional recipe entries. 1006 | Added advancement name calculation from the recipe ID. 1007 | 1008 | ========= 1009 | Build: 1.16.3-34.1.14 - Thu Oct 08 21:08:45 GMT 2020 1010 | 32142731+flanks255: 1011 | Additions to the mdk build.gradle to accommodate datagens. (#7398) 1012 | 1013 | ========= 1014 | Build: 1.16.3-34.1.13 - Thu Oct 08 21:02:59 GMT 2020 1015 | daemonumbra: 1016 | Added Basic Class-Level SAS Capability to checkSAS, added Vector4f to SAS (#7385) 1017 | 1018 | ========= 1019 | Build: 1.16.3-34.1.12 - Wed Oct 07 20:04:11 GMT 2020 1020 | richard: 1021 | Add hooks to allow modification of structures spawn lists (#7344) 1022 | 1023 | ========= 1024 | Build: 1.16.3-34.1.11 - Tue Oct 06 19:38:36 GMT 2020 1025 | richard: 1026 | Add back patches to Screen allowing for item tooltips to be auto wrapped again (#7378) 1027 | 1028 | Only deals with the methods receiving an ItemStack or ITextComponent(s), the methods that take IReorderingProcessor(s) are left alone. 1029 | 1030 | ========= 1031 | Build: 1.16.3-34.1.10 - Mon Oct 05 14:34:56 GMT 2020 1032 | adam: 1033 | Bump mixin version to 0.8.2 1034 | 1035 | ========= 1036 | Build: 1.16.3-34.1.9 - Mon Oct 05 10:30:12 GMT 2020 1037 | cpw: 1038 | Remove redundant call to CrashReport generator - Vanilla is doing a crashreport for itself at startup now. 1039 | 1040 | Add a UUID into crashreport that is also logged in all channels at crash report generation time. This will allow to associate crash reports and the logs. 1041 | 1042 | Signed-off-by: cpw 1043 | 1044 | cpw: 1045 | Add in extra debug logging 1046 | 1047 | Signed-off-by: cpw 1048 | 1049 | ========= 1050 | Build: 1.16.3-34.1.7 - Sun Oct 04 19:51:37 GMT 2020 1051 | cpw: 1052 | Modify how ModLoadingStage handles dispatch to Registry Events. Stops the objectholder spam and generally improves performance on larger packs. 1053 | 1054 | Signed-off-by: cpw 1055 | 1056 | cpw: 1057 | Fix doc README and answer lex's question 1058 | 1059 | Signed-off-by: cpw 1060 | 1061 | ========= 1062 | Build: 1.16.3-34.1.5 - Fri Oct 02 23:40:14 GMT 2020 1063 | daemonumbra: 1064 | Added "Bukkit Plugin" to InvalidModIdentifier (#7384) 1065 | 1066 | ========= 1067 | Build: 1.16.3-34.1.4 - Fri Oct 02 23:34:26 GMT 2020 1068 | richard: 1069 | Fix vanilla Campfire smoke bug. MC-201374 (#7381) 1070 | 1071 | ========= 1072 | Build: 1.16.3-34.1.3 - Fri Oct 02 23:28:31 GMT 2020 1073 | sciwhiz12: 1074 | Fix toggleable keybindings still being active while in GUI Fixes #7370 (#7373) 1075 | 1076 | ========= 1077 | Build: 1.16.3-34.1.2 - Fri Oct 02 22:06:59 GMT 2020 1078 | dev: 1079 | Fix modded EntityClassifications not being useable in the codec. (#7337) 1080 | 1081 | ========= 1082 | Build: 1.16.3-34.1.1 - Mon Sep 28 18:02:11 GMT 2020 1083 | cech12: 1084 | Support effective materials of vanilla AxeItem (#7351) 1085 | 1086 | ========= 1087 | Build: 1.16.3-34.1.0 - Thu Sep 24 07:05:13 GMT 2020 1088 | lexmanos: 1089 | Prep new RB. 1090 | 1091 | ========= 1092 | Build: 1.16.3-34.0.21 - Thu Sep 24 06:46:57 GMT 2020 1093 | ichttt: 1094 | Fix grass disappearing when alwaysSetupTerrainOffThread is true (#7291) 1095 | 1096 | ========= 1097 | Build: 1.16.3-34.0.20 - Thu Sep 24 06:41:41 GMT 2020 1098 | 35673674+alcatrazescapee: 1099 | Accessors for inspecting and removal of biome generation settings. Fixed carvers still being immutable. (#7339) 1100 | 1101 | ========= 1102 | Build: 1.16.3-34.0.19 - Thu Sep 24 06:36:25 GMT 2020 1103 | lexmanos: 1104 | Revive BiomeManager and BiomeLayer hooks. 1105 | 1106 | ========= 1107 | Build: 1.16.3-34.0.18 - Thu Sep 24 03:12:19 GMT 2020 1108 | richard: 1109 | Fix a few minor issues with custom tag types and fix OptionalNamedTags (#7316) 1110 | 1111 | ========= 1112 | Build: 1.16.3-34.0.17 - Wed Sep 23 22:10:11 GMT 2020 1113 | diesieben07: 1114 | Fix ToggleableKeyBinding differences to vanilla. (#7338) 1115 | 1116 | ========= 1117 | Build: 1.16.3-34.0.16 - Wed Sep 23 21:34:47 GMT 2020 1118 | yunus1903: 1119 | Updated build badge versions to 1.16.3 in readme (#7325) 1120 | 1121 | diesieben07: 1122 | Fix forge light pipeline applying block offsets twice (#7323) 1123 | 1124 | ========= 1125 | Build: 1.16.3-34.0.14 - Wed Sep 23 21:16:46 GMT 2020 1126 | ichttt: 1127 | Add a better license error screen (#7350) 1128 | 1129 | ========= 1130 | Build: 1.16.3-34.0.13 - Tue Sep 22 19:14:17 GMT 2020 1131 | darklime: 1132 | Fixed container item being consumed in brewing stand. #7307 (#7314) 1133 | 1134 | ========= 1135 | Build: 1.16.3-34.0.12 - Tue Sep 22 19:06:10 GMT 2020 1136 | sciwhiz12: 1137 | Fix parse results of CommandEvent being disregarded (#7303) 1138 | 1139 | ========= 1140 | Build: 1.16.3-34.0.11 - Tue Sep 22 18:58:28 GMT 2020 1141 | 17338378+nightenom: 1142 | [1.16] Fix possible crash when using rendering regionCache (#7207) 1143 | 1144 | ========= 1145 | Build: 1.16.3-34.0.10 - Tue Sep 22 18:41:16 GMT 2020 1146 | 35673674+alcatrazescapee: 1147 | [1.16] Reimplement ICloudRenderHandler, ISkyRenderHandler and IWeatherRenderHandler (#6994) 1148 | 1149 | ========= 1150 | Build: 1.16.3-34.0.9 - Fri Sep 18 00:58:08 GMT 2020 1151 | 35673674+alcatrazescapee: 1152 | Make Biome.Climate and BiomeAmbiance fields accessible (#7336) 1153 | 1154 | ========= 1155 | Build: 1.16.3-34.0.8 - Thu Sep 17 20:42:53 GMT 2020 1156 | cpw: 1157 | Use mixin 0.8.1. Should fix problems with mixin not working properly with latest modlauncher. 1158 | 1159 | Signed-off-by: cpw 1160 | 1161 | ========= 1162 | Build: 1.16.3-34.0.7 - Tue Sep 15 20:07:25 GMT 2020 1163 | sebastian: 1164 | Sets the empty/fill sounds for vanilla fluids. 1165 | Use Fluid's fillSound rather than emptySound when filling buckets. 1166 | 1167 | ========= 1168 | Build: 1.16.3-34.0.6 - Tue Sep 15 19:47:08 GMT 2020 1169 | cyborgmas18: 1170 | Add MatrixStack-aware alternatives to the methods in GuiUtils (#7127) 1171 | 1172 | ========= 1173 | Build: 1.16.3-34.0.5 - Tue Sep 15 16:51:58 GMT 2020 1174 | justin_wiblin: 1175 | Fix json biomes not setting registry name correctly for the BiomeLoadingEvent. (#7329) 1176 | 1177 | ========= 1178 | Build: 1.16.3-34.0.4 - Tue Sep 15 14:18:16 GMT 2020 1179 | gigaherz: 1180 | Fix inconsistencies in how the values from the model are passed into the baked model. 1181 | This puts them in line with vanilla, as intended. 1182 | 1183 | ========= 1184 | Build: 1.16.3-34.0.3 - Tue Sep 15 13:23:05 GMT 2020 1185 | yunus1903: 1186 | Reimplemented drawHoveringText (#7268) 1187 | 1188 | ========= 1189 | Build: 1.16.3-34.0.2 - Tue Sep 15 00:43:19 GMT 2020 1190 | lexmanos: 1191 | New BiomeLoadingEvent that allows modders to edit biomes as they are being deserialized. 1192 | 1193 | ========= 1194 | Build: 1.16.3-34.0.1 - Fri Sep 11 15:55:28 GMT 2020 1195 | lexmanos: 1196 | Bump MCP version for lambda issue. 1197 | 1198 | ========= 1199 | Build: 1.16.3-34.0.0 - Thu Sep 10 19:10:33 GMT 2020 1200 | lexmanos: 1201 | 1.16.3 Update 1202 | Also included a bunch of warning cleanups. 1203 | 1204 | ========= 1205 | Build: 1.16.2-33.0.61 - Thu Sep 10 18:54:56 GMT 2020 1206 | 42962686+redstonedubstep: 1207 | Fix tile entities being replaced when not needed. (#7318) 1208 | 1209 | ========= 1210 | Build: 1.16.2-33.0.60 - Thu Sep 10 18:02:15 GMT 2020 1211 | malte0811: 1212 | Fix exception when getting rendering box for tile entities with no collision boxes. (#7301) 1213 | 1214 | ========= 1215 | Build: 1.16.2-33.0.59 - Wed Sep 09 23:05:21 GMT 2020 1216 | cpw: 1217 | More crash reporting tweaks. Don't crash when trying to show warnings. Also, put the exception name in the error screen on the second line! 1218 | 1219 | Signed-off-by: cpw 1220 | 1221 | ========= 1222 | Build: 1.16.2-33.0.58 - Wed Sep 09 17:09:09 GMT 2020 1223 | diesieben07: 1224 | Fix Minecart speed cap on rail being initialized to 0 (#7315) 1225 | 1226 | ========= 1227 | Build: 1.16.2-33.0.57 - Wed Sep 09 02:10:45 GMT 2020 1228 | richard: 1229 | Add support for custom tag types (#7289) 1230 | 1231 | ========= 1232 | Build: 1.16.2-33.0.56 - Wed Sep 09 00:06:22 GMT 2020 1233 | cpw: 1234 | More crash report tweaks. Put a button to open the generated crash report on the error screen, tweak formatting of crash report, and add the enhanced stack trace data (transformers et al) 1235 | 1236 | Signed-off-by: cpw 1237 | 1238 | ========= 1239 | Build: 1.16.2-33.0.55 - Tue Sep 08 21:00:19 GMT 2020 1240 | championash5357: 1241 | New hook for better custom scaffolding movement (#7261) 1242 | 1243 | ========= 1244 | Build: 1.16.2-33.0.54 - Tue Sep 08 20:47:48 GMT 2020 1245 | mrtschipp: 1246 | Add partialTicks to RenderNameplateEvent (#7277) 1247 | 1248 | cyborgmas18: 1249 | Prevent duplicate wrapper tags from crashing (#7283) 1250 | 1251 | matthrewp: 1252 | Fix custom teleporters NPE (#7296) 1253 | 1254 | cyborgmas18: 1255 | Fixed crash with zip paths (#7300) 1256 | 1257 | ========= 1258 | Build: 1.16.2-33.0.50 - Tue Sep 08 20:23:27 GMT 2020 1259 | nrbeech: 1260 | Fixing logic in getCurrentRailPosition to correctly identify the rail… (#7276) 1261 | 1262 | ========= 1263 | Build: 1.16.2-33.0.49 - Tue Sep 08 20:14:58 GMT 2020 1264 | sciwhiz12: 1265 | Remove dead ForgeHooks.canToolHarvestBlock function. (#7262) 1266 | 1267 | sciwhiz12: 1268 | Bump resource pack version to 6 (#7299) 1269 | 1270 | edwin.mindcraft: 1271 | [1.16.x] Fixes for Bamboo, Enchantments and Conduits, small adjustments to bring some patches closer to the vanilla code. (#7239) 1272 | 1273 | ========= 1274 | Build: 1.16.2-33.0.46 - Tue Sep 08 19:50:14 GMT 2020 1275 | championash5357: 1276 | Re-implement DrawHighlightEvent$HighlightEntity Firing (#7233) 1277 | 1278 | ========= 1279 | Build: 1.16.2-33.0.45 - Tue Sep 08 19:25:58 GMT 2020 1280 | ichttt: 1281 | Reimplement FarmlandWaterManager (#7213) 1282 | 1283 | ========= 1284 | Build: 1.16.2-33.0.44 - Tue Sep 08 19:11:16 GMT 2020 1285 | cyborgmas18: 1286 | Add dataprovider for Global Loot Modifiers (#6960) 1287 | 1288 | ========= 1289 | Build: 1.16.2-33.0.43 - Tue Sep 08 19:01:09 GMT 2020 1290 | ichttt: 1291 | Fix crash when dumping crash report for an exception that has a null cause (#7308) 1292 | 1293 | ========= 1294 | Build: 1.16.2-33.0.42 - Mon Sep 07 01:29:40 GMT 2020 1295 | cpw: 1296 | Tweak crash report dump to visit all the causes up to the top. 1297 | 1298 | Signed-off-by: cpw 1299 | 1300 | ========= 1301 | Build: 1.16.2-33.0.41 - Sun Sep 06 23:39:13 GMT 2020 1302 | cpw: 1303 | Fix ExplodedDirectoryLocator visiting non-existent paths. Closes #7203 1304 | 1305 | Also, bump modlauncher to 7.0.1 to fix resources. 1306 | 1307 | Signed-off-by: cpw 1308 | 1309 | ========= 1310 | Build: 1.16.2-33.0.40 - Sun Sep 06 22:08:22 GMT 2020 1311 | cpw: 1312 | Use new enumeration mechanism in ModLauncher, to allow getResources to work. This enables serviceloader-in-mods, and other stuff that might need to visit multiple mod jars. Also, tweaked the visitor code slightly, may result in a trivial performance change. Closing #7302 as it's not really relevant any more. 1313 | 1314 | Signed-off-by: cpw 1315 | 1316 | cpw: 1317 | Park the polling thread for a bit, if we're not the one driving the task list forwards. This allows for the actual driver to work on low cpu count machines. 1318 | 1319 | Signed-off-by: cpw 1320 | 1321 | cpw: 1322 | Fix some potential issues in crash dumping during mod loading 1323 | 1324 | Signed-off-by: cpw 1325 | 1326 | ========= 1327 | Build: 1.16.2-33.0.37 - Thu Sep 03 16:37:38 GMT 2020 1328 | cpw: 1329 | Fix compiler issue in eclipse properly 1330 | 1331 | Signed-off-by: cpw 1332 | 1333 | ========= 1334 | Build: 1.16.2-33.0.36 - Thu Sep 03 12:40:52 GMT 2020 1335 | sciwhiz12: 1336 | Fix crash caused by previous commit (#7298) 1337 | 1338 | ========= 1339 | Build: 1.16.2-33.0.35 - Thu Sep 03 04:15:27 GMT 2020 1340 | lexmanos: 1341 | Dirty casting hacks to fix eclipse compiler inference issue. I'm sorry cpw. 1342 | 1343 | ========= 1344 | Build: 1.16.2-33.0.34 - Thu Sep 03 03:38:16 GMT 2020 1345 | tterrag: 1346 | Fix broken ExistingFileHelper import 1347 | 1348 | Add licenses to some new files 1349 | 1350 | tterrag: 1351 | Add validation via resources for tag providers (#7271) 1352 | 1353 | BREAKING CHANGE: Moved ExistingFileHelper to common package 1354 | Remove various workarounds from forge tag providers 1355 | 1356 | ========= 1357 | Build: 1.16.2-33.0.32 - Tue Sep 01 18:36:21 GMT 2020 1358 | cpw: 1359 | Move the "modloading" thread activity onto _our_ worker pool. It turns out that the vanilla worker pool can deadlock during stitching if it's insufficiently large, if modloader "waitForTransition" is also a worker member of that pool. 1360 | 1361 | Closes #7293 (to reproduce issue easily, modify Util.func_240979_a_ and change the values in the MathHelper.clamp call). I've verified that 3 and below for "max" cause the problem. (I didn't test a whole range of values, just sufficient to reproduce problem and verify fix). Note that setting it to zero (and using the "direct executor" that's inaccessible in normal operation) works as well with this fix. 1362 | 1363 | Signed-off-by: cpw 1364 | 1365 | ========= 1366 | Build: 1.16.2-33.0.31 - Tue Sep 01 02:27:07 GMT 2020 1367 | cpw: 1368 | Fix missed debugging code. Read the config from the config. 1369 | 1370 | Signed-off-by: cpw 1371 | 1372 | ========= 1373 | Build: 1.16.2-33.0.30 - Tue Sep 01 01:31:57 GMT 2020 1374 | cpw: 1375 | Revert "Shut down all other mod handlers if the loading cycle errors. This prevents other mods from throwing errors and being blamed for initial cause. This is a temporary hack until cpw re-writes the mod event dispatcher." 1376 | 1377 | This reverts commit 7592bbe8 1378 | 1379 | Signed-off-by: cpw 1380 | 1381 | cpw: 1382 | Revert "Properly shutdown FMLModContainer's event bus when an error in a lifecycle event is detected." 1383 | 1384 | This reverts commit 30bad1e2 1385 | 1386 | Signed-off-by: cpw 1387 | 1388 | cpw: 1389 | Redo event dispatch, removes a bunch of nonsense, and tries to integrate with the vanilla CF system where possible 1390 | 1391 | Signed-off-by: cpw 1392 | 1393 | cpw: 1394 | Fix up all the things. Removed SidedProvider because it served no real purpose anymore. 1395 | 1396 | Signed-off-by: cpw 1397 | 1398 | cpw: 1399 | Fix up slight registry change and other 1.16.2 stuffs. 1400 | 1401 | Signed-off-by: cpw 1402 | 1403 | ========= 1404 | Build: 1.16.2-33.0.23 - Sun Aug 30 23:05:24 GMT 2020 1405 | ichttt: 1406 | Add particle culling (#6981) 1407 | 1408 | ========= 1409 | Build: 1.16.2-33.0.22 - Wed Aug 26 16:50:02 GMT 2020 1410 | lexmanos: 1411 | Wrap vanilla's 'default' biome registry in ForgeRegistry. 1412 | This should allow registering mod dimensions like in 1.16.1, while the data driven system is fleshed out. 1413 | 1414 | ========= 1415 | Build: 1.16.2-33.0.21 - Tue Aug 25 01:11:38 GMT 2020 1416 | gigaherz: 1417 | Clarify in the LazyOptional which methods carry the lazyness over to the returned value and which don't. (#6750) 1418 | 1419 | For consistency, this meant making a few changes: 1420 | - Renamed the existing lazy mapping method to lazyMap, to indicate that it doesn't run the mapping immediately. 1421 | - Added a new implementation of map(), which returns Optional, and resolves the value in the process. 1422 | - Changed filter() to return Optional, since there's no way to filter lazily. 1423 | - Added a new method resolve(), which helps convert the custom LazyOptional class into a standard Optional, for use 1424 | with library methods that expect Optional. 1425 | 1426 | * Update License headers. 1427 | 1428 | ========= 1429 | Build: 1.16.2-33.0.20 - Fri Aug 21 21:27:21 GMT 2020 1430 | sciwhiz12: 1431 | Add user-friendly exceptions when config loading fails (#7214) 1432 | 1433 | ========= 1434 | Build: 1.16.2-33.0.19 - Fri Aug 21 18:53:46 GMT 2020 1435 | dev: 1436 | Replace EntityHeight event with EntitySize event (#6858) 1437 | 1438 | ========= 1439 | Build: 1.16.2-33.0.18 - Fri Aug 21 18:38:31 GMT 2020 1440 | davide2910: 1441 | [1.16] ForgeEventFactory#canCreateFluidSource reintroduced (#7181) 1442 | 1443 | ========= 1444 | Build: - Fri Aug 21 18:31:19 GMT 2020 1445 | cyborgmas18: 1446 | Cleanup and expand Forge tags (#7004) 1447 | 1448 | ========= 1449 | Build: 1.16.2-33.0.16 - Fri Aug 21 18:25:49 GMT 2020 1450 | sciwhiz12: 1451 | Fix modproperties property in mods.toml causing exception (#7192) 1452 | 1453 | ========= 1454 | Build: 1.16.2-33.0.15 - Fri Aug 21 18:15:53 GMT 2020 1455 | me: 1456 | Log info about server list warning (#7209) 1457 | 1458 | Make it easier to figure out what mods are missing or have to be marked as client/server side only. 1459 | 1460 | ========= 1461 | Build: 1.16.2-33.0.14 - Fri Aug 21 18:06:47 GMT 2020 1462 | goto.minecraft: 1463 | Fix ItemStack#isDamageable is not calling Item#isDamagable (#7221) 1464 | 1465 | ========= 1466 | Build: 1.16.2-33.0.13 - Fri Aug 21 17:48:58 GMT 2020 1467 | diesieben07: 1468 | Improve performance and cleanup code for DelegatingResourcePack (#7228) 1469 | 1470 | ========= 1471 | Build: 1.16.2-33.0.12 - Fri Aug 21 17:29:33 GMT 2020 1472 | cyborgmas18: 1473 | Fix small logging issues with loading pack.png for mods (#7265) 1474 | 1475 | ========= 1476 | Build: 1.16.2-33.0.11 - Fri Aug 21 17:23:30 GMT 2020 1477 | diesieben07: 1478 | Fix config iteration order (#7230) 1479 | 1480 | ========= 1481 | Build: 1.16.2-33.0.10 - Fri Aug 21 09:47:23 GMT 2020 1482 | lexmanos: 1483 | Cleanup Forge's build script, fix some unneeded patches. 1484 | Add checkExcscheckAll tasks. 1485 | 1486 | ========= 1487 | Build: 1.16.2-33.0.9 - Fri Aug 21 04:35:17 GMT 2020 1488 | championash5357: 1489 | Readding DifficultyChangeEvent hooks (#7240) 1490 | 1491 | ========= 1492 | Build: 1.16.2-33.0.8 - Fri Aug 21 04:29:10 GMT 2020 1493 | malte0811: 1494 | Improve startup time by caching the manifest data for mod jars (#7256) 1495 | 1496 | ========= 1497 | Build: 1.16.2-33.0.7 - Wed Aug 19 05:47:46 GMT 2020 1498 | yunus1903: 1499 | Removed HarvestDropsEvent (#7193) 1500 | 1501 | ========= 1502 | Build: 1.16.2-33.0.6 - Wed Aug 19 05:22:45 GMT 2020 1503 | cyborgmas18: 1504 | Remove forge optional tags in favor of Vanilla's new system. (#7246) 1505 | 1506 | ========= 1507 | Build: 1.16.2-33.0.5 - Fri Aug 14 19:05:15 GMT 2020 1508 | lexmanos: 1509 | Fix creating nether portals. 1510 | 1511 | lexmanos: 1512 | New method for creating modded tag references, fix connecting to vanilla servers. 1513 | 1514 | ========= 1515 | Build: 1.16.2-33.0.3 - Fri Aug 14 02:17:01 GMT 2020 1516 | 43609023+spnda: 1517 | Print mod file name on InvalidModFileException (#7241) 1518 | 1519 | ========= 1520 | Build: 1.16.2-33.0.2 - Thu Aug 13 19:26:22 GMT 2020 1521 | cyborgmas18: 1522 | Fix server connection, misapplied patch (#7245) 1523 | 1524 | yunus1903: 1525 | Updated MDK and README for 1.16.2 (#7243) 1526 | 1527 | ========= 1528 | Build: 1.16.2-33.0.0 - Thu Aug 13 07:37:04 GMT 2020 1529 | lexmanos: 1530 | Initial 1.16.2 Update 1531 | 1532 | ========= 1533 | Build: 1.16.1-32.0.108 - Sun Aug 09 20:05:01 GMT 2020 1534 | gigaherz: 1535 | Fix ModelRegistryEvent firing every time resources reload instead of just once. 1536 | 1537 | ========= 1538 | Build: 1.16.1-32.0.107 - Sat Aug 08 01:00:42 GMT 2020 1539 | gigaherz: 1540 | Move ModelRegistryEvent invocation to when the model loading is about to start. 1541 | Freeze the ModelLoaderRegistry right after this event happens, just before model loading actually begins. 1542 | This means ModelRegistryEvent is now the correct place to register loaders, as it was intended. 1543 | This is a slight breaking change, but any mod that used FMLClientSetupEvent before will need to be updated regardless due to the existing race condition. 1544 | 1545 | ========= 1546 | Build: 1.16.1-32.0.106 - Tue Aug 04 00:19:22 GMT 2020 1547 | diesieben07: 1548 | Fix wrong BlockState param passed into canSustainPlant from FarmlandBlock (#7212) 1549 | 1550 | ========= 1551 | Build: 1.16.1-32.0.105 - Tue Aug 04 00:06:45 GMT 2020 1552 | sciwhiz12: 1553 | Add harvest levels for hoes and new 1.16 blocks for pickaxes Fixes #7187 (#7189) 1554 | 1555 | ========= 1556 | Build: 1.16.1-32.0.104 - Tue Aug 04 00:00:40 GMT 2020 1557 | sciwhiz12: 1558 | Fix debug world not generating modded blocks (#6926) 1559 | 1560 | championash5357: 1561 | New IForgeBlock#getToolModifiedState hook allow better control over tools interacting with blocks. (#7176) 1562 | 1563 | email.squishling: 1564 | Added new hook to allow Biomes to control their Edge biomes (#7000) 1565 | 1566 | ========= 1567 | Build: 1.16.1-32.0.101 - Mon Aug 03 22:55:18 GMT 2020 1568 | diesieben07: 1569 | Re-introduce "outdated" notification on Mods button in main menu (#7123) 1570 | 1571 | brandon4261: 1572 | Add support for custom elytra (#7202) 1573 | 1574 | ========= 1575 | Build: 1.16.1-32.0.99 - Mon Aug 03 18:53:31 GMT 2020 1576 | sciwhiz12: 1577 | Fix RenderTickEvent using wrong partial ticks value when game is paused. Fixes #6991 (#7208) 1578 | 1579 | ========= 1580 | Build: 1.16.1-32.0.98 - Thu Jul 30 03:18:00 GMT 2020 1581 | tterrag: 1582 | Implement forge IBakedModel methods in vanilla wrapper models 1583 | 1584 | ========= 1585 | Build: 1.16.1-32.0.97 - Tue Jul 28 23:44:41 GMT 2020 1586 | lexmanos: 1587 | Fix another case of swallowed errors not shutting down mods. 1588 | 1589 | ========= 1590 | Build: 1.16.1-32.0.96 - Tue Jul 28 21:40:06 GMT 2020 1591 | lexmanos: 1592 | Shut down all other mod handlers if the loading cycle errors. 1593 | This prevents other mods from throwing errors and being blamed for initial cause. 1594 | This is a temporary hack until cpw re-writes the mod event dispatcher. 1595 | 1596 | ========= 1597 | Build: - Tue Jul 28 19:01:27 GMT 2020 1598 | lexmanos: 1599 | Properly shutdown FMLModContainer's event bus when an error in a lifecycle event is detected. 1600 | 1601 | lexmanos: 1602 | Enable EventBus type check during ForgeDev, and add IModBusEvent marker to ModelRegistryEvent. 1603 | 1604 | ========= 1605 | Build: 1.16.1-32.0.93 - Tue Jul 28 07:16:31 GMT 2020 1606 | lexmanos: 1607 | Make license toml entry optional during 1.16.1 1608 | There are to many existing mods to make this required. 1609 | Yes, we are technically before a RB and can do breaking changes. However this is too large. 1610 | 1611 | ========= 1612 | Build: 1.16.1-32.0.92 - Tue Jul 28 01:14:20 GMT 2020 1613 | cpw: 1614 | Missed one event. NewRegistry needs the marker. 1615 | 1616 | Signed-off-by: cpw 1617 | 1618 | ========= 1619 | Build: 1.16.1-32.0.91 - Tue Jul 28 01:07:03 GMT 2020 1620 | cpw: 1621 | Update MDK license to default to All rights reserved, and offer a link to chooseyourlicense.com as a place to research appropriate licenses. 1622 | 1623 | Note: the license field _is_ backwards compatible and will simply be ignored on older forge versions. 1624 | Signed-off-by: cpw 1625 | 1626 | ========= 1627 | Build: 1.16.1-32.0.90 - Tue Jul 28 00:47:35 GMT 2020 1628 | cpw: 1629 | Update modlauncher, eventbus, accesstransformers and more to use a newer mechanism for generating ASM. 1630 | 1631 | Introduced IModBusEvent as a marker interface for events on the ModBus. Expect exceptions if you use 1632 | the modbus for events not listened there. 1633 | 1634 | Signed-off-by: cpw 1635 | 1636 | cpw: 1637 | Update coremods and spi, include mandatory license field in metadata. Added at top level of mods.toml file. 1638 | 1639 | Signed-off-by: cpw 1640 | 1641 | ========= 1642 | Build: 1.16.1-32.0.88 - Mon Jul 27 23:35:24 GMT 2020 1643 | ray.neiheiser: 1644 | Fix rail 180 rotations (#7177) 1645 | 1646 | jmansfield: 1647 | Fire AnimalTameEvent for cats (#7172) Closes #7171 1648 | 1649 | ========= 1650 | Build: 1.16.1-32.0.86 - Mon Jul 27 22:56:16 GMT 2020 1651 | lexmanos: 1652 | Fix Biome generation error. 1653 | 1654 | ========= 1655 | Build: 1.16.1-32.0.85 - Mon Jul 27 21:36:07 GMT 2020 1656 | dev: 1657 | Fix SleepingTimeCheckEvent not being fired in initial sleep test. (#7005) 1658 | 1659 | ========= 1660 | Build: 1.16.1-32.0.84 - Mon Jul 27 21:30:24 GMT 2020 1661 | yunus1903: 1662 | Fix ClimberPathNavigator spinning when width is small. Closes #6993 (#6997) 1663 | 1664 | ========= 1665 | Build: 1.16.1-32.0.83 - Mon Jul 27 21:19:50 GMT 2020 1666 | mrtschipp: 1667 | Re-added PlayerEvent.NameFormat (#6992) 1668 | 1669 | ========= 1670 | Build: 1.16.1-32.0.82 - Mon Jul 27 21:14:02 GMT 2020 1671 | email.squishling: 1672 | Fixed modded overworld biomes not spawning [1.16.x] (#6990) 1673 | 1674 | ========= 1675 | Build: 1.16.1-32.0.81 - Mon Jul 27 21:08:23 GMT 2020 1676 | christ.klinge: 1677 | Added EntityLeaveWorldEvent (#6984) 1678 | 1679 | ========= 1680 | Build: 1.16.1-32.0.80 - Mon Jul 27 21:02:53 GMT 2020 1681 | aqscode: 1682 | Re-implement moddable flammabilities (#6983) 1683 | 1684 | ========= 1685 | Build: 1.16.1-32.0.79 - Mon Jul 27 20:46:11 GMT 2020 1686 | diesieben07: 1687 | Re-add patch for PlayerSetSpawnEvent (#6977) 1688 | 1689 | yunus1903: 1690 | Updated versions in README and removed flocker.tv mentions (#6978) 1691 | 1692 | ========= 1693 | Build: 1.16.1-32.0.77 - Mon Jul 27 20:40:33 GMT 2020 1694 | sciwhiz12: 1695 | Fix ChunkDataEvents using different data tags (#6961) Fixes #6957 1696 | 1697 | ========= 1698 | Build: - Mon Jul 27 20:27:00 GMT 2020 1699 | joetarbit: 1700 | Post SoundLoadEvent on mod bus instead of forge bus (#6955) 1701 | 1702 | ========= 1703 | Build: 1.16.1-32.0.75 - Wed Jul 22 01:26:19 GMT 2020 1704 | cpw: 1705 | Remove startupquery. Currently wasn't functional, and 1.16 has out of band state loading in all cases, so the complex functionality there is no longer needed. Going to research using the Lifecycle indicator from DFU as a proxy/replacement. Probably with some codec FUN. 1706 | 1707 | Signed-off-by: cpw 1708 | 1709 | ========= 1710 | Build: 1.16.1-32.0.74 - Wed Jul 22 00:34:43 GMT 2020 1711 | lexmanos: 1712 | Run Forge's data generators to sync 1.16 vanilla changes. 1713 | 1714 | ========= 1715 | Build: 1.16.1-32.0.73 - Wed Jul 22 00:13:48 GMT 2020 1716 | cpw: 1717 | Don't show the early launcher GUI when running data. It's not needed and prevents use on automated builds. 1718 | 1719 | Need to investigate why a bunch of tags seem to be being blown away by rerunning on forge. 1720 | 1721 | Signed-off-by: cpw 1722 | 1723 | ========= 1724 | Build: 1.16.1-32.0.72 - Tue Jul 21 23:56:54 GMT 2020 1725 | cpw: 1726 | Add mixin 1727 | 1728 | Signed-off-by: cpw 1729 | 1730 | ========= 1731 | Build: 1.16.1-32.0.71 - Mon Jul 20 22:56:31 GMT 2020 1732 | cyborgmas18: 1733 | Load Modded Datapacks in DatapackScreen, before world creation (#6913) 1734 | 1735 | ========= 1736 | Build: 1.16.1-32.0.70 - Sat Jul 18 22:35:53 GMT 2020 1737 | tterrag: 1738 | Fix inconsistencies with model/blockstate datagen 1739 | 1740 | ========= 1741 | Build: 1.16.1-32.0.69 - Fri Jul 17 17:35:47 GMT 2020 1742 | dev: 1743 | Filter duplicate mod files from mod file scan data (#6855) 1744 | 1745 | ========= 1746 | Build: 1.16.1-32.0.68 - Thu Jul 16 21:56:30 GMT 2020 1747 | lexmanos: 1748 | Fixed Forge commands. Closes #6973 Closes #6974 Closes #6976 1749 | 1750 | ========= 1751 | Build: 1.16.1-32.0.67 - Wed Jul 15 19:30:53 GMT 2020 1752 | jaredlll08: 1753 | Added an event for registering commands. closes #6968 (#6969) 1754 | 1755 | ========= 1756 | Build: 1.16.1-32.0.66 - Tue Jul 14 00:15:41 GMT 2020 1757 | darklime: 1758 | Make all functions in Style common. (#6931) 1759 | 1760 | ========= 1761 | Build: 1.16.1-32.0.65 - Mon Jul 13 22:44:53 GMT 2020 1762 | 55965249+seymourimadeit: 1763 | Mark Raid.WaveMembers as an extensible enum. (#6878) 1764 | 1765 | ========= 1766 | Build: 1.16.1-32.0.64 - Mon Jul 13 22:17:58 GMT 2020 1767 | lexmanos: 1768 | Fix checkPatches task. Closes #6956 1769 | Fix patched in method using srg name. Closes #6965 1770 | Fix capabilities not being collected for ClientWorld. Closes #6966 1771 | Fix TagEmptyCondition using client side copy of tags instead of server. Closes #6949 1772 | Fix ExtendedButton using narrator text. Closes #6958, Closes #6959 1773 | Fix misaligned patch in RepairContainer. Closes #6950, Closes #6953 1774 | Fix LivingJumpEvent not being fired for players jumping horses. Closes #6929 1775 | Remove extra getToughness method in ArmorItem. Closes #6970 1776 | Remove GetCollisionBoxesEvent. Closes #6921 1777 | 1778 | ========= 1779 | Build: 1.16.1-32.0.63 - Fri Jul 10 22:28:22 GMT 2020 1780 | richard: 1781 | Fix race condition with DeferredRegister for custom registries (#6951) 1782 | 1783 | ========= 1784 | Build: 1.16.1-32.0.62 - Fri Jul 10 17:49:51 GMT 2020 1785 | sciwhiz12: 1786 | Remove hooks into beacon base/payments. Vanilla uses tags now for extensibility. (#6948) 1787 | 1788 | ========= 1789 | Build: 1.16.1-32.0.61 - Wed Jul 08 21:33:38 GMT 2020 1790 | jaredlll08: 1791 | Expose the DataPackRegistries instance to the AddReloadListenerEvent (#6933) 1792 | 1793 | ========= 1794 | Build: 1.16.1-32.0.60 - Wed Jul 08 21:13:18 GMT 2020 1795 | sciwhiz12: 1796 | Fix canRepair not being set true as default (#6936) 1797 | 1798 | Closes #6934 and #6935 1799 | 1800 | ========= 1801 | Build: 1.16.1-32.0.59 - Wed Jul 08 14:56:39 GMT 2020 1802 | gigaherz: 1803 | Fix particles sometimes "losing" the lightmap and drawing fullbright. 1804 | 1805 | gigaherz: 1806 | Fix misaligned patch causing LivingEquipmentChangeEvent to never be posted. 1807 | 1808 | ========= 1809 | Build: 1.16.1-32.0.57 - Mon Jul 06 21:32:33 GMT 2020 1810 | jdlogic: 1811 | Add simple patch checker and cleanup patches (#6851) 1812 | 1813 | * Add simple patch checker and cleanup patches 1814 | 1815 | * Address comments 1816 | * move task implementation 1817 | * genPatches is now finalized by checkPatches 1818 | * the S2S artifacts are automatically removed 1819 | * added class and method access checking 1820 | 1821 | ========= 1822 | Build: 1.16.1-32.0.56 - Mon Jul 06 21:27:02 GMT 2020 1823 | richard: 1824 | Fix the modifier combined name for keybinds displaying two pluses outside of forgedev #6901 (#6902) 1825 | 1826 | ========= 1827 | Build: 1.16.1-32.0.55 - Mon Jul 06 21:12:45 GMT 2020 1828 | richard: 1829 | Fix harvest level and tool type not actually getting set #6906 (#6922) 1830 | 1831 | ========= 1832 | Build: 1.16.1-32.0.54 - Mon Jul 06 20:46:01 GMT 2020 1833 | richard: 1834 | Reimplement ITeleporter Patches (#6886) 1835 | 1836 | ========= 1837 | Build: 1.16.1-32.0.53 - Mon Jul 06 20:39:37 GMT 2020 1838 | 40738104+mysterious-dev: 1839 | Add function to add items with the same behavior as the pumpkin for enderman (#6890) 1840 | 1841 | ========= 1842 | Build: 1.16.1-32.0.52 - Mon Jul 06 20:33:17 GMT 2020 1843 | richard: 1844 | Custom Item integration with Piglins (#6914) 1845 | 1846 | ========= 1847 | Build: 1.16.1-32.0.51 - Mon Jul 06 20:20:02 GMT 2020 1848 | ichttt: 1849 | Some dead code cleanup, and re-implement some bed hooks. (#6903) 1850 | 1851 | ========= 1852 | Build: 1.16.1-32.0.50 - Mon Jul 06 20:06:39 GMT 2020 1853 | diesieben07: 1854 | Fix missing null checks in ForgeIngameGui (#6907) 1855 | 1856 | ========= 1857 | Build: 1.16.1-32.0.49 - Mon Jul 06 19:50:02 GMT 2020 1858 | sciwhiz12: 1859 | Fix swap offhand keybind not working in GUIs (#6920) 1860 | 1861 | ========= 1862 | Build: 1.16.1-32.0.48 - Mon Jul 06 19:42:07 GMT 2020 1863 | thpetuaudletang: 1864 | New AddReloadListenerEvent that gathers server side data reload handlers. (#6849) 1865 | 1866 | ========= 1867 | Build: 1.16.1-32.0.47 - Fri Jul 03 12:40:42 GMT 2020 1868 | gigaherz: 1869 | Attempt to use a more compatible method to initialize stencil support. 1870 | In case the separate attachments don't work for everyone, there's a new setting to choose the combined attachment. 1871 | 1872 | ========= 1873 | Build: 1.16.1-32.0.46 - Fri Jul 03 04:00:22 GMT 2020 1874 | gigaherz: 1875 | Update copyright year to 2020. 1876 | 1877 | gigaherz: 1878 | Fix multi-layer item rendering. 1879 | 1880 | ========= 1881 | Build: 1.16.1-32.0.44 - Thu Jul 02 17:17:45 GMT 2020 1882 | gigaherz: 1883 | Model system improvements: 1884 | - Port some things I did in 1.14 which I couldn't do in 1.15 due to breaking changes. 1885 | - Fix multi-layer block models not working (1.16 RenderType doesn't override toString the same way anymore) 1886 | - Implement multi-layer item rendering. 1887 | - Improve CompositeModel submodel data passing. 1888 | 1889 | ========= 1890 | Build: 1.16.1-32.0.43 - Thu Jul 02 12:54:03 GMT 2020 1891 | martijnvandenbrand: 1892 | Include model data in getQuads call (#6884) 1893 | 1894 | The model data wasn't included when getting quads from specific sides, but was when getting quads for side = null. 1895 | 1896 | thpetuaudletang: 1897 | Pass matrixstack in tooltip render events (#6885) 1898 | 1899 | ========= 1900 | Build: 1.16.1-32.0.41 - Thu Jul 02 05:54:25 GMT 2020 1901 | tterrag: 1902 | Fix improper handling of baked lighting in forge light pipeline 1903 | 1904 | Closes #6812 1905 | 1906 | ========= 1907 | Build: 1.16.1-32.0.40 - Thu Jul 02 01:59:30 GMT 2020 1908 | pupnewfster: 1909 | Fix FMLServerAboutToStartEvent being fired too late on the integrated server https://github.com/MinecraftForge/MinecraftForge/issues/6859 1910 | 1911 | ========= 1912 | Build: 1.16.1-32.0.39 - Wed Jul 01 18:14:25 GMT 2020 1913 | ichttt: 1914 | Fix miss-aligned patch ItemEntity (#6895) 1915 | 1916 | ========= 1917 | Build: 1.16.1-32.0.38 - Tue Jun 30 20:19:32 GMT 2020 1918 | info: 1919 | Add hoe tool type (#6872) 1920 | 1921 | ========= 1922 | Build: 1.16.1-32.0.36 - Tue Jun 30 20:09:21 GMT 2020 1923 | curle: 1924 | Allow any armor to have custom knockback resistance (#6877) 1925 | 1926 | ========= 1927 | Build: 1.16.1-32.0.35 - Tue Jun 30 19:57:32 GMT 2020 1928 | diesieben07: 1929 | Add senderUUID to ClientChatReceivedEvent (#6881) 1930 | 1931 | ========= 1932 | Build: 1.16.1-32.0.34 - Tue Jun 30 02:33:58 GMT 2020 1933 | lexmanos: 1934 | Re-write checkATs function and automate making Items/Blocks public. 1935 | 1936 | ========= 1937 | Build: 1.16.1-32.0.33 - Tue Jun 30 02:10:14 GMT 2020 1938 | cpw: 1939 | Reorganize modloading on the dediserver. This removes the DedicatedServer parameter from the FMLDedicatedServerSetupEvent. 1940 | Code for customizing the server instance should be moved to the ServerAboutToStartEvent or similar, where the server instance 1941 | is available. 1942 | 1943 | This reorganization means that mods will load fully before the server is even constructed, or the server properties loaded. We also move the EULA right to the front so we don't have to wait for bootstrap. 1944 | 1945 | This should fix the problems with mods which customize world data and other things. 1946 | 1947 | Signed-off-by: cpw 1948 | 1949 | ========= 1950 | Build: 1.16.1-32.0.32 - Mon Jun 29 23:43:01 GMT 2020 1951 | thpetuaudletang: 1952 | Fix datagen resolving tags and exploding. (#6865) 1953 | 1954 | ========= 1955 | Build: 1.16.1-32.0.31 - Mon Jun 29 23:37:30 GMT 2020 1956 | mattmess1221: 1957 | Fix Language.javaLocale parsing (#6862) 1958 | 1959 | ========= 1960 | Build: 1.16.1-32.0.30 - Mon Jun 29 22:58:30 GMT 2020 1961 | diesieben07: 1962 | Fix IItemHandler wrappers for chests not updating both chests (#6875) 1963 | 1964 | ========= 1965 | Build: 1.16.1-32.0.29 - Mon Jun 29 21:08:55 GMT 2020 1966 | lexmanos: 1967 | Fix missed patch in PlayerList and EntitySelectioonContext. Closes #6846 Closes #6850 1968 | 1969 | ========= 1970 | Build: 1.16.1-32.0.27 - Mon Jun 29 20:09:12 GMT 2020 1971 | richard: 1972 | Fix access levels being hardcoded to private via patch overriding AT entry (#6848) 1973 | 1974 | ========= 1975 | Build: 1.16.1-32.0.26 - Mon Jun 29 19:42:50 GMT 2020 1976 | lexmanos: 1977 | Fix tag related issues when connecting to a vanilla server. 1978 | 1979 | ========= 1980 | Build: 1.16.1-32.0.25 - Sun Jun 28 22:08:15 GMT 2020 1981 | lexmanos: 1982 | Fix Forge's internal handler being registered in wrong place. 1983 | Fix double call to loader end. 1984 | 1985 | ========= 1986 | Build: 1.16.1-32.0.24 - Sat Jun 27 22:50:54 GMT 2020 1987 | gigaherz: 1988 | Add a model loader that lets mods specify different models for different perspectives. 1989 | Allow custom models to reference vanilla item models as child models. 1990 | 1991 | ========= 1992 | Build: 1.16.1-32.0.23 - Fri Jun 26 23:55:23 GMT 2020 1993 | thpetuaudletang: 1994 | fix misapplied patch 1995 | 1996 | also sneak in an import patch removal 1997 | 1998 | ========= 1999 | Build: 1.16.1-32.0.21 - Fri Jun 26 22:40:19 GMT 2020 2000 | lexmanos: 2001 | Fix blocks being harvested with incorrect tools. 2002 | 2003 | ========= 2004 | Build: 1.16.1-32.0.20 - Fri Jun 26 19:53:02 GMT 2020 2005 | lexmanos: 2006 | Make installer use MCPConfig version to identify MC assets. 2007 | 2008 | ========= 2009 | Build: 1.16.1-32.0.19 - Fri Jun 26 18:27:49 GMT 2020 2010 | cpw: 2011 | Tweak the server startup a bit, make sure methods that can't work because they run before a server exists explode saying so. 2012 | Also fix other launch profiles. 2013 | 2014 | Signed-off-by: cpw 2015 | 2016 | ========= 2017 | Build: 1.16.1-32.0.18 - Fri Jun 26 16:56:37 GMT 2020 2018 | lexmanos: 2019 | Fix dedicated server loading by constructing mods before data packs are created. 2020 | 2021 | ========= 2022 | Build: 1.16.1-32.0.17 - Fri Jun 26 15:20:37 GMT 2020 2023 | gigaherz: 2024 | Fix create method. 2025 | Fix test mods not loading correctly. 2026 | 2027 | ========= 2028 | Build: 1.16.1-32.0.16 - Fri Jun 26 14:43:19 GMT 2020 2029 | gigaherz: 2030 | Reintroduce missed patch in EntityClassification. 2031 | 2032 | ========= 2033 | Build: 1.16.1-32.0.15 - Fri Jun 26 13:55:42 GMT 2020 2034 | thpetuaudletang: 2035 | Include a getter for the matrix stack in OverlayEvent (#6834) 2036 | 2037 | ========= 2038 | Build: 1.16.1-32.0.14 - Fri Jun 26 13:23:07 GMT 2020 2039 | thpetuaudletang: 2040 | Fix block render types not being properly applied to item entities (#6832) 2041 | 2042 | ========= 2043 | Build: 1.16.1-32.0.13 - Fri Jun 26 13:05:18 GMT 2020 2044 | mods.itsmeow: 2045 | [1.16.x] Allow GlobalEntityTypeAttributes' EntityType -> AttributeModifierMap to be added to (#6822) 2046 | 2047 | * Make GlobalEntityTypeAttributes map able to be added to 2048 | 2049 | * Split get patch into two lines 2050 | 2051 | * Favor Forge's map over vanilla 2052 | 2053 | ========= 2054 | Build: 1.16.1-32.0.12 - Fri Jun 26 12:59:19 GMT 2020 2055 | thpetuaudletang: 2056 | Fixed creative screen arrows (#6827) 2057 | 2058 | yunus1903: 2059 | Added call to method for tooltip with FontRenderer (#6831) 2060 | 2061 | ========= 2062 | Build: 1.16.1-32.0.10 - Fri Jun 26 12:36:59 GMT 2020 2063 | curle: 2064 | Retarget Block.Properties patch to the new AbstractBlock, reintroduce harvestLevel and harvestTool fields (#6819) 2065 | 2066 | * Retarget Block.Properties patch to the new AbstractBlock, reintroduces the harvestLevel and harvestTool fields. 2067 | 2068 | * Slight adjustment to fix the lootTableSupplier. 2069 | 2070 | ========= 2071 | Build: 1.16.1-32.0.9 - Fri Jun 26 12:31:37 GMT 2020 2072 | yunus1903: 2073 | Fixed sneaking while swimming (#6817) 2074 | 2075 | ========= 2076 | Build: - Fri Jun 26 12:25:07 GMT 2020 2077 | thpetuaudletang: 2078 | Fixed tooltip rendering issues (#6815) 2079 | 2080 | ========= 2081 | Build: 1.16.1-32.0.7 - Fri Jun 26 02:30:54 GMT 2020 2082 | thpetuaudletang: 2083 | Fixed villager trades having non-applicable enchants 2084 | 2085 | Also added an AT at lex's request 2086 | 2087 | ========= 2088 | Build: 1.16.1-32.0.6 - Fri Jun 26 01:52:19 GMT 2020 2089 | thpetuaudletang: 2090 | Fix locate command (#6811) 2091 | 2092 | thpetuaudletang: 2093 | Fix block drops (#6810) 2094 | 2095 | contact: 2096 | Add missing patch to ScreenShotHelper (#6809) 2097 | 2098 | Adds the missed patch back 2099 | 2100 | yunus1903: 2101 | Updated MDK mods.toml versions (#6808) 2102 | 2103 | thpetuaudletang: 2104 | Fix locate command (#6811) 2105 | 2106 | thpetuaudletang: 2107 | Fix block drops (#6810) 2108 | 2109 | contact: 2110 | Add missing patch to ScreenShotHelper (#6809) 2111 | 2112 | Adds the missed patch back 2113 | 2114 | yunus1903: 2115 | Updated MDK mods.toml versions (#6808) 2116 | 2117 | thpetuaudletang: 2118 | Fix locate command (#6811) 2119 | 2120 | thpetuaudletang: 2121 | Fix block drops (#6810) 2122 | 2123 | contact: 2124 | Add missing patch to ScreenShotHelper (#6809) 2125 | 2126 | Adds the missed patch back 2127 | 2128 | yunus1903: 2129 | Updated MDK mods.toml versions (#6808) 2130 | 2131 | ========= 2132 | Build: 1.16.1-32.0.2 - Fri Jun 26 01:41:51 GMT 2020 2133 | lexmanos: 2134 | Rework BlockSnapshot and fix client notifications. Closes #6807 2135 | 2136 | ========= 2137 | Build: 1.16.1-32.0.1 - Thu Jun 25 23:24:48 GMT 2020 2138 | lexmanos: 2139 | Bump MCPConfig version. 2140 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # abort on errors 4 | set -e 5 | 6 | # build 7 | npm run docs:build 8 | 9 | # navigate into the build output directory 10 | cd docs/.vuepress/dist 11 | 12 | # if you are deploying to a custom domain 13 | # echo 'www.example.com' > CNAME 14 | 15 | git init 16 | git add -A 17 | git commit -m 'feat: deploy docs' 18 | 19 | # if you are deploying to https://.github.io/ 20 | git push -f https://github.com/Codestian/HomeAssistantMC.git master:gh-pages 21 | 22 | cd - 23 | -------------------------------------------------------------------------------- /docs/.vuepress/components/Foo/Bar.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /docs/.vuepress/components/OtherComponent.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /docs/.vuepress/components/demo-component.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const { description } = require('../../package') 2 | 3 | module.exports = { 4 | title: 'HomeAssistantMC', 5 | base: '/HomeAssistantMC/', 6 | description: description, 7 | head: [ 8 | ['meta', { name: 'theme-color', content: '#03a9f4' }], 9 | ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], 10 | ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }] 11 | ], 12 | themeConfig: { 13 | repo: '', 14 | editLinks: false, 15 | docsDir: '', 16 | editLinkText: '', 17 | lastUpdated: false, 18 | nav: [ 19 | { 20 | text: 'Guide', 21 | link: '/guide/', 22 | }, 23 | { 24 | text: 'Github', 25 | link: 'https://github.com/Codestian/HomeAssistantMC' 26 | }, 27 | { 28 | text: 'CurseForge', 29 | link: 'https://www.curseforge.com/minecraft/mc-mods/homeassistantmc' 30 | } 31 | ], 32 | sidebar: { 33 | '/guide/': [ 34 | { 35 | title: 'Guide', 36 | collapsable: false, 37 | children: [ 38 | '', 39 | 'installation', 40 | 'configuration', 41 | ['state-block', 'State Block'], 42 | ['service-block', 'Service Block'], 43 | 'building-automations', 44 | 'faq' 45 | ] 46 | } 47 | ], 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | export default ({ 2 | Vue, 3 | options, 4 | router, 5 | siteData 6 | }) => {} 7 | -------------------------------------------------------------------------------- /docs/.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/.vuepress/public/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Styles here. 3 | * 4 | * ref:https://v1.vuepress.vuejs.org/config/#index-styl 5 | */ 6 | 7 | .home .hero img 8 | max-width 450px!important 9 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom palette here. 3 | * 4 | * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl 5 | */ 6 | 7 | $accentColor = #03a9f4 8 | $textColor = #2c3e50 9 | $borderColor = #eaecef 10 | $codeBgColor = #282c34 11 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ![Logo of HomeAssistantMC](./assets/images/logofull1.png) 4 | 5 | HomeAssistantMC is a Minecraft mod that integrates Home Assistant to Minecraft, allowing retrieval of entity states and calling of services. This allows you to build and execute automations entirely ingame. 6 | 7 | ## Use cases 8 | - Build and run automations/scripts 9 | - Setup a 3D virtual dashboard 10 | - Create a house floorplan 11 | - Turn on smart devices without leaving the game 12 | - Teach other people on home automation 13 | 14 | ## How it works 15 | 16 | HomeAssistantMC connects to Home Assistant via the [WebSocket API](https://developers.home-assistant.io/docs/api/websocket/) with an access token. It subscribes to the event bus and listens for any entity state changes. Essentially, Minecraft becomes a websocket client of Home Asssitant. 17 | 18 | ## Why not...? 19 | 20 | ### Mine Assistant 21 | 22 | [Mine Assistant](https://www.spigotmc.org/resources/mine-assistant.92469/) is a server plugin for Bukkit, a modification of Minecraft's server software. While its great for keeping things vanilla, it has limited functionality and can strictly only call services to turn on and off entities. HomeAssistantMC allows more freedom to configure and set entities to listen to as well as calling services even with custom yaml. 23 | 24 | ### ComputerCraft 25 | 26 | [ComputerCraft](https://tweaked.cc/) is a Minecraft mod that adds programmable computers, turtles and more to the game. The current version of the mod is called CC Tweaked, as the original version has been discontinued. ComputerCraft does support WebSockets that can connect to Home Assistant, but it may be tedious and time consuming to set up. HomeAsssitantMC is designed for a plug and play experience as well as minimal maintanence for future Minecraft versions. -------------------------------------------------------------------------------- /docs/guide/assets/images/automation_chunks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/automation_chunks.png -------------------------------------------------------------------------------- /docs/guide/assets/images/automation_delays.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/automation_delays.png -------------------------------------------------------------------------------- /docs/guide/assets/images/automation_logic_gates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/automation_logic_gates.png -------------------------------------------------------------------------------- /docs/guide/assets/images/logofull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/logofull.png -------------------------------------------------------------------------------- /docs/guide/assets/images/logofull1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/logofull1.png -------------------------------------------------------------------------------- /docs/guide/assets/images/original/logofull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/original/logofull.png -------------------------------------------------------------------------------- /docs/guide/assets/images/original/logofull1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/original/logofull1.png -------------------------------------------------------------------------------- /docs/guide/assets/images/service_block_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/service_block_icon.png -------------------------------------------------------------------------------- /docs/guide/assets/images/service_block_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/service_block_screen.png -------------------------------------------------------------------------------- /docs/guide/assets/images/service_developer_tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/service_developer_tools.png -------------------------------------------------------------------------------- /docs/guide/assets/images/state_block_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/state_block_icon.png -------------------------------------------------------------------------------- /docs/guide/assets/images/state_block_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/state_block_screen.png -------------------------------------------------------------------------------- /docs/guide/assets/images/state_developer_tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/images/state_developer_tools.png -------------------------------------------------------------------------------- /docs/guide/assets/videos/automation_example01.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/automation_example01.mp4 -------------------------------------------------------------------------------- /docs/guide/assets/videos/service_block_example01.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/service_block_example01.mp4 -------------------------------------------------------------------------------- /docs/guide/assets/videos/state_block_example01.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/state_block_example01.mp4 -------------------------------------------------------------------------------- /docs/guide/assets/videos/state_block_example02.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/state_block_example02.mp4 -------------------------------------------------------------------------------- /docs/guide/assets/videos/state_block_example03.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/state_block_example03.mp4 -------------------------------------------------------------------------------- /docs/guide/assets/videos/state_block_example04.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/docs/guide/assets/videos/state_block_example04.mp4 -------------------------------------------------------------------------------- /docs/guide/building-automations.md: -------------------------------------------------------------------------------- 1 | # Building automations 2 | 3 | Combined with redstone mechanics such as repeaters and pistons, it is possible to build and execute automations entirely within Minecraft. 4 | 5 | ## Keeping chunks loaded 6 | 7 | Before we can embark on building automations, we need to ensure that our automations will be able to run all the time, even without player presence. 8 | 9 | ### What are Minecraft chunks? 10 | 11 | A Minecraft chunk is a 256 tall, 16 by 16 segment of a world. They are used by the world generator to divide maps into managable pieces. In Minecraft, chunks are unloaded when players are either far away or are not present in the world. Game mechanics will stop, including command blocks, mob spawning and redstone mechanics. The `/forceload` command can help us to ensure selected chunks are constantly loaded. 12 | 13 | ![Image of Minecraft chunks](./assets/images/automation_chunks.png) 14 | 15 | ### How to forceload a chunk 16 | 17 | Stand over a selected chunk and run the command `/forceload add ~ ~`. To easily identify the borders of chunks, hit `F3 + G` to enable debug mode. Chunks that have been forceloaded will now stay loaded persistently, allowing us to build our automations and have them run all the time. 18 | 19 | ## Simple automation 20 | 21 | This example demonstrates how to build an automation which **Turns on the ceiling light `light.ceiling_light` when a seat is occupied `binary_sensor.seat_sensor`** and vice versa (turns off). 22 | 23 | 27 | 28 | Note the seat sensor `binary_sensor.seat_sensor` state is set to `off` when someone is seated. 29 | 30 | ## Logic gates 31 | 32 | HomeAssistantMC allows you to create flow based automations similar to Node Red. Examples of logic gates are below. 33 | 34 | ![Image of redstone logic gates](./assets/images/automation_logic_gates.png) 35 | 36 | ## Setting delays 37 | 38 | To build delays, we can use redstone repeaters. To create a 1 second delay with repeaters, we need 10 ticks, so use 2 on full delay (8 redstone ticks) and 1 set halfway (2 redstone ticks). 39 | 40 | ![Image of redstone repeaters as delays](./assets/images/automation_delays.png) 41 | -------------------------------------------------------------------------------- /docs/guide/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | Once HomeAssistantMC has been successfully installed, you need to setup the configuration. 4 | 5 | To do so, navigate to the `/.minecraft/config/` folder and create a new file named `homeassistantmc-common.toml` file. Edit the variables `url` and `token` to the url of your Home Assistant instance and long lived token respectively. Examples of urls: 6 | - `ws://homeassistant.local:8123` 7 | - `wss://sampletextXXX.ui.nabu.casa` 8 | 9 | Join a Minecraft world and HomeAssistantMC will be successfully connected. 10 | 11 | :::tip 12 | If an entity has been modified on Home Assistant's end, you need to reload the websocket connection. This can be done either by rejoining the world again (singleplayer) or restarting the server (multiplayer). 13 | ::: -------------------------------------------------------------------------------- /docs/guide/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | Answers to most frequent questions or questions that were never asked but good to know. 4 | 5 | - [What versions of Minecraft are supported?](##does-this-mod-work-on-singleplayer) 6 | - [Does this mod work on Singleplayer?](#does-this-mod-work-on-singleplayer) 7 | - [How do I backup the stuff I built with this mod?](#how-do-i-backup-the-stuff-i-built-with-this-mod) 8 | - [The mod fails to connect to Home Assistant when entering the world!](#the-mod-fails-to-connect-to-home-assistant-when-entering-the-world) 9 | - [Minecraft crashes when I install the mod!](#minecraft-crashes-when-i-install-the-mod) 10 | - [Do I need to install anything on Home Assistant?](#do-i-need-to-install-anything-on-home-assistant) 11 | - [Can I use other mods with this?](#can-i-use-other-mods-with-this) 12 | - [How can I contribute to this project?](#how-can-i-contribute-to-this-project) 13 | - [Is there a fabric version available?](#is-there-a-fabric-version-available) 14 | - [Can I control Minecraft from Home Assistant?](#can-i-control-minecraft-from-home-assistant) 15 | 16 | ## What versions of Minecraft are supported? 17 | 18 | Currently supported Minecraft versions: 19 | 20 | | | Forge | Fabric | 21 | |--------|-------|--------| 22 | | 1.17.x | Yes | TBD | 23 | | 1.16.x | Yes | TBD | 24 | | 1.12.x | No | No | 25 | 26 | HomeAssistantMC will only be developed for 1.16+. There are no plans to develop for 1.12. 27 | 28 | ## Does this mod work on Singleplayer? 29 | 30 | HomeAssistantMC works on both singleplayer and multiplayer. Do note that for singleplayer, it is recommended to enable `Open to LAN` to prevent the game from pausing and not receiving updates from Home Asssitant. 31 | 32 | ## How do I backup the stuff I built with this mod? 33 | 34 | You can back up the Minecraft world folder located in `/.minecraft/saves/` if you are on singleplayer. It is always recommended to backup Minecraft worlds before using or updating mods. 35 | 36 | ## The mod fails to connect to Home Assistant when entering the world! 37 | 38 | To check if the Minecraft world is connected to Home Assistant, run the command `/hass status`. If it is not connected, rejoin the game in singleplayer or restart the server in multiplayer. If it still does not work, ensure the variables in the `homeassistantmc-common.config` file are correct and retry again. 39 | 40 | ## Minecraft crashes when I install the mod! 41 | 42 | Ensure that it is HomeAssistantMC that is causing the crash. If it does, submit an issue on the GitHub repository. 43 | 44 | ## Do I need to install anything on Home Assistant? 45 | 46 | HomeAssistantMC works out of the box on its own, as long as you have the url and access token. No integration or custom components are needed as the mod only connects to Home Assistant as a websocket client. The access token can be retrieved from the profile page. 47 | 48 | ## How do I keep redstone running with nobody in the server? 49 | 50 | The `/forceload` command was introduced in Minecraft 1.14, allowing players up to permission level 2 to set chunks to load constantly. Automation contraptions on these chunks will be able run continuously even without players. 51 | 52 | ## Can I use other mods with this? 53 | 54 | HomeAssistantMC is built with the Forge API, allowing compatibility with other Minecraft forge mods. You can try and install redstone related mods such as [Create](https://www.curseforge.com/minecraft/mc-mods/create) and [More Red](https://www.curseforge.com/minecraft/mc-mods/more-red) to create even more complex automation contraptions. 55 | 56 | ## How can I contribute to this project? 57 | 58 | The source code for HomeAssistantMC is on GitHub. Feel free to submit pull requests to improve code or add new functionalities. 59 | 60 | ## Is there a fabric version available? 61 | 62 | A fabric port will be developed in the near future. 63 | 64 | ## Can I control Minecraft from Home Assistant? 65 | 66 | Controlling Minecraft from Home Assistant is possible, but access to command blocks is required. Create helper entities in Home Assistant and listen to them with the state block. You can then connect the redstone signal output of the state block ingame to a command block. 67 | 68 | If you would like to dynamically trigger automations based on the data from the Minecraft world (current biome, player health), check out the MqttMC mod (In development). -------------------------------------------------------------------------------- /docs/guide/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | HomeAssistantMC can be downloaded either from the GitHub repository or CurseForge. 4 | 5 | :::warning 6 | It is recommended to download HomeAssistantMC only from official sources. 7 | ::: 8 | 9 | ## Singleplayer 10 | 11 | 1. Download HomeAssistantMC, it should be a .jar file. 12 | 2. Open the folder where Minecraft is installed. `(/.minecraft/)` 13 | 3. Place the jar file into the `mods` folder. 14 | 15 | ## Multiplayer 16 | 17 | 1. Setup a [Minecraft Forge server](https://minecraft.fandom.com/wiki/Tutorials/Setting_up_a_Minecraft_Forge_server). 18 | 2. Download HomeAssistantMC, it should be a .jar file. 19 | 3. Open the folder where the server has been installed. 20 | 4. Place the jar file into the `mods` folder. 21 | 22 | :::danger 23 | HomeAssistantMC may grant full access to the entities in Home Assistant to the server. If you are planning to expose your Minecraft server to the internet, it is highly recommended to use a Home Assistant token from a user with less privileges (limited access to certain entities and services). 24 | ::: -------------------------------------------------------------------------------- /docs/guide/service-block.md: -------------------------------------------------------------------------------- 1 | ![Icon of Service Block](./assets/images/service_block_icon.png) 2 | 3 | # Service Block 4 | 5 | The service block is an input redstone block. When the block is powered by a redstone source, it will call a home assistant service along with the specified configuration. 6 | 7 | ### Examples 8 | 9 | - Turn on the light bulb at 40% brightness and color red. 10 | - Play music on the smart speaker at 70% volume. 11 | - Turn off the smart plug. 12 | - Turn on the Air Conditioner set to 22 degrees Celsius. 13 | - Send a telegram message. 14 | 15 | ## Creating service yaml 16 | 17 | Before getting started, it's best to know what service and parameters you are planning to call upon. The service block only accepts a call service configuration in yaml. JSON is also considered valid yaml. The best way to do this is to create the configuration in the services tab of the Developer Tools of the Home Assistant Frontend. 18 | 19 | ![Image of Developer Tools Services page](./assets/images/service_developer_tools.png) 20 | 21 | Here, we can set which service we would like to call and which parameters we would like to be filled up as well. In this example, a call service is configured to turn on the floor lamp `light.floor_lamp` with 70% `brightness` and the `color_name` set to red. 22 | 23 | You can also use the `ui mode` to set the configuration, but you need to copy the yaml text by clicking on `go to yaml mode`. 24 | 25 | :::tip 26 | The keys `service` and `data` are required to be considered a valid configuration. 27 | ::: 28 | 29 | ## GUI Configuration 30 | 31 | Currently, HomeAssistantMC does not provide an ingame text editor. Instead, the yaml configuration needs to be typed on an external program, ideally the Home Assistant Developer Tools webpage. To set the yaml configuration to a service block, click on the `Paste` button. To edit the configuration, click on the `Copy` button and edit it on an external text editor. 32 | 33 | ![Image of Service Block GUI](./assets/images/service_block_screen.png) 34 | 35 | To call a service, the service block needs to be powered with a redstone signal. 36 | 37 | ## Turn on/off entity 38 | 39 | This example demonstrates how to configure a service block to call a service to **turn on and off the floor lamp `light.floor_lamp`.** Additional parameters can be easily customized to your liking. 40 | 41 | 45 | 46 | ## Send notification to Telegram 47 | 48 | This example demonstrates how to configure a service block to call a service to **send a simple Telegram message `telegram_bot`.** 49 | 50 | ### TODO 51 | -------------------------------------------------------------------------------- /docs/guide/state-block.md: -------------------------------------------------------------------------------- 1 | 2 | ![Icon of State Block](./assets/images/state_block_icon.png) 3 | 4 | # State Block 5 | 6 | The state block is an output redstone block. It emits a redstone signal when certain conditions of a specified entity is met. The attributes of the entity can even be tracked. It is only obtainable in creative mode. 7 | 8 | ### Examples 9 | - Room temperature is below 27 degrees Celsius. 10 | - The seat sensor is occupied. 11 | - The ceiling light has been turned on. 12 | - Smart speaker is playing something. 13 | - The smart bulb brightness is above 70%. 14 | 15 | ## Retrieving entity info 16 | 17 | Before getting started, it's best to know what entity and attributes you are planning to listen to. The best way to retrieve data for entities is in the states tab in the Developer Tools of the Home Assistant Frontend. Here, we can retrieve the `state` of the entity, along with the supported `attributes` and their respective values. 18 | 19 | ![Image of Developer Tools State page](./assets/images/state_developer_tools.png) 20 | 21 | ## GUI configuration 22 | 23 | Minimally, only the entity (top left) and value (top right) inputs are required. By default, the value input (top right) is set to `on`. The attribute (bottom left) and value (bottom right) inputs are optional and can be left empty. The operators in the middle can be toggled to either `=`, `>` or `<`. The operators can only be set to `<` and `>` when the values on the right side are numbers (5, -5, 5.0, 5.333). 24 | 25 | ![Image of State Block GUI](./assets/images/state_block_screen.png) 26 | 27 | 28 | ## On/off states 29 | 30 | This example demonstrates how to configure a state block to output a redstone signal **when the floor lamp `light.floor_lamp` is switched on.** As many entities only have `on` and `off` states, this will satisfy most use cases. 31 | 32 | 36 | 37 | The value input (top right) can be changed from `on` to `off` to invert the redstone signal. Note the texture of the state block slightly changes depending on whether a redstone signal is outputted. 38 | 39 | ## String states 40 | 41 | This example demonstrates how to configure a state block to output a redstone signal **when the phone `sensor phone_ringer_mode` is set to normal mode.** Some entities use words for entity states, so the state block needs to listen to the same word the entity state will be in. 42 | 43 | 47 | 48 | ## Numerical states 49 | This example demonstrates how to configure a state block to output a redstone signal **when the room temperature is below 27.4 degrees.** Besides `on` and `off` states, many other entities make use of numbers as entity states. As stated, when the value inputs are numbers, the operators `<` and `>` can also be used as a condition. 50 | 51 | 55 | 56 | ## Using attributes 57 | 58 | This example demonstrates how to configure a state block to output a redstone signal **when the floor lamp `light.floor_lamp` is switched on with brightness of more than 50%.** In addition to entity states, the state block can also listen for entity attributes. 59 | 60 | 64 | 65 | Note for the brightness attribute, the range is from` 0 - 255` where `128` is 50% brightness and `255` is 100% brightness. -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: ./logo.png 4 | tagline: Home Automation with Minecraft 5 | actionText: Get started → 6 | actionLink: /guide/ 7 | features: 8 | - title: Build and run automations 9 | details: Unleash your creativity building functional automations with redstone and other Minecraft mods. 10 | - title: Works out of the box 11 | details: Installation is easy and configuration is straightforward. The documentation also contain tutorials. 12 | - title: Bridge IOT with Minecraft 13 | details: Get notified of game events by using command blocks. The possibilities are endless. 14 | footer: Made by Codestian with ❤️ 15 | --- 16 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | org.gradle.daemon=false -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HomeAssistantMC", 3 | "version": "1.0.0", 4 | "description": "Documentation for the HomeAssistantMC mod", 5 | "main": "index.js", 6 | "authors": { 7 | "name": "Codestian", 8 | "email": "" 9 | }, 10 | "repository": "/docs", 11 | "scripts": { 12 | "dev": "vuepress dev docs", 13 | "build": "vuepress build docs", 14 | "docs:build": "vuepress build docs" 15 | }, 16 | "license": "MIT", 17 | "devDependencies": { 18 | "vuepress": "^1.5.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/HomeAssistantMC.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc; 2 | 3 | import com.codestian.homeassistantmc.config.Config; 4 | import com.codestian.homeassistantmc.init.ModBlocks; 5 | import com.codestian.homeassistantmc.init.ModItems; 6 | import com.codestian.homeassistantmc.init.ModTileEntities; 7 | import com.codestian.homeassistantmc.network.Network; 8 | import net.minecraftforge.common.MinecraftForge; 9 | import net.minecraftforge.eventbus.api.IEventBus; 10 | import net.minecraftforge.fml.ModLoadingContext; 11 | import net.minecraftforge.fml.common.Mod; 12 | import net.minecraftforge.fml.config.ModConfig; 13 | import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; 14 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; 15 | import net.minecraftforge.fml.loading.FMLPaths; 16 | import org.apache.logging.log4j.LogManager; 17 | import org.apache.logging.log4j.Logger; 18 | 19 | @Mod("homeassistantmc") 20 | public class HomeAssistantMC { 21 | 22 | public static final Logger logger = LogManager.getLogger(); 23 | public static final String MOD_ID = "homeassistantmc"; 24 | 25 | public HomeAssistantMC() { 26 | IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); 27 | 28 | ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.common_config); 29 | Config.loadConfig(Config.common_config, FMLPaths.CONFIGDIR.get().resolve("homeassistantmc-common.toml").toString()); 30 | 31 | bus.addListener(this::commonSetup); 32 | ModBlocks.BLOCKS.register(bus); 33 | ModTileEntities.TILE_ENTITY_TYPE.register(bus); 34 | ModItems.ITEMS.register(bus); 35 | 36 | MinecraftForge.EVENT_BUS.register(this); 37 | } 38 | 39 | public void commonSetup(final FMLCommonSetupEvent event) { 40 | Network.init(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/block/ServiceBlock.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.block; 2 | 3 | import com.codestian.homeassistantmc.init.ModTileEntities; 4 | import com.codestian.homeassistantmc.network.Network; 5 | import com.codestian.homeassistantmc.network.message.OpenServiceScreen; 6 | import com.codestian.homeassistantmc.te.ServiceTileEntity; 7 | import com.google.gson.Gson; 8 | import com.google.gson.JsonObject; 9 | import net.minecraft.block.*; 10 | import net.minecraft.block.material.Material; 11 | import net.minecraft.entity.player.PlayerEntity; 12 | import net.minecraft.entity.player.ServerPlayerEntity; 13 | import net.minecraft.item.BlockItemUseContext; 14 | import net.minecraft.state.BooleanProperty; 15 | import net.minecraft.state.StateContainer; 16 | import net.minecraft.tileentity.TileEntity; 17 | import net.minecraft.util.ActionResultType; 18 | import net.minecraft.util.Hand; 19 | import net.minecraft.util.math.BlockPos; 20 | import net.minecraft.util.math.BlockRayTraceResult; 21 | import net.minecraft.world.IBlockReader; 22 | import net.minecraft.world.World; 23 | import net.minecraft.world.server.ServerWorld; 24 | import net.minecraftforge.fml.network.PacketDistributor; 25 | 26 | import javax.annotation.Nullable; 27 | import java.util.Random; 28 | 29 | import static com.codestian.homeassistantmc.event.ServerEvent.webSocket; 30 | 31 | public class ServiceBlock extends Block { 32 | 33 | public static final BooleanProperty LIT = RedstoneTorchBlock.LIT; 34 | private final Gson gson = new Gson(); 35 | 36 | public ServiceBlock() { 37 | super(AbstractBlock.Properties.of(Material.METAL) 38 | .strength(1.5F) 39 | .sound(SoundType.METAL)); 40 | } 41 | 42 | @Override 43 | public boolean hasTileEntity(BlockState state) { 44 | return true; 45 | } 46 | 47 | @Override 48 | public TileEntity createTileEntity(BlockState state, IBlockReader world) { 49 | return ModTileEntities.SERVICE_TILE_ENTITY_TYPE.get().create(); 50 | } 51 | 52 | @SuppressWarnings("deprecation") 53 | @Override 54 | public ActionResultType use(BlockState blockstate, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockRayTraceResult p_225533_6_) { 55 | if (world.isClientSide) { 56 | return ActionResultType.SUCCESS; 57 | } else { 58 | TileEntity tileEntity = world.getBlockEntity(blockPos); 59 | if (tileEntity instanceof ServiceTileEntity) { 60 | Network.CHANNEL.send(PacketDistributor.PLAYER.with( 61 | () -> (ServerPlayerEntity) player), 62 | new OpenServiceScreen(((ServiceTileEntity) tileEntity).getHaServiceConfig(), blockPos) 63 | ); 64 | } else { 65 | throw new IllegalStateException("Our named container provider is missing!"); 66 | } 67 | return ActionResultType.CONSUME; 68 | } 69 | } 70 | 71 | @Nullable 72 | public BlockState getStateForPlacement(BlockItemUseContext p_196258_1_) { 73 | return this.defaultBlockState().setValue(LIT, p_196258_1_.getLevel().hasNeighborSignal(p_196258_1_.getClickedPos())); 74 | } 75 | 76 | @SuppressWarnings("deprecation") 77 | @Override 78 | public void neighborChanged(BlockState blockState, World world, BlockPos blockPos, Block block, BlockPos p_220069_5_, boolean p_220069_6_) { 79 | if (!world.isClientSide) { 80 | boolean flag = blockState.getValue(LIT); 81 | if (flag != world.hasNeighborSignal(blockPos)) { 82 | if (flag) { 83 | world.getBlockTicks().scheduleTick(blockPos, this, 4); 84 | } else { 85 | world.setBlock(blockPos, blockState.cycle(LIT), 2); 86 | if (world.hasNeighborSignal(blockPos)) { 87 | TileEntity tileEntity = world.getBlockEntity(blockPos); 88 | if (tileEntity instanceof ServiceTileEntity) { 89 | ServiceTileEntity stateTileEntity = (ServiceTileEntity) tileEntity; 90 | try { 91 | JsonObject jsonObject = gson.fromJson(stateTileEntity.getHaServiceConfig(), JsonObject.class); 92 | String[] service = jsonObject.get("service").getAsString().split("\\."); 93 | JsonObject serviceData = new JsonObject(); 94 | JsonObject serviceTarget = new JsonObject(); 95 | 96 | if (jsonObject.has("data")) { 97 | serviceData = jsonObject.get("data").getAsJsonObject(); 98 | } 99 | if (jsonObject.has("target")) { 100 | serviceTarget = jsonObject.get("target").getAsJsonObject(); 101 | } 102 | webSocket.callService(service[0], service[1], serviceData, serviceTarget); 103 | } catch (Exception ignored) { 104 | } 105 | } 106 | } 107 | } 108 | } 109 | 110 | 111 | } 112 | } 113 | 114 | @SuppressWarnings("deprecation") 115 | @Override 116 | public void tick(BlockState blockState, ServerWorld serverWorld, BlockPos blockPos, Random p_225534_4_) { 117 | if (blockState.getValue(LIT) && !serverWorld.hasNeighborSignal(blockPos)) { 118 | serverWorld.setBlock(blockPos, blockState.cycle(LIT), 2); 119 | } 120 | 121 | } 122 | 123 | protected void createBlockStateDefinition(StateContainer.Builder p_206840_1_) { 124 | p_206840_1_.add(LIT); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/block/StateBlock.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.block; 2 | 3 | import com.codestian.homeassistantmc.init.ModTileEntities; 4 | import com.codestian.homeassistantmc.network.Network; 5 | import com.codestian.homeassistantmc.network.message.OpenStateScreen; 6 | import com.codestian.homeassistantmc.te.StateTileEntity; 7 | import com.codestian.homeassistantmc.worldsaveddata.EntityData; 8 | import com.google.gson.JsonObject; 9 | import net.minecraft.block.AbstractBlock; 10 | import net.minecraft.block.Block; 11 | import net.minecraft.block.BlockState; 12 | import net.minecraft.block.SoundType; 13 | import net.minecraft.block.material.Material; 14 | import net.minecraft.entity.player.PlayerEntity; 15 | import net.minecraft.entity.player.ServerPlayerEntity; 16 | import net.minecraft.state.BooleanProperty; 17 | import net.minecraft.state.IntegerProperty; 18 | import net.minecraft.state.StateContainer; 19 | import net.minecraft.state.properties.BlockStateProperties; 20 | import net.minecraft.tileentity.TileEntity; 21 | import net.minecraft.util.ActionResultType; 22 | import net.minecraft.util.Direction; 23 | import net.minecraft.util.Hand; 24 | import net.minecraft.util.math.BlockPos; 25 | import net.minecraft.util.math.BlockRayTraceResult; 26 | import net.minecraft.world.IBlockReader; 27 | import net.minecraft.world.World; 28 | import net.minecraftforge.fml.network.PacketDistributor; 29 | 30 | public class StateBlock extends Block { 31 | public static final IntegerProperty POWER = BlockStateProperties.POWER; 32 | public static final BooleanProperty INVERTED = BlockStateProperties.INVERTED; 33 | 34 | private static String entityState = ""; 35 | private static String attributeValue = ""; 36 | 37 | public StateBlock() { 38 | super(AbstractBlock.Properties.of(Material.METAL) 39 | .strength(1.5F) 40 | .sound(SoundType.METAL)); 41 | this.registerDefaultState(this.stateDefinition.any().setValue(POWER, 0).setValue(INVERTED, Boolean.FALSE)); 42 | } 43 | 44 | public static void updateSignalStrength(BlockState blockState, World world, BlockPos blockPos) { 45 | TileEntity tileEntity = world.getBlockEntity(blockPos); 46 | if (tileEntity instanceof StateTileEntity) { 47 | EntityData entityData = EntityData.get(world); 48 | StateTileEntity stateTileEntity = (StateTileEntity) tileEntity; 49 | if (entityData.getEntities().size() != 0) { 50 | try { 51 | JsonObject entity = entityData.getOneEntity(stateTileEntity.getHaEntityId()); 52 | 53 | boolean entityCondition = false; 54 | boolean attributeCondition = false; 55 | 56 | if (!stateTileEntity.getHaEntityId().isEmpty() && !stateTileEntity.getHaEntityStateToCheck().isEmpty()) { 57 | String state = entity.get("state").getAsString(); 58 | entityState = state; 59 | try { 60 | switch (stateTileEntity.getHaEntityOperator()) { 61 | case "=": 62 | if (state.equals(stateTileEntity.getHaEntityStateToCheck()) || Double.parseDouble(state) == Double.parseDouble(stateTileEntity.getHaEntityStateToCheck())) { 63 | entityCondition = true; 64 | } 65 | break; 66 | case "<": 67 | if (Double.parseDouble(state) < Double.parseDouble(stateTileEntity.getHaEntityStateToCheck())) { 68 | entityCondition = true; 69 | } 70 | break; 71 | case ">": 72 | if (Double.parseDouble(state) > Double.parseDouble(stateTileEntity.getHaEntityStateToCheck())) { 73 | entityCondition = true; 74 | } 75 | break; 76 | } 77 | } catch (NumberFormatException ignored) { 78 | } 79 | } 80 | 81 | if (!stateTileEntity.getHaAttributeName().isEmpty() && !stateTileEntity.getHaAttributeValueToCheck().isEmpty()) { 82 | if (entity.get("attributes").getAsJsonObject().has(stateTileEntity.getHaAttributeName())) { 83 | 84 | String attribute = entity.get("attributes").getAsJsonObject().get(stateTileEntity.getHaAttributeName()).toString(); 85 | attributeValue = attribute; 86 | 87 | try { 88 | switch (stateTileEntity.getHaAttributeOperator()) { 89 | case "=": 90 | if (attribute.equals(stateTileEntity.getHaAttributeValueToCheck()) || Double.parseDouble(attribute) == Double.parseDouble(stateTileEntity.getHaAttributeValueToCheck())) { 91 | attributeCondition = true; 92 | } 93 | break; 94 | case "<": 95 | if (Double.parseDouble(attribute) < Double.parseDouble(stateTileEntity.getHaAttributeValueToCheck())) { 96 | attributeCondition = true; 97 | } 98 | break; 99 | case ">": 100 | if (Double.parseDouble(attribute) > Double.parseDouble(stateTileEntity.getHaAttributeValueToCheck())) { 101 | attributeCondition = true; 102 | } 103 | break; 104 | } 105 | } catch (NumberFormatException ignored) { 106 | } 107 | } else { 108 | // Put initial values for attributes that don't exist in current entity object 109 | if (stateTileEntity.getHaAttributeName().equals("brightness")) { 110 | attributeValue = "0"; 111 | } else if (stateTileEntity.getHaAttributeName().equals("rgb_color")) { 112 | attributeValue = "[0.0,0.0,0.0]"; 113 | } 114 | } 115 | } else { 116 | attributeCondition = true; 117 | } 118 | 119 | if (entityCondition && attributeCondition) { 120 | world.setBlock(blockPos, blockState.setValue(POWER, 15).setValue(INVERTED, true), 3); 121 | } else { 122 | world.setBlock(blockPos, blockState.setValue(POWER, 0).setValue(INVERTED, false), 3); 123 | } 124 | } catch (Exception ignored) { 125 | } 126 | 127 | } 128 | } 129 | } 130 | 131 | @Override 132 | public boolean hasTileEntity(BlockState state) { 133 | return true; 134 | } 135 | 136 | @Override 137 | public TileEntity createTileEntity(BlockState state, IBlockReader world) { 138 | return ModTileEntities.STATE_TILE_ENTITY_TYPE.get().create(); 139 | } 140 | 141 | @SuppressWarnings("deprecation") 142 | @Override 143 | public ActionResultType use(BlockState blockstate, World world, BlockPos blockPos, PlayerEntity player, Hand hand, BlockRayTraceResult p_225533_6_) { 144 | if (world.isClientSide) { 145 | return ActionResultType.SUCCESS; 146 | } else { 147 | TileEntity tileEntity = world.getBlockEntity(blockPos); 148 | if (tileEntity instanceof StateTileEntity) { 149 | StateTileEntity stateTileEntity = (StateTileEntity) tileEntity; 150 | Network.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), 151 | new OpenStateScreen( 152 | stateTileEntity.getHaEntityId(), 153 | stateTileEntity.getHaEntityOperator(), 154 | stateTileEntity.getHaEntityStateToCheck(), 155 | stateTileEntity.getHaAttributeName(), 156 | stateTileEntity.getHaAttributeOperator(), 157 | stateTileEntity.getHaAttributeValueToCheck(), 158 | entityState, 159 | attributeValue, 160 | blockPos) 161 | ); 162 | } else { 163 | throw new IllegalStateException("Our named container provider is missing!"); 164 | } 165 | return ActionResultType.CONSUME; 166 | } 167 | } 168 | 169 | @SuppressWarnings("deprecation") 170 | @Override 171 | public boolean isSignalSource(BlockState blockstate) { 172 | return true; 173 | } 174 | 175 | @SuppressWarnings("deprecation") 176 | @Override 177 | public int getSignal(BlockState blockstate, IBlockReader blockReader, BlockPos pos, Direction direction) { 178 | return blockstate.getValue(POWER); 179 | } 180 | 181 | @Override 182 | protected void createBlockStateDefinition(StateContainer.Builder p_206840_1_) { 183 | p_206840_1_.add(POWER, INVERTED); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/client/gui/ServiceScreen.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.client.gui; 2 | 3 | import com.codestian.homeassistantmc.network.Network; 4 | import com.codestian.homeassistantmc.network.message.UpdateServiceBlockData; 5 | import com.google.gson.Gson; 6 | import com.google.gson.JsonObject; 7 | import com.mojang.blaze3d.matrix.MatrixStack; 8 | import com.mojang.blaze3d.systems.RenderSystem; 9 | import net.minecraft.client.Minecraft; 10 | import net.minecraft.client.gui.DialogTexts; 11 | import net.minecraft.client.gui.screen.Screen; 12 | import net.minecraft.client.gui.widget.TextFieldWidget; 13 | import net.minecraft.client.gui.widget.button.Button; 14 | import net.minecraft.util.math.BlockPos; 15 | import net.minecraft.util.text.ITextComponent; 16 | import net.minecraft.util.text.TranslationTextComponent; 17 | import net.minecraftforge.api.distmarker.Dist; 18 | import net.minecraftforge.api.distmarker.OnlyIn; 19 | import org.yaml.snakeyaml.Yaml; 20 | 21 | import java.util.LinkedHashMap; 22 | 23 | @OnlyIn(Dist.CLIENT) 24 | public class ServiceScreen extends Screen { 25 | 26 | private final String entityConfig; 27 | private final BlockPos blockPos; 28 | private final Yaml yaml = new Yaml(); 29 | private final Gson gson = new Gson(); 30 | protected Button clearButton; 31 | protected Button copyButton; 32 | protected Button pasteButton; 33 | protected Button doneButton; 34 | protected Button cancelButton; 35 | protected TextFieldWidget inputServiceConfig; 36 | 37 | public ServiceScreen(ITextComponent p_i51108_1_, String entityConfig, BlockPos blockPos) { 38 | super(p_i51108_1_); 39 | this.entityConfig = entityConfig; 40 | this.blockPos = blockPos; 41 | } 42 | 43 | @Override 44 | protected void init() { 45 | super.init(); 46 | this.minecraft.keyboardHandler.setSendRepeatsToGui(true); 47 | 48 | this.clearButton = this.addButton(new Button(this.width / 2 - 50 - 100 - 4, 80, 100, 20, new TranslationTextComponent("Clear"), (p_214187_1_) -> { 49 | this.onClear(); 50 | })); 51 | this.copyButton = this.addButton(new Button(this.width / 2 - 50, 80, 100, 20, new TranslationTextComponent("Copy"), (p_214186_1_) -> { 52 | this.onCopy(); 53 | })); 54 | this.pasteButton = this.addButton(new Button(this.width / 2 + 50 + 4, 80, 100, 20, new TranslationTextComponent("Paste"), (p_214186_1_) -> { 55 | this.onPaste(); 56 | })); 57 | 58 | this.doneButton = this.addButton(new Button(this.width / 2 - 4 - 150, this.height / 4 + 120 + 12, 150, 20, DialogTexts.GUI_DONE, (p_214187_1_) -> { 59 | this.onDone(); 60 | })); 61 | this.cancelButton = this.addButton(new Button(this.width / 2 + 4, this.height / 4 + 120 + 12, 150, 20, DialogTexts.GUI_CANCEL, (p_214186_1_) -> { 62 | this.onClose(); 63 | })); 64 | 65 | this.inputServiceConfig = new TextFieldWidget(this.font, this.width / 2 - 150, 50, 300, 20, new TranslationTextComponent("advMode.command")) { 66 | }; 67 | 68 | this.inputServiceConfig.setMaxLength(1024); 69 | this.inputServiceConfig.setEditable(false); 70 | 71 | this.children.add(this.inputServiceConfig); 72 | 73 | this.inputServiceConfig.setValue(entityConfig != null ? entityConfig : ""); 74 | 75 | } 76 | 77 | public void onClear() { 78 | this.inputServiceConfig.setValue(""); 79 | } 80 | 81 | public void onCopy() { 82 | if ( 83 | !this.inputServiceConfig.getValue().equals("YAML key service is invalid") || 84 | !this.inputServiceConfig.getValue().equals("YAML configuration requires service and data keys") || 85 | !this.inputServiceConfig.getValue().equals("Please input valid YAML configuration") 86 | ) { 87 | Minecraft.getInstance().keyboardHandler.setClipboard(this.inputServiceConfig.getValue()); 88 | } 89 | } 90 | 91 | public void onPaste() { 92 | 93 | String text = Minecraft.getInstance().keyboardHandler.getClipboard(); 94 | try { 95 | Object yamlText = yaml.load(text); 96 | 97 | JsonObject jsonObject = gson.fromJson(gson.toJson(yamlText, LinkedHashMap.class), JsonObject.class); 98 | 99 | if (jsonObject.has("service")) { 100 | if (jsonObject.get("service").getAsString().chars().filter(num -> num == '.').count() == 1) { 101 | this.inputServiceConfig.setValue(jsonObject.toString()); 102 | } else { 103 | this.inputServiceConfig.setValue("YAML key service is invalid"); 104 | } 105 | } else { 106 | this.inputServiceConfig.setValue("YAML configuration requires service and data keys"); 107 | } 108 | } catch (Exception e) { 109 | this.inputServiceConfig.setValue("Please input valid YAML configuration"); 110 | } 111 | } 112 | 113 | public void onDone() { 114 | Network.CHANNEL.sendToServer(new UpdateServiceBlockData(this.inputServiceConfig.getValue(), this.blockPos)); 115 | this.minecraft.setScreen(null); 116 | } 117 | 118 | @Override 119 | public void onClose() { 120 | super.onClose(); 121 | } 122 | 123 | @Override 124 | public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { 125 | this.renderBackground(matrixStack); 126 | drawCenteredString(matrixStack, this.font, "Set call service config for Block", this.width / 2, 20, 16777215); 127 | drawString(matrixStack, this.font, "Set yaml config", this.width / 2 - 150, 40, 10526880); 128 | this.inputServiceConfig.render(matrixStack, mouseX, mouseY, partialTicks); 129 | super.render(matrixStack, mouseX, mouseY, partialTicks); 130 | } 131 | 132 | @Override 133 | public void renderBackground(MatrixStack p_230446_1_) { 134 | super.renderBackground(p_230446_1_); 135 | RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); 136 | } 137 | } -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/client/gui/StateScreen.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.client.gui; 2 | 3 | import com.codestian.homeassistantmc.network.Network; 4 | import com.codestian.homeassistantmc.network.message.UpdateStateBlockData; 5 | import com.mojang.blaze3d.matrix.MatrixStack; 6 | import com.mojang.blaze3d.systems.RenderSystem; 7 | import net.minecraft.client.gui.DialogTexts; 8 | import net.minecraft.client.gui.screen.Screen; 9 | import net.minecraft.client.gui.widget.TextFieldWidget; 10 | import net.minecraft.client.gui.widget.button.Button; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.util.text.ITextComponent; 13 | import net.minecraft.util.text.TranslationTextComponent; 14 | import net.minecraftforge.api.distmarker.Dist; 15 | import net.minecraftforge.api.distmarker.OnlyIn; 16 | 17 | @OnlyIn(Dist.CLIENT) 18 | public class StateScreen extends Screen { 19 | 20 | private final String entityId; 21 | private final String entityOperator; 22 | private final String entityStateToCheck; 23 | private final String attributeName; 24 | private final String attributeOperator; 25 | private final String attributeValueToCheck; 26 | private final String currentEntityState; 27 | private final String currentAttributeValue; 28 | private final BlockPos blockPos; 29 | protected Button doneButton; 30 | protected Button cancelButton; 31 | protected Button toggleEntityOperatorButton; 32 | protected Button toggleAttributeOperatorButton; 33 | protected TextFieldWidget inputEntityId; 34 | protected TextFieldWidget inputEntityStateToCheck; 35 | protected TextFieldWidget inputAttributeName; 36 | protected TextFieldWidget inputAttributeValueToCheck; 37 | protected TextFieldWidget outputEntityId; 38 | protected TextFieldWidget outputAttributeName; 39 | 40 | public StateScreen( 41 | ITextComponent p_i51108_1_, 42 | String entityId, 43 | String entityOperator, 44 | String entityStateToCheck, 45 | String attributeName, 46 | String attributeOperator, 47 | String attributeValueToCheck, 48 | String currentEntityState, 49 | String currentAttributeValue, 50 | BlockPos blockPos 51 | ) { 52 | super(p_i51108_1_); 53 | 54 | this.entityId = entityId; 55 | this.entityOperator = entityOperator; 56 | this.entityStateToCheck = entityStateToCheck; 57 | 58 | this.attributeName = attributeName; 59 | this.attributeOperator = attributeOperator; 60 | this.attributeValueToCheck = attributeValueToCheck; 61 | 62 | this.currentEntityState = currentEntityState; 63 | this.currentAttributeValue = currentAttributeValue; 64 | 65 | this.blockPos = blockPos; 66 | 67 | } 68 | 69 | public static boolean isNumeric(String strNum) { 70 | if (strNum == null) { 71 | return false; 72 | } 73 | try { 74 | double d = Double.parseDouble(strNum); 75 | } catch (NumberFormatException nfe) { 76 | return false; 77 | } 78 | return true; 79 | } 80 | 81 | @Override 82 | protected void init() { 83 | this.minecraft.keyboardHandler.setSendRepeatsToGui(true); 84 | 85 | this.doneButton = this.addButton(new Button(this.width / 2 - 4 - 150, this.height / 4 + 120 + 12, 150, 20, DialogTexts.GUI_DONE, (p_214187_1_) -> { 86 | this.onDone(); 87 | })); 88 | this.cancelButton = this.addButton(new Button(this.width / 2 + 4, this.height / 4 + 120 + 12, 150, 20, DialogTexts.GUI_CANCEL, (p_214186_1_) -> { 89 | this.onClose(); 90 | })); 91 | 92 | this.toggleEntityOperatorButton = this.addButton(new Button(this.width / 2 - 10, 50, 20, 20, new TranslationTextComponent("="), (p_214187_1_) -> { 93 | setOperatorIcon(inputEntityStateToCheck, toggleEntityOperatorButton); 94 | })); 95 | this.toggleAttributeOperatorButton = this.addButton(new Button(this.width / 2 - 10, 90, 20, 20, new TranslationTextComponent("="), (p_214186_1_) -> { 96 | setOperatorIcon(inputAttributeValueToCheck, toggleAttributeOperatorButton); 97 | })); 98 | 99 | this.inputEntityId = new TextFieldWidget(this.font, this.width / 2 - 150, 50, 150 - 15, 20, new TranslationTextComponent("PLACEHOLDER")) { 100 | }; 101 | this.inputEntityStateToCheck = new TextFieldWidget(this.font, this.width / 2 + 15, 50, 150 - 15, 20, new TranslationTextComponent("PLACEHOLDER")) { 102 | }; 103 | this.inputAttributeName = new TextFieldWidget(this.font, this.width / 2 - 150, 90, 150 - 15, 20, new TranslationTextComponent("PLACEHOLDER")) { 104 | }; 105 | this.inputAttributeValueToCheck = new TextFieldWidget(this.font, this.width / 2 + 15, 90, 150 - 15, 20, new TranslationTextComponent("PLACEHOLDER")) { 106 | }; 107 | 108 | this.outputEntityId = new TextFieldWidget(this.font, this.width / 2 - 150 + 4, this.height / 4 + 120 - 12 - 10 - 20 + 6, 300, 20, new TranslationTextComponent("PLACEHOLDER")) { 109 | }; 110 | this.outputAttributeName = new TextFieldWidget(this.font, this.width / 2 - 150 + 4, this.height / 4 + 120 - 12 - 10 + 6, 300, 20, new TranslationTextComponent("PLACEHOLDER")) { 111 | }; 112 | 113 | this.children.add(this.inputEntityId); 114 | this.children.add(this.inputEntityStateToCheck); 115 | this.children.add(this.inputAttributeName); 116 | this.children.add(this.inputAttributeValueToCheck); 117 | 118 | this.children.add(this.outputEntityId); 119 | this.children.add(this.outputAttributeName); 120 | 121 | this.inputEntityId.setMaxLength(128); 122 | this.inputEntityStateToCheck.setMaxLength(64); 123 | this.inputAttributeName.setMaxLength(128); 124 | this.inputAttributeValueToCheck.setMaxLength(64); 125 | this.outputEntityId.setMaxLength(512); 126 | this.outputAttributeName.setMaxLength(512); 127 | 128 | this.outputEntityId.setBordered(false); 129 | this.outputAttributeName.setBordered(false); 130 | 131 | this.outputEntityId.setEditable(false); 132 | this.outputAttributeName.setEditable(false); 133 | 134 | this.inputEntityId.setValue(this.entityId); 135 | this.toggleEntityOperatorButton.setMessage(new TranslationTextComponent(this.entityOperator)); 136 | this.inputEntityStateToCheck.setValue(this.entityStateToCheck); 137 | 138 | this.inputAttributeName.setValue(this.attributeName); 139 | this.toggleAttributeOperatorButton.setMessage(new TranslationTextComponent(this.attributeOperator)); 140 | this.inputAttributeValueToCheck.setValue(this.attributeValueToCheck); 141 | 142 | this.outputEntityId.setValue(this.entityId + ": " + this.currentEntityState); 143 | this.outputAttributeName.setValue(this.attributeName.isEmpty() ? "" : this.attributeName + ": " + this.currentAttributeValue); 144 | 145 | if (this.entityId.isEmpty()) { 146 | this.outputEntityId.setVisible(false); 147 | this.outputAttributeName.setVisible(false); 148 | } 149 | 150 | } 151 | 152 | @Override 153 | public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { 154 | this.renderBackground(matrixStack); 155 | 156 | drawCenteredString(matrixStack, this.font, "Set entity to listen for Block", this.width / 2, 20, 16777215); 157 | drawString(matrixStack, this.font, "Entity", this.width / 2 - 150, 40, 10526880); 158 | drawString(matrixStack, this.font, "Value", this.width / 2 + 15, 40, 10526880); 159 | drawString(matrixStack, this.font, "Attribute (optional)", this.width / 2 - 150, 80, 10526880); 160 | drawString(matrixStack, this.font, "Value", this.width / 2 + 15, 80, 10526880); 161 | 162 | // fill(matrixStack, this.width/ 2 - 150, this.height / 4 + 120 - 12 - 10 - 20, this.width/2 + 150, this.height / 4 + 120 - 12 - 10 + 20, -16777216); 163 | if (!this.entityId.isEmpty()) { 164 | fill(matrixStack, this.width / 2 - 150, this.height / 4 + 120 - 12 - 10 - 20, this.width / 2 + 150, this.height / 4 + 120 - 12 - 10 + 20, -16777216); 165 | } 166 | 167 | this.inputEntityId.render(matrixStack, mouseX, mouseY, partialTicks); 168 | this.inputEntityStateToCheck.render(matrixStack, mouseX, mouseY, partialTicks); 169 | this.inputAttributeName.render(matrixStack, mouseX, mouseY, partialTicks); 170 | this.inputAttributeValueToCheck.render(matrixStack, mouseX, mouseY, partialTicks); 171 | 172 | this.outputEntityId.render(matrixStack, mouseX, mouseY, partialTicks); 173 | this.outputAttributeName.render(matrixStack, mouseX, mouseY, partialTicks); 174 | 175 | super.render(matrixStack, mouseX, mouseY, partialTicks); 176 | } 177 | 178 | @Override 179 | public void renderBackground(MatrixStack p_230446_1_) { 180 | super.renderBackground(p_230446_1_); 181 | RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); 182 | } 183 | 184 | @Override 185 | public boolean keyReleased(int p_223281_1_, int p_223281_2_, int p_223281_3_) { 186 | if (!isNumeric(this.inputEntityStateToCheck.getValue())) { 187 | if (!this.inputEntityStateToCheck.getValue().isEmpty()) { 188 | this.toggleEntityOperatorButton.setMessage(new TranslationTextComponent("=")); 189 | } 190 | } else if (!isNumeric(this.inputAttributeValueToCheck.getValue())) { 191 | if (!this.inputAttributeValueToCheck.getValue().isEmpty()) { 192 | this.toggleAttributeOperatorButton.setMessage(new TranslationTextComponent("=")); 193 | } 194 | } 195 | return super.keyReleased(p_223281_1_, p_223281_2_, p_223281_3_); 196 | } 197 | 198 | public void setOperatorIcon(TextFieldWidget toCheck, Button OperatorButton) { 199 | if (isNumeric(toCheck.getValue()) || toCheck.getValue().isEmpty()) { 200 | switch (OperatorButton.getMessage().getString()) { 201 | case "=": 202 | OperatorButton.setMessage(new TranslationTextComponent(">")); 203 | break; 204 | case ">": 205 | OperatorButton.setMessage(new TranslationTextComponent("<")); 206 | break; 207 | case "<": 208 | OperatorButton.setMessage(new TranslationTextComponent("=")); 209 | break; 210 | } 211 | } else { 212 | OperatorButton.setMessage(new TranslationTextComponent("=")); 213 | } 214 | } 215 | 216 | @Override 217 | public void onClose() { 218 | super.onClose(); 219 | } 220 | 221 | public void onDone() { 222 | // if (!this.inputEntityId.getValue().isEmpty() 223 | // && !this.inputEntityStateToCheck.getValue().isEmpty() 224 | // && (!this.inputEntityId.getValue().equals(entityId) 225 | // || !this.inputEntityStateToCheck.getValue().equals(entityStateToCheck) 226 | // || !this.toggleEntityOperatorButton.getMessage().getString().equals(entityOperator) 227 | // || !this.toggleAttributeOperatorButton.getMessage().getString().equals(attributeOperator)) 228 | // ) { 229 | 230 | Network.CHANNEL.sendToServer(new UpdateStateBlockData( 231 | this.inputEntityId.getValue(), 232 | this.toggleEntityOperatorButton.getMessage().getString(), 233 | this.inputEntityStateToCheck.getValue(), 234 | this.inputAttributeName.getValue(), 235 | this.toggleAttributeOperatorButton.getMessage().getString(), 236 | this.inputAttributeValueToCheck.getValue(), 237 | this.blockPos)); 238 | // } 239 | this.minecraft.setScreen(null); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/commands/Command.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.commands; 2 | 3 | import com.codestian.homeassistantmc.worldsaveddata.EntityData; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.mojang.brigadier.CommandDispatcher; 7 | import com.mojang.brigadier.arguments.IntegerArgumentType; 8 | import com.mojang.brigadier.context.CommandContext; 9 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 10 | import net.minecraft.command.CommandSource; 11 | import net.minecraft.command.Commands; 12 | import net.minecraft.entity.Entity; 13 | import net.minecraft.entity.player.ServerPlayerEntity; 14 | import net.minecraft.util.text.StringTextComponent; 15 | import net.minecraft.world.World; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collections; 19 | import java.util.List; 20 | 21 | import static com.codestian.homeassistantmc.event.ServerEvent.webSocket; 22 | 23 | public class Command { 24 | public static void register(CommandDispatcher dispatcher) { 25 | dispatcher.register(Commands.literal("hass") 26 | .then(Commands.literal("list") 27 | .then(Commands.argument("index", IntegerArgumentType.integer()) 28 | .executes(Command::listAllEntities) 29 | ) 30 | ) 31 | .then(Commands.literal("status") 32 | .executes(Command::getWebSocketStatus) 33 | ) 34 | .then(Commands.literal("version") 35 | .executes(Command::getModVersion) 36 | ) 37 | ); 38 | } 39 | 40 | private static int getModVersion(CommandContext commandContext) { 41 | Entity player = commandContext.getSource().getEntity(); 42 | if (player instanceof ServerPlayerEntity) { 43 | player.sendMessage(new StringTextComponent("HomeAssistantMC 1.0.0 by Codestian"), player.getUUID()); 44 | } 45 | return 1; 46 | } 47 | 48 | private static int getWebSocketStatus(CommandContext commandContext) { 49 | Entity player = commandContext.getSource().getEntity(); 50 | if (player instanceof ServerPlayerEntity) { 51 | player.sendMessage(new StringTextComponent("[HomeAssistantMC] " + webSocket.getStatus()), player.getUUID()); 52 | } 53 | return 1; 54 | } 55 | 56 | private static int listAllEntities(CommandContext commandContext) throws CommandSyntaxException { 57 | 58 | int index = IntegerArgumentType.getInteger(commandContext, "index") - 1; 59 | World world = commandContext.getSource().getLevel(); 60 | Entity player = commandContext.getSource().getEntity(); 61 | if (!world.isClientSide() && player instanceof ServerPlayerEntity) { 62 | EntityData entityData = EntityData.get(world); 63 | JsonArray entities = entityData.getEntities(); 64 | List entitiesList = new ArrayList<>(); 65 | for (JsonElement entity : entities) { 66 | entitiesList.add(entity.getAsJsonObject().get("entity_id").getAsString()); 67 | } 68 | Collections.sort(entitiesList); 69 | 70 | List paginatedEntitiesList = entitiesList.subList(10 * index, 10 * index + 10); 71 | paginatedEntitiesList.add(0, ""); 72 | player.sendMessage(new StringTextComponent(String.join("\n", paginatedEntitiesList)), player.getUUID()); 73 | } 74 | 75 | return 1; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/config/Config.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.config; 2 | 3 | import com.electronwill.nightconfig.core.file.CommentedFileConfig; 4 | import com.electronwill.nightconfig.core.io.WritingMode; 5 | import net.minecraftforge.common.ForgeConfigSpec; 6 | import net.minecraftforge.fml.common.Mod; 7 | 8 | import java.io.File; 9 | 10 | import static com.codestian.homeassistantmc.HomeAssistantMC.logger; 11 | 12 | @Mod.EventBusSubscriber 13 | public class Config { 14 | 15 | public static final ForgeConfigSpec common_config; 16 | private static final ForgeConfigSpec.Builder common_builder = new ForgeConfigSpec.Builder(); 17 | 18 | static { 19 | WebSocketConfig.init(common_builder); 20 | common_config = common_builder.build(); 21 | } 22 | 23 | public static void loadConfig(ForgeConfigSpec config, String path) { 24 | logger.info("Loading config:" + path); 25 | final CommentedFileConfig file = CommentedFileConfig.builder(new File(path)).sync().autosave().writingMode(WritingMode.REPLACE).build(); 26 | logger.info("Built config" + path); 27 | file.load(); 28 | logger.info("Loaded config " + path); 29 | config.setConfig(file); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.config; 2 | 3 | import net.minecraftforge.common.ForgeConfigSpec; 4 | 5 | public class WebSocketConfig { 6 | public static ForgeConfigSpec.ConfigValue url; 7 | public static ForgeConfigSpec.ConfigValue token; 8 | 9 | public static void init(ForgeConfigSpec.Builder builder) { 10 | builder.comment("WebSocket Config"); 11 | 12 | token = builder.comment("Long lived access token from Home Assistant").define("ha_token", ""); 13 | url = builder.comment("The URL of the Home Assistant instance").define("ha_url", ""); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/event/ServerEvent.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.event; 2 | 3 | import com.codestian.homeassistantmc.HomeAssistantMC; 4 | import com.codestian.homeassistantmc.commands.Command; 5 | import com.codestian.homeassistantmc.config.WebSocketConfig; 6 | import com.codestian.homeassistantmc.websocket.WebSocket; 7 | import com.mojang.brigadier.CommandDispatcher; 8 | import net.minecraft.command.CommandSource; 9 | import net.minecraft.util.text.StringTextComponent; 10 | import net.minecraftforge.event.RegisterCommandsEvent; 11 | import net.minecraftforge.event.entity.player.PlayerEvent; 12 | import net.minecraftforge.eventbus.api.SubscribeEvent; 13 | import net.minecraftforge.fml.common.Mod.EventBusSubscriber; 14 | import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; 15 | import net.minecraftforge.fml.event.server.FMLServerStartingEvent; 16 | 17 | import java.net.URISyntaxException; 18 | 19 | @EventBusSubscriber(modid = HomeAssistantMC.MOD_ID, bus = Bus.FORGE) 20 | public class ServerEvent { 21 | 22 | public static WebSocket webSocket = null; 23 | 24 | @SubscribeEvent 25 | public static void onRegisterCommandEvent(RegisterCommandsEvent event) { 26 | CommandDispatcher commandDispatcher = event.getDispatcher(); 27 | Command.register(commandDispatcher); 28 | } 29 | 30 | @SubscribeEvent 31 | public static void onServerStart(FMLServerStartingEvent event) throws URISyntaxException { 32 | webSocket = new WebSocket(WebSocketConfig.url.get(), WebSocketConfig.token.get(), event.getServer()); 33 | if (!WebSocketConfig.token.get().isEmpty() && !WebSocketConfig.url.get().isEmpty()) { 34 | webSocket.connect(); 35 | } else { 36 | webSocket.setStatus("Please configure url and token"); 37 | } 38 | } 39 | 40 | @SubscribeEvent 41 | public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { 42 | event.getPlayer().sendMessage(new StringTextComponent("[HomeAssistantMC] " + webSocket.getStatus()), event.getPlayer().getUUID()); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/init/ModBlocks.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.init; 2 | 3 | import com.codestian.homeassistantmc.block.ServiceBlock; 4 | import com.codestian.homeassistantmc.block.StateBlock; 5 | import net.minecraft.block.Block; 6 | import net.minecraftforge.fml.RegistryObject; 7 | import net.minecraftforge.registries.DeferredRegister; 8 | import net.minecraftforge.registries.ForgeRegistries; 9 | 10 | import static com.codestian.homeassistantmc.HomeAssistantMC.MOD_ID; 11 | 12 | public class ModBlocks { 13 | 14 | public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MOD_ID); 15 | 16 | public static final RegistryObject STATE_BLOCK = BLOCKS.register("state_block", StateBlock::new); 17 | public static final RegistryObject SERVCE_BLOCK = BLOCKS.register("service_block", ServiceBlock::new); 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/init/ModItems.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.init; 2 | 3 | import net.minecraft.item.BlockItem; 4 | import net.minecraft.item.Item; 5 | import net.minecraft.item.ItemGroup; 6 | import net.minecraftforge.fml.RegistryObject; 7 | import net.minecraftforge.registries.DeferredRegister; 8 | import net.minecraftforge.registries.ForgeRegistries; 9 | 10 | import static com.codestian.homeassistantmc.HomeAssistantMC.MOD_ID; 11 | 12 | public class ModItems { 13 | 14 | public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID); 15 | 16 | public static final RegistryObject STATE_BLOCK = ITEMS.register("state_block", () -> new BlockItem(ModBlocks.STATE_BLOCK.get(), new Item.Properties().tab(ItemGroup.TAB_REDSTONE))); 17 | public static final RegistryObject SERVICE_BLOCK = ITEMS.register("service_block", () -> new BlockItem(ModBlocks.SERVCE_BLOCK.get(), new Item.Properties().tab(ItemGroup.TAB_REDSTONE))); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/init/ModTileEntities.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.init; 2 | 3 | import com.codestian.homeassistantmc.te.ServiceTileEntity; 4 | import com.codestian.homeassistantmc.te.StateTileEntity; 5 | import net.minecraft.tileentity.TileEntityType; 6 | import net.minecraftforge.fml.RegistryObject; 7 | import net.minecraftforge.registries.DeferredRegister; 8 | import net.minecraftforge.registries.ForgeRegistries; 9 | 10 | import static com.codestian.homeassistantmc.HomeAssistantMC.MOD_ID; 11 | 12 | public class ModTileEntities { 13 | 14 | public static final DeferredRegister> TILE_ENTITY_TYPE = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, MOD_ID); 15 | 16 | public static final RegistryObject> STATE_TILE_ENTITY_TYPE = TILE_ENTITY_TYPE 17 | .register("state", () -> TileEntityType.Builder.of(StateTileEntity::new, ModBlocks.STATE_BLOCK.get()).build(null)); 18 | 19 | public static final RegistryObject> SERVICE_TILE_ENTITY_TYPE = TILE_ENTITY_TYPE 20 | .register("service", () -> TileEntityType.Builder.of(ServiceTileEntity::new, ModBlocks.SERVCE_BLOCK.get()).build(null)); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/Network.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network; 2 | 3 | import com.codestian.homeassistantmc.network.message.OpenServiceScreen; 4 | import com.codestian.homeassistantmc.network.message.OpenStateScreen; 5 | import com.codestian.homeassistantmc.network.message.UpdateServiceBlockData; 6 | import com.codestian.homeassistantmc.network.message.UpdateStateBlockData; 7 | import net.minecraft.util.ResourceLocation; 8 | import net.minecraftforge.fml.network.NetworkRegistry; 9 | import net.minecraftforge.fml.network.simple.SimpleChannel; 10 | 11 | import static com.codestian.homeassistantmc.HomeAssistantMC.MOD_ID; 12 | 13 | public class Network { 14 | 15 | public static final String NETWORK_VERSION = "0.2.0"; 16 | 17 | public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( 18 | new ResourceLocation(MOD_ID, "network"), () -> NETWORK_VERSION, 19 | version -> version.equals(NETWORK_VERSION), version -> version.equals(NETWORK_VERSION)); 20 | 21 | public static void init() { 22 | CHANNEL.registerMessage(0, UpdateStateBlockData.class, UpdateStateBlockData::encode, UpdateStateBlockData::decode, UpdateStateBlockData::handle); 23 | CHANNEL.registerMessage(1, UpdateServiceBlockData.class, UpdateServiceBlockData::encode, UpdateServiceBlockData::decode, UpdateServiceBlockData::handle); 24 | CHANNEL.registerMessage(2, OpenStateScreen.class, OpenStateScreen::encode, OpenStateScreen::decode, OpenStateScreen::handle); 25 | CHANNEL.registerMessage(3, OpenServiceScreen.class, OpenServiceScreen::encode, OpenServiceScreen::decode, OpenServiceScreen::handle); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/OpenServiceHandler.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import com.codestian.homeassistantmc.client.gui.ServiceScreen; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.util.text.ITextComponent; 7 | import net.minecraft.util.text.TranslationTextComponent; 8 | 9 | public class OpenServiceHandler { 10 | public static void handlePacket(String entityConfig, BlockPos blockPos) { 11 | ITextComponent test = new TranslationTextComponent("screen.forgepractice.service_block"); 12 | Minecraft.getInstance().setScreen(new ServiceScreen(test, entityConfig, blockPos)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/OpenServiceScreen.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraftforge.api.distmarker.Dist; 6 | import net.minecraftforge.fml.DistExecutor; 7 | import net.minecraftforge.fml.network.NetworkEvent; 8 | 9 | import java.util.function.Supplier; 10 | 11 | public class OpenServiceScreen { 12 | private final String entityConfig; 13 | private final BlockPos blockPos; 14 | 15 | public OpenServiceScreen(String entityConfig, BlockPos blockPos) { 16 | this.entityConfig = entityConfig; 17 | this.blockPos = blockPos; 18 | } 19 | 20 | public static void encode(OpenServiceScreen message, PacketBuffer buffer) { 21 | buffer.writeUtf(message.entityConfig); 22 | buffer.writeBlockPos(message.blockPos); 23 | } 24 | 25 | public static OpenServiceScreen decode(PacketBuffer buffer) { 26 | return new OpenServiceScreen(buffer.readUtf(32767), buffer.readBlockPos()); 27 | } 28 | 29 | public static void handle(OpenServiceScreen message, Supplier contextSupplier) { 30 | contextSupplier.get().enqueueWork(() -> 31 | DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> OpenServiceHandler.handlePacket(message.entityConfig, message.blockPos)) 32 | ); 33 | contextSupplier.get().setPacketHandled(true); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/OpenStateHandler.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import com.codestian.homeassistantmc.client.gui.StateScreen; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.util.text.ITextComponent; 7 | import net.minecraft.util.text.TranslationTextComponent; 8 | 9 | public class OpenStateHandler { 10 | public static void handlePacket( 11 | String entityId, 12 | String entityOperator, 13 | String entityStateToCheck, 14 | String attributeName, 15 | String attributeOperator, 16 | String attributeValueToCheck, 17 | String currentEntityState, 18 | String currentAttributeValue, 19 | BlockPos blockPos) { 20 | ITextComponent test = new TranslationTextComponent("screen.forgepractice.service_block"); 21 | Minecraft.getInstance().setScreen(new StateScreen( 22 | test, 23 | entityId, 24 | entityOperator, 25 | entityStateToCheck, 26 | attributeName, 27 | attributeOperator, 28 | attributeValueToCheck, 29 | currentEntityState, 30 | currentAttributeValue, 31 | blockPos)); 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/OpenStateScreen.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraftforge.api.distmarker.Dist; 6 | import net.minecraftforge.fml.DistExecutor; 7 | import net.minecraftforge.fml.network.NetworkEvent; 8 | 9 | import java.util.function.Supplier; 10 | 11 | public class OpenStateScreen { 12 | private final String entityId; 13 | private final String entityOperator; 14 | private final String entityStateToCheck; 15 | 16 | private final String attributeName; 17 | private final String attributeOperator; 18 | private final String attributeValueToCheck; 19 | 20 | private final String currentEntityState; 21 | private final String currentAttributeValue; 22 | 23 | private final BlockPos blockPos; 24 | 25 | public OpenStateScreen( 26 | String entityId, 27 | String entityOperator, 28 | String entityStateToCheck, 29 | String attributeName, 30 | String attributeOperator, 31 | String attributeValueToCheck, 32 | String currentEntityState, 33 | String currentAttributeValue, 34 | BlockPos blockPos 35 | ) { 36 | this.entityId = entityId; 37 | this.entityOperator = entityOperator; 38 | this.entityStateToCheck = entityStateToCheck; 39 | 40 | this.attributeName = attributeName; 41 | this.attributeOperator = attributeOperator; 42 | this.attributeValueToCheck = attributeValueToCheck; 43 | 44 | this.currentEntityState = currentEntityState; 45 | this.currentAttributeValue = currentAttributeValue; 46 | 47 | this.blockPos = blockPos; 48 | } 49 | 50 | public static void encode(OpenStateScreen message, PacketBuffer buffer) { 51 | buffer.writeUtf(message.entityId); 52 | buffer.writeUtf(message.entityOperator); 53 | buffer.writeUtf(message.entityStateToCheck); 54 | 55 | buffer.writeUtf(message.attributeName); 56 | buffer.writeUtf(message.attributeOperator); 57 | buffer.writeUtf(message.attributeValueToCheck); 58 | 59 | buffer.writeUtf(message.currentEntityState); 60 | buffer.writeUtf(message.currentAttributeValue); 61 | 62 | buffer.writeBlockPos(message.blockPos); 63 | } 64 | 65 | public static OpenStateScreen decode(PacketBuffer buffer) { 66 | return new OpenStateScreen( 67 | buffer.readUtf(512), 68 | buffer.readUtf(1), 69 | buffer.readUtf(512), 70 | buffer.readUtf(512), 71 | buffer.readUtf(1), 72 | buffer.readUtf(512), 73 | buffer.readUtf(512), 74 | buffer.readUtf(512), 75 | buffer.readBlockPos()); 76 | } 77 | 78 | public static void handle(OpenStateScreen message, Supplier contextSupplier) { 79 | contextSupplier.get().enqueueWork(() -> 80 | DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> OpenStateHandler.handlePacket(message.entityId, 81 | message.entityOperator, 82 | message.entityStateToCheck, 83 | message.attributeName, 84 | message.attributeOperator, 85 | message.attributeValueToCheck, 86 | message.currentEntityState, 87 | message.currentAttributeValue, message.blockPos)) 88 | ); 89 | contextSupplier.get().setPacketHandled(true); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/UpdateServiceBlockData.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import com.codestian.homeassistantmc.te.ServiceTileEntity; 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonObject; 6 | import com.google.gson.JsonSyntaxException; 7 | import net.minecraft.entity.player.ServerPlayerEntity; 8 | import net.minecraft.network.PacketBuffer; 9 | import net.minecraft.tileentity.TileEntity; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.util.text.StringTextComponent; 12 | import net.minecraft.world.server.ServerWorld; 13 | import net.minecraftforge.fml.network.NetworkEvent; 14 | 15 | import java.util.function.Supplier; 16 | 17 | public class UpdateServiceBlockData { 18 | private final String entityConfig; 19 | private final BlockPos blockPos; 20 | 21 | public UpdateServiceBlockData(String entityConfig, BlockPos blockPos) { 22 | this.entityConfig = entityConfig; 23 | this.blockPos = blockPos; 24 | } 25 | 26 | public static void encode(UpdateServiceBlockData message, PacketBuffer buffer) { 27 | buffer.writeUtf(message.entityConfig); 28 | buffer.writeBlockPos(message.blockPos); 29 | } 30 | 31 | public static UpdateServiceBlockData decode(PacketBuffer buffer) { 32 | return new UpdateServiceBlockData(buffer.readUtf(32767), buffer.readBlockPos()); 33 | } 34 | 35 | public static void handle(UpdateServiceBlockData message, Supplier contextSupplier) { 36 | NetworkEvent.Context context = contextSupplier.get(); 37 | context.enqueueWork(() -> { 38 | ServerPlayerEntity player = context.getSender(); 39 | ServerWorld world = player.getLevel(); 40 | TileEntity tileEntity = world.getBlockEntity(message.blockPos); 41 | if (tileEntity instanceof ServiceTileEntity) { 42 | ServiceTileEntity serviceTileEntity = (ServiceTileEntity) tileEntity; 43 | Gson gson = new Gson(); 44 | try { 45 | gson.fromJson(message.entityConfig, JsonObject.class); 46 | serviceTileEntity.setHaServiceConfig(message.entityConfig); 47 | player.sendMessage(new StringTextComponent("Service configuration set"), player.getUUID()); 48 | } catch (JsonSyntaxException e) { 49 | player.sendMessage(new StringTextComponent("Service configuration is not set"), player.getUUID()); 50 | } 51 | } 52 | }); 53 | context.setPacketHandled(true); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/network/message/UpdateStateBlockData.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.network.message; 2 | 3 | import com.codestian.homeassistantmc.te.StateTileEntity; 4 | import com.codestian.homeassistantmc.worldsaveddata.EntityData; 5 | import com.google.gson.JsonElement; 6 | import net.minecraft.entity.player.ServerPlayerEntity; 7 | import net.minecraft.network.PacketBuffer; 8 | import net.minecraft.tileentity.TileEntity; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.util.text.StringTextComponent; 11 | import net.minecraft.world.server.ServerWorld; 12 | import net.minecraftforge.fml.network.NetworkEvent; 13 | 14 | import java.util.function.Supplier; 15 | 16 | public class UpdateStateBlockData { 17 | 18 | private final String entityId; 19 | private final String entityOperator; 20 | private final String entityStateToCheck; 21 | 22 | private final String attributeName; 23 | private final String attributeOperator; 24 | private final String attributeValueToCheck; 25 | 26 | private final BlockPos blockPos; 27 | 28 | public UpdateStateBlockData( 29 | String entityId, 30 | String entityOperator, 31 | String entityStateToCheck, 32 | String attributeName, 33 | String attributeOperator, 34 | String attributeValueToCheck, 35 | BlockPos blockPos 36 | ) { 37 | this.entityId = entityId; 38 | this.entityOperator = entityOperator; 39 | this.entityStateToCheck = entityStateToCheck; 40 | this.attributeName = attributeName; 41 | this.attributeOperator = attributeOperator; 42 | this.attributeValueToCheck = attributeValueToCheck; 43 | this.blockPos = blockPos; 44 | } 45 | 46 | public static void encode(UpdateStateBlockData message, PacketBuffer buffer) { 47 | buffer.writeUtf(message.entityId); 48 | buffer.writeUtf(message.entityOperator); 49 | buffer.writeUtf(message.entityStateToCheck); 50 | buffer.writeUtf(message.attributeName); 51 | buffer.writeUtf(message.attributeOperator); 52 | buffer.writeUtf(message.attributeValueToCheck); 53 | buffer.writeBlockPos(message.blockPos); 54 | } 55 | 56 | public static UpdateStateBlockData decode(PacketBuffer buffer) { 57 | return new UpdateStateBlockData( 58 | buffer.readUtf(1024), 59 | buffer.readUtf(1024), 60 | buffer.readUtf(1024), 61 | buffer.readUtf(1024), 62 | buffer.readUtf(1024), 63 | buffer.readUtf(1024), 64 | buffer.readBlockPos() 65 | ); 66 | } 67 | 68 | public static void handle(UpdateStateBlockData message, Supplier contextSupplier) { 69 | NetworkEvent.Context context = contextSupplier.get(); 70 | context.enqueueWork(() -> { 71 | 72 | ServerPlayerEntity player = context.getSender(); 73 | ServerWorld world = player.getLevel(); 74 | 75 | TileEntity tileEntity = world.getBlockEntity(message.blockPos); 76 | if (tileEntity instanceof StateTileEntity) { 77 | StateTileEntity stateTileEntity = (StateTileEntity) tileEntity; 78 | EntityData entityData = EntityData.get(world); 79 | 80 | boolean isEntityExist = false; 81 | 82 | for (JsonElement entity : entityData.getEntities()) { 83 | if (entity.getAsJsonObject().get("entity_id").getAsString().equals(message.entityId)) { 84 | isEntityExist = true; 85 | break; 86 | } 87 | } 88 | 89 | if (isEntityExist) { 90 | stateTileEntity.setHaEntityId(message.entityId); 91 | stateTileEntity.setHaEntityOperator(message.entityOperator); 92 | stateTileEntity.setHaEntityStateToCheck(message.entityStateToCheck); 93 | stateTileEntity.setHaAttributeName(message.attributeName); 94 | stateTileEntity.setHaAttributeOperator(message.attributeOperator); 95 | stateTileEntity.setHaAttributeValueToCheck(message.attributeValueToCheck); 96 | player.sendMessage(new StringTextComponent("Entity set: " + message.entityId), 97 | player.getUUID()); 98 | } else { 99 | if (message.entityId.isEmpty()) { 100 | player.sendMessage(new StringTextComponent("Please input an entity first"), 101 | player.getUUID()); 102 | } else { 103 | player.sendMessage(new StringTextComponent("Entity " + message.entityId + " does not exist"), 104 | player.getUUID()); 105 | } 106 | } 107 | } 108 | }); 109 | context.setPacketHandled(true); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/te/ServiceTileEntity.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.te; 2 | 3 | import com.codestian.homeassistantmc.init.ModTileEntities; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.block.BlockState; 6 | import net.minecraft.nbt.CompoundNBT; 7 | import net.minecraft.nbt.StringNBT; 8 | import net.minecraft.tileentity.ITickableTileEntity; 9 | import net.minecraft.tileentity.TileEntity; 10 | import net.minecraft.tileentity.TileEntityType; 11 | 12 | public class ServiceTileEntity extends TileEntity implements ITickableTileEntity { 13 | private String haServiceConfig = ""; 14 | 15 | public ServiceTileEntity(TileEntityType tileEntityTypeIn) { 16 | super(tileEntityTypeIn); 17 | } 18 | 19 | public ServiceTileEntity() { 20 | this(ModTileEntities.SERVICE_TILE_ENTITY_TYPE.get()); 21 | } 22 | 23 | public String getHaServiceConfig() { 24 | return haServiceConfig; 25 | } 26 | 27 | public void setHaServiceConfig(String haServiceConfig) { 28 | this.haServiceConfig = haServiceConfig; 29 | } 30 | 31 | @Override 32 | public void load(BlockState blockState, CompoundNBT parentNBTTagCompound) { 33 | super.load(blockState, parentNBTTagCompound); 34 | 35 | String readTestString1 = null; 36 | final int NBT_STRING_ID = StringNBT.valueOf("").getId(); 37 | 38 | if (parentNBTTagCompound.contains("ha_service_config", NBT_STRING_ID)) { 39 | haServiceConfig = parentNBTTagCompound.getString("ha_service_config"); 40 | } 41 | 42 | } 43 | 44 | @Override 45 | public CompoundNBT save(CompoundNBT parentNBTTagCompound) { 46 | super.save(parentNBTTagCompound); 47 | if (haServiceConfig != null) { 48 | parentNBTTagCompound.putString("ha_service_config", haServiceConfig); 49 | } 50 | return parentNBTTagCompound; 51 | } 52 | 53 | @Override 54 | public void tick() { 55 | if (this.level != null && !this.level.isClientSide) { 56 | BlockState blockstate = this.getBlockState(); 57 | Block block = blockstate.getBlock(); 58 | // if (block instanceof StateBlock) { 59 | // } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/te/StateTileEntity.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.te; 2 | 3 | import com.codestian.homeassistantmc.block.StateBlock; 4 | import com.codestian.homeassistantmc.init.ModTileEntities; 5 | import net.minecraft.block.Block; 6 | import net.minecraft.block.BlockState; 7 | import net.minecraft.nbt.CompoundNBT; 8 | import net.minecraft.nbt.StringNBT; 9 | import net.minecraft.tileentity.ITickableTileEntity; 10 | import net.minecraft.tileentity.TileEntity; 11 | import net.minecraft.tileentity.TileEntityType; 12 | 13 | public class StateTileEntity extends TileEntity implements ITickableTileEntity { 14 | private String haEntityId = ""; 15 | private String haEntityOperator = "="; 16 | private String haEntityStateToCheck = "on"; 17 | private String haAttributeName = ""; 18 | private String haAttributeOperator = "="; 19 | private String haAttributeValueToCheck = ""; 20 | 21 | public StateTileEntity(TileEntityType tileEntityTypeIn) { 22 | super(tileEntityTypeIn); 23 | } 24 | 25 | public StateTileEntity() { 26 | this(ModTileEntities.STATE_TILE_ENTITY_TYPE.get()); 27 | } 28 | 29 | public String getHaEntityId() { 30 | return haEntityId; 31 | } 32 | 33 | public void setHaEntityId(String haEntityId) { 34 | this.haEntityId = haEntityId; 35 | } 36 | 37 | public String getHaEntityStateToCheck() { 38 | return haEntityStateToCheck; 39 | } 40 | 41 | public void setHaEntityStateToCheck(String haEntityStateToCheck) { 42 | this.haEntityStateToCheck = haEntityStateToCheck; 43 | } 44 | 45 | public String getHaEntityOperator() { 46 | return haEntityOperator; 47 | } 48 | 49 | public void setHaEntityOperator(String haEntityOperator) { 50 | this.haEntityOperator = haEntityOperator; 51 | } 52 | 53 | public String getHaAttributeName() { 54 | return haAttributeName; 55 | } 56 | 57 | public void setHaAttributeName(String attributeName) { 58 | this.haAttributeName = attributeName; 59 | } 60 | 61 | public String getHaAttributeOperator() { 62 | return haAttributeOperator; 63 | } 64 | 65 | public void setHaAttributeOperator(String attributeOperator) { 66 | this.haAttributeOperator = attributeOperator; 67 | } 68 | 69 | public String getHaAttributeValueToCheck() { 70 | return haAttributeValueToCheck; 71 | } 72 | 73 | public void setHaAttributeValueToCheck(String attributeValueToCheck) { 74 | this.haAttributeValueToCheck = attributeValueToCheck; 75 | } 76 | 77 | @Override 78 | public void load(BlockState blockState, CompoundNBT parentNBTTagCompound) { 79 | super.load(blockState, parentNBTTagCompound); 80 | 81 | final int NBT_STRING_ID = StringNBT.valueOf("").getId(); 82 | 83 | if (parentNBTTagCompound.contains("ha_entity_id", NBT_STRING_ID)) { 84 | haEntityId = parentNBTTagCompound.getString("ha_entity_id"); 85 | } 86 | if (parentNBTTagCompound.contains("ha_entity_operator", NBT_STRING_ID)) { 87 | haEntityOperator = parentNBTTagCompound.getString("ha_entity_operator"); 88 | } 89 | if (parentNBTTagCompound.contains("ha_entity_state_to_check", NBT_STRING_ID)) { 90 | haEntityStateToCheck = parentNBTTagCompound.getString("ha_entity_state_to_check"); 91 | } 92 | 93 | if (parentNBTTagCompound.contains("ha_attribute_name", NBT_STRING_ID)) { 94 | haAttributeName = parentNBTTagCompound.getString("ha_attribute_name"); 95 | } 96 | if (parentNBTTagCompound.contains("ha_attribute_operator", NBT_STRING_ID)) { 97 | haAttributeOperator = parentNBTTagCompound.getString("ha_attribute_operator"); 98 | } 99 | if (parentNBTTagCompound.contains("ha_attribute_to_check", NBT_STRING_ID)) { 100 | haAttributeValueToCheck = parentNBTTagCompound.getString("ha_attribute_to_check"); 101 | } 102 | // if (!"ha_entity_id".equals(haEntityId)) { 103 | // System.err.println("ha_entity_id mismatch:" + haEntityId); 104 | // } 105 | } 106 | 107 | @Override 108 | public CompoundNBT save(CompoundNBT parentNBTTagCompound) { 109 | super.save(parentNBTTagCompound); 110 | 111 | if (haEntityId != null) { 112 | parentNBTTagCompound.putString("ha_entity_id", haEntityId); 113 | } 114 | if (haEntityOperator != null) { 115 | parentNBTTagCompound.putString("ha_entity_operator", haEntityOperator); 116 | } 117 | if (haEntityStateToCheck != null) { 118 | parentNBTTagCompound.putString("ha_entity_state_to_check", haEntityStateToCheck); 119 | } 120 | 121 | if (haAttributeName != null) { 122 | parentNBTTagCompound.putString("ha_attribute_name", haAttributeName); 123 | } 124 | if (haAttributeOperator != null) { 125 | parentNBTTagCompound.putString("ha_attribute_operator", haAttributeOperator); 126 | } 127 | if (haAttributeValueToCheck != null) { 128 | parentNBTTagCompound.putString("ha_attribute_to_check", haAttributeValueToCheck); 129 | } 130 | return parentNBTTagCompound; 131 | } 132 | 133 | @Override 134 | public void tick() { 135 | if (this.level != null && !this.level.isClientSide) { 136 | BlockState blockstate = this.getBlockState(); 137 | Block block = blockstate.getBlock(); 138 | if (block instanceof StateBlock) { 139 | StateBlock.updateSignalStrength(blockstate, this.level, this.worldPosition); 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/websocket/WebSocket.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.websocket; 2 | 3 | import com.codestian.homeassistantmc.worldsaveddata.EntityData; 4 | import com.google.gson.Gson; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.JsonPrimitive; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.util.Util; 10 | import net.minecraft.util.text.TranslationTextComponent; 11 | import org.java_websocket.client.WebSocketClient; 12 | import org.java_websocket.handshake.ServerHandshake; 13 | 14 | import java.net.URI; 15 | import java.net.URISyntaxException; 16 | import java.util.logging.Logger; 17 | 18 | public class WebSocket extends WebSocketClient { 19 | 20 | private final Logger logger = Logger.getLogger("HomeAssistant"); 21 | private final Gson gson = new Gson(); 22 | private final String accessToken; 23 | private final MinecraftServer server; 24 | private final EntityData entityData; 25 | private int id = 0; 26 | private String status = ""; 27 | 28 | public WebSocket(String url, String accessToken, MinecraftServer server) throws URISyntaxException { 29 | super(new URI(url + "/api/websocket")); 30 | this.accessToken = accessToken; 31 | this.server = server; 32 | this.entityData = EntityData.get(server.overworld()); 33 | } 34 | 35 | @Override 36 | public void onOpen(ServerHandshake handshakedata) { 37 | logger.info("Opening socket to Home Assistant..."); 38 | } 39 | 40 | @Override 41 | public void onMessage(String message) { 42 | final JsonObject response = gson.fromJson(message, JsonObject.class); 43 | switch (response.get("type").getAsString()) { 44 | case "auth_required": 45 | sendAuth(); 46 | status = "Attempting connection"; 47 | server.sendMessage(new TranslationTextComponent("[HomeAssistantMC] Attemping to connect to Home Assistant..."), Util.NIL_UUID); 48 | break; 49 | case "auth_invalid": 50 | logger.warning("Unable to authenticate with Home Assistant: " + response.get("message").getAsString()); 51 | status = "Failed to connect: " + response.get("message").getAsString(); 52 | server.sendMessage(new TranslationTextComponent("[HomeAssistantMC] Unable to connect: " + response.get("message").getAsString()), Util.NIL_UUID); 53 | break; 54 | case "auth_ok": 55 | logger.info("Successfully connected to Home Assistant"); 56 | logger.info("Retrieving entities..."); 57 | status = "Successfully connected"; 58 | server.sendMessage(new TranslationTextComponent("[HomeAssistantMC] Successfully connected!"), Util.NIL_UUID); 59 | getEntities(); 60 | break; 61 | case "result": 62 | if (id == 1) { 63 | if (!response.get("success").getAsBoolean()) { 64 | logger.warning("An error occurred with retrieving entities from Home Assistant"); 65 | } 66 | logger.info("Successfully retrieved all entities"); 67 | storeEntities(response.getAsJsonArray("result")); 68 | logger.info("Storing the entities..."); 69 | setListenEvent(); 70 | } else if (id == 2) { 71 | logger.info("Listening to state changes..."); 72 | setListenEvent(); 73 | } else if (id == 3) { 74 | logger.info("Successfully subscribed to state changes events. Listening..."); 75 | server.sendMessage(new TranslationTextComponent("[HomeAssistantMC] Listening to state changes..."), Util.NIL_UUID); 76 | } 77 | break; 78 | case "event": 79 | if (response.get("event").getAsJsonObject().get("event_type").getAsString().equals("state_changed")) { 80 | JsonObject entity_new_state = response.get("event").getAsJsonObject().get("data").getAsJsonObject().get("new_state").getAsJsonObject(); 81 | updateEntity(entity_new_state); 82 | } 83 | break; 84 | } 85 | } 86 | 87 | @Override 88 | public void onClose(int code, String reason, boolean remote) { 89 | status = "Connection closed by " + (remote ? "remote peer" : "us") + " Code: " + code + " Reason: " + reason; 90 | logger.warning("Connection closed by " + (remote ? "remote peer" : "us") + " Code: " + code + " Reason: " + reason); 91 | } 92 | 93 | @Override 94 | public void onError(Exception ex) { 95 | status = "Error: " + ex.getMessage(); 96 | logger.warning(ex.getMessage()); 97 | } 98 | 99 | public void sendAuth() { 100 | JsonObject obj = new JsonObject(); 101 | obj.add("type", new JsonPrimitive("auth")); 102 | obj.add("access_token", new JsonPrimitive(accessToken)); 103 | send(gson.toJson(obj)); 104 | } 105 | 106 | public void getEntities() { 107 | JsonObject obj = new JsonObject(); 108 | obj.add("id", new JsonPrimitive(++id)); 109 | obj.add("type", new JsonPrimitive("get_states")); 110 | send(gson.toJson(obj)); 111 | } 112 | 113 | public void storeEntities(JsonArray result) { 114 | entityData.putEntities(result); 115 | } 116 | 117 | public void updateEntity(JsonObject result) { 118 | entityData.putOneEntity(result); 119 | } 120 | 121 | public void callService(String domain, String service, JsonObject data, JsonObject target) { 122 | JsonObject obj = new JsonObject(); 123 | obj.add("id", new JsonPrimitive(++id)); 124 | obj.add("type", new JsonPrimitive("call_service")); 125 | obj.add("domain", new JsonPrimitive(domain)); 126 | obj.add("service", new JsonPrimitive(service)); 127 | obj.add("service_data", data); 128 | obj.add("target", target); 129 | send(gson.toJson(obj)); 130 | } 131 | 132 | public void setListenEvent() { 133 | JsonObject obj = new JsonObject(); 134 | obj.add("id", new JsonPrimitive(++id)); 135 | obj.add("type", new JsonPrimitive("subscribe_events")); 136 | obj.add("event_type", new JsonPrimitive("state_changed")); 137 | send(gson.toJson(obj)); 138 | } 139 | 140 | public String getStatus() { 141 | return status; 142 | } 143 | 144 | public void setStatus(String status) { 145 | this.status = status; 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/codestian/homeassistantmc/worldsaveddata/EntityData.java: -------------------------------------------------------------------------------- 1 | package com.codestian.homeassistantmc.worldsaveddata; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonObject; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import net.minecraft.nbt.CompoundNBT; 9 | import net.minecraft.nbt.JsonToNBT; 10 | import net.minecraft.world.World; 11 | import net.minecraft.world.server.ServerWorld; 12 | import net.minecraft.world.storage.DimensionSavedDataManager; 13 | import net.minecraft.world.storage.WorldSavedData; 14 | 15 | import java.util.Map; 16 | import java.util.logging.Logger; 17 | 18 | public class EntityData extends WorldSavedData { 19 | 20 | private static final String NAME = "HassEntityData"; 21 | private final Logger logger = Logger.getLogger("HomeAssistant"); 22 | private final Gson gson = new Gson(); 23 | private JsonArray entities = new JsonArray(); 24 | 25 | public EntityData() { 26 | super(NAME); 27 | } 28 | 29 | public EntityData(String name) { 30 | super(name); 31 | } 32 | 33 | public static EntityData get(World worldIn) { 34 | if (!(worldIn instanceof ServerWorld)) { 35 | throw new RuntimeException("Attempted to get data from client world. A server world is required for this argument."); 36 | } 37 | ServerWorld world = worldIn.getServer().getLevel(World.OVERWORLD); 38 | DimensionSavedDataManager storage = world.getDataStorage(); 39 | return storage.computeIfAbsent(EntityData::new, NAME); 40 | } 41 | 42 | public JsonArray getEntities() { 43 | return entities; 44 | } 45 | 46 | public JsonObject getOneEntity(String entity_id) { 47 | for (JsonElement entity : entities) { 48 | try { 49 | if (entity.getAsJsonObject().get("entity_id").getAsString().equals(entity_id)) { 50 | return entity.getAsJsonObject(); 51 | } 52 | } catch (IllegalStateException ignored) { 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | public void putEntities(JsonArray result) { 59 | entities = result; 60 | setDirty(); 61 | } 62 | 63 | public void putOneEntity(JsonObject result) { 64 | int i = 0; 65 | for (JsonElement entity : entities) { 66 | if (entity.getAsJsonObject().get("entity_id").getAsString().equals(result.get("entity_id").getAsString())) { 67 | Map firstObject = gson.fromJson(gson.toJson(entity), Map.class); 68 | Map secondObject = gson.fromJson(gson.toJson(result), Map.class); 69 | firstObject.putAll(secondObject); 70 | entities.set(i, gson.fromJson(gson.toJson(firstObject), JsonObject.class)); 71 | setDirty(); 72 | break; 73 | } 74 | i++; 75 | } 76 | } 77 | 78 | @Override 79 | public void load(CompoundNBT nbt) { 80 | // for (String key : nbt.getAllKeys()) { 81 | // if (key.equals("entities")) { 82 | // CompoundNBT compoundNBT = (CompoundNBT) nbt.get(key); 83 | // if (compoundNBT != null) { 84 | // JsonArray jsonArray = new JsonArray(); 85 | // for (String entity : compoundNBT.getAllKeys()) { 86 | // jsonArray.add(compoundNBT.get(entity).toString()); 87 | // } 88 | // entities = jsonArray; 89 | // } 90 | // } 91 | // } 92 | } 93 | 94 | @Override 95 | public CompoundNBT save(CompoundNBT compound) { 96 | logger.info("SAVING DATA"); 97 | if (entities.size() > 0) { 98 | CompoundNBT compoundNBT = new CompoundNBT(); 99 | 100 | for (JsonElement entity : entities) { 101 | JsonObject entityObject = entity.getAsJsonObject(); 102 | try { 103 | compoundNBT.put(entityObject.get("entity_id").getAsString(), JsonToNBT.parseTag(entityObject.toString())); 104 | } catch (CommandSyntaxException e) { 105 | e.printStackTrace(); 106 | } 107 | } 108 | compound.put("entities", compoundNBT); 109 | } 110 | return compound; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader = "javafml" 2 | loaderVersion = "[36,)" 3 | license = "MIT" 4 | [[mods]] 5 | modId = "homeassistantmc" 6 | version = "${file.jarVersion}" 7 | displayName = "HomeAssistantMC" 8 | displayURL = "https://github.com/Codestian/homeassistantmc" 9 | logoFile = "logo.png" 10 | credits = "Credits to the developers of Home Assistant" 11 | authors = "Codestian" 12 | description = ''' 13 | Control Home Assistant from Minecraft. 14 | Build scripts and automations ingame with redstone contraptions. 15 | ''' 16 | [[dependencies.homeassistantmc]] 17 | modId = "forge" 18 | mandatory = true 19 | versionRange = "[36,)" 20 | ordering = "NONE" 21 | side = "BOTH" 22 | [[dependencies.homeassistantmc]] 23 | modId = "minecraft" 24 | mandatory = true 25 | versionRange = "[1.16.5,1.17)" 26 | ordering = "NONE" 27 | side = "BOTH" 28 | -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/blockstates/service_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "": [ 4 | { 5 | "model": "homeassistantmc:block/service_block" 6 | } 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/blockstates/state_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "inverted=false": { 4 | "model": "homeassistantmc:block/state_block_off" 5 | }, 6 | "inverted=true": { 7 | "model": "homeassistantmc:block/state_block_on" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "block.homeassistantmc.state_block": "State Block", 3 | "block.homeassistantmc.service_block": "Service Block" 4 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/models/block/service_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "particle": "homeassistantmc:blocks/service_block_top", 5 | "north": "homeassistantmc:blocks/service_block_side", 6 | "south": "homeassistantmc:blocks/service_block_side", 7 | "east": "homeassistantmc:blocks/service_block_side", 8 | "west": "homeassistantmc:blocks/service_block_side", 9 | "up": "homeassistantmc:blocks/service_block_top", 10 | "down": "homeassistantmc:blocks/service_block_top" 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/models/block/state_block_off.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "particle": "homeassistantmc:blocks/state_block_top", 5 | "north": "homeassistantmc:blocks/state_block_side_off", 6 | "south": "homeassistantmc:blocks/state_block_side_off", 7 | "east": "homeassistantmc:blocks/state_block_side_off", 8 | "west": "homeassistantmc:blocks/state_block_side_off", 9 | "up": "homeassistantmc:blocks/state_block_top", 10 | "down": "homeassistantmc:blocks/state_block_top" 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/models/block/state_block_on.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "particle": "homeassistantmc:blocks/state_block_top", 5 | "north": "homeassistantmc:blocks/state_block_side_on", 6 | "south": "homeassistantmc:blocks/state_block_side_on", 7 | "east": "homeassistantmc:blocks/state_block_side_on", 8 | "west": "homeassistantmc:blocks/state_block_side_on", 9 | "up": "homeassistantmc:blocks/state_block_top", 10 | "down": "homeassistantmc:blocks/state_block_top" 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/models/item/service_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "homeassistantmc:block/service_block" 3 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/models/item/state_block.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "homeassistantmc:block/state_block_off" 3 | } -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/textures/blocks/service_block_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/assets/homeassistantmc/textures/blocks/service_block_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/textures/blocks/service_block_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/assets/homeassistantmc/textures/blocks/service_block_top.png -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/textures/blocks/state_block_side_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/assets/homeassistantmc/textures/blocks/state_block_side_off.png -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/textures/blocks/state_block_side_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/assets/homeassistantmc/textures/blocks/state_block_side_on.png -------------------------------------------------------------------------------- /src/main/resources/assets/homeassistantmc/textures/blocks/state_block_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/assets/homeassistantmc/textures/blocks/state_block_top.png -------------------------------------------------------------------------------- /src/main/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Codestian/HomeAssistantMC/04ab5ff6e19f47f7abc1adb6a89f8c1a4bc896d8/src/main/resources/logo.png -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "homeassistantmc resources", 4 | "pack_format": 6, 5 | "_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." 6 | } 7 | } 8 | --------------------------------------------------------------------------------