Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bfcd5cd98 | ||
|
|
7bee6aa9c4 | ||
|
|
21da7aae0e | ||
|
|
eacf6f7dd7 | ||
|
|
cd90218a37 | ||
|
|
93b3283d8b | ||
|
|
51cc5d1cd1 | ||
|
|
614b2d4e3e | ||
|
|
aebd3ebf8c | ||
|
|
ccb66ee3b1 | ||
|
|
d37209b9e1 | ||
|
|
972ccacc69 | ||
|
|
e58530f587 | ||
|
|
c75c509fda | ||
|
|
b2c051b597 | ||
|
|
5b34a69e2b | ||
|
|
582ed32314 | ||
|
|
f1324c86be | ||
|
|
77d2debe5d | ||
|
|
cca754773a | ||
|
|
ebc1762cb6 | ||
|
|
6820516d89 | ||
|
|
3529de5863 | ||
|
|
58973e61f7 | ||
|
|
35ca8210c0 | ||
|
|
b13c6544b6 | ||
|
|
9be7a99f25 | ||
|
|
cffa422164 | ||
|
|
79ea033e26 | ||
|
|
da006885b4 | ||
|
|
fd90fdeec4 | ||
|
|
0e8d8ac7f0 |
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
# Ignore spotlessApply reformat
|
||||||
|
79ea033e261260e200647154a04f97c5e638b07a
|
||||||
@@ -3,9 +3,9 @@ name: Build and test
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master, main ]
|
branches: [ master, main, release/** ]
|
||||||
push:
|
push:
|
||||||
branches: [ master, main ]
|
branches: [ master, main, release/** ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build-and-test:
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name: Optimize images
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ master, main, release/** ]
|
||||||
|
paths:
|
||||||
|
- "**/*.png"
|
||||||
|
|
||||||
|
push:
|
||||||
|
branches: [ master, main, release/** ]
|
||||||
|
paths:
|
||||||
|
- "**/*.png"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
optimize-images:
|
||||||
|
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/optimize-images.yml@master
|
||||||
|
secrets: inherit
|
||||||
@@ -30,3 +30,4 @@ src/main/resources/mixins.*.json
|
|||||||
*.bat
|
*.bat
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
!gradlew.bat
|
!gradlew.bat
|
||||||
|
layout.json
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'FMLCorePlugin': 'mrtjp.relocation.asm.RelocationPlugin'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.github.GTNewHorizons:MrTJPCore:1.1.1:dev'
|
api('com.github.GTNewHorizons:CodeChickenCore:1.4.17:dev')
|
||||||
|
api 'com.github.GTNewHorizons:MrTJPCore:1.3.7:dev'
|
||||||
}
|
}
|
||||||
@@ -1,65 +1,135 @@
|
|||||||
|
# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable.
|
||||||
|
# LOCAL to test local config updates.
|
||||||
|
gtnh.settings.blowdryerTag = 0.2.0
|
||||||
|
|
||||||
|
# Human-readable mod name, available for mcmod.info population.
|
||||||
modName = ForgeRelocation
|
modName = ForgeRelocation
|
||||||
|
|
||||||
# This is a case-sensitive string to identify your mod. Convention is to use lower case.
|
# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation.
|
||||||
|
# Conventionally lowercase.
|
||||||
modId = ForgeRelocation
|
modId = ForgeRelocation
|
||||||
|
|
||||||
|
# Root package of the mod, used to find various classes in other properties,
|
||||||
|
# mcmod.info substitution, enabling assertions in run tasks, etc.
|
||||||
modGroup = mrtjp.relocation
|
modGroup = mrtjp.relocation
|
||||||
|
|
||||||
# WHY is there no version field?
|
# Whether to use modGroup as the maven publishing group.
|
||||||
# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the
|
# When false, com.github.GTNewHorizons is used.
|
||||||
# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/
|
useModGroupForPublishing = false
|
||||||
|
|
||||||
# Will update your build.gradle automatically whenever an update is available
|
# Updates your build.gradle and settings.gradle automatically whenever an update is available.
|
||||||
autoUpdateBuildScript = false
|
autoUpdateBuildScript = false
|
||||||
|
|
||||||
|
# Version of Minecraft to target
|
||||||
minecraftVersion = 1.7.10
|
minecraftVersion = 1.7.10
|
||||||
|
|
||||||
|
# Version of Minecraft Forge to target
|
||||||
forgeVersion = 10.13.4.1614
|
forgeVersion = 10.13.4.1614
|
||||||
|
|
||||||
# Specify a MCP channel and mappings version for dependency deobfuscation and the deobfParams task.
|
# Specify an MCP channel for dependency deobfuscation and the deobfParams task.
|
||||||
channel = stable
|
channel = stable
|
||||||
|
|
||||||
|
# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task.
|
||||||
mappingsVersion = 12
|
mappingsVersion = 12
|
||||||
|
|
||||||
# Define other MCP mappings for dependency deobfuscation
|
# Defines other MCP mappings for dependency deobfuscation.
|
||||||
remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
|
remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
|
||||||
|
|
||||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
|
# Select a default username for testing your mod. You can always override this per-run by running
|
||||||
# restart Minecraft in development. Choose this dependent on your mod:
|
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
|
||||||
# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
|
|
||||||
# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
|
|
||||||
developmentEnvironmentUserName = Developer
|
developmentEnvironmentUserName = Developer
|
||||||
|
|
||||||
# Define a source file of your project with:
|
# Enables modern Java syntax support. Valid values:
|
||||||
|
# - false: No modern syntax, Java 8 only
|
||||||
|
# - jabel: Jabel syntax-only support, compiles to J8 bytecode
|
||||||
|
# - jvmDowngrader: Full modern Java via JVM Downgrader (syntax + stdlib APIs)
|
||||||
|
# - modern: Native modern Java bytecode, no downgrading
|
||||||
|
enableModernJavaSyntax = false
|
||||||
|
|
||||||
|
# If set, ignores the above setting and compiles with the given toolchain. This may cause unexpected issues,
|
||||||
|
# and should *not* be used in most situations. -1 disables this.
|
||||||
|
# forceToolchainVersion = -1
|
||||||
|
|
||||||
|
# Target JVM version for JVM Downgrader bytecode downgrading.
|
||||||
|
# Only used when enableModernJavaSyntax = jvmDowngrader
|
||||||
|
# downgradeTargetVersion = 8
|
||||||
|
|
||||||
|
# Comma-separated list of Java versions for multi-release jar support (JVM Downgrader only).
|
||||||
|
# Classes will be available in META-INF/versions/N/ for each version N in this list.
|
||||||
|
# Default: "21,25" (J25+ gets native classes, J21-24 gets partial downgrade, J8-20 gets full downgrade).
|
||||||
|
# jvmDowngraderMultiReleaseVersions = 21,25
|
||||||
|
|
||||||
|
# Specifies how JVM Downgrader API stubs are provided. Options:
|
||||||
|
# - shade: Shade minimized stubs into the jar
|
||||||
|
# - gtnhlib: GTNHLib provides stubs at runtime (adds version constraint)
|
||||||
|
# - external: Another dependency provides stubs (no constraint, no warning)
|
||||||
|
# - (empty): Warning reminding you to configure stubs
|
||||||
|
# Note: 'shade' option requires you to verify license compliance, see: https://github.com/unimined/JvmDowngrader/blob/main/LICENSE.md
|
||||||
|
# jvmDowngraderStubsProvider =
|
||||||
|
|
||||||
|
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||||
|
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||||
|
enableGenericInjection = false
|
||||||
|
|
||||||
|
# Generate a class with a String field for the mod version named as defined below.
|
||||||
|
# If generateGradleTokenClass is empty or not missing, no such class will be generated.
|
||||||
|
# If gradleTokenVersion is empty or missing, the field will not be present in the class.
|
||||||
|
generateGradleTokenClass = mrtjp.relocation.Tags
|
||||||
|
|
||||||
|
# Name of the token containing the project's current version to generate/replace.
|
||||||
|
gradleTokenVersion = VERSION
|
||||||
|
|
||||||
|
# [DEPRECATED] Mod ID replacement token.
|
||||||
|
gradleTokenModId =
|
||||||
|
|
||||||
|
# [DEPRECATED] Mod name replacement token.
|
||||||
|
gradleTokenModName =
|
||||||
|
|
||||||
|
# [DEPRECATED] Mod Group replacement token.
|
||||||
|
gradleTokenGroupName =
|
||||||
|
|
||||||
|
# [DEPRECATED]
|
||||||
|
# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java
|
||||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||||
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
|
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
|
||||||
# version in @Mod([...], version = VERSION, [...])
|
# version in @Mod([...], version = VERSION, [...]).
|
||||||
# Leave these properties empty to skip individual token replacements
|
# Leave these properties empty to skip individual token replacements.
|
||||||
replaceGradleTokenInFile = mod.scala,package-info.java
|
replaceGradleTokenInFile =
|
||||||
gradleTokenModId =
|
|
||||||
gradleTokenModName =
|
|
||||||
gradleTokenVersion = GRADLETOKEN_VERSION
|
|
||||||
gradleTokenGroupName =
|
|
||||||
|
|
||||||
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
|
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
|
||||||
# leave this property empty.
|
# leave this property empty.
|
||||||
# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
|
# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api
|
||||||
apiPackage =
|
apiPackage =
|
||||||
|
|
||||||
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
|
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
|
||||||
# Example value: mymodid_at.cfg
|
# There can be multiple files in a space-separated list.
|
||||||
|
# Example value: mymodid_at.cfg nei_at.cfg
|
||||||
accessTransformersFile =
|
accessTransformersFile =
|
||||||
|
|
||||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||||
usesMixins = false
|
usesMixins = false
|
||||||
# Adds some debug arguments like verbose output and export
|
|
||||||
|
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||||
|
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||||
|
# Mixin classes will have access to "main" classes, but not the other way around.
|
||||||
|
separateMixinSourceSet =
|
||||||
|
|
||||||
|
# Adds some debug arguments like verbose output and class export.
|
||||||
usesMixinDebug = false
|
usesMixinDebug = false
|
||||||
|
|
||||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||||
mixinPlugin =
|
mixinPlugin =
|
||||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
|
||||||
|
# Specify the package that contains all of your Mixins. The package must exist or
|
||||||
|
# the build will fail. If you have a package property defined in your mixins.<modid>.json,
|
||||||
|
# it must match with this or the build will fail.
|
||||||
mixinsPackage =
|
mixinsPackage =
|
||||||
|
|
||||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||||
# This parameter is for legacy compatibility only
|
# This parameter is for legacy compatibility only
|
||||||
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
|
# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin
|
||||||
coreModClass =
|
coreModClass = asm.RelocationPlugin
|
||||||
|
|
||||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||||
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
||||||
containsMixinsAndOrCoreModOnly = false
|
containsMixinsAndOrCoreModOnly = false
|
||||||
@@ -67,15 +137,38 @@ containsMixinsAndOrCoreModOnly = false
|
|||||||
# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins.
|
# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins.
|
||||||
forceEnableMixins = false
|
forceEnableMixins = false
|
||||||
|
|
||||||
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your
|
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your
|
||||||
# responsibility check the licence and request permission for distribution, if required.
|
# responsibility to check the license and request permission for distribution if required.
|
||||||
usesShadowedDependencies = false
|
usesShadowedDependencies = false
|
||||||
|
|
||||||
|
# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access
|
||||||
|
# their own classes, making the minimization unreliable.
|
||||||
|
minimizeShadowedDependencies = true
|
||||||
|
|
||||||
# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token.
|
# If disabled, won't rename the shadowed classes.
|
||||||
|
relocateShadowedDependencies = true
|
||||||
|
|
||||||
|
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||||
|
includeWellKnownRepositories = true
|
||||||
|
|
||||||
|
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
|
||||||
|
# list of strings, with the acceptable keys being(case does not matter):
|
||||||
|
# cursemaven
|
||||||
|
# modrinth
|
||||||
|
excludeWellKnownRepositories =
|
||||||
|
|
||||||
|
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
|
||||||
|
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
|
||||||
|
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
|
||||||
|
usesMavenPublishing = true
|
||||||
|
|
||||||
|
# Maven repository to publish the mod to.
|
||||||
|
# mavenPublishUrl = https\://nexus.gtnewhorizons.com/repository/releases/
|
||||||
|
|
||||||
|
# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token.
|
||||||
|
#
|
||||||
# The project's ID on Modrinth. Can be either the slug or the ID.
|
# The project's ID on Modrinth. Can be either the slug or the ID.
|
||||||
# Leave this empty if you don't want to publish on Modrinth.
|
# Leave this empty if you don't want to publish to Modrinth.
|
||||||
modrinthProjectId =
|
modrinthProjectId =
|
||||||
|
|
||||||
# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth.
|
# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth.
|
||||||
@@ -84,12 +177,11 @@ modrinthProjectId =
|
|||||||
# type can be one of [project, version],
|
# type can be one of [project, version],
|
||||||
# and the name is the Modrinth project or version slug/id of the other mod.
|
# and the name is the Modrinth project or version slug/id of the other mod.
|
||||||
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
|
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
|
||||||
# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
|
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
|
||||||
modrinthRelations =
|
modrinthRelations =
|
||||||
|
|
||||||
|
|
||||||
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
|
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
|
||||||
|
#
|
||||||
# The project's numeric ID on CurseForge. You can find this in the About Project box.
|
# The project's numeric ID on CurseForge. You can find this in the About Project box.
|
||||||
# Leave this empty if you don't want to publish on CurseForge.
|
# Leave this empty if you don't want to publish on CurseForge.
|
||||||
curseForgeProjectId =
|
curseForgeProjectId =
|
||||||
@@ -99,18 +191,48 @@ curseForgeProjectId =
|
|||||||
# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
|
# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
|
||||||
# and the name is the CurseForge project slug of the other mod.
|
# and the name is the CurseForge project slug of the other mod.
|
||||||
# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
|
# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
|
||||||
# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
|
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
|
||||||
curseForgeRelations =
|
curseForgeRelations =
|
||||||
|
|
||||||
|
# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older
|
||||||
# Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older
|
|
||||||
# projects. New projects should not use this parameter.
|
# projects. New projects should not use this parameter.
|
||||||
# customArchiveBaseName =
|
# customArchiveBaseName =
|
||||||
|
|
||||||
# Optional parameter to prevent the source code from being published
|
# Optional parameter to customize the default working directory used by the runClient* tasks. Relative to the project directory.
|
||||||
# noPublishedSources =
|
# runClientWorkingDirectory = run/client
|
||||||
|
|
||||||
# Uncomment this to disable spotless checks
|
# Optional parameter to customize the default working directory used by the runServer* tasks. Relative to the project directory.
|
||||||
|
# runServerWorkingDirectory = run/server
|
||||||
|
|
||||||
|
# Optional parameter to have the build automatically fail if an illegal version is used.
|
||||||
|
# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'.
|
||||||
|
# The check is ONLY performed if the version is a git tag.
|
||||||
|
# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+
|
||||||
|
# versionPattern =
|
||||||
|
|
||||||
|
# Uncomment to prevent the source code from being published.
|
||||||
|
# noPublishedSources = true
|
||||||
|
|
||||||
|
# Uncomment this to disable Spotless checks.
|
||||||
# This should only be uncommented to keep it easier to sync with upstream/other forks.
|
# This should only be uncommented to keep it easier to sync with upstream/other forks.
|
||||||
# That is, if there is no other active fork/upstream, NEVER change this.
|
# That is, if there is no other active fork/upstream, NEVER change this.
|
||||||
# disableSpotless = true
|
# disableSpotless = true
|
||||||
|
|
||||||
|
# Uncomment this to disable Checkstyle checks (currently wildcard import check).
|
||||||
|
# disableCheckstyle = true
|
||||||
|
|
||||||
|
# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle"
|
||||||
|
# (force use delegated build).
|
||||||
|
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||||
|
# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build.
|
||||||
|
# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want!
|
||||||
|
# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you.
|
||||||
|
# ideaOverrideBuildType = idea
|
||||||
|
|
||||||
|
# Whether IDEA should run spotless checks when pressing the Build button.
|
||||||
|
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||||
|
# ideaCheckSpotlessOnBuild = true
|
||||||
|
|
||||||
|
# Non-GTNH properties
|
||||||
|
org.gradle.configuration-cache = true
|
||||||
|
org.gradle.parallel = true
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#This file is generated by updateDaemonJvm
|
||||||
|
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
|
||||||
|
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
|
||||||
|
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
|
||||||
|
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
|
||||||
|
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1df82b76031285ef2e6a4f59ffe9299d/redirect
|
||||||
|
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/c7d5be6a02945ac2e045048ee54a7d32/redirect
|
||||||
|
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
|
||||||
|
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
|
||||||
|
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/643f404f769811f5f265fd66f7af5d89/redirect
|
||||||
|
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/38256085a73e137cb4937ea9c4807fec/redirect
|
||||||
|
toolchainVersion=25
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2015 the original author or authors.
|
# Copyright © 2015 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -15,80 +15,114 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## Gradle start up script for UN*X
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
##
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
# This is normally unused
|
||||||
APP_BASE_NAME=`basename "$0"`
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@@ -97,92 +131,118 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
ulimit -n $MAX_FD
|
warn "Could not query maximum file descriptor limit"
|
||||||
if [ $? -ne 0 ] ; then
|
esac
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
case $MAX_FD in #(
|
||||||
fi
|
'' | soft) :;; #(
|
||||||
else
|
*)
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
fi
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=$((i+1))
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
(0) set -- ;;
|
|
||||||
(1) set -- "$args0" ;;
|
|
||||||
(2) set -- "$args0" "$args1" ;;
|
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=$(save "$@")
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
@@ -13,8 +13,10 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,10 +27,14 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@@ -37,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -51,48 +57,35 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|||||||
@@ -1,6 +1,2 @@
|
|||||||
repositories {
|
repositories {
|
||||||
maven {
|
|
||||||
name 'GTNH Maven'
|
|
||||||
url 'http://jenkins.usrv.eu:8081/nexus/content/repositories/public/'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,23 @@
|
|||||||
|
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
// RetroFuturaGradle
|
||||||
|
name "GTNH Maven"
|
||||||
|
url "https://nexus.gtnewhorizons.com/repository/public/"
|
||||||
|
mavenContent {
|
||||||
|
includeGroup("com.gtnewhorizons")
|
||||||
|
includeGroupByRegex("com\\.gtnewhorizons\\..+")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.diffplug.blowdryerSetup' version '1.6.0'
|
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.27'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.diffplug.blowdryerSetup'
|
|
||||||
|
|
||||||
blowdryerSetup {
|
|
||||||
github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.5')
|
|
||||||
//devLocal '.' // Use this when testing config updates locally
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
|
tile.relocation.blockmovingrow.name=Moving Block
|
||||||
|
|
||||||
tile.mcframes.frame.name=Frame
|
tile.mcframes.frame.name=Frame
|
||||||
tile.mcframes.motor|0.name=Debug Frame Motor
|
tile.mcframes.motor.name=Debug Frame Motor
|
||||||
|
tile.mcframes.motor|0.name=Debug Frame Motor
|
||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -1,6 +0,0 @@
|
|||||||
[{
|
|
||||||
"repo": "https://github.com/GTNewHorizons/MrTJPCore/releases/download/1.1.1/",
|
|
||||||
"file": "MrTJPCore-1.7.10-1.1.1.jar",
|
|
||||||
"dev": "MrTJPCore-1.7.10-1.1.1-dev.jar",
|
|
||||||
"class": "mrtjp.core.handler.MrTJPCoreMod"
|
|
||||||
}]
|
|
||||||
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 205 KiB |
@@ -12,11 +12,7 @@
|
|||||||
"credits": "",
|
"credits": "",
|
||||||
"logoFile": "",
|
"logoFile": "",
|
||||||
"screenshots": [],
|
"screenshots": [],
|
||||||
"parent": "",
|
"parent": ""
|
||||||
"requiredMods": ["MrTJPCoreMod"],
|
|
||||||
"dependencies": [],
|
|
||||||
"dependants": [],
|
|
||||||
"useDependencyInformation": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"modid": "MCFrames",
|
"modid": "MCFrames",
|
||||||
@@ -30,10 +26,6 @@
|
|||||||
"credits": "",
|
"credits": "",
|
||||||
"logoFile": "fr_logo.png",
|
"logoFile": "fr_logo.png",
|
||||||
"screenshots": [],
|
"screenshots": [],
|
||||||
"parent": "",
|
"parent": ""
|
||||||
"requiredMods": ["${modId}"],
|
|
||||||
"dependencies": [],
|
|
||||||
"dependants": [],
|
|
||||||
"useDependencyInformation": true
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@@ -1,47 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014.
|
* Copyright (c) 2014. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
import mrtjp.relocation.api.Relocator;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import mrtjp.relocation.api.Relocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that can be implemented on Tile Entities or Blocks that wish to
|
* Interface that can be implemented on Tile Entities or Blocks that wish to act as frames, which are the blocks that
|
||||||
* act as frames, which are the blocks that stick together and form a
|
* stick together and form a moving structure when moved through the {@link Relocator}. No other action besides
|
||||||
* moving structure when moved through the {@link Relocator}. No other action besides
|
|
||||||
* implementation of this interface is needed for the block to function.
|
* implementation of this interface is needed for the block to function.
|
||||||
*/
|
*/
|
||||||
public interface IFrame {
|
public interface IFrame {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check if this frame block is allowed to grab
|
* Used to check if this frame block is allowed to grab a block on the given side.
|
||||||
* a block on the given side.
|
|
||||||
*
|
*
|
||||||
* Convention requires that this method yields the same result
|
* Convention requires that this method yields the same result on both client and server.
|
||||||
* on both client and server.
|
|
||||||
*
|
*
|
||||||
* @param w The world.
|
* @param w The world.
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @param side The side of this block, as a ForgeDirection
|
* @param side The side of this block, as a ForgeDirection
|
||||||
* @return True if the side can grab another block.
|
* @return True if the side can grab another block.
|
||||||
*/
|
*/
|
||||||
boolean stickOut(World w, int x, int y, int z, int side);
|
boolean stickOut(World w, int x, int y, int z, int side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check if this frame block can be grabbed on the
|
* Used to check if this frame block can be grabbed on the given side by another frame.
|
||||||
* given side by another frame.
|
|
||||||
*
|
*
|
||||||
* Convention requires that this method yields the same result
|
* Convention requires that this method yields the same result on both client and server.
|
||||||
* on both client and server.
|
|
||||||
*
|
*
|
||||||
* @param w The world.
|
* @param w The world.
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @param side The side of this block, as a ForgeDirection
|
* @param side The side of this block, as a ForgeDirection
|
||||||
* @return True if the side can be grabbed by a frame block.
|
* @return True if the side can be grabbed by a frame block.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014.
|
* Copyright (c) 2014. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
import mrtjp.relocation.api.RelocationAPI;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import mrtjp.relocation.api.RelocationAPI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used instead of {@link IFrame} to add frame capabilities
|
* Class used instead of {@link IFrame} to add frame capabilities to a block without having the block or tile in that
|
||||||
* to a block without having the block or tile in that location
|
* location implement the IFrame interface. This class must be registered in the {@link RelocationAPI}.
|
||||||
* implement the IFrame interface. This class must be registered in
|
|
||||||
* the {@link RelocationAPI}.
|
|
||||||
*/
|
*/
|
||||||
public interface IFrameInteraction extends IFrame {
|
public interface IFrameInteraction extends IFrame {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if this interaction can be executed at the given
|
* Check to see if this interaction can be executed at the given coordinates.
|
||||||
* coordinates.
|
|
||||||
*
|
*
|
||||||
* @param w The world.
|
* @param w The world.
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @return True if this interaction is valid for the given
|
* @return True if this interaction is valid for the given location.
|
||||||
* location.
|
|
||||||
*/
|
*/
|
||||||
boolean canInteract(World w, int x, int y, int z);
|
boolean canInteract(World w, int x, int y, int z);
|
||||||
}
|
}
|
||||||
@@ -1,36 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014.
|
* Copyright (c) 2014. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
import codechicken.lib.vec.Vector3;
|
|
||||||
import mrtjp.relocation.api.RelocationAPI;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import codechicken.lib.vec.Vector3;
|
||||||
|
import mrtjp.relocation.api.RelocationAPI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility interface used by the frame ItemBlock when placing.
|
* A utility interface used by the frame ItemBlock when placing. It can be used to add interactions to the default frame
|
||||||
* It can be used to add interactions to the default frame block
|
* block placement. This class can be registered through the {@link RelocationAPI}.
|
||||||
* placement. This class can be registered through the
|
|
||||||
* {@link RelocationAPI}.
|
|
||||||
*/
|
*/
|
||||||
public interface IFramePlacement {
|
public interface IFramePlacement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called sequentially on all registered IFrameBlockPlacements on
|
* Called sequentially on all registered IFrameBlockPlacements on the frame item block's onItemUse function, until
|
||||||
* the frame item block's onItemUse function, until one returns true.
|
* one returns true.
|
||||||
* @param item The itemstack of the frame block.
|
*
|
||||||
|
* @param item The itemstack of the frame block.
|
||||||
* @param player The player who is placing the block.
|
* @param player The player who is placing the block.
|
||||||
* @param world The world the block is being placed in.
|
* @param world The world the block is being placed in.
|
||||||
* @param x The x coordinate that the block is being placed in.
|
* @param x The x coordinate that the block is being placed in.
|
||||||
* @param y The y coordinate that the block is being placed in.
|
* @param y The y coordinate that the block is being placed in.
|
||||||
* @param z The z coordinate that the block is being placed in.
|
* @param z The z coordinate that the block is being placed in.
|
||||||
* @param side The side the player clicked on
|
* @param side The side the player clicked on
|
||||||
* @param hit The exact hit position of the click.
|
* @param hit The exact hit position of the click.
|
||||||
* @return True if something happened. This will subsequently block the actual placement of the block.
|
* @return True if something happened. This will subsequently block the actual placement of the block.
|
||||||
*/
|
*/
|
||||||
public boolean onItemUse(
|
public boolean onItemUse(ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side,
|
||||||
ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side, Vector3 hit);
|
Vector3 hit);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
@@ -10,20 +8,20 @@ import net.minecraft.util.MovingObjectPosition;
|
|||||||
import net.minecraft.util.Vec3;
|
import net.minecraft.util.Vec3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API class for MCFrames.
|
* API class for MCFrames. <br>
|
||||||
* <br><br>
|
* <br>
|
||||||
* It is recommended that mods access this class within a soft dependency class.
|
* It is recommended that mods access this class within a soft dependency class.
|
||||||
*/
|
*/
|
||||||
public abstract class MCFramesAPI {
|
public abstract class MCFramesAPI {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This field will contain an implementor of this API if Relocation is installed.
|
* This field will contain an implementor of this API if Relocation is installed.
|
||||||
*/
|
*/
|
||||||
public static MCFramesAPI instance;
|
public static MCFramesAPI instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to register a custom placment that can define how a frame is placed.
|
* Used to register a custom placment that can define how a frame is placed. This is useful for cases such as if the
|
||||||
* This is useful for cases such as if the frame is placed on a Multipart from
|
* frame is placed on a Multipart from the Forge Multipart API, this placement property can perform special actions
|
||||||
* the Forge Multipart API, this placement property can perform special actions
|
|
||||||
* that would add the frame to the multipart tile.
|
* that would add the frame to the multipart tile.
|
||||||
*
|
*
|
||||||
* @param placement The custom frame placement to register.
|
* @param placement The custom frame placement to register.
|
||||||
@@ -31,51 +29,49 @@ public abstract class MCFramesAPI {
|
|||||||
public abstract void registerFramePlacement(IFramePlacement placement);
|
public abstract void registerFramePlacement(IFramePlacement placement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to register a {@link IFrameInteraction}, which is a class that
|
* Used to register a {@link IFrameInteraction}, which is a class that can be used to add frame-like properties to
|
||||||
* can be used to add frame-like properties to any block.
|
* any block.
|
||||||
*
|
*
|
||||||
* @param interaction The interaction to register.
|
* @param interaction The interaction to register.
|
||||||
*/
|
*/
|
||||||
public abstract void registerFrameInteraction(IFrameInteraction interaction);
|
public abstract void registerFrameInteraction(IFrameInteraction interaction);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for the optional StickResolver object which can be used to quicky
|
* Getter for the optional StickResolver object which can be used to quicky resolve a structure based on default
|
||||||
* resolve a structure based on default Relocation frame blocks and stick
|
* Relocation frame blocks and stick rules.
|
||||||
* rules.
|
|
||||||
*
|
*
|
||||||
* @return The StickResolver object
|
* @return The StickResolver object
|
||||||
*/
|
*/
|
||||||
public abstract StickResolver getStickResolver();
|
public abstract StickResolver getStickResolver();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for the instance variable of the Frame block. Used if external
|
* Getter for the instance variable of the Frame block. Used if external implementations need the block. (i.e.
|
||||||
* implementations need the block. (i.e. registration purposes)
|
* registration purposes)
|
||||||
*
|
*
|
||||||
* @return The frame block.
|
* @return The frame block.
|
||||||
*/
|
*/
|
||||||
public abstract Block getFrameBlock();
|
public abstract Block getFrameBlock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tessellates the frame model at the given coordinates. Useful for making
|
* Tessellates the frame model at the given coordinates. Useful for making your block look like the default frame
|
||||||
* your block look like the default frame block.
|
* block.
|
||||||
*
|
*
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @param mask The mask of sides not to render.
|
* @param mask The mask of sides not to render.
|
||||||
*/
|
*/
|
||||||
public abstract void renderFrame(double x, double y, double z, int mask);
|
public abstract void renderFrame(double x, double y, double z, int mask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raytrace a frame block at the given world coords with start and end
|
* Raytrace a frame block at the given world coords with start and end points of a ray.
|
||||||
* points of a ray.
|
|
||||||
*
|
*
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @param mask The side mask for the model.
|
* @param mask The side mask for the model.
|
||||||
* @param start The start point of the ray.
|
* @param start The start point of the ray.
|
||||||
* @param end The end point of the ray.
|
* @param end The end point of the ray.
|
||||||
* @return The object position if anything from the frame model was hit.
|
* @return The object position if anything from the frame model was hit.
|
||||||
*/
|
*/
|
||||||
public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, int mask, Vec3 start, Vec3 end);
|
public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, int mask, Vec3 start, Vec3 end);
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import mrtjp.relocation.api.BlockPos;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import mrtjp.relocation.api.BlockPos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class used to resolve frame structures.
|
* Helper class used to resolve frame structures.
|
||||||
*/
|
*/
|
||||||
public abstract class StickResolver {
|
public abstract class StickResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to obtain the block coordinates of every block that is part of the same
|
* Method used to obtain the block coordinates of every block that is part of the same framed structure as the one
|
||||||
* framed structure as the one that was given as an argument.
|
* that was given as an argument.
|
||||||
*
|
*
|
||||||
* @param world The world
|
* @param world The world
|
||||||
* @param x The x coordinate of any block in the structure.
|
* @param x The x coordinate of any block in the structure.
|
||||||
* @param y The y coordinate of any block in the structure.
|
* @param y The y coordinate of any block in the structure.
|
||||||
* @param z The z coordinate of any block in the structure.
|
* @param z The z coordinate of any block in the structure.
|
||||||
* @param exclusions All coordinates to not include in the structure.
|
* @param exclusions All coordinates to not include in the structure. generally, one of these is the motor block
|
||||||
* generally, one of these is the motor block that moved the structure.
|
* that moved the structure.
|
||||||
* @return A set of all block coordinates that are part of the structure that the input block was in.
|
* @return A set of all block coordinates that are part of the structure that the input block was in.
|
||||||
*/
|
*/
|
||||||
public abstract Set<BlockPos> getStructure(World world, int x, int y, int z, BlockPos... exclusions);
|
public abstract Set<BlockPos> getStructure(World world, int x, int y, int z, BlockPos... exclusions);
|
||||||
|
|||||||
@@ -1,8 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @API(owner = "MCFrames", provides = "MCFrames|API", apiVersion = "GRADLETOKEN_VERSION")
|
// spotless:off
|
||||||
|
//
|
||||||
|
// You may wonder, "why is this commented out?"
|
||||||
|
// When FML sorts the modcontainers, it includes APIs. The API's dependency is always its owner but if an API is found
|
||||||
|
// embedded in a mod which isn't the owner, that mod is set as the API's dependant. In this case, the same jar contains
|
||||||
|
// both ForgeRelocation and MCFrames, each with an API. So when FML determins which APIs are embedded where, it sees
|
||||||
|
// MCFrames|API embedded in ForgeRelocation and ForgeRelocation|API embedded in MCFrames. This results in the following
|
||||||
|
// circular load order:
|
||||||
|
//
|
||||||
|
// MCFrames --------------> MCFrames|API <----+
|
||||||
|
// ^ ^ | |
|
||||||
|
// | | | |
|
||||||
|
// | +-------------------+ | +- MrTJPCore
|
||||||
|
// | | | |
|
||||||
|
// | | v |
|
||||||
|
// ForgeRelocation|API <--- ForgeRelocation <-+
|
||||||
|
//
|
||||||
|
// spotless:on
|
||||||
|
|
||||||
|
// @API(owner = "MCFrames", provides = "MCFrames|API", apiVersion = Tags.VERSION)
|
||||||
package mrtjp.mcframes.api;
|
package mrtjp.mcframes.api;
|
||||||
|
|
||||||
|
// import cpw.mods.fml.common.API;
|
||||||
|
// import mrtjp.relocation.Tags;
|
||||||
@@ -29,210 +29,267 @@ import net.minecraftforge.common.util.ForgeDirection
|
|||||||
|
|
||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
|
|
||||||
class BlockFrame extends BlockCore("mcframes.frame", Material.wood) with IFrame
|
class BlockFrame
|
||||||
{
|
extends BlockCore("mcframes.frame", Material.wood)
|
||||||
setResistance(5.0F)
|
with IFrame {
|
||||||
setHardness(2.0F)
|
setResistance(5.0f)
|
||||||
setStepSound(Block.soundTypeWood)
|
setHardness(2.0f)
|
||||||
setCreativeTab(CreativeTabs.tabTransport)
|
setStepSound(Block.soundTypeWood)
|
||||||
|
setCreativeTab(CreativeTabs.tabTransport)
|
||||||
|
|
||||||
override def getItemBlockClass = classOf[ItemBlockFrame]
|
override def getItemBlockClass = classOf[ItemBlockFrame]
|
||||||
|
|
||||||
override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = true
|
override def stickOut(w: World, x: Int, y: Int, z: Int, side: Int) = true
|
||||||
override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = true
|
override def stickIn(w: World, x: Int, y: Int, z: Int, side: Int) = true
|
||||||
|
|
||||||
override def isSideSolid(w:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = false
|
override def isSideSolid(
|
||||||
|
w: IBlockAccess,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int,
|
||||||
|
side: ForgeDirection
|
||||||
|
) = false
|
||||||
|
|
||||||
override def isOpaqueCube = false
|
override def isOpaqueCube = false
|
||||||
|
|
||||||
override def renderAsNormalBlock = false
|
override def renderAsNormalBlock = false
|
||||||
|
|
||||||
override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3) =
|
override def collisionRayTrace(
|
||||||
MCFramesAPI.instance.raytraceFrame(x, y, z, 0, start, end)
|
world: World,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int,
|
||||||
|
start: Vec3,
|
||||||
|
end: Vec3
|
||||||
|
) =
|
||||||
|
MCFramesAPI.instance.raytraceFrame(x, y, z, 0, start, end)
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def getSelectedBoundingBoxFromPool(w:World, x:Int, y:Int, z:Int) =
|
override def getSelectedBoundingBoxFromPool(
|
||||||
Cuboid6.full.copy.add(new Vector3(x, y, z)).toAABB
|
w: World,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int
|
||||||
|
) =
|
||||||
|
Cuboid6.full.copy.add(new Vector3(x, y, z)).toAABB
|
||||||
|
|
||||||
override def getRenderType = RenderFrame.renderID
|
override def getRenderType = RenderFrame.renderID
|
||||||
|
|
||||||
override def getIcon(side:Int, meta:Int) = RenderFrame.icon
|
override def getIcon(side: Int, meta: Int) = RenderFrame.icon
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def registerBlockIcons(reg:IIconRegister)
|
override def registerBlockIcons(reg: IIconRegister) {
|
||||||
{
|
RenderFrame.registerIcons(reg)
|
||||||
RenderFrame.registerIcons(reg)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object ItemBlockFrame
|
object ItemBlockFrame {
|
||||||
{
|
var placements = Seq[IFramePlacement]()
|
||||||
var placements = Seq[IFramePlacement]()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemBlockFrame(b:Block) extends ItemBlock(b)
|
class ItemBlockFrame(b: Block) extends ItemBlock(b) {
|
||||||
{
|
override def getMetadata(meta: Int) = meta
|
||||||
override def getMetadata(meta:Int) = meta
|
|
||||||
|
|
||||||
override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean =
|
override def onItemUse(
|
||||||
{
|
item: ItemStack,
|
||||||
if (ItemBlockFrame.placements.exists(_.onItemUse(item, player, world, x, y, z,
|
player: EntityPlayer,
|
||||||
side, new Vector3(hitX, hitY, hitZ))))
|
world: World,
|
||||||
{
|
x: Int,
|
||||||
SoundLib.playBlockPlacement(world, x, y, z, field_150939_a)
|
y: Int,
|
||||||
true
|
z: Int,
|
||||||
}
|
side: Int,
|
||||||
else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ)
|
hitX: Float,
|
||||||
}
|
hitY: Float,
|
||||||
|
hitZ: Float
|
||||||
|
): Boolean = {
|
||||||
|
if (
|
||||||
|
ItemBlockFrame.placements.exists(
|
||||||
|
_.onItemUse(
|
||||||
|
item,
|
||||||
|
player,
|
||||||
|
world,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
side,
|
||||||
|
new Vector3(hitX, hitY, hitZ)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
SoundLib.playBlockPlacement(world, x, y, z, field_150939_a)
|
||||||
|
true
|
||||||
|
} else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ)
|
||||||
|
}
|
||||||
|
|
||||||
override def func_150936_a(world:World, x:Int, y:Int, z:Int, side:Int, player:EntityPlayer, stack:ItemStack) = true
|
override def func_150936_a(
|
||||||
|
world: World,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int,
|
||||||
|
side: Int,
|
||||||
|
player: EntityPlayer,
|
||||||
|
stack: ItemStack
|
||||||
|
) = true
|
||||||
}
|
}
|
||||||
|
|
||||||
object RenderFrame extends ISimpleBlockRenderingHandler
|
object RenderFrame extends ISimpleBlockRenderingHandler {
|
||||||
{
|
var renderID = -1
|
||||||
var renderID = -1
|
var icon: IIcon = _
|
||||||
var icon:IIcon = _
|
|
||||||
|
|
||||||
private val model = parseModel("frame")
|
private val model = parseModel("frame")
|
||||||
private val models = new Array[CCModel](64)
|
private val models = new Array[CCModel](64)
|
||||||
|
|
||||||
private def parseModel(name:String) =
|
private def parseModel(name: String) = {
|
||||||
{
|
val m = combine(
|
||||||
val m = combine(parseObjModels(this.getClass.getResource(
|
parseObjModels(
|
||||||
"/assets/mcframes/obj/"+name+".obj").openStream(),
|
this.getClass
|
||||||
7, InvertX).values())
|
.getResource("/assets/mcframes/obj/" + name + ".obj")
|
||||||
|
.openStream(),
|
||||||
|
7,
|
||||||
|
InvertX
|
||||||
|
).values()
|
||||||
|
)
|
||||||
|
|
||||||
m.apply(new Scale(1.00075, 1.00075, 1.00075))
|
m.apply(new Scale(1.00075, 1.00075, 1.00075))
|
||||||
m.apply(new Translation(Vector3.center))
|
m.apply(new Translation(Vector3.center))
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
override def getRenderId = renderID
|
override def getRenderId = renderID
|
||||||
|
|
||||||
override def shouldRender3DInInventory(modelId:Int) = true
|
override def shouldRender3DInInventory(modelId: Int) = true
|
||||||
|
|
||||||
override def renderInventoryBlock(b:Block, meta:Int, id:Int, rb:RenderBlocks)
|
override def renderInventoryBlock(
|
||||||
{
|
b: Block,
|
||||||
renderInvBlock(rb, meta)
|
meta: Int,
|
||||||
}
|
id: Int,
|
||||||
|
rb: RenderBlocks
|
||||||
override def renderWorldBlock(world:IBlockAccess, x:Int, y:Int, z:Int, b:Block, id:Int, rb:RenderBlocks) =
|
) {
|
||||||
{
|
renderInvBlock(rb, meta)
|
||||||
renderWorldBlock(rb, world, x, y, z, world.getBlockMetadata(x, y, z))
|
}
|
||||||
true
|
|
||||||
}
|
override def renderWorldBlock(
|
||||||
|
world: IBlockAccess,
|
||||||
def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int)
|
x: Int,
|
||||||
{
|
y: Int,
|
||||||
TextureUtils.bindAtlas(0)
|
z: Int,
|
||||||
CCRenderState.reset()
|
b: Block,
|
||||||
CCRenderState.lightMatrix.locate(w, x, y, z)
|
id: Int,
|
||||||
CCRenderState.setBrightness(w, x, y, z)
|
rb: RenderBlocks
|
||||||
|
) = {
|
||||||
if (r.hasOverrideBlockTexture)
|
TextureUtils.bindAtlas(0)
|
||||||
{
|
val state = CCRenderState.instance
|
||||||
getOrGenerateModel(0).render(new Translation(x, y, z), new IconTransformation(r.overrideBlockTexture))
|
state.resetInstance()
|
||||||
}
|
state.lightMatrix.locate(world, x, y, z)
|
||||||
else RenderFrame.render(new Vector3(x, y, z), 0)
|
state.setBrightnessInstance(world, x, y, z)
|
||||||
}
|
|
||||||
|
if (rb.hasOverrideBlockTexture) {
|
||||||
def renderInvBlock(r:RenderBlocks, meta:Int)
|
getOrGenerateModel(0).render(
|
||||||
{
|
new Translation(x, y, z),
|
||||||
TextureUtils.bindAtlas(0)
|
new IconTransformation(rb.overrideBlockTexture)
|
||||||
CCRenderState.reset()
|
)
|
||||||
CCRenderState.setDynamic()
|
} else RenderFrame.render(new Vector3(x, y, z), 0)
|
||||||
CCRenderState.pullLightmap()
|
state.lightMatrix.access = null
|
||||||
|
true
|
||||||
CCRenderState.startDrawing()
|
}
|
||||||
RenderFrame.render(new Vector3(-0.5, -0.5, -0.5), 0)
|
|
||||||
|
def renderInvBlock(r: RenderBlocks, meta: Int) {
|
||||||
CCRenderState.render()
|
TextureUtils.bindAtlas(0)
|
||||||
CCRenderState.draw()
|
val state = CCRenderState.instance
|
||||||
}
|
state.resetInstance()
|
||||||
|
state.setDynamicInstance()
|
||||||
def registerIcons(reg:IIconRegister)
|
state.pullLightmapInstance()
|
||||||
{
|
|
||||||
icon = reg.registerIcon("mcframes:frame")
|
state.startDrawingInstance()
|
||||||
}
|
RenderFrame.render(new Vector3(-0.5, -0.5, -0.5), 0)
|
||||||
|
|
||||||
def render(pos:Vector3, mask:Int)
|
state.renderInstance()
|
||||||
{
|
state.drawInstance()
|
||||||
getOrGenerateModel(mask).render(pos.translation, new IconTransformation(icon))
|
}
|
||||||
}
|
|
||||||
|
def registerIcons(reg: IIconRegister) {
|
||||||
def getOrGenerateModel(mask:Int) =
|
icon = reg.registerIcon("mcframes:frame")
|
||||||
{
|
}
|
||||||
var m = models(mask&0x3F)
|
|
||||||
if (m == null)
|
def render(pos: Vector3, mask: Int) {
|
||||||
{
|
getOrGenerateModel(mask).render(
|
||||||
m = FrameModelGen.generate(model, mask)
|
pos.translation,
|
||||||
models(mask&0x3F) = m
|
new IconTransformation(icon)
|
||||||
}
|
)
|
||||||
m
|
}
|
||||||
|
|
||||||
|
def getOrGenerateModel(mask: Int) = {
|
||||||
|
var m = models(mask & 0x3f)
|
||||||
|
if (m == null) {
|
||||||
|
m = FrameModelGen.generate(model, mask)
|
||||||
|
models(mask & 0x3f) = m
|
||||||
}
|
}
|
||||||
|
m
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object FrameModelGen
|
object FrameModelGen {
|
||||||
{
|
val w = 2.0 / 16.0
|
||||||
val w = 2.0/16.0
|
val l = 16.0 / 16.0
|
||||||
val l = 16.0/16.0
|
val i = 1.0 / 16.0
|
||||||
val i = 1.0/16.0
|
val u = 0.5
|
||||||
val u = 0.5
|
val v = 0.5
|
||||||
val v = 0.5
|
|
||||||
|
|
||||||
def generate(box:CCModel, mask:Int) =
|
def generate(box: CCModel, mask: Int) = {
|
||||||
{
|
var m = generateSinglePeg
|
||||||
var m = generateSinglePeg
|
m = generateQuartRotated(m)
|
||||||
m = generateQuartRotated(m)
|
m = generateEightRotated(m)
|
||||||
m = generateEightRotated(m)
|
m = generateBackface(m)
|
||||||
m = generateBackface(m)
|
|
||||||
|
|
||||||
var b = Seq.newBuilder[CCModel]
|
var b = Seq.newBuilder[CCModel]
|
||||||
b += box
|
b += box
|
||||||
for (s <- 0 until 6) if ((mask&1<<s) == 0)
|
for (s <- 0 until 6)
|
||||||
b += generateSided(m.copy, s)
|
if ((mask & 1 << s) == 0)
|
||||||
|
b += generateSided(m.copy, s)
|
||||||
|
|
||||||
finishModel(combine(b.result()))
|
finishModel(combine(b.result()))
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateSinglePeg =
|
def generateSinglePeg = {
|
||||||
{
|
val dw = w / 2.0
|
||||||
val dw = w/2.0
|
val dl = l / 2.0
|
||||||
val dl = l/2.0
|
|
||||||
|
|
||||||
val m = quadModel(4)
|
val m = quadModel(4)
|
||||||
m.verts(0) = new Vertex5( dw, i, -dl, u+dw, v-dl)
|
m.verts(0) = new Vertex5(dw, i, -dl, u + dw, v - dl)
|
||||||
m.verts(1) = new Vertex5( dw, i, dl, u+dw, v+dl)
|
m.verts(1) = new Vertex5(dw, i, dl, u + dw, v + dl)
|
||||||
m.verts(2) = new Vertex5(-dw, i, dl, u-dw, v+dl)
|
m.verts(2) = new Vertex5(-dw, i, dl, u - dw, v + dl)
|
||||||
m.verts(3) = new Vertex5(-dw, i, -dl, u-dw, v-dl)
|
m.verts(3) = new Vertex5(-dw, i, -dl, u - dw, v - dl)
|
||||||
m.apply(new Translation(u, 0, v))
|
m.apply(new Translation(u, 0, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateQuartRotated(m:CCModel) =
|
def generateQuartRotated(m: CCModel) = {
|
||||||
{
|
combine(
|
||||||
combine(Seq(m, m.copy.apply(Rotation.quarterRotations(1)
|
Seq(
|
||||||
.at(Vector3.center) `with` new Translation(0, 0.01, 0))))
|
m,
|
||||||
}
|
m.copy.apply(
|
||||||
|
Rotation
|
||||||
|
.quarterRotations(1)
|
||||||
|
.at(Vector3.center) `with` new Translation(0, 0.01, 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
def generateEightRotated(m:CCModel) =
|
def generateEightRotated(m: CCModel) = {
|
||||||
{
|
m.apply(new Rotation(math.Pi / 4, 0, 1, 0).at(Vector3.center))
|
||||||
m.apply(new Rotation(math.Pi/4, 0, 1, 0).at(Vector3.center))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def generateBackface(m:CCModel) =
|
def generateBackface(m: CCModel) = {
|
||||||
{
|
combine(Seq(m, m.backfacedCopy()))
|
||||||
combine(Seq(m, m.backfacedCopy()))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def generateSided(m:CCModel, side:Int) =
|
def generateSided(m: CCModel, side: Int) = {
|
||||||
{
|
m.apply(Rotation.sideRotations(side).at(Vector3.center.copy))
|
||||||
m.apply(Rotation.sideRotations(side).at(Vector3.center.copy))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def finishModel(m:CCModel) =
|
def finishModel(m: CCModel) = {
|
||||||
{
|
m.shrinkUVs(0.0005)
|
||||||
m.shrinkUVs(0.0005)
|
m.computeNormals()
|
||||||
m.computeNormals()
|
m.computeLighting(LightModel.standardLightModel)
|
||||||
m.computeLighting(LightModel.standardLightModel)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -10,7 +10,12 @@ import java.util.{Set => JSet}
|
|||||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||||
import mrtjp.core.vec.ModelRayTracer
|
import mrtjp.core.vec.ModelRayTracer
|
||||||
import mrtjp.core.world.WorldLib
|
import mrtjp.core.world.WorldLib
|
||||||
import mrtjp.mcframes.api.{IFrameInteraction, IFramePlacement, MCFramesAPI, StickResolver}
|
import mrtjp.mcframes.api.{
|
||||||
|
IFrameInteraction,
|
||||||
|
IFramePlacement,
|
||||||
|
MCFramesAPI,
|
||||||
|
StickResolver
|
||||||
|
}
|
||||||
import mrtjp.mcframes.{ItemBlockFrame, RenderFrame, StickRegistry}
|
import mrtjp.mcframes.{ItemBlockFrame, RenderFrame, StickRegistry}
|
||||||
import mrtjp.relocation.api.{BlockPos, RelocationAPI}
|
import mrtjp.relocation.api.{BlockPos, RelocationAPI}
|
||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
@@ -21,70 +26,87 @@ import scala.annotation.tailrec
|
|||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
import scala.collection.immutable.Queue
|
import scala.collection.immutable.Queue
|
||||||
|
|
||||||
object MCFramesAPI_Impl extends MCFramesAPI
|
object MCFramesAPI_Impl extends MCFramesAPI {
|
||||||
{
|
override def registerFramePlacement(placement: IFramePlacement) {
|
||||||
override def registerFramePlacement(placement:IFramePlacement)
|
ItemBlockFrame.placements :+= placement
|
||||||
{
|
}
|
||||||
ItemBlockFrame.placements :+= placement
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getFrameBlock = MCFramesMod.blockFrame
|
override def getFrameBlock = MCFramesMod.blockFrame
|
||||||
|
|
||||||
override def registerFrameInteraction(interaction:IFrameInteraction)
|
override def registerFrameInteraction(interaction: IFrameInteraction) {
|
||||||
{
|
StickRegistry.interactionList :+= interaction
|
||||||
StickRegistry.interactionList :+= interaction
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def getStickResolver = StickResolver_Impl
|
override def getStickResolver = StickResolver_Impl
|
||||||
|
|
||||||
override def renderFrame(x:Double, y:Double, z:Double, mask:Int)
|
override def renderFrame(x: Double, y: Double, z: Double, mask: Int) {
|
||||||
{
|
RenderFrame.render(new Vector3(x, y, z), mask)
|
||||||
RenderFrame.render(new Vector3(x, y, z), mask)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def raytraceFrame(x:Double, y:Double, z:Double, mask:Int, start:Vec3, end:Vec3) =
|
override def raytraceFrame(
|
||||||
ModelRayTracer.raytraceModel(x, y, z, start, end, RenderFrame.getOrGenerateModel(mask))
|
x: Double,
|
||||||
|
y: Double,
|
||||||
|
z: Double,
|
||||||
|
mask: Int,
|
||||||
|
start: Vec3,
|
||||||
|
end: Vec3
|
||||||
|
) =
|
||||||
|
ModelRayTracer.raytraceModel(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
RenderFrame.getOrGenerateModel(mask)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object StickResolver_Impl extends StickResolver
|
object StickResolver_Impl extends StickResolver {
|
||||||
{
|
private var world: World = null
|
||||||
private var world:World = null
|
private var start: BlockCoord = null
|
||||||
private var start:BlockCoord = null
|
private var excl: Set[BlockCoord] = null
|
||||||
private var excl:Set[BlockCoord] = null
|
|
||||||
|
|
||||||
override def getStructure(w:World, x:Int, y:Int, z:Int, ex:BlockPos*):JSet[BlockPos] =
|
override def getStructure(
|
||||||
{
|
w: World,
|
||||||
world = w
|
x: Int,
|
||||||
start = new BlockCoord(x, y, z)
|
y: Int,
|
||||||
excl = ex.map(b => new BlockCoord(b.x, b.y, b.z)).toSet
|
z: Int,
|
||||||
val result = iterate(Queue(start))
|
ex: BlockPos*
|
||||||
world = null
|
): JSet[BlockPos] = {
|
||||||
start = null
|
world = w
|
||||||
excl = null
|
start = new BlockCoord(x, y, z)
|
||||||
result.map(b => new BlockPos(b.x, b.y, b.z))
|
excl = ex.map(b => new BlockCoord(b.x, b.y, b.z)).toSet
|
||||||
}
|
val result = iterate(Queue(start))
|
||||||
|
world = null
|
||||||
|
start = null
|
||||||
|
excl = null
|
||||||
|
result.map(b => new BlockPos(b.x, b.y, b.z))
|
||||||
|
}
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
private def iterate(open:Seq[BlockCoord], closed:Set[BlockCoord] = Set.empty):Set[BlockCoord] = open match
|
private def iterate(
|
||||||
{
|
open: Seq[BlockCoord],
|
||||||
case Seq() => closed
|
closed: Set[BlockCoord] = Set.empty
|
||||||
case Seq(next, rest@_*) => WorldLib.getBlock(world, next) match
|
): Set[BlockCoord] = open match {
|
||||||
{
|
case Seq() => closed
|
||||||
case block:Block =>
|
case Seq(next, rest @ _*) =>
|
||||||
val toCheck = Vector.newBuilder[BlockCoord]
|
WorldLib.getBlock(world, next) match {
|
||||||
for (s <- 0 until 6)
|
case block: Block =>
|
||||||
{
|
val toCheck = Vector.newBuilder[BlockCoord]
|
||||||
if (StickRegistry.resolveStick(world, next, s))
|
for (s <- 0 until 6) {
|
||||||
{
|
if (StickRegistry.resolveStick(world, next, s)) {
|
||||||
val to = next.copy.offset(s)
|
val to = next.copy.offset(s)
|
||||||
if (!excl(to) && !closed(to) && !open.contains(to))
|
if (!excl(to) && !closed(to) && !open.contains(to))
|
||||||
if (!world.isAirBlock(to.x, to.y, to.z) && !RelocationAPI.instance.isMoving(world, to.x, to.y, to.z)
|
if (
|
||||||
/**&& MovingTileRegistry.canMove(world, to.x, to.y, to.z)**/)//Dont ignore non-movables, have them halt movement.
|
!world.isAirBlock(to.x, to.y, to.z) && !RelocationAPI.instance
|
||||||
toCheck += to
|
.isMoving(world, to.x, to.y, to.z)
|
||||||
}
|
/** && MovingTileRegistry.canMove(world, to.x, to.y, to.z)* */
|
||||||
}
|
) // Dont ignore non-movables, have them halt movement.
|
||||||
iterate(rest++toCheck.result(), closed+next)
|
toCheck += to
|
||||||
case _ => iterate(rest, closed+next)
|
}
|
||||||
}
|
}
|
||||||
}
|
iterate(rest ++ toCheck.result(), closed + next)
|
||||||
}
|
case _ => iterate(rest, closed + next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,75 +6,86 @@
|
|||||||
package mrtjp.mcframes.handler
|
package mrtjp.mcframes.handler
|
||||||
|
|
||||||
import cpw.mods.fml.common.Mod
|
import cpw.mods.fml.common.Mod
|
||||||
import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent}
|
import cpw.mods.fml.common.event.{
|
||||||
|
FMLInitializationEvent,
|
||||||
|
FMLPostInitializationEvent,
|
||||||
|
FMLPreInitializationEvent
|
||||||
|
}
|
||||||
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
||||||
import mrtjp.mcframes.api.MCFramesAPI
|
import mrtjp.mcframes.api.MCFramesAPI
|
||||||
import mrtjp.mcframes.{BlockFrame, BlockMotor, StickRegistry}
|
import mrtjp.mcframes.{BlockFrame, BlockMotor, StickRegistry}
|
||||||
|
import mrtjp.relocation.Tags
|
||||||
import net.minecraft.client.gui.GuiScreen
|
import net.minecraft.client.gui.GuiScreen
|
||||||
|
|
||||||
@Mod(modid = MCFramesMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.mcframes.handler.GuiConfigFactory", acceptedMinecraftVersions = "[1.7.10]", dependencies = "required-after:MrTJPCoreMod", name = MCFramesMod.modName, version = MCFramesMod.version)
|
@Mod(
|
||||||
object MCFramesMod
|
modid = MCFramesMod.modID,
|
||||||
{
|
useMetadata = true,
|
||||||
MCFramesAPI.instance = MCFramesAPI_Impl
|
modLanguage = "scala",
|
||||||
|
guiFactory = "mrtjp.mcframes.handler.GuiConfigFactory",
|
||||||
|
acceptedMinecraftVersions = "[1.7.10]",
|
||||||
|
dependencies = "required-after:MrTJPCoreMod",
|
||||||
|
name = MCFramesMod.modName,
|
||||||
|
version = MCFramesMod.version
|
||||||
|
)
|
||||||
|
object MCFramesMod {
|
||||||
|
MCFramesAPI.instance = MCFramesAPI_Impl
|
||||||
|
|
||||||
final val modID = "MCFrames"
|
final val modID = "MCFrames"
|
||||||
final val modName = "MCFrames"
|
final val modName = "MCFrames"
|
||||||
final val version = "GRADLETOKEN_VERSION"
|
final val version = Tags.VERSION
|
||||||
|
|
||||||
var blockFrame:BlockFrame = _
|
var blockFrame: BlockFrame = _
|
||||||
var blockMotor:BlockMotor = _
|
var blockMotor: BlockMotor = _
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def preInit(event:FMLPreInitializationEvent)
|
def preInit(event: FMLPreInitializationEvent) {
|
||||||
{
|
MCFramesProxy.preinit()
|
||||||
MCFramesProxy.preinit()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def init(event:FMLInitializationEvent)
|
def init(event: FMLInitializationEvent) {
|
||||||
{
|
MCFramesConfig.loadConfig()
|
||||||
MCFramesConfig.loadConfig()
|
MCFramesProxy.init()
|
||||||
MCFramesProxy.init()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def postInit(event:FMLPostInitializationEvent)
|
def postInit(event: FMLPostInitializationEvent) {
|
||||||
{
|
MCFramesProxy.postinit()
|
||||||
MCFramesProxy.postinit()
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MCFramesConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "MCFrames", MCFramesConfig.config)
|
class MCFramesConfigGui(parent: GuiScreen)
|
||||||
class GuiConfigFactory extends TModGuiFactory
|
extends SpecialConfigGui(parent, "MCFrames", MCFramesConfig.config)
|
||||||
{
|
class GuiConfigFactory extends TModGuiFactory {
|
||||||
override def mainConfigGuiClass() = classOf[MCFramesConfigGui]
|
override def mainConfigGuiClass() = classOf[MCFramesConfigGui]
|
||||||
}
|
}
|
||||||
|
|
||||||
object MCFramesConfig extends ModConfig("MCFrames")
|
object MCFramesConfig extends ModConfig("MCFrames") {
|
||||||
{
|
var setMap = Array(
|
||||||
var setMap = Array(
|
"minecraft:bed -> minecraft:bed",
|
||||||
"minecraft:bed -> minecraft:bed",
|
"minecraft:wooden_door -> minecraft:wooden_door",
|
||||||
"minecraft:wooden_door -> minecraft:wooden_door",
|
"minecraft:iron_door -> minecraft:iron_door"
|
||||||
"minecraft:iron_door -> minecraft:iron_door"
|
)
|
||||||
|
|
||||||
|
override protected def initValues() {
|
||||||
|
val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc)
|
||||||
|
setMap = sets.put("latch registry", setMap)
|
||||||
|
setMap = sets.put(
|
||||||
|
"latch registry",
|
||||||
|
StickRegistry.parseAndAddLatchSets(setMap),
|
||||||
|
true
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override protected def initValues()
|
def buildLatchSetsDesc: String = {
|
||||||
{
|
var s = "Used to define which pairs of blocks will be stuck together. \n"
|
||||||
val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc)
|
s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n"
|
||||||
setMap = sets.put("latch registry", setMap)
|
s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n"
|
||||||
setMap = sets.put("latch registry", StickRegistry.parseAndAddLatchSets(setMap), true)
|
s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n"
|
||||||
}
|
s += "Sets are defined using the syntax of key -> value. \n"
|
||||||
|
s += "Possible keys and values:\n"
|
||||||
def buildLatchSetsDesc:String =
|
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||||
{
|
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||||
var s = "Used to define which pairs of blocks will be stuck together. \n"
|
s
|
||||||
s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n"
|
}
|
||||||
s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n"
|
|
||||||
s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n"
|
|
||||||
s += "Sets are defined using the syntax of key -> value. \n"
|
|
||||||
s += "Possible keys and values:\n"
|
|
||||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
|
||||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -17,47 +17,47 @@ import net.minecraft.init.Items
|
|||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraftforge.oredict.ShapedOreRecipe
|
import net.minecraftforge.oredict.ShapedOreRecipe
|
||||||
|
|
||||||
class MCFramesProxy_server
|
class MCFramesProxy_server {
|
||||||
{
|
def preinit() {
|
||||||
def preinit()
|
blockMotor = new BlockMotor
|
||||||
{
|
blockFrame = new BlockFrame
|
||||||
blockMotor = new BlockMotor
|
}
|
||||||
blockFrame = new BlockFrame
|
|
||||||
}
|
|
||||||
|
|
||||||
def init()
|
def init() {
|
||||||
{
|
MCFramesRecipes.initRecipes()
|
||||||
MCFramesRecipes.initRecipes()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def postinit(){}
|
def postinit() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MCFramesProxy_client extends MCFramesProxy_server
|
class MCFramesProxy_client extends MCFramesProxy_server {
|
||||||
{
|
@SideOnly(Side.CLIENT)
|
||||||
@SideOnly(Side.CLIENT)
|
override def preinit() {
|
||||||
override def preinit()
|
super.preinit()
|
||||||
{
|
|
||||||
super.preinit()
|
|
||||||
|
|
||||||
TileRenderRegistry.setRenderer(MCFramesMod.blockMotor, 0, RenderMotor)
|
TileRenderRegistry.setRenderer(MCFramesMod.blockMotor, 0, RenderMotor)
|
||||||
|
|
||||||
RenderFrame.renderID = RenderingRegistry.getNextAvailableRenderId
|
RenderFrame.renderID = RenderingRegistry.getNextAvailableRenderId
|
||||||
RenderingRegistry.registerBlockHandler(RenderFrame)
|
RenderingRegistry.registerBlockHandler(RenderFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MCFramesProxy extends MCFramesProxy_client
|
object MCFramesProxy extends MCFramesProxy_client
|
||||||
|
|
||||||
object MCFramesRecipes
|
object MCFramesRecipes {
|
||||||
{
|
def initRecipes() {
|
||||||
def initRecipes()
|
// Frame
|
||||||
{
|
GameRegistry.addRecipe(
|
||||||
//Frame
|
new ShapedOreRecipe(
|
||||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(blockFrame, 8),
|
new ItemStack(blockFrame, 8),
|
||||||
"sls","lsl","sls",
|
"sls",
|
||||||
's':JC, Items.stick,
|
"lsl",
|
||||||
'l':JC, "logWood"
|
"sls",
|
||||||
))
|
's': JC,
|
||||||
}
|
Items.stick,
|
||||||
}
|
'l': JC,
|
||||||
|
"logWood"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,155 +25,152 @@ import net.minecraft.util.IIcon
|
|||||||
import net.minecraft.world.{IBlockAccess, World}
|
import net.minecraft.world.{IBlockAccess, World}
|
||||||
import net.minecraftforge.common.util.ForgeDirection
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
class BlockMotor extends InstancedBlock("mcframes.motor", Material.iron)
|
class BlockMotor extends InstancedBlock("mcframes.motor", Material.iron) {
|
||||||
{
|
setHardness(5f)
|
||||||
setHardness(5f)
|
setResistance(10f)
|
||||||
setResistance(10f)
|
setStepSound(Block.soundTypeMetal)
|
||||||
setStepSound(Block.soundTypeMetal)
|
setCreativeTab(CreativeTabs.tabTransport)
|
||||||
setCreativeTab(CreativeTabs.tabTransport)
|
addSingleTile(classOf[TileMotor])
|
||||||
addSingleTile(classOf[TileMotor])
|
|
||||||
|
|
||||||
override def isSideSolid(world:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = true
|
override def isSideSolid(
|
||||||
|
world: IBlockAccess,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int,
|
||||||
|
side: ForgeDirection
|
||||||
|
) = true
|
||||||
|
|
||||||
override def renderAsNormalBlock = true
|
override def renderAsNormalBlock = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class TileMotor extends InstancedBlockTile with TTileOrient with IFrame
|
class TileMotor extends InstancedBlockTile with TTileOrient with IFrame {
|
||||||
{
|
override def save(tag: NBTTagCompound) {
|
||||||
override def save(tag:NBTTagCompound)
|
super.save(tag)
|
||||||
{
|
tag.setByte("orient", orientation)
|
||||||
super.save(tag)
|
}
|
||||||
tag.setByte("orient", orientation)
|
|
||||||
}
|
override def load(tag: NBTTagCompound) {
|
||||||
|
super.load(tag)
|
||||||
override def load(tag:NBTTagCompound)
|
orientation = tag.getByte("orient")
|
||||||
{
|
}
|
||||||
super.load(tag)
|
|
||||||
orientation = tag.getByte("orient")
|
override def readDesc(in: MCDataInput) {
|
||||||
}
|
super.readDesc(in)
|
||||||
|
orientation = in.readByte()
|
||||||
override def readDesc(in:MCDataInput)
|
}
|
||||||
{
|
|
||||||
super.readDesc(in)
|
override def writeDesc(out: MCDataOutput) {
|
||||||
orientation = in.readByte()
|
super.writeDesc(out)
|
||||||
}
|
out.writeByte(orientation)
|
||||||
|
}
|
||||||
override def writeDesc(out:MCDataOutput)
|
|
||||||
{
|
override def read(in: MCDataInput, key: Int) = key match {
|
||||||
super.writeDesc(out)
|
case 2 =>
|
||||||
out.writeByte(orientation)
|
orientation = in.readByte()
|
||||||
}
|
markRender()
|
||||||
|
case _ => super.read(in, key)
|
||||||
override def read(in:MCDataInput, key:Int) = key match
|
}
|
||||||
{
|
|
||||||
case 2 =>
|
def sendOrientUpdate() {
|
||||||
orientation = in.readByte()
|
if (!world.isRemote)
|
||||||
markRender()
|
writeStream(2).writeByte(orientation).sendToChunk()
|
||||||
case _ => super.read(in, key)
|
}
|
||||||
}
|
|
||||||
|
override def onBlockPlaced(
|
||||||
def sendOrientUpdate()
|
side: Int,
|
||||||
{
|
meta: Int,
|
||||||
if (!world.isRemote)
|
player: EntityPlayer,
|
||||||
writeStream(2).writeByte(orientation).sendToChunk()
|
stack: ItemStack,
|
||||||
}
|
hit: Vector3
|
||||||
|
) {
|
||||||
override def onBlockPlaced(side:Int, meta:Int, player:EntityPlayer, stack:ItemStack, hit:Vector3)
|
super.onBlockPlaced(side, meta, player, stack, hit)
|
||||||
{
|
setSide(side ^ 1)
|
||||||
super.onBlockPlaced(side, meta, player, stack, hit)
|
setRotation(Rotation.getSidedRotation(player, side ^ 1))
|
||||||
setSide(side^1)
|
}
|
||||||
setRotation(Rotation.getSidedRotation(player, side^1))
|
|
||||||
}
|
override def onBlockActivated(player: EntityPlayer, s: Int): Boolean = {
|
||||||
|
if (super.onBlockActivated(player, s)) return true
|
||||||
override def onBlockActivated(player:EntityPlayer, s:Int):Boolean =
|
|
||||||
{
|
if (player.isSneaking) setRotation((rotation + 1) % 4)
|
||||||
if (super.onBlockActivated(player, s)) return true
|
else setSide((side + 1) % 6)
|
||||||
|
|
||||||
if (player.isSneaking) setRotation((rotation+1)%4)
|
true
|
||||||
else setSide((side+1)%6)
|
}
|
||||||
|
|
||||||
true
|
override def onOrientChanged(oldOrient: Int) {
|
||||||
}
|
super.onOrientChanged(oldOrient)
|
||||||
|
sendOrientUpdate()
|
||||||
override def onOrientChanged(oldOrient:Int)
|
}
|
||||||
{
|
|
||||||
super.onOrientChanged(oldOrient)
|
override def getBlock = MCFramesMod.blockMotor
|
||||||
sendOrientUpdate()
|
|
||||||
}
|
def getMoveDir = absoluteDir((rotation + 2) % 4)
|
||||||
|
|
||||||
override def getBlock = MCFramesMod.blockMotor
|
override def stickOut(w: World, x: Int, y: Int, z: Int, side: Int) =
|
||||||
|
side == (this.side ^ 1)
|
||||||
def getMoveDir = absoluteDir((rotation+2)%4)
|
override def stickIn(w: World, x: Int, y: Int, z: Int, side: Int) =
|
||||||
|
side != (this.side ^ 1)
|
||||||
override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = side == (this.side^1)
|
|
||||||
override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = side != (this.side^1)
|
override def update() {
|
||||||
|
if (!world.isRemote && world.getBlockPowerInput(x, y, z) > 0) {
|
||||||
override def update()
|
val pos = position.offset(side ^ 1)
|
||||||
{
|
if (world.isAirBlock(pos.x, pos.y, pos.z)) return
|
||||||
if (!world.isRemote && world.getBlockPowerInput(x, y, z) > 0)
|
|
||||||
{
|
if (
|
||||||
val pos = position.offset(side^1)
|
!RelocationAPI.instance.isMoving(world, pos.x, pos.y, pos.z) &&
|
||||||
if (world.isAirBlock(pos.x, pos.y, pos.z)) return
|
!RelocationAPI.instance.isMoving(world, x, y, z)
|
||||||
|
) {
|
||||||
if (!RelocationAPI.instance.isMoving(world, pos.x, pos.y, pos.z) &&
|
val blocks = MCFramesAPI.instance.getStickResolver
|
||||||
!RelocationAPI.instance.isMoving(world, x, y, z))
|
.getStructure(world, pos.x, pos.y, pos.z, new BlockPos(x, y, z))
|
||||||
{
|
|
||||||
val blocks = MCFramesAPI.instance.getStickResolver
|
val r = RelocationAPI.instance.getRelocator
|
||||||
.getStructure(world, pos.x, pos.y, pos.z, new BlockPos(x, y, z))
|
r.push()
|
||||||
|
r.setWorld(world)
|
||||||
val r = RelocationAPI.instance.getRelocator
|
r.setDirection(getMoveDir)
|
||||||
r.push()
|
r.setSpeed(1 / 16d)
|
||||||
r.setWorld(world)
|
r.addBlocks(blocks)
|
||||||
r.setDirection(getMoveDir)
|
r.execute()
|
||||||
r.setSpeed(1/16D)
|
r.pop()
|
||||||
r.addBlocks(blocks)
|
}
|
||||||
r.execute()
|
|
||||||
r.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object RenderMotor extends TCubeMapRender
|
object RenderMotor extends TCubeMapRender {
|
||||||
{
|
var bottom: IIcon = _
|
||||||
var bottom:IIcon = _
|
var side: IIcon = _
|
||||||
var side:IIcon = _
|
var sidew: IIcon = _
|
||||||
var sidew:IIcon = _
|
var sidee: IIcon = _
|
||||||
var sidee:IIcon = _
|
var top: IIcon = _
|
||||||
var top:IIcon = _
|
|
||||||
|
|
||||||
override def getData(w:IBlockAccess, x:Int, y:Int, z:Int) =
|
override def getData(w: IBlockAccess, x: Int, y: Int, z: Int) = {
|
||||||
{
|
val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor])
|
||||||
val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor])
|
var s = 0
|
||||||
var s = 0
|
var r = 0
|
||||||
var r = 0
|
if (te != null) {
|
||||||
if (te != null)
|
s = te.side
|
||||||
{
|
r = te.rotation
|
||||||
s = te.side
|
|
||||||
r = te.rotation
|
|
||||||
}
|
|
||||||
(s, r, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
|
||||||
}
|
}
|
||||||
|
(s, r, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
||||||
|
}
|
||||||
|
|
||||||
override def getInvData =
|
override def getInvData =
|
||||||
(0, 0, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
(0, 0, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
||||||
|
|
||||||
override def getIcon(s:Int, meta:Int) = s match
|
override def getIcon(s: Int, meta: Int) = s match {
|
||||||
{
|
case 0 => bottom
|
||||||
case 0 => bottom
|
case 1 => top
|
||||||
case 1 => top
|
case 2 => side
|
||||||
case 2 => side
|
case 3 => side
|
||||||
case 3 => side
|
case 4 => sidew
|
||||||
case 4 => sidew
|
case 5 => sidee
|
||||||
case 5 => sidee
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def registerIcons(reg:IIconRegister)
|
override def registerIcons(reg: IIconRegister) {
|
||||||
{
|
bottom = reg.registerIcon("mcframes:motor/bottom")
|
||||||
bottom = reg.registerIcon("mcframes:motor/bottom")
|
top = reg.registerIcon("mcframes:motor/top")
|
||||||
top = reg.registerIcon("mcframes:motor/top")
|
side = reg.registerIcon("mcframes:motor/side")
|
||||||
side = reg.registerIcon("mcframes:motor/side")
|
sidew = reg.registerIcon("mcframes:motor/sidew")
|
||||||
sidew = reg.registerIcon("mcframes:motor/sidew")
|
sidee = reg.registerIcon("mcframes:motor/sidee")
|
||||||
sidee = reg.registerIcon("mcframes:motor/sidee")
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -11,79 +11,87 @@ import mrtjp.mcframes.api.{IFrame, IFrameInteraction}
|
|||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
|
||||||
object StickRegistry
|
object StickRegistry {
|
||||||
{
|
val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r
|
||||||
val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r
|
val rName = raw"(.+)".r
|
||||||
val rName = raw"(.+)".r
|
val rNameMetaM = raw"(.+)m(\d+)".r
|
||||||
val rNameMetaM = raw"(.+)m(\d+)".r
|
val rMod = raw"mod:(\w+)".r
|
||||||
val rMod = raw"mod:(\w+)".r
|
|
||||||
|
|
||||||
var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set())
|
var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set())
|
||||||
var interactionList = Seq[IFrameInteraction]()
|
var interactionList = Seq[IFrameInteraction]()
|
||||||
|
|
||||||
def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") }
|
def parseKV(kv: Seq[String]) = kv.map {
|
||||||
def parseBlockMeta(b:String) = b match
|
case rKeyVal(k, v) => (k, v);
|
||||||
{
|
case s => throw new MatchError(s"Illegal [k -> v] pair: $s")
|
||||||
case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt
|
}
|
||||||
case rName(name) => Block.getBlockFromName(fixName(name)) -> -1
|
def parseBlockMeta(b: String) = b match {
|
||||||
case _ => throw new MatchError(s"Illegal set part: $b")
|
case rNameMetaM(name, meta) =>
|
||||||
}
|
Block.getBlockFromName(fixName(name)) -> meta.toInt
|
||||||
def fixName(name:String) = name.indexOf(':') match
|
case rName(name) => Block.getBlockFromName(fixName(name)) -> -1
|
||||||
{
|
case _ => throw new MatchError(s"Illegal set part: $b")
|
||||||
case -1 => "minecraft:"+name
|
}
|
||||||
case i => name
|
def fixName(name: String) = name.indexOf(':') match {
|
||||||
}
|
case -1 => "minecraft:" + name
|
||||||
|
case i => name
|
||||||
|
}
|
||||||
|
|
||||||
def parseAndAddLatchSets(kv:Seq[String]):Array[String] =
|
def parseAndAddLatchSets(kv: Seq[String]): Array[String] = {
|
||||||
{
|
parseKV(kv).foreach(b =>
|
||||||
parseKV(kv).foreach(b => addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2)))
|
addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2))
|
||||||
latchMap.map{kv =>
|
)
|
||||||
val (b, i) = kv._1
|
latchMap
|
||||||
val e1 = Block.blockRegistry.getNameForObject(b)+(if (i != -1) s"m$i" else "")
|
.map { kv =>
|
||||||
kv._2.map { k =>
|
val (b, i) = kv._1
|
||||||
val (b2, i2) = k
|
val e1 = Block.blockRegistry.getNameForObject(b) + (if (i != -1) s"m$i"
|
||||||
val e2 = Block.blockRegistry.getNameForObject(b2)+(if (i2 != -1) s"m$i2" else "")
|
else "")
|
||||||
e1+" -> "+e2
|
kv._2.map { k =>
|
||||||
}
|
val (b2, i2) = k
|
||||||
}.flatten.toArray
|
val e2 =
|
||||||
}
|
Block.blockRegistry.getNameForObject(b2) + (if (i2 != -1) s"m$i2"
|
||||||
|
else "")
|
||||||
def addLatchSet(b1:(Block, Int), b2:(Block, Int))
|
e1 + " -> " + e2
|
||||||
{
|
|
||||||
latchMap += b1 -> (latchMap(b1)+b2)
|
|
||||||
}
|
|
||||||
|
|
||||||
def resolveStick(w:World, pos:BlockCoord, side:Int):Boolean =
|
|
||||||
{
|
|
||||||
def getFrame(pos:BlockCoord):IFrame =
|
|
||||||
{
|
|
||||||
val b = getBlock(w, pos)
|
|
||||||
if (b.isInstanceOf[IFrame]) return b.asInstanceOf[IFrame]
|
|
||||||
val te = getTileEntity(w, pos, classOf[IFrame])
|
|
||||||
if (te != null) return te
|
|
||||||
interactionList.find(_.canInteract(w, pos.x, pos.y, pos.z)).orNull
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.flatten
|
||||||
|
.toArray
|
||||||
|
}
|
||||||
|
|
||||||
val f1 = getFrame(pos)
|
def addLatchSet(b1: (Block, Int), b2: (Block, Int)) {
|
||||||
if (f1 != null && f1.stickOut(w, pos.x, pos.y, pos.z, side))
|
latchMap += b1 -> (latchMap(b1) + b2)
|
||||||
{
|
}
|
||||||
val p2 = pos.copy.offset(side)
|
|
||||||
val f2 = getFrame(p2)
|
|
||||||
return f2 == null || f2.stickIn(w, p2.x, p2.y, p2.z, side^1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (latchSet(w, pos.x, pos.y, pos.z, side)) return true
|
def resolveStick(w: World, pos: BlockCoord, side: Int): Boolean = {
|
||||||
|
val p2 = pos.copy.offset(side)
|
||||||
|
val target = getBlock(w, p2)
|
||||||
|
if (
|
||||||
|
target != null &&
|
||||||
|
target.getBlockHardness(w, p2.x, p2.y, p2.z) < 0
|
||||||
|
) return false
|
||||||
|
|
||||||
false
|
def getFrame(pos: BlockCoord): IFrame = {
|
||||||
|
val b = getBlock(w, pos)
|
||||||
|
if (b.isInstanceOf[IFrame]) return b.asInstanceOf[IFrame]
|
||||||
|
val te = getTileEntity(w, pos, classOf[IFrame])
|
||||||
|
if (te != null) return te
|
||||||
|
interactionList.find(_.canInteract(w, pos.x, pos.y, pos.z)).orNull
|
||||||
|
}
|
||||||
|
val f1 = getFrame(pos)
|
||||||
|
if (f1 != null && f1.stickOut(w, pos.x, pos.y, pos.z, side)) {
|
||||||
|
val f2 = getFrame(p2)
|
||||||
|
return f2 == null || f2.stickIn(w, p2.x, p2.y, p2.z, side ^ 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
def latchSet(w:World, x:Int, y:Int, z:Int, side:Int) =
|
if (latchSet(w, pos.x, pos.y, pos.z, side)) return true
|
||||||
{
|
|
||||||
val pos = new BlockCoord(x, y, z).offset(side)
|
|
||||||
val b1 = getBlockMetaPair(w, x, y, z)
|
|
||||||
val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z)
|
|
||||||
|
|
||||||
val set = latchMap.getOrElse(b1, latchMap((b1._1, -1)))
|
false
|
||||||
set.contains(b2) || set.contains((b2._1, -1))
|
}
|
||||||
}
|
|
||||||
}
|
def latchSet(w: World, x: Int, y: Int, z: Int, side: Int) = {
|
||||||
|
val pos = new BlockCoord(x, y, z).offset(side)
|
||||||
|
val b1 = getBlockMetaPair(w, x, y, z)
|
||||||
|
val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z)
|
||||||
|
|
||||||
|
val set = latchMap.getOrElse(b1, latchMap((b1._1, -1)))
|
||||||
|
set.contains(b2) || set.contains((b2._1, -1))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lightweight block position object used to keep dependencies confined
|
* Lightweight block position object used to keep dependencies confined to the api package, used by some of the API's
|
||||||
* to the api package, used by some of the API's methods.
|
* methods.
|
||||||
*/
|
*/
|
||||||
public class BlockPos {
|
public class BlockPos {
|
||||||
|
|
||||||
public int x;
|
public int x;
|
||||||
public int y;
|
public int y;
|
||||||
public int z;
|
public int z;
|
||||||
|
|||||||
@@ -1,32 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that can be used by things that wish to receive events for
|
* Interface that can be used by things that wish to receive events for a move that they executed. This interface is
|
||||||
* a move that they executed. This interface is passed into the {@link Relocator}
|
* passed into the {@link Relocator} during movement construction.
|
||||||
* during movement construction.
|
|
||||||
*
|
*
|
||||||
* For example, a motor may wish to know when the movement completes. In which case,
|
* For example, a motor may wish to know when the movement completes. In which case, the motor tile itself would
|
||||||
* the motor tile itself would implement this interface and pass itself into the
|
* implement this interface and pass itself into the Relocator.
|
||||||
* Relocator.
|
|
||||||
*
|
*
|
||||||
* These methods are only called server-side. Clients will not receive any of
|
* These methods are only called server-side. Clients will not receive any of these events, as this class is registered
|
||||||
* these events, as this class is registered during the execution of a move, which
|
* during the execution of a move, which can only happen server-side.
|
||||||
* can only happen server-side.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface IMovementCallback {
|
public interface IMovementCallback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called once move starts. The descriptor contains methods that
|
* Called once move starts. The descriptor contains methods that describe the state of the current movement that
|
||||||
* describe the state of the current movement that this callback
|
* this callback was registered to.
|
||||||
* was registered to.
|
|
||||||
*
|
*
|
||||||
* This descriptor is properly weak-referenced, keep or discard it
|
* This descriptor is properly weak-referenced, keep or discard it at your own leasure.
|
||||||
* at your own leasure.
|
|
||||||
*
|
*
|
||||||
* @param desc The movement descriptor for the current move.
|
* @param desc The movement descriptor for the current move.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the interface of the object that is given to an {@link IMovementCallback} so
|
* This is the interface of the object that is given to an {@link IMovementCallback} so it may access movement
|
||||||
* it may access movement information whenever it needs to during the movement.
|
* information whenever it needs to during the movement.
|
||||||
*
|
*
|
||||||
* Results of all methods is only valid during movement, undefined otherwise. Use
|
* Results of all methods is only valid during movement, undefined otherwise. Use isMoving() to check before using any
|
||||||
* isMoving() to check before using any values from this.
|
* values from this.
|
||||||
*/
|
*/
|
||||||
public interface IMovementDescriptor {
|
public interface IMovementDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if the structure is moving.
|
* @return True if the structure is moving.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014.
|
* Copyright (c) 2014. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for an object that manages the movement of blocks and tiles that are
|
* Interface for an object that manages the movement of blocks and tiles that are registered to it. This class should be
|
||||||
* registered to it. This class should be registered through the {@link RelocationAPI}.
|
* registered through the {@link RelocationAPI}.
|
||||||
*/
|
*/
|
||||||
public interface ITileMover {
|
public interface ITileMover {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check if the block at the given position can move. This
|
* Used to check if the block at the given position can move. This method is only called if the specified block is
|
||||||
* method is only called if the specified block is tied to this
|
* tied to this handler, so there is no need to check if the block is valid for this handler. This is called before
|
||||||
* handler, so there is no need to check if the block is valid
|
* actually moving. If everything is able to move, an animation will start.
|
||||||
* for this handler. This is called before actually moving. If
|
|
||||||
* everything is able to move, an animation will start.
|
|
||||||
*
|
*
|
||||||
* Called server-side only when determining what to move.
|
* Called server-side only when determining what to move.
|
||||||
*
|
*
|
||||||
@@ -30,25 +27,22 @@ public interface ITileMover {
|
|||||||
boolean canMove(World w, int x, int y, int z);
|
boolean canMove(World w, int x, int y, int z);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to actually move the tile. Called after the animation
|
* Method used to actually move the tile. Called after the animation has run. This is where you should tell the tile
|
||||||
* has run. This is where you should tell the tile that it is time
|
* that it is time to move, and peform any extra checks or calls. This should also move the block and tile as well.
|
||||||
* to move, and peform any extra checks or calls. This should also
|
* This is called on every block in the moving structure sequentially.
|
||||||
* move the block and tile as well. This is called
|
|
||||||
* on every block in the moving structure sequentially.
|
|
||||||
*
|
*
|
||||||
* Called on both server and client.
|
* Called on both server and client.
|
||||||
*
|
*
|
||||||
* @param w The world.
|
* @param w The world.
|
||||||
* @param x The x coordinate.
|
* @param x The x coordinate.
|
||||||
* @param y The y coordinate.
|
* @param y The y coordinate.
|
||||||
* @param z The z coordinate.
|
* @param z The z coordinate.
|
||||||
* @param dir The ForgeDirection the structure is moving in.
|
* @param dir The ForgeDirection the structure is moving in.
|
||||||
*/
|
*/
|
||||||
void move(World w, int x, int y, int z, int dir);
|
void move(World w, int x, int y, int z, int dir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after all blocks in the group have moved to their
|
* Called after all blocks in the group have moved to their new locations. This is where you would reload your tile,
|
||||||
* new locations. This is where you would reload your tile,
|
|
||||||
* tell it to refresh or reacknowledge its new position.
|
* tell it to refresh or reacknowledge its new position.
|
||||||
*
|
*
|
||||||
* Callod on both server and client.
|
* Callod on both server and client.
|
||||||
|
|||||||
@@ -1,90 +1,78 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014.
|
* Copyright (c) 2014. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Central API class for Relocation.
|
* Central API class for Relocation. If Relocation is installed, the appropriate field will contain an implementor of
|
||||||
* If Relocation is installed, the appropriate field will contain an
|
* these methods. <br>
|
||||||
* implementor of these methods.
|
* <br>
|
||||||
* <br><br>
|
|
||||||
* It is recommended that mods access this class within a soft dependency class.
|
* It is recommended that mods access this class within a soft dependency class.
|
||||||
*/
|
*/
|
||||||
public abstract class RelocationAPI {
|
public abstract class RelocationAPI {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This field will contain an implementor of this API if Relocation is installed.
|
* This field will contain an implementor of this API if Relocation is installed.
|
||||||
*/
|
*/
|
||||||
public static RelocationAPI instance;
|
public static RelocationAPI instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to register a {@link ITileMover} class that manages the movement of certain tiles.
|
* Used to register a {@link ITileMover} class that manages the movement of certain tiles. This method must be
|
||||||
* This method must be called during FML pre-initialization.
|
* called during FML pre-initialization.
|
||||||
*
|
*
|
||||||
* @param name The name of the mover that will be used to assign blocks to it.
|
* @param name The name of the mover that will be used to assign blocks to it.
|
||||||
* @param desc The description of what this mover is used for or why it is included.
|
* @param desc The description of what this mover is used for or why it is included.
|
||||||
* @param mover The {@link ITileMover} to register.
|
* @param mover The {@link ITileMover} to register.
|
||||||
*/
|
*/
|
||||||
public abstract void registerTileMover(String name, String desc, ITileMover mover);
|
public abstract void registerTileMover(String name, String desc, ITileMover mover);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to register an in-game block to a specific {@link ITileMover} which are registered
|
* Used to register an in-game block to a specific {@link ITileMover} which are registered with the method above.
|
||||||
* with the method above. This method adds the key-value pairs similar to the config,
|
* This method adds the key-value pairs similar to the config, but their assignments can be changed from the config
|
||||||
* but their assignments can be changed from the config file if you would like.
|
* file if you would like. This method must be called during FML pre-initialization.
|
||||||
* This method must be called during FML pre-initialization.
|
|
||||||
*
|
*
|
||||||
* @param key The mod or block key regex. This works the same way it does from the
|
* @param key The mod or block key regex. This works the same way it does from the config file: Possible keys:
|
||||||
* config file:
|
* default - to assign default mover mod:<modID> - to assign every block from a mod <modID>:<blockname>
|
||||||
* Possible keys:
|
* - to assign block from a mod for every meta <modID>:<blockname>m<meta> - to assign block from mod
|
||||||
* default - to assign default mover
|
* for specific meta
|
||||||
* mod:<modID> - to assign every block from a mod
|
|
||||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
|
||||||
* <modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
|
||||||
*
|
*
|
||||||
* @param value The name of the mover to assign this block. A list of all available
|
* @param value The name of the mover to assign this block. A list of all available movers will show up in the
|
||||||
* movers will show up in the configs.
|
* configs.
|
||||||
*/
|
*/
|
||||||
public abstract void registerPreferredMover(String key, String value);
|
public abstract void registerPreferredMover(String key, String value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to register an in-game block to a specific {@link ITileMover} which are registered
|
* Used to register an in-game block to a specific {@link ITileMover} which are registered with the method above.
|
||||||
* with the method above. This method adds the key-value pairs similar to the config. These
|
* This method adds the key-value pairs similar to the config. These assignments are manatory, and blocks that are
|
||||||
* assignments are manatory, and blocks that are registered will be locked to the specified
|
* registered will be locked to the specified mover, and it cannot be changed from the config. This method must be
|
||||||
* mover, and it cannot be changed from the config.
|
* called during FML pre-initialization.
|
||||||
* This method must be called during FML pre-initialization.
|
|
||||||
*
|
*
|
||||||
* @param key The mod or block key regex. This works the same way it does from the
|
* @param key The mod or block key regex. This works the same way it does from the config file: Possible keys:
|
||||||
* config file:
|
* default - to assign default mover mod:<modID> - to assign every block from a mod <modID>:<blockname>
|
||||||
* Possible keys:
|
* - to assign block from a mod for every meta <modID>:<blockname>m<meta> - to assign block from mod
|
||||||
* default - to assign default mover
|
* for specific meta
|
||||||
* mod:<modID> - to assign every block from a mod
|
|
||||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
|
||||||
* <modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
|
||||||
*
|
*
|
||||||
* @param value The name of the mover to assign this block. A list of all available
|
* @param value The name of the mover to assign this block. A list of all available movers will show up in the
|
||||||
* movers will show up in the configs.
|
* configs.
|
||||||
*/
|
*/
|
||||||
public abstract void registerMandatoryMover(String key, String value);
|
public abstract void registerMandatoryMover(String key, String value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter for the global Relocator object which is what is used
|
* Getter for the global Relocator object which is what is used to actually initiate movements.
|
||||||
* to actually initiate movements.
|
|
||||||
*
|
*
|
||||||
* @return The Relocator object
|
* @return The Relocator object
|
||||||
*/
|
*/
|
||||||
public abstract Relocator getRelocator();
|
public abstract Relocator getRelocator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to check if the given block is currently moving. This method is
|
* Used to check if the given block is currently moving. This method is client and server safe.
|
||||||
* client and server safe.
|
|
||||||
*
|
*
|
||||||
* @param world The world the block is in.
|
* @param world The world the block is in.
|
||||||
* @param x The x coordinate of the block.
|
* @param x The x coordinate of the block.
|
||||||
* @param y The y coordinate of the block.
|
* @param y The y coordinate of the block.
|
||||||
* @param z The z coordinate of the block.
|
* @param z The z coordinate of the block.
|
||||||
*
|
*
|
||||||
* @return True if the block is currently moving.
|
* @return True if the block is currently moving.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class used to queue and execute the movement of a set of blocks.
|
* Helper class used to queue and execute the movement of a set of blocks. See {@link mrtjp.mcframes.TileMotor} for
|
||||||
* See {@link mrtjp.mcframes.TileMotor} for usage.
|
* usage.
|
||||||
*/
|
*/
|
||||||
public abstract class Relocator {
|
public abstract class Relocator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes an instance of the Relocator onto the stack.
|
* Pushes an instance of the Relocator onto the stack. Must be called before using any methods.
|
||||||
* Must be called before using any methods.
|
|
||||||
*/
|
*/
|
||||||
public abstract void push();
|
public abstract void push();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pops the instance of the Relocator off the stack.
|
* Pops the instance of the Relocator off the stack. Must be called after you are done using this.
|
||||||
* Must be called after you are done using this.
|
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException If there is no Relocator on the stack.
|
* @throws IllegalStateException If there is no Relocator on the stack.
|
||||||
*/
|
*/
|
||||||
@@ -36,8 +34,7 @@ public abstract class Relocator {
|
|||||||
public abstract void setWorld(World world);
|
public abstract void setWorld(World world);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the direction towards which all the queued blocks will move.
|
* Sets the direction towards which all the queued blocks will move. This is a ForgeDirection index, from 0 to 5
|
||||||
* This is a ForgeDirection index, from 0 to 5
|
|
||||||
*
|
*
|
||||||
* @param dir The direction to move the blocks.
|
* @param dir The direction to move the blocks.
|
||||||
*
|
*
|
||||||
@@ -47,8 +44,7 @@ public abstract class Relocator {
|
|||||||
public abstract void setDirection(int dir);
|
public abstract void setDirection(int dir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the speed of the movement. Must be greater than 0 and
|
* Sets the speed of the movement. Must be greater than 0 and less than 1.
|
||||||
* less than 1.
|
|
||||||
*
|
*
|
||||||
* @param speed The speed of the movement, in meters/tick.
|
* @param speed The speed of the movement, in meters/tick.
|
||||||
*
|
*
|
||||||
@@ -58,8 +54,8 @@ public abstract class Relocator {
|
|||||||
public abstract void setSpeed(double speed);
|
public abstract void setSpeed(double speed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a callback object that receives events during the actual move.
|
* Sets a callback object that receives events during the actual move. This is optional and is not required to be
|
||||||
* This is optional and is not required to be set.
|
* set.
|
||||||
*
|
*
|
||||||
* @param callback The callback to register for this move.
|
* @param callback The callback to register for this move.
|
||||||
*
|
*
|
||||||
@@ -80,14 +76,12 @@ public abstract class Relocator {
|
|||||||
public abstract void addBlocks(Set<BlockPos> blocks);
|
public abstract void addBlocks(Set<BlockPos> blocks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to execute the queued movement. Before calling, the world, direction,
|
* Used to execute the queued movement. Before calling, the world, direction, and queue of blocks must be set.
|
||||||
* and queue of blocks must be set.
|
|
||||||
*
|
*
|
||||||
* @return True if the movement was successfully started.
|
* @return True if the movement was successfully started.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException If the Relocator is not on the stack.
|
* @throws IllegalStateException If the Relocator is not on the stack.
|
||||||
* @throws IllegalStateException If any of the required parameters are not set
|
* @throws IllegalStateException If any of the required parameters are not set or are invalid.
|
||||||
* or are invalid.
|
|
||||||
*/
|
*/
|
||||||
public abstract boolean execute();
|
public abstract boolean execute();
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015.
|
* Copyright (c) 2015. Created by MrTJP. All rights reserved.
|
||||||
* Created by MrTJP.
|
|
||||||
* All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@API(owner = "ForgeRelocation", provides = "ForgeRelocation|API", apiVersion = "GRADLETOKEN_VERSION")
|
@API(owner = "ForgeRelocation", provides = "ForgeRelocation|API", apiVersion = Tags.VERSION)
|
||||||
package mrtjp.relocation.api;
|
package mrtjp.relocation.api;
|
||||||
|
|
||||||
import cpw.mods.fml.common.API;
|
import cpw.mods.fml.common.API;
|
||||||
|
import mrtjp.relocation.Tags;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package mrtjp.relocation.asm
|
||||||
|
|
||||||
|
import java.util.{Map => JMap}
|
||||||
|
import cpw.mods.fml.relauncher.IFMLLoadingPlugin
|
||||||
|
|
||||||
|
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||||
|
@IFMLLoadingPlugin.TransformerExclusions(value =
|
||||||
|
Array("mrtjp.relocation.asm.*", "scala")
|
||||||
|
)
|
||||||
|
class RelocationPlugin extends IFMLLoadingPlugin {
|
||||||
|
|
||||||
|
override def getASMTransformerClass = Array(
|
||||||
|
"mrtjp.relocation.asm.Transformer"
|
||||||
|
)
|
||||||
|
override def getSetupClass = null
|
||||||
|
override def getModContainerClass = null
|
||||||
|
override def getAccessTransformerClass = null
|
||||||
|
override def injectData(data: JMap[String, AnyRef]): Unit = {}
|
||||||
|
}
|
||||||
@@ -5,10 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package mrtjp.relocation.asm
|
package mrtjp.relocation.asm
|
||||||
|
|
||||||
import java.util.{Map => JMap}
|
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{
|
||||||
|
INSTANCE => mapper
|
||||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{INSTANCE => mapper}
|
}
|
||||||
import cpw.mods.fml.relauncher.{IFMLCallHook, IFMLLoadingPlugin}
|
|
||||||
import mrtjp.relocation.handler.RelocationMod
|
import mrtjp.relocation.handler.RelocationMod
|
||||||
import net.minecraft.launchwrapper.{IClassTransformer, Launch}
|
import net.minecraft.launchwrapper.{IClassTransformer, Launch}
|
||||||
import org.objectweb.asm.Opcodes._
|
import org.objectweb.asm.Opcodes._
|
||||||
@@ -17,92 +16,91 @@ import org.objectweb.asm.{ClassReader, ClassWriter}
|
|||||||
|
|
||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
|
|
||||||
/**
|
class Transformer extends IClassTransformer {
|
||||||
* Add "Dfml.coreMods.load=mrtjp.relocation.asm.RelocationPlugin" to launch configs
|
type MethodChecker = (String, MethodNode) => Boolean
|
||||||
* to enable in a development workspace.
|
type InsTransformer = MethodNode => Unit
|
||||||
*/
|
|
||||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
|
||||||
@IFMLLoadingPlugin.TransformerExclusions(value = Array("mrtjp.relocation.asm.*", "scala"))
|
|
||||||
class RelocationPlugin extends IFMLLoadingPlugin with IFMLCallHook
|
|
||||||
{
|
|
||||||
override def getASMTransformerClass = Array("mrtjp.relocation.asm.Transformer")
|
|
||||||
override def getSetupClass = "mrtjp.relocation.asm.RelocationPlugin"
|
|
||||||
override def getModContainerClass = null
|
|
||||||
override def getAccessTransformerClass = null
|
|
||||||
override def injectData(data:JMap[String, AnyRef]): Unit ={}
|
|
||||||
override def call():Void = null
|
|
||||||
}
|
|
||||||
|
|
||||||
class Transformer extends IClassTransformer
|
lazy val deobfEnv =
|
||||||
{
|
(Launch.blackboard get "fml.deobfuscatedEnvironment").asInstanceOf[Boolean]
|
||||||
type MethodChecker = (String, MethodNode) => Boolean
|
lazy val blockClass = mapper.unmap("net/minecraft/block/Block")
|
||||||
type InsTransformer = MethodNode => Unit
|
lazy val teClass = mapper.unmap("net/minecraft/tileentity/TileEntity")
|
||||||
|
|
||||||
lazy val deobfEnv = (Launch.blackboard get "fml.deobfuscatedEnvironment").asInstanceOf[Boolean]
|
def transformBlockRender(m: MethodNode) {
|
||||||
lazy val blockClass = mapper.unmap("net/minecraft/block/Block")
|
val old = m.instructions.toArray.collectFirst { case i: MethodInsnNode =>
|
||||||
lazy val teClass = mapper.unmap("net/minecraft/tileentity/TileEntity")
|
i
|
||||||
|
}.get
|
||||||
def transformBlockRender(m:MethodNode)
|
val list = new InsnList
|
||||||
{
|
list.add(new VarInsnNode(ILOAD, 2))
|
||||||
val old = m.instructions.toArray.collectFirst{ case i:MethodInsnNode => i }.get
|
list.add(new VarInsnNode(ILOAD, 3))
|
||||||
val list = new InsnList
|
list.add(new VarInsnNode(ILOAD, 4))
|
||||||
list.add(new VarInsnNode(ILOAD, 2))
|
list.add(
|
||||||
list.add(new VarInsnNode(ILOAD, 3))
|
new MethodInsnNode(
|
||||||
list.add(new VarInsnNode(ILOAD, 4))
|
INVOKESTATIC,
|
||||||
list.add(new MethodInsnNode(INVOKESTATIC, "mrtjp/relocation/ASMHacks",
|
"mrtjp/relocation/ASMHacks",
|
||||||
"getRenderType", "(Lnet/minecraft/block/Block;III)I", false))
|
"getRenderType",
|
||||||
m.instructions.insert(old, list)
|
"(Lnet/minecraft/block/Block;III)I",
|
||||||
m.instructions.remove(old)
|
false
|
||||||
}
|
)
|
||||||
|
|
||||||
def transformTERender(m:MethodNode)
|
|
||||||
{
|
|
||||||
val old = m.instructions.toArray.collect{ case i:MethodInsnNode => i }.last
|
|
||||||
m.instructions.insert(old, new InsnNode(POP))
|
|
||||||
m.instructions.insert(old, new MethodInsnNode(INVOKESTATIC,
|
|
||||||
"mrtjp/relocation/ASMHacks", "renderTileEntityAt", old.desc, false))
|
|
||||||
m.instructions.remove(old)
|
|
||||||
}
|
|
||||||
|
|
||||||
val classData = Map[String, (MethodChecker, MethodChecker, InsTransformer)](
|
|
||||||
"net.minecraft.client.renderer.RenderBlocks" -> ((
|
|
||||||
(_:String, m:MethodNode) => m.name == "renderBlockByRenderType",
|
|
||||||
(n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147805_b",
|
|
||||||
transformBlockRender _
|
|
||||||
)),
|
|
||||||
"net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher" -> ((
|
|
||||||
(_:String, m:MethodNode) => m.name == "renderTileEntity",
|
|
||||||
(n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147544_a",
|
|
||||||
transformTERender _
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
|
m.instructions.insert(old, list)
|
||||||
|
m.instructions.remove(old)
|
||||||
|
}
|
||||||
|
|
||||||
var matched = Set[String]()
|
def transformTERender(m: MethodNode) {
|
||||||
|
val old = m.instructions.toArray.collect { case i: MethodInsnNode =>
|
||||||
|
i
|
||||||
|
}.last
|
||||||
|
m.instructions.insert(old, new InsnNode(POP))
|
||||||
|
m.instructions.insert(
|
||||||
|
old,
|
||||||
|
new MethodInsnNode(
|
||||||
|
INVOKESTATIC,
|
||||||
|
"mrtjp/relocation/ASMHacks",
|
||||||
|
"renderTileEntityAt",
|
||||||
|
old.desc,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
m.instructions.remove(old)
|
||||||
|
}
|
||||||
|
|
||||||
override def transform(name:String, tName:String, data:Array[Byte]) =
|
val classData = Map[String, (MethodChecker, MethodChecker, InsTransformer)](
|
||||||
{
|
"net.minecraft.client.renderer.RenderBlocks" -> ((
|
||||||
if (classData.keys.contains(tName) && !matched.contains(tName))
|
(_: String, m: MethodNode) => m.name == "renderBlockByRenderType",
|
||||||
{
|
(n: String, m: MethodNode) =>
|
||||||
RelocationMod.log.info(s"transforming: $tName")
|
mapper.mapMethodName(n, m.name, m.desc) == "func_147805_b",
|
||||||
val (ch1, ch2, tr) = classData(tName)
|
transformBlockRender _
|
||||||
|
)),
|
||||||
|
"net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher" -> ((
|
||||||
|
(_: String, m: MethodNode) => m.name == "renderTileEntity",
|
||||||
|
(n: String, m: MethodNode) =>
|
||||||
|
mapper.mapMethodName(n, m.name, m.desc) == "func_147544_a",
|
||||||
|
transformTERender _
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
val node = new ClassNode
|
var matched = Set[String]()
|
||||||
val reader = new ClassReader(data)
|
|
||||||
reader.accept(node, 0)
|
|
||||||
|
|
||||||
for (m@(_m:MethodNode) <- node.methods)
|
override def transform(name: String, tName: String, data: Array[Byte]) = {
|
||||||
if ((deobfEnv && ch1(name, m)) || (!deobfEnv && ch2(name, m)))
|
if (classData.keys.contains(tName) && !matched.contains(tName)) {
|
||||||
{
|
RelocationMod.log.info(s"transforming: $tName")
|
||||||
RelocationMod.log.info(s"$name $tName ${m.name} ${m.desc}")
|
val (ch1, ch2, tr) = classData(tName)
|
||||||
tr(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
matched += tName
|
val node = new ClassNode
|
||||||
|
val reader = new ClassReader(data)
|
||||||
|
reader.accept(node, 0)
|
||||||
|
|
||||||
val writer = new ClassWriter(ClassWriter.COMPUTE_MAXS)
|
for (m @ (_m: MethodNode) <- node.methods)
|
||||||
node.accept(writer)
|
if ((deobfEnv && ch1(name, m)) || (!deobfEnv && ch2(name, m))) {
|
||||||
writer.toByteArray
|
RelocationMod.log.info(s"$name $tName ${m.name} ${m.desc}")
|
||||||
|
tr(m)
|
||||||
}
|
}
|
||||||
else data
|
|
||||||
}
|
matched += tName
|
||||||
|
|
||||||
|
val writer = new ClassWriter(ClassWriter.COMPUTE_MAXS)
|
||||||
|
node.accept(writer)
|
||||||
|
writer.toByteArray
|
||||||
|
} else data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -18,75 +18,69 @@ import net.minecraft.world.World
|
|||||||
|
|
||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
|
|
||||||
class BlockMovingRow extends InstancedBlock("relocation.blockmovingrow", Material.iron)
|
class BlockMovingRow
|
||||||
{
|
extends InstancedBlock("relocation.blockmovingrow", Material.iron) {
|
||||||
setHardness(-1F)
|
setHardness(-1f)
|
||||||
setStepSound(Block.soundTypeGravel)
|
setStepSound(Block.soundTypeGravel)
|
||||||
setCreativeTab(null)
|
setCreativeTab(null)
|
||||||
addSingleTile(classOf[TileMovingRow])
|
addSingleTile(classOf[TileMovingRow])
|
||||||
}
|
}
|
||||||
|
|
||||||
object TileMovingRow
|
object TileMovingRow {
|
||||||
{
|
def setBlockForRow(w: World, r: BlockRow) {
|
||||||
def setBlockForRow(w:World, r:BlockRow)
|
w.setBlock(r.pos.x, r.pos.y, r.pos.z, RelocationMod.blockMovingRow, 0, 3)
|
||||||
{
|
}
|
||||||
w.setBlock(r.pos.x, r.pos.y, r.pos.z, RelocationMod.blockMovingRow, 0, 3)
|
|
||||||
}
|
def getBoxFor(w: World, r: BlockRow, progress: Double): Cuboid6 = {
|
||||||
|
val p = r.pos.copy.offset(r.moveDir ^ 1)
|
||||||
def getBoxFor(w:World, r:BlockRow, progress:Double):Cuboid6 =
|
val bl = w.getBlock(p.x, p.y, p.z)
|
||||||
{
|
|
||||||
val p = r.pos.copy.offset(r.moveDir^1)
|
if (bl == RelocationMod.blockMovingRow) return Cuboid6.full.copy()
|
||||||
val bl = w.getBlock(p.x, p.y, p.z)
|
|
||||||
|
bl.getCollisionBoundingBoxFromPool(w, p.x, p.y, p.z) match {
|
||||||
if (bl == RelocationMod.blockMovingRow) return Cuboid6.full.copy()
|
case aabb: AxisAlignedBB =>
|
||||||
|
new Cuboid6(aabb)
|
||||||
bl.getCollisionBoundingBoxFromPool(w, p.x, p.y, p.z) match
|
.sub(new Vector3(r.pos))
|
||||||
{
|
.add(new Vector3(BlockCoord.sideOffsets(r.moveDir)) * progress)
|
||||||
case aabb:AxisAlignedBB => new Cuboid6(aabb).sub(new Vector3(r.pos))
|
case _ => Cuboid6.full.copy
|
||||||
.add(new Vector3(BlockCoord.sideOffsets(r.moveDir))*progress)
|
|
||||||
case _ => Cuboid6.full.copy
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TileMovingRow extends InstancedBlockTile
|
class TileMovingRow extends InstancedBlockTile {
|
||||||
{
|
var prevProg = 0.0
|
||||||
var prevProg = 0.0
|
|
||||||
|
|
||||||
override def update()
|
override def update() {
|
||||||
{
|
if (!MovementManager2.isMoving(world, x, y, z)) world.setBlockToAir(x, y, z)
|
||||||
if (!MovementManager2.isMoving(world, x, y, z)) world.setBlockToAir(x, y, z)
|
}
|
||||||
|
|
||||||
|
override def getBlock = RelocationMod.blockMovingRow
|
||||||
|
|
||||||
|
override def getBlockBounds = {
|
||||||
|
val s = MovementManager2.getEnclosedStructure(world, x, y, z)
|
||||||
|
if (s != null) {
|
||||||
|
val r = s.rows.find(_.contains(x, y, z)).get
|
||||||
|
TileMovingRow.getBoxFor(world, r, s.progress)
|
||||||
|
} else Cuboid6.full
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getCollisionBounds = getBlockBounds
|
||||||
|
|
||||||
|
def pushEntities(r: BlockRow, progress: Double) {
|
||||||
|
val box = Cuboid6.full.copy
|
||||||
|
.add(new Vector3(r.preMoveBlocks.head))
|
||||||
|
.add(new Vector3(BlockCoord.sideOffsets(r.moveDir)).multiply(progress))
|
||||||
|
.toAABB
|
||||||
|
|
||||||
|
val dp = (if (progress >= 1.0) progress + 0.1 else progress) - prevProg
|
||||||
|
val d = new Vector3(BlockCoord.sideOffsets(r.moveDir)) * dp
|
||||||
|
world.getEntitiesWithinAABBExcludingEntity(null, box) match {
|
||||||
|
case list: JList[_] =>
|
||||||
|
for (e <- list.asInstanceOf[JList[Entity]])
|
||||||
|
e.moveEntity(d.x, d.y max 0, d.z)
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
override def getBlock = RelocationMod.blockMovingRow
|
prevProg = progress
|
||||||
|
}
|
||||||
override def getBlockBounds =
|
}
|
||||||
{
|
|
||||||
val s = MovementManager2.getEnclosedStructure(world, x, y, z)
|
|
||||||
if (s != null)
|
|
||||||
{
|
|
||||||
val r = s.rows.find(_.contains(x, y, z)).get
|
|
||||||
TileMovingRow.getBoxFor(world, r, s.progress)
|
|
||||||
}
|
|
||||||
else Cuboid6.full
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getCollisionBounds = getBlockBounds
|
|
||||||
|
|
||||||
def pushEntities(r:BlockRow, progress:Double)
|
|
||||||
{
|
|
||||||
val box = Cuboid6.full.copy.add(new Vector3(r.preMoveBlocks.head))
|
|
||||||
.add(new Vector3(BlockCoord.sideOffsets(r.moveDir)).multiply(progress)).toAABB
|
|
||||||
|
|
||||||
val dp = (if (progress >= 1.0) progress+0.1 else progress)-prevProg
|
|
||||||
val d = new Vector3(BlockCoord.sideOffsets(r.moveDir))*dp
|
|
||||||
world.getEntitiesWithinAABBExcludingEntity(null, box) match
|
|
||||||
{
|
|
||||||
case list:JList[_] =>
|
|
||||||
for (e <- list.asInstanceOf[JList[Entity]]) e.moveEntity(d.x, d.y max 0, d.z)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
|
|
||||||
prevProg = progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,58 +11,50 @@ import mrtjp.relocation.handler.RelocationSPH
|
|||||||
import net.minecraftforge.client.event.RenderWorldLastEvent
|
import net.minecraftforge.client.event.RenderWorldLastEvent
|
||||||
import net.minecraftforge.event.world.{ChunkWatchEvent, WorldEvent}
|
import net.minecraftforge.event.world.{ChunkWatchEvent, WorldEvent}
|
||||||
|
|
||||||
object RelocationEventHandler
|
object RelocationEventHandler {
|
||||||
{
|
@SubscribeEvent
|
||||||
@SubscribeEvent
|
def worldUnload(event: WorldEvent.Unload) {
|
||||||
def worldUnload(event:WorldEvent.Unload)
|
RelocationSPH.onWorldUnload(event.world)
|
||||||
{
|
MovementManager2.onWorldUnload(event.world)
|
||||||
RelocationSPH.onWorldUnload(event.world)
|
}
|
||||||
MovementManager2.onWorldUnload(event.world)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
def chunkWatch(event:ChunkWatchEvent.Watch)
|
def chunkWatch(event: ChunkWatchEvent.Watch) {
|
||||||
{
|
RelocationSPH.onChunkWatch(event.player, event.chunk)
|
||||||
RelocationSPH.onChunkWatch(event.player, event.chunk)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
def chunkUnwatch(event:ChunkWatchEvent.UnWatch)
|
def chunkUnwatch(event: ChunkWatchEvent.UnWatch) {
|
||||||
{
|
RelocationSPH.onChunkUnWatch(event.player, event.chunk)
|
||||||
RelocationSPH.onChunkUnWatch(event.player, event.chunk)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
def serverTick(event:TickEvent.ServerTickEvent)
|
def serverTick(event: TickEvent.ServerTickEvent) {
|
||||||
{
|
if (event.phase == TickEvent.Phase.END) {
|
||||||
if (event.phase == TickEvent.Phase.END)
|
RelocationSPH.onTickEnd()
|
||||||
{
|
MovementManager2.onTick(false)
|
||||||
RelocationSPH.onTickEnd()
|
|
||||||
MovementManager2.onTick(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object RelocationClientEventHandler
|
object RelocationClientEventHandler {
|
||||||
{
|
@SubscribeEvent
|
||||||
@SubscribeEvent
|
def onRenderTick(e: TickEvent.RenderTickEvent) {
|
||||||
def onRenderTick(e:TickEvent.RenderTickEvent)
|
if (e.phase == TickEvent.Phase.START)
|
||||||
{
|
MovingRenderer.onPreRenderTick(e.renderTickTime)
|
||||||
if (e.phase == TickEvent.Phase.START)
|
else MovingRenderer.onPostRenderTick()
|
||||||
MovingRenderer.onPreRenderTick(e.renderTickTime)
|
}
|
||||||
else MovingRenderer.onPostRenderTick()
|
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
def onRenderWorld(e:RenderWorldLastEvent)
|
def onRenderWorld(e: RenderWorldLastEvent) {
|
||||||
{
|
MovingRenderer.onRenderWorldEvent()
|
||||||
MovingRenderer.onRenderWorldEvent()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
def clientTick(event:TickEvent.ClientTickEvent)
|
def clientTick(event: TickEvent.ClientTickEvent) {
|
||||||
{
|
if (event.phase == TickEvent.Phase.END) {
|
||||||
if (event.phase == TickEvent.Phase.END)
|
MovementManager2.onTick(true)
|
||||||
MovementManager2.onTick(true)
|
MovingRenderer.onTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -12,28 +12,53 @@ import net.minecraft.client.Minecraft
|
|||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
|
||||||
object ASMHacks
|
object ASMHacks {
|
||||||
{
|
@SideOnly(Side.CLIENT)
|
||||||
@SideOnly(Side.CLIENT)
|
def renderTileEntityAt(
|
||||||
def renderTileEntityAt(te:TileEntity, x:Double, y:Double, z:Double, tick:Float):Unit =
|
te: TileEntity,
|
||||||
{
|
x: Double,
|
||||||
if (MovementManager2.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord))
|
y: Double,
|
||||||
{
|
z: Double,
|
||||||
val s = MovementManager2.getEnclosedStructure(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)
|
tick: Float
|
||||||
val vec = MovingRenderer.renderPos(s, tick)
|
): Unit = {
|
||||||
|
if (
|
||||||
|
MovementManager2.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)
|
||||||
|
) {
|
||||||
|
val s = MovementManager2.getEnclosedStructure(
|
||||||
|
te.getWorldObj,
|
||||||
|
te.xCoord,
|
||||||
|
te.yCoord,
|
||||||
|
te.zCoord
|
||||||
|
)
|
||||||
|
val vec = MovingRenderer.renderPos(s, tick)
|
||||||
|
|
||||||
TileEntityRendererDispatcher.instance.renderTileEntityAt(te,
|
TileEntityRendererDispatcher.instance.renderTileEntityAt(
|
||||||
x+MathLib.clamp(-1F, 1F, vec.x.toFloat),
|
te,
|
||||||
y+MathLib.clamp(-1F, 1F, vec.y.toFloat),
|
x + MathLib.clamp(-1f, 1f, vec.x.toFloat),
|
||||||
z+MathLib.clamp(-1F, 1F, vec.z.toFloat), tick)
|
y + MathLib.clamp(-1f, 1f, vec.y.toFloat),
|
||||||
}
|
z + MathLib.clamp(-1f, 1f, vec.z.toFloat),
|
||||||
else TileEntityRendererDispatcher.instance.renderTileEntityAt(te, x, y, z, tick)
|
tick
|
||||||
}
|
)
|
||||||
|
} else
|
||||||
|
TileEntityRendererDispatcher.instance.renderTileEntityAt(
|
||||||
|
te,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
tick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
def getRenderType(block:Block, x:Int, y:Int, z:Int):Int =
|
def getRenderType(block: Block, x: Int, y: Int, z: Int): Int = {
|
||||||
{
|
if (
|
||||||
if (MovingRenderer.renderHack && MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) -1
|
MovingRenderer.renderHack && MovementManager2.isMoving(
|
||||||
else block.getRenderType
|
Minecraft.getMinecraft.theWorld,
|
||||||
}
|
x,
|
||||||
}
|
y,
|
||||||
|
z
|
||||||
|
)
|
||||||
|
) -1
|
||||||
|
else block.getRenderType
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,30 +9,30 @@ import mrtjp.relocation.api.{ITileMover, RelocationAPI}
|
|||||||
import mrtjp.relocation.{MovementManager2, MovingTileRegistry}
|
import mrtjp.relocation.{MovementManager2, MovingTileRegistry}
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
|
|
||||||
object RelocationAPI_Impl extends RelocationAPI
|
object RelocationAPI_Impl extends RelocationAPI {
|
||||||
{
|
var isPreInit = true
|
||||||
var isPreInit = true
|
|
||||||
|
|
||||||
override def registerTileMover(name:String, desc:String, handler:ITileMover) =
|
override def registerTileMover(
|
||||||
{
|
name: String,
|
||||||
assert(isPreInit)
|
desc: String,
|
||||||
MovingTileRegistry.registerTileMover(name, desc, handler)
|
handler: ITileMover
|
||||||
}
|
) = {
|
||||||
|
assert(isPreInit)
|
||||||
|
MovingTileRegistry.registerTileMover(name, desc, handler)
|
||||||
|
}
|
||||||
|
|
||||||
override def registerPreferredMover(key:String, value:String)
|
override def registerPreferredMover(key: String, value: String) {
|
||||||
{
|
assert(isPreInit)
|
||||||
assert(isPreInit)
|
MovingTileRegistry.preferredMovers :+= (key, value)
|
||||||
MovingTileRegistry.preferredMovers :+= (key, value)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def registerMandatoryMover(key:String, value:String)
|
override def registerMandatoryMover(key: String, value: String) {
|
||||||
{
|
assert(isPreInit)
|
||||||
assert(isPreInit)
|
MovingTileRegistry.mandatoryMovers :+= (key, value)
|
||||||
MovingTileRegistry.mandatoryMovers :+= (key, value)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def getRelocator = Relocator_Impl
|
override def getRelocator = Relocator_Impl
|
||||||
|
|
||||||
override def isMoving(world:World, x:Int, y:Int, z:Int) =
|
override def isMoving(world: World, x: Int, y: Int, z: Int) =
|
||||||
MovementManager2.isMoving(world, x, y, z)
|
MovementManager2.isMoving(world, x, y, z)
|
||||||
}
|
}
|
||||||
@@ -15,107 +15,108 @@ import net.minecraft.world.World
|
|||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
import scala.collection.mutable.{Set => MSet, Stack => MStack}
|
import scala.collection.mutable.{Set => MSet, Stack => MStack}
|
||||||
|
|
||||||
class RelocationRun
|
class RelocationRun {
|
||||||
{
|
var world: World = null
|
||||||
var world:World = null
|
var dir = -1
|
||||||
var dir = -1
|
var speed = 0.0
|
||||||
var speed = 0.0
|
var callback: IMovementCallback = null
|
||||||
var callback:IMovementCallback = null
|
val blocks = MSet[BlockCoord]()
|
||||||
val blocks = MSet[BlockCoord]()
|
|
||||||
|
|
||||||
def clear()
|
def clear() {
|
||||||
{
|
world = null
|
||||||
world = null
|
dir = -1
|
||||||
dir = -1
|
speed = 0
|
||||||
speed = 0
|
callback = null
|
||||||
callback = null
|
blocks.clear()
|
||||||
blocks.clear()
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Relocator_Impl extends Relocator
|
object Relocator_Impl extends Relocator {
|
||||||
{
|
var mainStack = new MStack[RelocationRun]()
|
||||||
var mainStack = new MStack[RelocationRun]()
|
var tempStack = new MStack[RelocationRun]()
|
||||||
var tempStack = new MStack[RelocationRun]()
|
|
||||||
|
|
||||||
private def assertState()
|
private def assertState() {
|
||||||
{
|
if (mainStack.isEmpty)
|
||||||
if (mainStack.isEmpty) throw new IllegalStateException("Relocator stack is empty.")
|
throw new IllegalStateException("Relocator stack is empty.")
|
||||||
}
|
}
|
||||||
|
|
||||||
override def push()
|
override def push() {
|
||||||
{
|
val r = if (tempStack.isEmpty) new RelocationRun else tempStack.pop()
|
||||||
val r = if (tempStack.isEmpty) new RelocationRun else tempStack.pop()
|
mainStack.push(r)
|
||||||
mainStack.push(r)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def pop()
|
override def pop() {
|
||||||
{
|
assertState()
|
||||||
assertState()
|
val r = mainStack.pop()
|
||||||
val r = mainStack.pop()
|
r.clear()
|
||||||
r.clear()
|
tempStack.push(r)
|
||||||
tempStack.push(r)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def setWorld(world:World)
|
override def setWorld(world: World) {
|
||||||
{
|
assertState()
|
||||||
assertState()
|
val top = mainStack.top
|
||||||
val top = mainStack.top
|
if (top.world != null) throw new IllegalStateException("World already set.")
|
||||||
if (top.world != null) throw new IllegalStateException("World already set.")
|
top.world = world
|
||||||
top.world = world
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def setDirection(dir:Int)
|
override def setDirection(dir: Int) {
|
||||||
{
|
assertState()
|
||||||
assertState()
|
val top = mainStack.top
|
||||||
val top = mainStack.top
|
if (top.dir != -1) throw new IllegalStateException("Direction already set.")
|
||||||
if (top.dir != -1) throw new IllegalStateException("Direction already set.")
|
top.dir = dir
|
||||||
top.dir = dir
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def setSpeed(speed:Double)
|
override def setSpeed(speed: Double) {
|
||||||
{
|
assertState()
|
||||||
assertState()
|
val top = mainStack.top
|
||||||
val top = mainStack.top
|
if (top.speed > 0) throw new IllegalStateException("Speed already set.")
|
||||||
if (top.speed > 0) throw new IllegalStateException("Speed already set.")
|
top.speed = speed
|
||||||
top.speed = speed
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
override def setCallback(callback: IMovementCallback) {
|
||||||
|
assertState()
|
||||||
|
val top = mainStack.top
|
||||||
|
if (top.callback != null)
|
||||||
|
throw new IllegalStateException("Callback already set.")
|
||||||
|
top.callback = callback
|
||||||
|
}
|
||||||
|
|
||||||
override def setCallback(callback:IMovementCallback)
|
override def addBlock(x: Int, y: Int, z: Int) {
|
||||||
{
|
assertState()
|
||||||
assertState()
|
mainStack.top.blocks += new BlockCoord(x, y, z)
|
||||||
val top = mainStack.top
|
}
|
||||||
if (top.callback != null) throw new IllegalStateException("Callback already set.")
|
|
||||||
top.callback = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
override def addBlock(x:Int, y:Int, z:Int)
|
override def addBlock(bc: BlockPos) {
|
||||||
{
|
addBlock(bc.x, bc.y, bc.z)
|
||||||
assertState()
|
}
|
||||||
mainStack.top.blocks += new BlockCoord(x, y, z)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def addBlock(bc:BlockPos)
|
override def addBlocks(blocks: JSet[BlockPos]) {
|
||||||
{
|
for (b <- blocks) addBlock(b)
|
||||||
addBlock(bc.x, bc.y, bc.z)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override def addBlocks(blocks:JSet[BlockPos])
|
override def execute() = {
|
||||||
{
|
assertState()
|
||||||
for (b <- blocks) addBlock(b)
|
val top = mainStack.top
|
||||||
}
|
if (top.world == null)
|
||||||
|
throw new IllegalStateException("World must be set before move.")
|
||||||
override def execute() =
|
if (top.world.isRemote)
|
||||||
{
|
throw new IllegalStateException(
|
||||||
assertState()
|
"Movements cannot be executed client-side."
|
||||||
val top = mainStack.top
|
)
|
||||||
if (top.world == null) throw new IllegalStateException("World must be set before move.")
|
if (top.dir == -1)
|
||||||
if (top.world.isRemote) throw new IllegalStateException("Movements cannot be executed client-side.")
|
throw new IllegalStateException("Direction must be set before move.")
|
||||||
if (top.dir == -1) throw new IllegalStateException("Direction must be set before move.")
|
if (top.speed <= 0)
|
||||||
if (top.speed <= 0) throw new IllegalStateException("Speed must be greater than 0.")
|
throw new IllegalStateException("Speed must be greater than 0.")
|
||||||
if (top.speed >= 1) throw new IllegalStateException("Speed must be less than 1.")
|
if (top.speed >= 1)
|
||||||
if (top.blocks.isEmpty) throw new IllegalStateException("No blocks queued for move.")
|
throw new IllegalStateException("Speed must be less than 1.")
|
||||||
MovementManager2.tryStartMove(top.world, top.blocks.toSet, top.dir, top.speed, top.callback)
|
if (top.blocks.isEmpty)
|
||||||
}
|
throw new IllegalStateException("No blocks queued for move.")
|
||||||
}
|
MovementManager2.tryStartMove(
|
||||||
|
top.world,
|
||||||
|
top.blocks.toSet,
|
||||||
|
top.dir,
|
||||||
|
top.speed,
|
||||||
|
top.callback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,94 +6,109 @@
|
|||||||
package mrtjp.relocation.handler
|
package mrtjp.relocation.handler
|
||||||
|
|
||||||
import cpw.mods.fml.common.Mod
|
import cpw.mods.fml.common.Mod
|
||||||
import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent}
|
import cpw.mods.fml.common.event.{
|
||||||
|
FMLInitializationEvent,
|
||||||
|
FMLPostInitializationEvent,
|
||||||
|
FMLPreInitializationEvent
|
||||||
|
}
|
||||||
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
||||||
import mrtjp.relocation.api._
|
import mrtjp.relocation.api._
|
||||||
import mrtjp.relocation.{BlockMovingRow, MovingTileRegistry}
|
import mrtjp.relocation.{BlockMovingRow, MovingTileRegistry}
|
||||||
|
import mrtjp.relocation.Tags
|
||||||
import net.minecraft.client.gui.GuiScreen
|
import net.minecraft.client.gui.GuiScreen
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
|
|
||||||
@Mod(modid = RelocationMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.relocation.handler.GuiConfigFactory", acceptedMinecraftVersions = "[1.7.10]", dependencies = "required-after:MrTJPCoreMod", name = RelocationMod.modName, version = RelocationMod.version)
|
@Mod(
|
||||||
object RelocationMod
|
modid = RelocationMod.modID,
|
||||||
{
|
useMetadata = true,
|
||||||
RelocationAPI.instance = RelocationAPI_Impl
|
modLanguage = "scala",
|
||||||
|
guiFactory = "mrtjp.relocation.handler.GuiConfigFactory",
|
||||||
|
acceptedMinecraftVersions = "[1.7.10]",
|
||||||
|
dependencies = "required-after:MrTJPCoreMod",
|
||||||
|
name = RelocationMod.modName,
|
||||||
|
version = RelocationMod.version
|
||||||
|
)
|
||||||
|
object RelocationMod {
|
||||||
|
RelocationAPI.instance = RelocationAPI_Impl
|
||||||
|
|
||||||
final val modID = "ForgeRelocation"
|
final val modID = "ForgeRelocation"
|
||||||
final val modName = "ForgeRelocation"
|
final val modName = "ForgeRelocation"
|
||||||
final val version = "GRADLETOKEN_VERSION"
|
final val version = Tags.VERSION
|
||||||
|
|
||||||
val log = LogManager.getFormatterLogger(modID)
|
val log = LogManager.getFormatterLogger(modID)
|
||||||
|
|
||||||
var blockMovingRow:BlockMovingRow = _
|
var blockMovingRow: BlockMovingRow = _
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def preInit(event:FMLPreInitializationEvent)
|
def preInit(event: FMLPreInitializationEvent) {
|
||||||
{
|
RelocationProxy.preinit()
|
||||||
RelocationProxy.preinit()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def init(event:FMLInitializationEvent)
|
def init(event: FMLInitializationEvent) {
|
||||||
{
|
RelocationAPI_Impl.isPreInit = false
|
||||||
RelocationAPI_Impl.isPreInit = false
|
RelocationConfig.loadConfig()
|
||||||
RelocationConfig.loadConfig()
|
RelocationProxy.init()
|
||||||
RelocationProxy.init()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
def postInit(event:FMLPostInitializationEvent)
|
def postInit(event: FMLPostInitializationEvent) {
|
||||||
{
|
RelocationProxy.postinit()
|
||||||
RelocationProxy.postinit()
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RelocationConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "ForgeRelocation", RelocationConfig.config)
|
class RelocationConfigGui(parent: GuiScreen)
|
||||||
class GuiConfigFactory extends TModGuiFactory
|
extends SpecialConfigGui(parent, "ForgeRelocation", RelocationConfig.config)
|
||||||
{
|
class GuiConfigFactory extends TModGuiFactory {
|
||||||
override def mainConfigGuiClass() = classOf[RelocationConfigGui]
|
override def mainConfigGuiClass() = classOf[RelocationConfigGui]
|
||||||
}
|
}
|
||||||
|
|
||||||
object RelocationConfig extends ModConfig("ForgeRelocation")
|
object RelocationConfig extends ModConfig("ForgeRelocation") {
|
||||||
{
|
var moveLimit = 2048
|
||||||
var moveLimit = 2048
|
|
||||||
|
|
||||||
var moverMap = Array(
|
var moverMap = Array(
|
||||||
"default -> saveload"
|
"default -> saveload"
|
||||||
|
)
|
||||||
|
|
||||||
|
override protected def initValues() {
|
||||||
|
val general = new BaseCategory("General", "Basic settings")
|
||||||
|
moveLimit = general.put(
|
||||||
|
"moveLimit",
|
||||||
|
moveLimit,
|
||||||
|
"Maximum amount of blocks that can be moved at once."
|
||||||
)
|
)
|
||||||
|
|
||||||
override protected def initValues()
|
val movers = new BaseCategory("Tile Movers", buildMoverDesc)
|
||||||
{
|
moverMap = movers.put("mover registry", moverMap)
|
||||||
val general = new BaseCategory("General", "Basic settings")
|
moverMap = movers.put(
|
||||||
moveLimit = general.put("moveLimit", moveLimit, "Maximum amount of blocks that can be moved at once.")
|
"mover registry",
|
||||||
|
MovingTileRegistry.parseAndSetMovers(moverMap),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val movers = new BaseCategory("Tile Movers", buildMoverDesc)
|
def buildMoverDesc: String = {
|
||||||
moverMap = movers.put("mover registry", moverMap)
|
var s =
|
||||||
moverMap = movers.put("mover registry", MovingTileRegistry.parseAndSetMovers(moverMap), true)
|
"Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" +
|
||||||
|
"the syntax key -> value. \n"
|
||||||
|
s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" +
|
||||||
|
"blocks.\n"
|
||||||
|
s += "Possible keys: \n"
|
||||||
|
s += " 'default' - to assign default handler. \n"
|
||||||
|
s += " 'mod:<modID>' - to assign every block from a mod. \n"
|
||||||
|
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||||
|
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||||
|
|
||||||
|
s += "\nAvailable tile movers:\n"
|
||||||
|
for ((k, v) <- MovingTileRegistry.moverDescMap)
|
||||||
|
s += " '" + k + "' - " + v + "\n"
|
||||||
|
|
||||||
|
if (MovingTileRegistry.mandatoryMovers.nonEmpty) {
|
||||||
|
s += "\nMovers locked via API:\n"
|
||||||
|
for ((k, v) <- MovingTileRegistry.mandatoryMovers)
|
||||||
|
s += " " + k + " -> " + v + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildMoverDesc:String =
|
s
|
||||||
{
|
}
|
||||||
var s = "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" +
|
|
||||||
"the syntax key -> value. \n"
|
|
||||||
s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" +
|
|
||||||
"blocks.\n"
|
|
||||||
s += "Possible keys: \n"
|
|
||||||
s += " 'default' - to assign default handler. \n"
|
|
||||||
s += " 'mod:<modID>' - to assign every block from a mod. \n"
|
|
||||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
|
||||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
|
||||||
|
|
||||||
s += "\nAvailable tile movers:\n"
|
|
||||||
for ((k, v) <- MovingTileRegistry.moverDescMap)
|
|
||||||
s += " '"+k+"' - "+v+"\n"
|
|
||||||
|
|
||||||
if (MovingTileRegistry.mandatoryMovers.nonEmpty)
|
|
||||||
{
|
|
||||||
s += "\nMovers locked via API:\n"
|
|
||||||
for ((k, v) <- MovingTileRegistry.mandatoryMovers)
|
|
||||||
s += " "+k+" -> "+v+"\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,10 @@ import java.util.{LinkedList => JLinkedList, List => JList}
|
|||||||
|
|
||||||
import codechicken.lib.data.MCDataOutputWrapper
|
import codechicken.lib.data.MCDataOutputWrapper
|
||||||
import codechicken.lib.packet.PacketCustom
|
import codechicken.lib.packet.PacketCustom
|
||||||
import codechicken.lib.packet.PacketCustom.{IClientPacketHandler, IServerPacketHandler}
|
import codechicken.lib.packet.PacketCustom.{
|
||||||
|
IClientPacketHandler,
|
||||||
|
IServerPacketHandler
|
||||||
|
}
|
||||||
import mrtjp.relocation.MovementManager2
|
import mrtjp.relocation.MovementManager2
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
||||||
@@ -21,163 +24,168 @@ import net.minecraft.util.ChatComponentText
|
|||||||
import net.minecraft.world.{ChunkCoordIntPair, World}
|
import net.minecraft.world.{ChunkCoordIntPair, World}
|
||||||
|
|
||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
import scala.collection.mutable.{HashMap => MHashMap, Map => MMap, MultiMap => MMultiMap, Set => MSet}
|
import scala.collection.mutable.{
|
||||||
|
HashMap => MHashMap,
|
||||||
/**
|
Map => MMap,
|
||||||
* Tweaked version of Chickenbones' compressed end-of-tick tile data stream.
|
MultiMap => MMultiMap,
|
||||||
*/
|
Set => MSet
|
||||||
class RelocationPH
|
|
||||||
{
|
|
||||||
val channel = RelocationMod
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object RelocationCPH extends RelocationPH with IClientPacketHandler
|
/** Tweaked version of Chickenbones' compressed end-of-tick tile data stream.
|
||||||
{
|
*/
|
||||||
def handlePacket(packet: PacketCustom, mc: Minecraft, netHandler:INetHandlerPlayClient) {
|
class RelocationPH {
|
||||||
try {
|
val channel = RelocationMod
|
||||||
packet.getType match {
|
|
||||||
case 1 => handleChunkDesc(packet, mc.theWorld)
|
|
||||||
case 2 => handleChunkData(packet, mc.theWorld)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
case e:RuntimeException if e.getMessage.startsWith("DC: ") =>
|
|
||||||
netHandler.handleDisconnect(new S40PacketDisconnect(new ChatComponentText(e.getMessage.substring(4))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def handleChunkData(packet:PacketCustom, world:World)
|
|
||||||
{
|
|
||||||
var i = packet.readUByte()
|
|
||||||
while (i != 255) {
|
|
||||||
MovementManager2.read(world, packet, i)
|
|
||||||
i = packet.readUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def handleChunkDesc(packet:PacketCustom, world:World)
|
|
||||||
{
|
|
||||||
MovementManager2.readDesc(world, packet)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object RelocationSPH extends RelocationPH with IServerPacketHandler
|
object RelocationCPH extends RelocationPH with IClientPacketHandler {
|
||||||
{
|
def handlePacket(
|
||||||
class MCByteStream(bout:ByteArrayOutputStream) extends MCDataOutputWrapper(new DataOutputStream(bout))
|
packet: PacketCustom,
|
||||||
{
|
mc: Minecraft,
|
||||||
def getBytes = bout.toByteArray
|
netHandler: INetHandlerPlayClient
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
packet.getType match {
|
||||||
|
case 1 => handleChunkDesc(packet, mc.theWorld)
|
||||||
|
case 2 => handleChunkData(packet, mc.theWorld)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case e: RuntimeException if e.getMessage.startsWith("DC: ") =>
|
||||||
|
netHandler.handleDisconnect(
|
||||||
|
new S40PacketDisconnect(
|
||||||
|
new ChatComponentText(e.getMessage.substring(4))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def handlePacket(packetCustom:PacketCustom, entityPlayerMP:EntityPlayerMP, iNetHandlerPlayServer:INetHandlerPlayServer){}
|
def handleChunkData(packet: PacketCustom, world: World) {
|
||||||
|
var i = packet.readUByte()
|
||||||
|
while (i != 255) {
|
||||||
|
MovementManager2.read(world, packet, i)
|
||||||
|
i = packet.readUByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val updateMap = MMap[World, MMap[Set[ChunkCoordIntPair], MCByteStream]]()
|
def handleChunkDesc(packet: PacketCustom, world: World) {
|
||||||
private val chunkWatchers = new MHashMap[Int, MSet[ChunkCoordIntPair]] with MMultiMap[Int, ChunkCoordIntPair]
|
MovementManager2.readDesc(world, packet)
|
||||||
private val newWatchers = MMap[Int, JLinkedList[ChunkCoordIntPair]]()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def onTickEnd()
|
object RelocationSPH extends RelocationPH with IServerPacketHandler {
|
||||||
{
|
class MCByteStream(bout: ByteArrayOutputStream)
|
||||||
|
extends MCDataOutputWrapper(new DataOutputStream(bout)) {
|
||||||
|
def getBytes = bout.toByteArray
|
||||||
|
}
|
||||||
|
|
||||||
|
override def handlePacket(
|
||||||
|
packetCustom: PacketCustom,
|
||||||
|
entityPlayerMP: EntityPlayerMP,
|
||||||
|
iNetHandlerPlayServer: INetHandlerPlayServer
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private val updateMap =
|
||||||
|
MMap[World, MMap[Set[ChunkCoordIntPair], MCByteStream]]()
|
||||||
|
private val chunkWatchers = new MHashMap[Int, MSet[ChunkCoordIntPair]]
|
||||||
|
with MMultiMap[Int, ChunkCoordIntPair]
|
||||||
|
private val newWatchers = MMap[Int, JLinkedList[ChunkCoordIntPair]]()
|
||||||
|
|
||||||
|
def onTickEnd() {
|
||||||
|
val players = getServerPlayers
|
||||||
|
sendData(players)
|
||||||
|
sendDesc(players)
|
||||||
|
}
|
||||||
|
|
||||||
|
def onWorldUnload(world: World) {
|
||||||
|
if (!world.isRemote) {
|
||||||
|
updateMap.remove(world)
|
||||||
|
if (chunkWatchers.nonEmpty) {
|
||||||
val players = getServerPlayers
|
val players = getServerPlayers
|
||||||
sendData(players)
|
for (p <- players)
|
||||||
sendDesc(players)
|
if (p.worldObj.provider.dimensionId == world.provider.dimensionId)
|
||||||
|
chunkWatchers.remove(p.getEntityId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def onWorldUnload(world:World)
|
def onChunkWatch(p: EntityPlayer, c: ChunkCoordIntPair) {
|
||||||
{
|
newWatchers.getOrElseUpdate(p.getEntityId, new JLinkedList).add(c)
|
||||||
if(!world.isRemote)
|
}
|
||||||
{
|
|
||||||
updateMap.remove(world)
|
def onChunkUnWatch(p: EntityPlayer, c: ChunkCoordIntPair) {
|
||||||
if (chunkWatchers.nonEmpty)
|
newWatchers.get(p.getEntityId) match {
|
||||||
{
|
case Some(chunks) => chunks.remove(c)
|
||||||
val players = getServerPlayers
|
case _ =>
|
||||||
for (p <- players) if (p.worldObj.provider.dimensionId == world.provider.dimensionId)
|
}
|
||||||
chunkWatchers.remove(p.getEntityId)
|
chunkWatchers.removeBinding(p.getEntityId, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def getServerPlayers: Seq[EntityPlayerMP] =
|
||||||
|
MinecraftServer.getServer.getConfigurationManager.playerEntityList
|
||||||
|
.asInstanceOf[JList[EntityPlayerMP]]
|
||||||
|
|
||||||
|
private def sendData(players: Seq[EntityPlayerMP]) {
|
||||||
|
for (p <- players if chunkWatchers.containsKey(p.getEntityId)) {
|
||||||
|
updateMap.get(p.worldObj) match {
|
||||||
|
case Some(m) if m.nonEmpty =>
|
||||||
|
val chunks = chunkWatchers(p.getEntityId)
|
||||||
|
val packet = new PacketCustom(channel, 2).compress()
|
||||||
|
var send = false
|
||||||
|
for ((uchunks, stream) <- m if uchunks.exists(chunks.contains)) {
|
||||||
|
send = true
|
||||||
|
packet.writeByteArray(stream.getBytes)
|
||||||
|
packet.writeByte(255) // terminator
|
||||||
|
}
|
||||||
|
if (send) packet.sendToPlayer(p)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateMap.foreach(_._2.clear())
|
||||||
|
}
|
||||||
|
|
||||||
|
private def sendDesc(players: Seq[EntityPlayerMP]) {
|
||||||
|
for (p <- players if newWatchers.containsKey(p.getEntityId)) {
|
||||||
|
val watched = newWatchers(p.getEntityId)
|
||||||
|
val pkt = getDescPacket(p.worldObj, watched.toSet)
|
||||||
|
if (pkt != null) pkt.sendToPlayer(p)
|
||||||
|
for (c <- watched)
|
||||||
|
chunkWatchers.addBinding(p.getEntityId, c)
|
||||||
|
}
|
||||||
|
newWatchers.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private def getDescPacket(
|
||||||
|
world: World,
|
||||||
|
chunks: Set[ChunkCoordIntPair]
|
||||||
|
): PacketCustom = {
|
||||||
|
val packet = new PacketCustom(channel, 1)
|
||||||
|
if (MovementManager2.writeDesc(world, chunks, packet)) packet else null
|
||||||
|
}
|
||||||
|
|
||||||
|
def forceSendData() {
|
||||||
|
sendData(getServerPlayers)
|
||||||
|
}
|
||||||
|
|
||||||
|
def forceSendDesc() {
|
||||||
|
sendDesc(getServerPlayers)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getStream(world: World, chunks: Set[ChunkCoordIntPair], key: Int) = {
|
||||||
|
updateMap
|
||||||
|
.getOrElseUpdate(
|
||||||
|
world, {
|
||||||
|
if (world.isRemote)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot use RelocationSPH on a client world"
|
||||||
|
)
|
||||||
|
MMap()
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
|
.getOrElseUpdate(
|
||||||
def onChunkWatch(p:EntityPlayer, c:ChunkCoordIntPair)
|
chunks, {
|
||||||
{
|
val s = new MCByteStream(new ByteArrayOutputStream)
|
||||||
newWatchers.getOrElseUpdate(p.getEntityId, new JLinkedList).add(c)
|
s.writeByte(key)
|
||||||
}
|
s
|
||||||
|
|
||||||
def onChunkUnWatch(p:EntityPlayer, c:ChunkCoordIntPair)
|
|
||||||
{
|
|
||||||
newWatchers.get(p.getEntityId) match
|
|
||||||
{
|
|
||||||
case Some(chunks) => chunks.remove(c)
|
|
||||||
case _ =>
|
|
||||||
}
|
}
|
||||||
chunkWatchers.removeBinding(p.getEntityId, c)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private def getServerPlayers:Seq[EntityPlayerMP] =
|
|
||||||
MinecraftServer.getServer.getConfigurationManager.playerEntityList
|
|
||||||
.asInstanceOf[JList[EntityPlayerMP]]
|
|
||||||
|
|
||||||
private def sendData(players:Seq[EntityPlayerMP])
|
|
||||||
{
|
|
||||||
for(p <- players if chunkWatchers.containsKey(p.getEntityId))
|
|
||||||
{
|
|
||||||
updateMap.get(p.worldObj) match
|
|
||||||
{
|
|
||||||
case Some(m) if m.nonEmpty =>
|
|
||||||
val chunks = chunkWatchers(p.getEntityId)
|
|
||||||
val packet = new PacketCustom(channel, 2).compress()
|
|
||||||
var send = false
|
|
||||||
for((uchunks, stream) <- m if uchunks.exists(chunks.contains))
|
|
||||||
{
|
|
||||||
send = true
|
|
||||||
packet.writeByteArray(stream.getBytes)
|
|
||||||
packet.writeByte(255) //terminator
|
|
||||||
}
|
|
||||||
if(send) packet.sendToPlayer(p)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateMap.foreach(_._2.clear())
|
|
||||||
}
|
|
||||||
|
|
||||||
private def sendDesc(players:Seq[EntityPlayerMP])
|
|
||||||
{
|
|
||||||
for(p <- players if newWatchers.containsKey(p.getEntityId))
|
|
||||||
{
|
|
||||||
val watched = newWatchers(p.getEntityId)
|
|
||||||
val pkt = getDescPacket(p.worldObj, watched.toSet)
|
|
||||||
if(pkt != null) pkt.sendToPlayer(p)
|
|
||||||
for(c <- watched)
|
|
||||||
chunkWatchers.addBinding(p.getEntityId, c)
|
|
||||||
}
|
|
||||||
newWatchers.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
private def getDescPacket(world:World, chunks:Set[ChunkCoordIntPair]):PacketCustom =
|
|
||||||
{
|
|
||||||
val packet = new PacketCustom(channel, 1)
|
|
||||||
if(MovementManager2.writeDesc(world, chunks, packet)) packet else null
|
|
||||||
}
|
|
||||||
|
|
||||||
def forceSendData()
|
|
||||||
{
|
|
||||||
sendData(getServerPlayers)
|
|
||||||
}
|
|
||||||
|
|
||||||
def forceSendDesc()
|
|
||||||
{
|
|
||||||
sendDesc(getServerPlayers)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getStream(world:World, chunks:Set[ChunkCoordIntPair], key:Int) =
|
|
||||||
{
|
|
||||||
updateMap.getOrElseUpdate(world,
|
|
||||||
{
|
|
||||||
if(world.isRemote)
|
|
||||||
throw new IllegalArgumentException("Cannot use RelocationSPH on a client world")
|
|
||||||
MMap()
|
|
||||||
}).getOrElseUpdate(chunks,
|
|
||||||
{
|
|
||||||
val s = new MCByteStream(new ByteArrayOutputStream)
|
|
||||||
s.writeByte(key)
|
|
||||||
s
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,66 +12,66 @@ import mrtjp.relocation._
|
|||||||
import mrtjp.relocation.api.RelocationAPI.{instance => API}
|
import mrtjp.relocation.api.RelocationAPI.{instance => API}
|
||||||
import net.minecraftforge.common.MinecraftForge
|
import net.minecraftforge.common.MinecraftForge
|
||||||
|
|
||||||
class RelocationProxy_server
|
class RelocationProxy_server {
|
||||||
{
|
def preinit() {
|
||||||
def preinit()
|
RelocationMod.blockMovingRow = new BlockMovingRow
|
||||||
{
|
|
||||||
RelocationMod.blockMovingRow = new BlockMovingRow
|
|
||||||
|
|
||||||
API.registerTileMover("saveload",
|
API.registerTileMover(
|
||||||
"Saves the tile and then reloads it in the next position. Reliable but CPU intensive.",
|
"saveload",
|
||||||
new SaveLoadTileMover)
|
"Saves the tile and then reloads it in the next position. Reliable but CPU intensive.",
|
||||||
|
new SaveLoadTileMover
|
||||||
|
)
|
||||||
|
|
||||||
API.registerTileMover("coordpush",
|
API.registerTileMover(
|
||||||
"Physically changes the location of tiles. Works if tiles do not cache their position.",
|
"coordpush",
|
||||||
new CoordPushTileMover)
|
"Physically changes the location of tiles. Works if tiles do not cache their position.",
|
||||||
|
new CoordPushTileMover
|
||||||
|
)
|
||||||
|
|
||||||
API.registerTileMover("static", "Setting this disables movement for the specified block.",
|
API.registerTileMover(
|
||||||
new StaticTileMover)
|
"static",
|
||||||
|
"Setting this disables movement for the specified block.",
|
||||||
|
new StaticTileMover
|
||||||
|
)
|
||||||
|
|
||||||
API.registerPreferredMover("default", "saveload")
|
API.registerPreferredMover("default", "saveload")
|
||||||
API.registerPreferredMover("mod:minecraft", "coordpush")
|
API.registerPreferredMover("mod:minecraft", "coordpush")
|
||||||
API.registerPreferredMover("mod:Relocation", "coordpush")
|
API.registerPreferredMover("mod:Relocation", "coordpush")
|
||||||
API.registerPreferredMover("mod:ComputerCraft", "coordpush")
|
API.registerPreferredMover("mod:ComputerCraft", "coordpush")
|
||||||
API.registerPreferredMover("mod:EnderStorage", "coordpush")
|
API.registerPreferredMover("mod:EnderStorage", "coordpush")
|
||||||
API.registerPreferredMover("mod:ChickenChunks", "coordpush")
|
API.registerPreferredMover("mod:ChickenChunks", "coordpush")
|
||||||
API.registerPreferredMover("mod:Translocator", "coordpush")
|
API.registerPreferredMover("mod:Translocator", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Compatibility", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Compatibility", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Core", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Core", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Expansion", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Expansion", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Exploration", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Exploration", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Fabrication", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Fabrication", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Illumination", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Illumination", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Integration", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Integration", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Transmission", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Transmission", "coordpush")
|
||||||
API.registerPreferredMover("mod:ProjRed|Transportation", "coordpush")
|
API.registerPreferredMover("mod:ProjRed|Transportation", "coordpush")
|
||||||
}
|
}
|
||||||
|
|
||||||
def init()
|
def init() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
def postinit()
|
def postinit() {
|
||||||
{
|
PacketCustom.assignHandler(RelocationSPH.channel, RelocationSPH)
|
||||||
PacketCustom.assignHandler(RelocationSPH.channel, RelocationSPH)
|
|
||||||
|
|
||||||
FMLCommonHandler.instance.bus.register(RelocationEventHandler)
|
FMLCommonHandler.instance.bus.register(RelocationEventHandler)
|
||||||
MinecraftForge.EVENT_BUS.register(RelocationEventHandler)
|
MinecraftForge.EVENT_BUS.register(RelocationEventHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RelocationProxy_client extends RelocationProxy_server
|
class RelocationProxy_client extends RelocationProxy_server {
|
||||||
{
|
@SideOnly(Side.CLIENT)
|
||||||
@SideOnly(Side.CLIENT)
|
override def postinit() {
|
||||||
override def postinit()
|
super.postinit()
|
||||||
{
|
PacketCustom.assignHandler(RelocationCPH.channel, RelocationCPH)
|
||||||
super.postinit()
|
|
||||||
PacketCustom.assignHandler(RelocationCPH.channel, RelocationCPH)
|
|
||||||
|
|
||||||
FMLCommonHandler.instance.bus.register(RelocationClientEventHandler)
|
FMLCommonHandler.instance.bus.register(RelocationClientEventHandler)
|
||||||
MinecraftForge.EVENT_BUS.register(RelocationClientEventHandler)
|
MinecraftForge.EVENT_BUS.register(RelocationClientEventHandler)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object RelocationProxy extends RelocationProxy_client
|
object RelocationProxy extends RelocationProxy_client
|
||||||
@@ -17,403 +17,559 @@ import net.minecraft.client.Minecraft
|
|||||||
import net.minecraft.init.Blocks
|
import net.minecraft.init.Blocks
|
||||||
import net.minecraft.world.{ChunkCoordIntPair, World}
|
import net.minecraft.world.{ChunkCoordIntPair, World}
|
||||||
import net.minecraftforge.common.DimensionManager
|
import net.minecraftforge.common.DimensionManager
|
||||||
|
import scala.collection.mutable.{
|
||||||
|
HashMap => MHashMap,
|
||||||
|
MultiMap => MMultiMap,
|
||||||
|
Set => MSet
|
||||||
|
}
|
||||||
|
|
||||||
import scala.collection.mutable.{HashMap => MHashMap, MultiMap => MMultiMap, Set => MSet}
|
|
||||||
import scala.ref.WeakReference
|
import scala.ref.WeakReference
|
||||||
|
|
||||||
object MovementManager2
|
object MovementManager2 {
|
||||||
{
|
val serverRelocations = new WorldStructsMap
|
||||||
val serverRelocations = MHashMap[Int, WorldStructs]()
|
val clientRelocations = new WorldStructsMap
|
||||||
val clientRelocations = MHashMap[Int, WorldStructs]()
|
|
||||||
|
|
||||||
def relocationMap(isClient:Boolean) = if (isClient) clientRelocations else serverRelocations
|
def relocationMap(isClient: Boolean) =
|
||||||
|
if (isClient) clientRelocations else serverRelocations
|
||||||
|
|
||||||
def getWorldStructs(w:World) =
|
def getWorldStructs(w: World) =
|
||||||
relocationMap(w.isRemote).getOrElseUpdate(w.provider.dimensionId, new WorldStructs)
|
relocationMap(w.isRemote).getOrCreate(w.provider.dimensionId)
|
||||||
|
|
||||||
def getWorld(dim:Int, isClient:Boolean) =
|
def getWorld(dim: Int, isClient: Boolean) =
|
||||||
if (!isClient) DimensionManager.getWorld(dim)
|
if (!isClient) DimensionManager.getWorld(dim)
|
||||||
else getClientWorld(dim)
|
else getClientWorld(dim)
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
private def getClientWorld(dim:Int):World =
|
private def getClientWorld(dim: Int): World = {
|
||||||
{
|
val w = Minecraft.getMinecraft.theWorld
|
||||||
val w = Minecraft.getMinecraft.theWorld
|
if (w.provider.dimensionId == dim) w else null
|
||||||
if (w.provider.dimensionId == dim) w else null
|
}
|
||||||
|
|
||||||
|
def writeDesc(w: World, chunks: Set[ChunkCoordIntPair], out: MCDataOutput) = {
|
||||||
|
var send = false
|
||||||
|
for (
|
||||||
|
s <- getWorldStructs(w).structs if s.getChunks.exists(chunks.contains)
|
||||||
|
) {
|
||||||
|
send = true
|
||||||
|
out.writeShort(s.id)
|
||||||
|
s.writeDesc(out)
|
||||||
|
}
|
||||||
|
if (send) out.writeShort(Short.MaxValue)
|
||||||
|
send
|
||||||
|
}
|
||||||
|
|
||||||
|
def readDesc(w: World, in: MCDataInput) {
|
||||||
|
var id = in.readUShort()
|
||||||
|
while (id != Short.MaxValue) {
|
||||||
|
val struct = new BlockStruct
|
||||||
|
struct.id = id
|
||||||
|
struct.readDesc(in)
|
||||||
|
addStructToWorld(w, struct)
|
||||||
|
id = in.readUShort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def read(w: World, in: MCDataInput, key: Int) = key match {
|
||||||
|
case 1 =>
|
||||||
|
val struct = new BlockStruct
|
||||||
|
struct.id = in.readUShort()
|
||||||
|
struct.readDesc(in)
|
||||||
|
addStructToWorld(w, struct)
|
||||||
|
for (b <- struct.allBlocks) // rerender all moving blocks
|
||||||
|
w.func_147479_m(b.x, b.y, b.z)
|
||||||
|
case 2 =>
|
||||||
|
val id = in.readUShort()
|
||||||
|
getWorldStructs(w).structs.find(_.id == id) match {
|
||||||
|
case Some(struct) => clientCycleMove(w, struct)
|
||||||
|
case None =>
|
||||||
|
throw new RuntimeException(
|
||||||
|
s"DC: Moving structure with id $id was not found client-side."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
throw new RuntimeException(
|
||||||
|
s"DC: Packet with ID $key was not handled. " +
|
||||||
|
s"Skipped ${in.asInstanceOf[PacketCustom].getByteBuf.array().length} bytes."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendStruct(w: World, struct: BlockStruct) {
|
||||||
|
val out = RelocationSPH.getStream(w, struct.getChunks, 1)
|
||||||
|
out.writeShort(struct.id)
|
||||||
|
struct.writeDesc(out)
|
||||||
|
RelocationSPH.forceSendData()
|
||||||
|
}
|
||||||
|
|
||||||
|
def sendCycle(w: World, struct: BlockStruct) {
|
||||||
|
RelocationSPH.getStream(w, struct.getChunks, 2).writeShort(struct.id)
|
||||||
|
RelocationSPH.forceSendData()
|
||||||
|
}
|
||||||
|
|
||||||
|
def isMoving(w: World, x: Int, y: Int, z: Int) = {
|
||||||
|
if (w == null) false
|
||||||
|
else getWorldStructs(w).contains(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
def addStructToWorld(w: World, b: BlockStruct) {
|
||||||
|
getWorldStructs(w).addStruct(b)
|
||||||
|
b.onAdded(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getEnclosedStructure(w: World, x: Int, y: Int, z: Int) =
|
||||||
|
getWorldStructs(w).structs.find(_.contains(x, y, z)).orNull
|
||||||
|
|
||||||
|
def tryStartMove(
|
||||||
|
w: World,
|
||||||
|
blocks: Set[BlockCoord],
|
||||||
|
moveDir: Int,
|
||||||
|
speed: Double,
|
||||||
|
c: IMovementCallback
|
||||||
|
): Boolean = {
|
||||||
|
if (blocks.size > RelocationConfig.moveLimit) return false
|
||||||
|
if (
|
||||||
|
blocks.exists { b =>
|
||||||
|
val block = w.getBlock(b.x, b.y, b.z)
|
||||||
|
block != null && block.getBlockHardness(w, b.x, b.y, b.z) < 0
|
||||||
|
}
|
||||||
|
) return false
|
||||||
|
|
||||||
|
val map = new MHashMap[(Int, Int), MSet[Int]]
|
||||||
|
with MMultiMap[(Int, Int), Int]
|
||||||
|
for (b <- blocks)
|
||||||
|
map.addBinding(MathLib.normal(b, moveDir), MathLib.basis(b, moveDir))
|
||||||
|
|
||||||
|
val shift = if ((moveDir & 1) == 1) 1 else -1
|
||||||
|
val rowB = Array.newBuilder[BlockRow]
|
||||||
|
for (normal <- map.keys) {
|
||||||
|
val line = map(normal).toArray
|
||||||
|
val sline =
|
||||||
|
if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse)
|
||||||
|
for ((basis, size) <- MathLib.splitLine(sline, shift)) {
|
||||||
|
val c = MathLib.rhrAxis(moveDir, normal, basis + shift)
|
||||||
|
rowB += new BlockRow(c, moveDir, size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def writeDesc(w:World, chunks:Set[ChunkCoordIntPair], out:MCDataOutput) =
|
val rows = rowB.result()
|
||||||
{
|
if (
|
||||||
var send = false
|
rows.exists(row =>
|
||||||
for (s <- getWorldStructs(w).structs if s.getChunks.exists(chunks.contains))
|
!MovingTileRegistry.canRunOverBlock(w, row.pos.x, row.pos.y, row.pos.z)
|
||||||
{
|
)
|
||||||
send = true
|
) return false
|
||||||
out.writeShort(s.id)
|
for (r <- rows) TileMovingRow.setBlockForRow(w, r)
|
||||||
s.writeDesc(out)
|
|
||||||
|
val struct = new BlockStruct
|
||||||
|
struct.id = BlockStruct.claimID()
|
||||||
|
struct.speed = speed
|
||||||
|
struct.rows = rows
|
||||||
|
struct.callback = WeakReference(c)
|
||||||
|
addStructToWorld(w, struct)
|
||||||
|
sendStruct(w, struct)
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
def onTick(isClient: Boolean) {
|
||||||
|
val map = relocationMap(isClient)
|
||||||
|
map.foreach { (dim, ws) =>
|
||||||
|
if (ws.nonEmpty) {
|
||||||
|
ws.pushAll()
|
||||||
|
val world = getWorld(dim, isClient)
|
||||||
|
if (world != null)
|
||||||
|
for (bs <- ws.structs)
|
||||||
|
for (br <- bs.rows)
|
||||||
|
br.pushEntities(world, bs.progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isClient) {
|
||||||
|
map.foreach { (dim, ws) =>
|
||||||
|
val finished = ws.removeFinished()
|
||||||
|
if (finished.nonEmpty) {
|
||||||
|
val w = getWorld(dim, false)
|
||||||
|
if (w != null) for (s <- finished) {
|
||||||
|
cycleMove(w, s)
|
||||||
|
sendCycle(w, s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (send) out.writeShort(Short.MaxValue)
|
}
|
||||||
send
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def readDesc(w:World, in:MCDataInput)
|
def onWorldUnload(w: World) {
|
||||||
{
|
getWorldStructs(w).clear()
|
||||||
var id = in.readUShort()
|
}
|
||||||
while (id != Short.MaxValue)
|
|
||||||
{
|
|
||||||
val struct = new BlockStruct
|
|
||||||
struct.id = id
|
|
||||||
struct.readDesc(in)
|
|
||||||
addStructToWorld(w, struct)
|
|
||||||
id = in.readUShort()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def read(w:World, in:MCDataInput, key:Int) = key match
|
def clientCycleMove(w: World, struct: BlockStruct) {
|
||||||
{
|
getWorldStructs(w).removeStruct(struct)
|
||||||
case 1 =>
|
struct.rows.foreach(_.pushEntities(w, 1.0))
|
||||||
val struct = new BlockStruct
|
cycleMove(w, struct)
|
||||||
struct.id = in.readUShort()
|
}
|
||||||
struct.readDesc(in)
|
|
||||||
addStructToWorld(w, struct)
|
|
||||||
for (b <- struct.allBlocks) //rerender all moving blocks
|
|
||||||
w.func_147479_m(b.x, b.y, b.z)
|
|
||||||
case 2 =>
|
|
||||||
val id = in.readUShort()
|
|
||||||
getWorldStructs(w).structs.find(_.id == id) match
|
|
||||||
{
|
|
||||||
case Some(struct) => clientCycleMove(w, struct)
|
|
||||||
case None => throw new RuntimeException(s"DC: Moving structure with id $id was not found client-side.")
|
|
||||||
}
|
|
||||||
case _ => throw new RuntimeException(s"DC: Packet with ID $key was not handled. " +
|
|
||||||
s"Skipped ${in.asInstanceOf[PacketCustom].getByteBuf.array().length} bytes.")
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendStruct(w:World, struct:BlockStruct)
|
def cycleMove(w: World, struct: BlockStruct) {
|
||||||
{
|
struct.doMove(w)
|
||||||
val out = RelocationSPH.getStream(w, struct.getChunks, 1)
|
struct.postMove(w)
|
||||||
out.writeShort(struct.id)
|
struct.endMove(w)
|
||||||
struct.writeDesc(out)
|
|
||||||
RelocationSPH.forceSendData()
|
|
||||||
}
|
|
||||||
|
|
||||||
def sendCycle(w:World, struct:BlockStruct)
|
Utils.rescheduleTicks(
|
||||||
{
|
w,
|
||||||
RelocationSPH.getStream(w, struct.getChunks, 2).writeShort(struct.id)
|
struct.preMoveBlocks,
|
||||||
RelocationSPH.forceSendData()
|
struct.allBlocks,
|
||||||
}
|
struct.moveDir
|
||||||
|
)
|
||||||
|
|
||||||
def isMoving(w:World, x:Int, y:Int, z:Int) = getWorldStructs(w).contains(x, y, z)
|
val changes = MSet[BlockCoord]()
|
||||||
|
for (r <- struct.rows) r.cacheChanges(w, changes)
|
||||||
|
for (bc <- changes)
|
||||||
|
w.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air)
|
||||||
|
|
||||||
def addStructToWorld(w:World, b:BlockStruct)
|
Utils.rerenderBlocks(w, struct.preMoveBlocks)
|
||||||
{
|
}
|
||||||
getWorldStructs(w).addStruct(b)
|
|
||||||
b.onAdded(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getEnclosedStructure(w:World, x:Int, y:Int, z:Int) =
|
|
||||||
getWorldStructs(w).structs.find(_.contains(x, y, z)).orNull
|
|
||||||
|
|
||||||
def tryStartMove(w:World, blocks:Set[BlockCoord], moveDir:Int, speed:Double, c:IMovementCallback):Boolean =
|
|
||||||
{
|
|
||||||
if (blocks.size > RelocationConfig.moveLimit) return false
|
|
||||||
|
|
||||||
val map = new MHashMap[(Int, Int), MSet[Int]] with MMultiMap[(Int, Int), Int]
|
|
||||||
for (b <- blocks) map.addBinding(MathLib.normal(b, moveDir), MathLib.basis(b, moveDir))
|
|
||||||
|
|
||||||
val shift = if ((moveDir&1) == 1) 1 else -1
|
|
||||||
val rowB = Set.newBuilder[BlockRow]
|
|
||||||
for (normal <- map.keys)
|
|
||||||
{
|
|
||||||
val line = map(normal).toArray
|
|
||||||
val sline = if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse)
|
|
||||||
for ((basis, size) <- MathLib.splitLine(sline, shift))
|
|
||||||
{
|
|
||||||
val c = MathLib.rhrAxis(moveDir, normal, basis+shift)
|
|
||||||
rowB += new BlockRow(c, moveDir, size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val rows = rowB.result()
|
|
||||||
if (rows.exists(row => !MovingTileRegistry.canRunOverBlock(w, row.pos.x, row.pos.y, row.pos.z))) return false
|
|
||||||
for (r <- rows) TileMovingRow.setBlockForRow(w, r)
|
|
||||||
|
|
||||||
val struct = new BlockStruct
|
|
||||||
struct.id = BlockStruct.claimID()
|
|
||||||
struct.speed = speed
|
|
||||||
struct.rows = rows
|
|
||||||
struct.callback = WeakReference(c)
|
|
||||||
addStructToWorld(w, struct)
|
|
||||||
sendStruct(w, struct)
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
def onTick(isClient:Boolean)
|
|
||||||
{
|
|
||||||
val map = relocationMap(isClient)
|
|
||||||
for ((dim, ws) <- map) if (ws.nonEmpty)
|
|
||||||
{
|
|
||||||
ws.pushAll()
|
|
||||||
val world = getWorld(dim, isClient)
|
|
||||||
if (world != null) for (bs <- ws.structs) for (br <- bs.rows)
|
|
||||||
br.pushEntities(world, bs.progress)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isClient)
|
|
||||||
{
|
|
||||||
val fin = map.map(pair => (pair._1, pair._2.removeFinished())).filter(_._2.nonEmpty)
|
|
||||||
for ((dim, b) <- fin)
|
|
||||||
{
|
|
||||||
val w = getWorld(dim, false)
|
|
||||||
if (w != null) for (s <- b)
|
|
||||||
{
|
|
||||||
cycleMove(w, s)
|
|
||||||
sendCycle(w, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def onWorldUnload(w:World)
|
|
||||||
{
|
|
||||||
getWorldStructs(w).clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
def clientCycleMove(w:World, struct:BlockStruct)
|
|
||||||
{
|
|
||||||
getWorldStructs(w).removeStruct(struct)
|
|
||||||
struct.rows.foreach(_.pushEntities(w, 1.0))
|
|
||||||
cycleMove(w, struct)
|
|
||||||
}
|
|
||||||
|
|
||||||
def cycleMove(w:World, struct:BlockStruct)
|
|
||||||
{
|
|
||||||
struct.doMove(w)
|
|
||||||
struct.postMove(w)
|
|
||||||
struct.endMove(w)
|
|
||||||
|
|
||||||
Utils.rescheduleTicks(w, struct.preMoveBlocks, struct.allBlocks, struct.moveDir)
|
|
||||||
|
|
||||||
val changes = MSet[BlockCoord]()
|
|
||||||
for (r <- struct.rows) r.cacheChanges(w, changes)
|
|
||||||
for (bc <- changes) w.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air)
|
|
||||||
|
|
||||||
Utils.rerenderBlocks(w, struct.preMoveBlocks)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorldStructs
|
class WorldStructsMap {
|
||||||
{
|
private var dims = new Array[Int](4)
|
||||||
var structs:Set[BlockStruct] = Set.empty
|
private var structs = new Array[WorldStructs](4)
|
||||||
|
private var size = 0
|
||||||
|
|
||||||
def isEmpty = structs.isEmpty
|
def getOrCreate(dim: Int): WorldStructs = synchronized {
|
||||||
|
var i = 0
|
||||||
def nonEmpty = !isEmpty
|
while (i < size) {
|
||||||
|
if (dims(i) == dim) return structs(i)
|
||||||
def contains(x:Int, y:Int, z:Int) = structs.exists(_.contains(x, y, z))
|
i += 1
|
||||||
|
|
||||||
def addStruct(b:BlockStruct){ structs += b }
|
|
||||||
|
|
||||||
def pushAll(){ structs.foreach(_.push()) }
|
|
||||||
|
|
||||||
def removeFinished() =
|
|
||||||
{
|
|
||||||
val finished = structs.filter(_.isFinished)
|
|
||||||
structs = structs.filterNot(_.isFinished)
|
|
||||||
finished
|
|
||||||
}
|
}
|
||||||
|
val ws = new WorldStructs
|
||||||
def removeStruct(s:BlockStruct)
|
if (size == dims.length) {
|
||||||
{
|
val nd = new Array[Int](dims.length * 2)
|
||||||
structs = structs.filterNot(_ == s)
|
val ns = new Array[WorldStructs](dims.length * 2)
|
||||||
|
System.arraycopy(dims, 0, nd, 0, size)
|
||||||
|
System.arraycopy(structs, 0, ns, 0, size)
|
||||||
|
dims = nd
|
||||||
|
structs = ns
|
||||||
}
|
}
|
||||||
|
dims(size) = dim
|
||||||
|
structs(size) = ws
|
||||||
|
size += 1
|
||||||
|
ws
|
||||||
|
}
|
||||||
|
|
||||||
def clear(){structs = Set.empty}
|
def foreach(f: (Int, WorldStructs) => Unit) {
|
||||||
|
val n = synchronized { size }
|
||||||
def getChunks:Set[ChunkCoordIntPair] =
|
val ds = new Array[Int](n)
|
||||||
{
|
val ss = new Array[WorldStructs](n)
|
||||||
structs.flatMap(_.getChunks)
|
synchronized {
|
||||||
|
System.arraycopy(dims, 0, ds, 0, n)
|
||||||
|
System.arraycopy(structs, 0, ss, 0, n)
|
||||||
}
|
}
|
||||||
|
var i = 0
|
||||||
|
while (i < n) {
|
||||||
|
f(ds(i), ss(i))
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object BlockStruct
|
class WorldStructs {
|
||||||
{
|
private val noStructs = new Array[BlockStruct](0)
|
||||||
private var maxID = 0
|
private var structsArr = new Array[BlockStruct](4)
|
||||||
def claimID() =
|
private var numStructs = 0
|
||||||
{
|
|
||||||
if (maxID < 32765) maxID += 1//little less than Short.MaxValue (reserved for terminator)
|
def isEmpty = synchronized { numStructs == 0 }
|
||||||
else maxID = 0
|
|
||||||
maxID
|
def nonEmpty = synchronized { numStructs > 0 }
|
||||||
|
|
||||||
|
def contains(x: Int, y: Int, z: Int): Boolean = synchronized {
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
if (structsArr(i).contains(x, y, z)) return true
|
||||||
|
i += 1
|
||||||
}
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
def addStruct(b: BlockStruct): Unit = synchronized {
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
if (structsArr(i).id == b.id) return
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
if (numStructs == structsArr.length) {
|
||||||
|
val ns = new Array[BlockStruct](structsArr.length * 2)
|
||||||
|
System.arraycopy(structsArr, 0, ns, 0, numStructs)
|
||||||
|
structsArr = ns
|
||||||
|
}
|
||||||
|
structsArr(numStructs) = b
|
||||||
|
numStructs += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
def pushAll() = synchronized {
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
structsArr(i).push()
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def removeFinished(): Array[BlockStruct] = synchronized {
|
||||||
|
var nf = 0
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
if (structsArr(i).isFinished) nf += 1
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nf == 0) return noStructs
|
||||||
|
|
||||||
|
val finished = new Array[BlockStruct](nf)
|
||||||
|
var finish = 0
|
||||||
|
var keep = 0
|
||||||
|
i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
val s = structsArr(i)
|
||||||
|
if (s.isFinished) {
|
||||||
|
finished(finish) = s
|
||||||
|
finish += 1
|
||||||
|
} else {
|
||||||
|
structsArr(keep) = s
|
||||||
|
keep += 1
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
var j = keep
|
||||||
|
while (j < numStructs) {
|
||||||
|
structsArr(j) = null
|
||||||
|
j += 1
|
||||||
|
}
|
||||||
|
numStructs = keep
|
||||||
|
finished
|
||||||
|
}
|
||||||
|
|
||||||
|
def removeStruct(s: BlockStruct) = synchronized {
|
||||||
|
var keep = 0
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
val cur = structsArr(i)
|
||||||
|
if (cur != s) {
|
||||||
|
structsArr(keep) = cur
|
||||||
|
keep += 1
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
var j = keep
|
||||||
|
while (j < numStructs) {
|
||||||
|
structsArr(j) = null
|
||||||
|
j += 1
|
||||||
|
}
|
||||||
|
numStructs = keep
|
||||||
|
}
|
||||||
|
|
||||||
|
def clear() = synchronized {
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
structsArr(i) = null
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
numStructs = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
def foreachStruct(f: BlockStruct => Unit) = synchronized {
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
f(structsArr(i))
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def structs: Array[BlockStruct] = synchronized {
|
||||||
|
java.util.Arrays.copyOf(structsArr, numStructs)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getChunks: Set[ChunkCoordIntPair] = synchronized {
|
||||||
|
val c = Set.newBuilder[ChunkCoordIntPair]
|
||||||
|
var i = 0
|
||||||
|
while (i < numStructs) {
|
||||||
|
c ++= structsArr(i).getChunks
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
c.result()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoveDesc(b:WeakReference[BlockStruct]) extends IMovementDescriptor
|
object BlockStruct {
|
||||||
{
|
private var maxID = 0
|
||||||
def this(b:BlockStruct) = this(new WeakReference(b))
|
def claimID() = {
|
||||||
|
if (maxID < 32765)
|
||||||
override def isMoving = b match {
|
maxID += 1 // little less than Short.MaxValue (reserved for terminator)
|
||||||
case WeakReference(b:BlockStruct) => !b.isFinished
|
else maxID = 0
|
||||||
case _ => false
|
maxID
|
||||||
}
|
}
|
||||||
|
|
||||||
override def getProgress = b match {
|
|
||||||
case WeakReference(b:BlockStruct) => b.progress
|
|
||||||
case _ => -1
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getSize = b match {
|
|
||||||
case WeakReference(b:BlockStruct) => b.allBlocks.size
|
|
||||||
case _ => 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlockStruct
|
class MoveDesc(b: WeakReference[BlockStruct]) extends IMovementDescriptor {
|
||||||
{
|
def this(b: BlockStruct) = this(new WeakReference(b))
|
||||||
var id = -1
|
|
||||||
var speed = 1/16D
|
|
||||||
var rows:Set[BlockRow] = Set.empty
|
|
||||||
var callback = WeakReference[IMovementCallback](null)
|
|
||||||
|
|
||||||
var progress = 0.0D
|
override def isMoving = b match {
|
||||||
|
case WeakReference(b: BlockStruct) => !b.isFinished
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
lazy val allBlocks = rows.flatMap(_.allBlocks)
|
override def getProgress = b match {
|
||||||
lazy val preMoveBlocks = rows.flatMap(_.preMoveBlocks)
|
case WeakReference(b: BlockStruct) => b.progress
|
||||||
lazy val postMoveBlocks = rows.flatMap(_.postMoveBlocks)
|
case _ => -1
|
||||||
|
}
|
||||||
|
|
||||||
def moveDir = rows.head.moveDir
|
override def getSize = b match {
|
||||||
|
case WeakReference(b: BlockStruct) => b.allBlocks.size
|
||||||
def contains(x:Int, y:Int, z:Int) = rows.exists(_.contains(x, y, z))
|
case _ => 0
|
||||||
|
}
|
||||||
def push(){ progress = math.min(1.0, progress+speed) }
|
|
||||||
|
|
||||||
def isFinished = progress >= 1.0D
|
|
||||||
|
|
||||||
def getChunks:Set[ChunkCoordIntPair] =
|
|
||||||
{
|
|
||||||
val c = Set.newBuilder[ChunkCoordIntPair]
|
|
||||||
for (b <- allBlocks)
|
|
||||||
c += new ChunkCoordIntPair(b.x>>4, b.z>>4)
|
|
||||||
c.result()
|
|
||||||
}
|
|
||||||
|
|
||||||
def onAdded(w:World)
|
|
||||||
{
|
|
||||||
if (!w.isRemote) callback match
|
|
||||||
{
|
|
||||||
case WeakReference(c) =>
|
|
||||||
c.setDescriptor(new MoveDesc(this))
|
|
||||||
c.onMovementStarted()
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def doMove(w:World)
|
|
||||||
{
|
|
||||||
for (r <- rows) r.doMove(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
def postMove(w:World)
|
|
||||||
{
|
|
||||||
for (r <- rows) r.postMove(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
def endMove(w:World)
|
|
||||||
{
|
|
||||||
for (r <- rows) r.endMove(w)
|
|
||||||
if (!w.isRemote) callback match
|
|
||||||
{
|
|
||||||
case WeakReference(c) => c.onMovementFinished()
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def equals(obj:scala.Any) = obj match
|
|
||||||
{
|
|
||||||
case that:BlockStruct => id == that.id
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
|
|
||||||
def writeDesc(out:MCDataOutput)
|
|
||||||
{
|
|
||||||
out.writeFloat(progress.toFloat)
|
|
||||||
out.writeFloat(speed.toFloat)
|
|
||||||
out.writeByte(rows.size)
|
|
||||||
for (r <- rows)
|
|
||||||
{
|
|
||||||
out.writeLong(WorldLib.packCoords(r.pos))
|
|
||||||
out.writeByte(r.moveDir)
|
|
||||||
out.writeShort(r.size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def readDesc(in:MCDataInput)
|
|
||||||
{
|
|
||||||
progress = in.readFloat()
|
|
||||||
speed = in.readFloat()
|
|
||||||
val rb = Set.newBuilder[BlockRow]
|
|
||||||
for (i <- 0 until in.readUByte())
|
|
||||||
rb += new BlockRow(WorldLib.unpackCoords(in.readLong()), in.readUByte(), in.readUShort())
|
|
||||||
rows = rb.result()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BlockRow(val pos:BlockCoord, val moveDir:Int, val size:Int)
|
class BlockStruct {
|
||||||
{
|
var id = -1
|
||||||
val allBlocks = 0 to size map {i => pos.copy.offset(moveDir^1, i)}
|
var speed = 1 / 16d
|
||||||
val preMoveBlocks = allBlocks drop 1
|
var rows: Array[BlockRow] = Array.empty
|
||||||
val postMoveBlocks = allBlocks dropRight 1
|
var callback = WeakReference[IMovementCallback](null)
|
||||||
|
|
||||||
def contains(x:Int, y:Int, z:Int) =
|
var progress = 0.0d
|
||||||
{
|
|
||||||
import MathLib.{basis, normal, shift}
|
|
||||||
|
|
||||||
import math.{max, min}
|
lazy val allBlocks: Set[BlockCoord] = rows.iterator.flatMap(_.allBlocks).toSet
|
||||||
|
lazy val preMoveBlocks: Set[BlockCoord] =
|
||||||
|
rows.iterator.flatMap(_.preMoveBlocks).toSet
|
||||||
|
lazy val postMoveBlocks: Set[BlockCoord] =
|
||||||
|
rows.iterator.flatMap(_.postMoveBlocks).toSet
|
||||||
|
|
||||||
if (normal(x, y, z, moveDir) == normal(pos, moveDir))
|
def moveDir = rows(0).moveDir
|
||||||
{
|
|
||||||
val b1 = basis(pos, moveDir)
|
def contains(x: Int, y: Int, z: Int): Boolean = {
|
||||||
val b2 = b1+size*shift(moveDir^1)
|
var i = 0
|
||||||
min(b1, b2) to max(b1, b2) contains basis(x, y, z, moveDir)
|
while (i < rows.length) {
|
||||||
}
|
if (rows(i).contains(x, y, z)) return true
|
||||||
else false
|
i += 1
|
||||||
}
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
def pushEntities(w:World, progress:Double)
|
def push() { progress = math.min(1.0, progress + speed) }
|
||||||
{
|
|
||||||
WorldLib.uncheckedGetTileEntity(w, pos.x, pos.y, pos.z) match
|
def isFinished = progress >= 1.0d
|
||||||
{
|
|
||||||
case te:TileMovingRow => te.pushEntities(this, progress)
|
def getChunks: Set[ChunkCoordIntPair] = {
|
||||||
case _ =>
|
val c = Set.newBuilder[ChunkCoordIntPair]
|
||||||
}
|
for (b <- allBlocks)
|
||||||
|
c += new ChunkCoordIntPair(b.x >> 4, b.z >> 4)
|
||||||
|
c.result()
|
||||||
|
}
|
||||||
|
|
||||||
|
def onAdded(w: World) {
|
||||||
|
if (!w.isRemote) callback match {
|
||||||
|
case WeakReference(c) =>
|
||||||
|
c.setDescriptor(new MoveDesc(this))
|
||||||
|
c.onMovementStarted()
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def doMove(w:World)
|
def doMove(w: World) {
|
||||||
{
|
for (r <- rows) r.doMove(w)
|
||||||
if (pos.y < 0 || pos.y >= 256) return
|
}
|
||||||
|
|
||||||
w.removeTileEntity(pos.x, pos.y, pos.z)
|
def postMove(w: World) {
|
||||||
WorldLib.uncheckedSetBlock(w, pos.x, pos.y, pos.z, Blocks.air, 0) //Remove movement block
|
for (r <- rows) r.postMove(w)
|
||||||
|
}
|
||||||
|
|
||||||
for (b <- preMoveBlocks)
|
def endMove(w: World) {
|
||||||
MovingTileRegistry.move(w, b.x, b.y, b.z, moveDir)
|
for (r <- rows) r.endMove(w)
|
||||||
|
if (!w.isRemote) callback match {
|
||||||
|
case WeakReference(c) => c.onMovementFinished()
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def postMove(w:World)
|
override def equals(obj: scala.Any) = obj match {
|
||||||
{
|
case that: BlockStruct => id == that.id
|
||||||
for (b <- postMoveBlocks)
|
case _ => false
|
||||||
MovingTileRegistry.postMove(w, b.x, b.y, b.z)
|
}
|
||||||
|
|
||||||
|
override def hashCode() = id
|
||||||
|
|
||||||
|
def writeDesc(out: MCDataOutput) {
|
||||||
|
out.writeFloat(progress.toFloat)
|
||||||
|
out.writeFloat(speed.toFloat)
|
||||||
|
out.writeByte(rows.length)
|
||||||
|
for (r <- rows) {
|
||||||
|
out.writeLong(WorldLib.packCoords(r.pos))
|
||||||
|
out.writeByte(r.moveDir)
|
||||||
|
out.writeShort(r.size)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def endMove(w:World){}
|
def readDesc(in: MCDataInput) {
|
||||||
|
progress = in.readFloat()
|
||||||
|
speed = in.readFloat()
|
||||||
|
val rb = Array.newBuilder[BlockRow]
|
||||||
|
for (i <- 0 until in.readUByte())
|
||||||
|
rb += new BlockRow(
|
||||||
|
WorldLib.unpackCoords(in.readLong()),
|
||||||
|
in.readUByte(),
|
||||||
|
in.readUShort()
|
||||||
|
)
|
||||||
|
rows = rb.result()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def cacheChanges(w:World, changes:MSet[BlockCoord])
|
class BlockRow(val pos: BlockCoord, val moveDir: Int, val size: Int) {
|
||||||
{
|
val allBlocks = 0 to size map { i => pos.copy.offset(moveDir ^ 1, i) }
|
||||||
for (i <- 0 to size)
|
val preMoveBlocks = allBlocks drop 1
|
||||||
{
|
val postMoveBlocks = allBlocks dropRight 1
|
||||||
val c = pos.copy.offset(moveDir^1, i)
|
|
||||||
changes += c
|
def contains(x: Int, y: Int, z: Int) = {
|
||||||
for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s^1))
|
import MathLib.{basis, normal, shift}
|
||||||
changes += c.copy.offset(s).offset(s1)
|
|
||||||
}
|
if (normal(x, y, z, moveDir) == normal(pos, moveDir)) {
|
||||||
|
val b1 = basis(pos, moveDir)
|
||||||
|
val b2 = b1 + size * shift(moveDir ^ 1)
|
||||||
|
val b = basis(x, y, z, moveDir)
|
||||||
|
b >= math.min(b1, b2) && b <= math.max(b1, b2)
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
|
||||||
|
def pushEntities(w: World, progress: Double) {
|
||||||
|
WorldLib.uncheckedGetTileEntity(w, pos.x, pos.y, pos.z) match {
|
||||||
|
case te: TileMovingRow => te.pushEntities(this, progress)
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def doMove(w: World) {
|
||||||
|
if (pos.y < 0 || pos.y >= 256) return
|
||||||
|
|
||||||
|
w.removeTileEntity(pos.x, pos.y, pos.z)
|
||||||
|
WorldLib.uncheckedSetBlock(
|
||||||
|
w,
|
||||||
|
pos.x,
|
||||||
|
pos.y,
|
||||||
|
pos.z,
|
||||||
|
Blocks.air,
|
||||||
|
0
|
||||||
|
) // Remove movement block
|
||||||
|
|
||||||
|
for (b <- preMoveBlocks)
|
||||||
|
MovingTileRegistry.move(w, b.x, b.y, b.z, moveDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
def postMove(w: World) {
|
||||||
|
for (b <- postMoveBlocks)
|
||||||
|
MovingTileRegistry.postMove(w, b.x, b.y, b.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
def endMove(w: World) {}
|
||||||
|
|
||||||
|
def cacheChanges(w: World, changes: MSet[BlockCoord]) {
|
||||||
|
for (i <- 0 to size) {
|
||||||
|
val c = pos.copy.offset(moveDir ^ 1, i)
|
||||||
|
changes += c
|
||||||
|
for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s ^ 1))
|
||||||
|
changes += c.copy.offset(s).offset(s1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,176 +20,166 @@ import net.minecraft.world.World
|
|||||||
|
|
||||||
import scala.collection.immutable.ListMap
|
import scala.collection.immutable.ListMap
|
||||||
|
|
||||||
object MovingTileRegistry extends ITileMover
|
object MovingTileRegistry extends ITileMover {
|
||||||
{
|
val rKeyVal = raw"([^\s]+.+[^\s]+)\s*->\s*([^\s]+.+[^\s]+)".r
|
||||||
val rKeyVal = raw"([^\s]+.+[^\s]+)\s*->\s*([^\s]+.+[^\s]+)".r
|
val rName = raw"([^\s]+.+[^\s]+)".r
|
||||||
val rName = raw"([^\s]+.+[^\s]+)".r
|
val rNameMetaM = raw"([^\s]+.+[^\s]+)m(\d+)".r
|
||||||
val rNameMetaM = raw"([^\s]+.+[^\s]+)m(\d+)".r
|
val rMod = raw"mod:([^\s]+.+[^\s]+)".r
|
||||||
val rMod = raw"mod:([^\s]+.+[^\s]+)".r
|
|
||||||
|
|
||||||
var blockMetaMap = Map[(Block, Int), ITileMover]()
|
var blockMetaMap = Map[(Block, Int), ITileMover]()
|
||||||
var modMap = Map[String, ITileMover]()
|
var modMap = Map[String, ITileMover]()
|
||||||
|
|
||||||
var moverDescMap = Map[String, String]()
|
var moverDescMap = Map[String, String]()
|
||||||
var moverNameMap = Map[String, ITileMover]()
|
var moverNameMap = Map[String, ITileMover]()
|
||||||
|
|
||||||
var defaultMover:ITileMover = _
|
var defaultMover: ITileMover = _
|
||||||
var preferredMovers = Seq[(String, String)]()
|
var preferredMovers = Seq[(String, String)]()
|
||||||
var mandatoryMovers = Seq[(String, String)]()
|
var mandatoryMovers = Seq[(String, String)]()
|
||||||
|
|
||||||
def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") }
|
def parseKV(kv: Seq[String]) = kv.map {
|
||||||
def parseBlockMeta(b:String) = b match
|
case rKeyVal(k, v) => (k, v);
|
||||||
{
|
case s => throw new MatchError(s"Illegal [k -> v] pair: $s")
|
||||||
case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt
|
}
|
||||||
case rName(name) => Block.getBlockFromName(fixName(name)) -> -1
|
def parseBlockMeta(b: String) = b match {
|
||||||
case _ => throw new MatchError(s"Illegal set part: $b")
|
case rNameMetaM(name, meta) =>
|
||||||
}
|
Block.getBlockFromName(fixName(name)) -> meta.toInt
|
||||||
def fixName(name:String) = name.indexOf(':') match
|
case rName(name) => Block.getBlockFromName(fixName(name)) -> -1
|
||||||
{
|
case _ => throw new MatchError(s"Illegal set part: $b")
|
||||||
case -1 => "minecraft:"+name
|
}
|
||||||
case i => name
|
def fixName(name: String) = name.indexOf(':') match {
|
||||||
|
case -1 => "minecraft:" + name
|
||||||
|
case i => name
|
||||||
|
}
|
||||||
|
|
||||||
|
def parseAndSetMovers(kv: Seq[String]) = {
|
||||||
|
var moverMap = ListMap(parseKV(kv): _*)
|
||||||
|
for ((k, v) <- preferredMovers)
|
||||||
|
if (!moverMap.contains(k)) moverMap += k -> v
|
||||||
|
for (pair <- mandatoryMovers) moverMap += pair
|
||||||
|
moverMap.foreach(h => setMover(h._1, h._2))
|
||||||
|
moverMap.map(p => p._1 + " -> " + p._2).toArray
|
||||||
|
}
|
||||||
|
|
||||||
|
def setMover(that: String, m: String) {
|
||||||
|
if (!moverNameMap.contains(m)) return
|
||||||
|
val h = moverNameMap(m)
|
||||||
|
that match {
|
||||||
|
case "default" => defaultMover = h
|
||||||
|
case rMod(mod) if Loader.isModLoaded(mod) => modMap += mod -> h
|
||||||
|
case _ => blockMetaMap += parseBlockMeta(that) -> h
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def parseAndSetMovers(kv:Seq[String]) =
|
def registerTileMover(name: String, desc: String, m: ITileMover) {
|
||||||
{
|
moverDescMap += name -> desc
|
||||||
var moverMap = ListMap(parseKV(kv):_*)
|
moverNameMap += name -> m
|
||||||
for ((k, v) <- preferredMovers) if (!moverMap.contains(k)) moverMap += k -> v
|
}
|
||||||
for (pair <- mandatoryMovers) moverMap += pair
|
|
||||||
moverMap.foreach(h => setMover(h._1, h._2))
|
|
||||||
moverMap.map(p => p._1+" -> "+p._2).toArray
|
|
||||||
}
|
|
||||||
|
|
||||||
def setMover(that:String, m:String)
|
private def getHandler(b: Block, m: Int) = {
|
||||||
{
|
blockMetaMap.getOrElse(
|
||||||
if (!moverNameMap.contains(m)) return
|
(b, m),
|
||||||
val h = moverNameMap(m)
|
blockMetaMap.getOrElse(
|
||||||
that match
|
(b, -1),
|
||||||
{
|
modMap.getOrElse(BlockLib.getModId(b), defaultMover)
|
||||||
case "default" => defaultMover = h
|
)
|
||||||
case rMod(mod) if Loader.isModLoaded(mod) => modMap += mod -> h
|
)
|
||||||
case _ => blockMetaMap += parseBlockMeta(that) -> h
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def registerTileMover(name:String, desc:String, m:ITileMover)
|
override def canMove(w: World, x: Int, y: Int, z: Int) = {
|
||||||
{
|
val meta = w.getBlockMetadata(x, y, z)
|
||||||
moverDescMap += name -> desc
|
w.getBlock(x, y, z) match {
|
||||||
moverNameMap += name -> m
|
case block: Block => getHandler(block, meta).canMove(w, x, y, z)
|
||||||
|
case _ => false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private def getHandler(b:Block, m:Int) =
|
override def move(w: World, x: Int, y: Int, z: Int, side: Int) {
|
||||||
{
|
val meta = w.getBlockMetadata(x, y, z)
|
||||||
blockMetaMap.getOrElse((b, m), blockMetaMap.getOrElse((b, -1),
|
w.getBlock(x, y, z) match {
|
||||||
modMap.getOrElse(BlockLib.getModId(b), defaultMover)))
|
case block: Block => getHandler(block, meta).move(w, x, y, z, side)
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def canMove(w:World, x:Int, y:Int, z:Int) =
|
override def postMove(w: World, x: Int, y: Int, z: Int) {
|
||||||
{
|
val meta = w.getBlockMetadata(x, y, z)
|
||||||
val meta = w.getBlockMetadata(x, y, z)
|
w.getBlock(x, y, z) match {
|
||||||
w.getBlock(x, y, z) match
|
case block: Block => getHandler(block, meta).postMove(w, x, y, z)
|
||||||
{
|
case _ =>
|
||||||
case block:Block => getHandler(block, meta).canMove(w, x, y, z)
|
|
||||||
case _ => false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def move(w:World, x:Int, y:Int, z:Int, side:Int)
|
def canRunOverBlock(w: World, x: Int, y: Int, z: Int) = {
|
||||||
{
|
if (w.blockExists(x, y, z))
|
||||||
val meta = w.getBlockMetadata(x, y, z)
|
w.isAirBlock(x, y, z) || WorldLib.isBlockSoft(
|
||||||
w.getBlock(x, y, z) match
|
w,
|
||||||
{
|
x,
|
||||||
case block:Block => getHandler(block, meta).move(w, x, y, z, side)
|
y,
|
||||||
case _ =>
|
z,
|
||||||
}
|
w.getBlock(x, y, z)
|
||||||
}
|
)
|
||||||
|
else false
|
||||||
override def postMove(w:World, x:Int, y:Int, z:Int)
|
}
|
||||||
{
|
|
||||||
val meta = w.getBlockMetadata(x, y, z)
|
|
||||||
w.getBlock(x, y, z) match
|
|
||||||
{
|
|
||||||
case block:Block => getHandler(block, meta).postMove(w, x, y, z)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def canRunOverBlock(w:World, x:Int, y:Int, z:Int) =
|
|
||||||
{
|
|
||||||
if (w.blockExists(x, y, z))
|
|
||||||
w.isAirBlock(x, y, z) || WorldLib.isBlockSoft(w, x, y, z, w.getBlock(x, y, z))
|
|
||||||
else false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoordPushTileMover extends ITileMover
|
class CoordPushTileMover extends ITileMover {
|
||||||
{
|
override def canMove(w: World, x: Int, y: Int, z: Int) = true
|
||||||
override def canMove(w:World, x:Int, y:Int, z:Int) = true
|
|
||||||
|
|
||||||
override def move(w:World, x:Int, y:Int, z:Int, side:Int)
|
override def move(w: World, x: Int, y: Int, z: Int, side: Int) {
|
||||||
{
|
val (b, meta, te) = getBlockInfo(w, x, y, z)
|
||||||
val (b, meta, te) = getBlockInfo(w, x, y, z)
|
val pos = new BlockCoord(x, y, z).offset(side)
|
||||||
val pos = new BlockCoord(x, y, z).offset(side)
|
if (te != null) {
|
||||||
if (te != null)
|
te.invalidate()
|
||||||
{
|
uncheckedRemoveTileEntity(w, x, y, z)
|
||||||
te.invalidate()
|
|
||||||
uncheckedRemoveTileEntity(w, x, y, z)
|
|
||||||
}
|
|
||||||
uncheckedSetBlock(w, x, y, z, Blocks.air, 0)
|
|
||||||
uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta)
|
|
||||||
if (te != null)
|
|
||||||
{
|
|
||||||
te.xCoord = pos.x
|
|
||||||
te.yCoord = pos.y
|
|
||||||
te.zCoord = pos.z
|
|
||||||
te.validate()
|
|
||||||
uncheckedSetTileEntity(w, pos.x, pos.y, pos.z, te)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
uncheckedSetBlock(w, x, y, z, Blocks.air, 0)
|
||||||
|
uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta)
|
||||||
|
if (te != null) {
|
||||||
|
te.xCoord = pos.x
|
||||||
|
te.yCoord = pos.y
|
||||||
|
te.zCoord = pos.z
|
||||||
|
te.validate()
|
||||||
|
uncheckedSetTileEntity(w, pos.x, pos.y, pos.z, te)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def postMove(w:World, x:Int, y:Int, z:Int){}
|
override def postMove(w: World, x: Int, y: Int, z: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveLoadTileMover extends ITileMover
|
class SaveLoadTileMover extends ITileMover {
|
||||||
{
|
override def canMove(w: World, x: Int, y: Int, z: Int) = true
|
||||||
override def canMove(w:World, x:Int, y:Int, z:Int) = true
|
|
||||||
|
|
||||||
override def move(w:World, x:Int, y:Int, z:Int, side:Int)
|
override def move(w: World, x: Int, y: Int, z: Int, side: Int) {
|
||||||
{
|
val (b, meta, te) = getBlockInfo(w, x, y, z)
|
||||||
val (b, meta, te) = getBlockInfo(w, x, y, z)
|
val pos = new BlockCoord(x, y, z).offset(side)
|
||||||
val pos = new BlockCoord(x, y, z).offset(side)
|
val tag = if (te != null) {
|
||||||
val tag = if (te != null)
|
val tag = new NBTTagCompound
|
||||||
{
|
te.writeToNBT(tag)
|
||||||
val tag = new NBTTagCompound
|
tag.setInteger("x", pos.x)
|
||||||
te.writeToNBT(tag)
|
tag.setInteger("y", pos.y)
|
||||||
tag.setInteger("x", pos.x)
|
tag.setInteger("z", pos.z)
|
||||||
tag.setInteger("y", pos.y)
|
te.onChunkUnload()
|
||||||
tag.setInteger("z", pos.z)
|
w.removeTileEntity(x, y, z)
|
||||||
te.onChunkUnload()
|
tag
|
||||||
w.removeTileEntity(x, y, z)
|
} else null
|
||||||
tag
|
uncheckedSetBlock(w, x, y, z, Blocks.air, 0)
|
||||||
}
|
uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta)
|
||||||
else null
|
if (tag != null) {
|
||||||
uncheckedSetBlock(w, x, y, z, Blocks.air, 0)
|
TileEntity.createAndLoadEntity(tag) match {
|
||||||
uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta)
|
case te: TileEntity =>
|
||||||
if (tag != null)
|
w.getChunkFromBlockCoords(pos.x, pos.z).addTileEntity(te)
|
||||||
{
|
case _ =>
|
||||||
TileEntity.createAndLoadEntity(tag) match
|
}
|
||||||
{
|
|
||||||
case te:TileEntity =>
|
|
||||||
w.getChunkFromBlockCoords(pos.x, pos.z).addTileEntity(te)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def postMove(w:World, x:Int, y:Int, z:Int){}
|
override def postMove(w: World, x: Int, y: Int, z: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticTileMover extends ITileMover
|
class StaticTileMover extends ITileMover {
|
||||||
{
|
override def canMove(w: World, x: Int, y: Int, z: Int) = false
|
||||||
override def canMove(w:World, x:Int, y:Int, z:Int) = false
|
|
||||||
|
|
||||||
override def move(w:World, x:Int, y:Int, z:Int, side:Int){}
|
override def move(w: World, x: Int, y: Int, z: Int, side: Int) {}
|
||||||
|
|
||||||
override def postMove(w:World, x:Int, y:Int, z:Int){}
|
override def postMove(w: World, x: Int, y: Int, z: Int) {}
|
||||||
}
|
}
|
||||||
@@ -12,164 +12,193 @@ import net.minecraft.block.Block
|
|||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.renderer.texture.TextureMap
|
import net.minecraft.client.renderer.texture.TextureMap
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
||||||
import net.minecraft.client.renderer.{OpenGlHelper, RenderBlocks, RenderHelper, Tessellator}
|
import net.minecraft.client.renderer.{
|
||||||
|
OpenGlHelper,
|
||||||
|
RenderBlocks,
|
||||||
|
RenderHelper,
|
||||||
|
Tessellator
|
||||||
|
}
|
||||||
import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World}
|
import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World}
|
||||||
import net.minecraftforge.common.util.ForgeDirection
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
import org.lwjgl.opengl.GL11._
|
import org.lwjgl.opengl.GL11._
|
||||||
|
|
||||||
object MovingRenderer
|
object MovingRenderer {
|
||||||
{
|
var isRendering = false
|
||||||
var isRendering = false
|
var renderHack = true
|
||||||
var renderHack = true
|
|
||||||
|
|
||||||
private var oldWorld:World = null
|
private var oldWorld: World = null
|
||||||
private var frame = 0.0f
|
private var frame = 0.0f
|
||||||
private var renderBlocks:RenderBlocks = null
|
private var renderBlocks: RenderBlocks = null
|
||||||
|
|
||||||
private def mc = Minecraft.getMinecraft
|
private val renderStruct: BlockStruct => Unit = { s =>
|
||||||
private def world = mc.theWorld
|
for (b <- s.preMoveBlocks)
|
||||||
private def tes = Tessellator.instance
|
render(b.x, b.y, b.z, renderPos(s, frame))
|
||||||
|
}
|
||||||
|
|
||||||
private def render(x:Int, y:Int, z:Int, rpos:Vector3)
|
private def mc = Minecraft.getMinecraft
|
||||||
{
|
private def world = mc.theWorld
|
||||||
val oldOcclusion = mc.gameSettings.ambientOcclusion
|
|
||||||
mc.gameSettings.ambientOcclusion = 0
|
|
||||||
|
|
||||||
val block = world.getBlock(x, y, z)
|
private def render(x: Int, y: Int, z: Int, rpos: Vector3) {
|
||||||
if (block == null) return
|
val oldOcclusion = mc.gameSettings.ambientOcclusion
|
||||||
|
mc.gameSettings.ambientOcclusion = 0
|
||||||
|
|
||||||
val engine = TileEntityRendererDispatcher.instance.field_147553_e
|
val block = world.getBlock(x, y, z)
|
||||||
if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture)
|
if (block == null) return
|
||||||
mc.entityRenderer.enableLightmap(frame)
|
|
||||||
|
|
||||||
val light = world.getLightBrightnessForSkyBlocks(x, y, z, block.getLightValue(world, x, y, z))
|
val engine = TileEntityRendererDispatcher.instance.field_147553_e
|
||||||
val l1 = light%65536
|
if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture)
|
||||||
val l2 = light/65536
|
mc.entityRenderer.enableLightmap(frame)
|
||||||
|
|
||||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
val light = world.getLightBrightnessForSkyBlocks(
|
||||||
glColor4f(0, 0, 0, 0)
|
x,
|
||||||
RenderHelper.disableStandardItemLighting()
|
y,
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
z,
|
||||||
glEnable(GL_BLEND)
|
block.getLightValue(world, x, y, z)
|
||||||
glDisable(GL_CULL_FACE)
|
)
|
||||||
glShadeModel(if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT)
|
val l1 = light % 65536
|
||||||
|
val l2 = light / 65536
|
||||||
|
|
||||||
for (pass <- 0 to 1)
|
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
||||||
{
|
glColor4f(0, 0, 0, 0)
|
||||||
tes.startDrawingQuads()
|
RenderHelper.disableStandardItemLighting()
|
||||||
tes.setTranslation(
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
-TileEntityRendererDispatcher.staticPlayerX+MathLib.clamp(-1F, 1F, rpos.x.toFloat),
|
glEnable(GL_BLEND)
|
||||||
-TileEntityRendererDispatcher.staticPlayerY+MathLib.clamp(-1F, 1F, rpos.y.toFloat),
|
glDisable(GL_CULL_FACE)
|
||||||
-TileEntityRendererDispatcher.staticPlayerZ+MathLib.clamp(-1F, 1F, rpos.z.toFloat))
|
glShadeModel(
|
||||||
tes.setColorOpaque(1, 1, 1)
|
if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT
|
||||||
|
)
|
||||||
|
|
||||||
block.getRenderBlockPass
|
for (pass <- 0 to 1) {
|
||||||
if (block.canRenderInPass(pass))
|
val tess = Tessellator.instance
|
||||||
{
|
tess.startDrawingQuads()
|
||||||
renderHack = false
|
tess.setTranslation(
|
||||||
renderBlocks.renderBlockByRenderType(block, x, y, z)
|
-TileEntityRendererDispatcher.staticPlayerX + MathLib
|
||||||
renderHack = true
|
.clamp(-1f, 1f, rpos.x.toFloat),
|
||||||
}
|
-TileEntityRendererDispatcher.staticPlayerY + MathLib
|
||||||
|
.clamp(-1f, 1f, rpos.y.toFloat),
|
||||||
|
-TileEntityRendererDispatcher.staticPlayerZ + MathLib.clamp(
|
||||||
|
-1f,
|
||||||
|
1f,
|
||||||
|
rpos.z.toFloat
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tess.setColorOpaque(1, 1, 1)
|
||||||
|
|
||||||
tes.setTranslation(0, 0, 0)
|
block.getRenderBlockPass
|
||||||
tes.draw()
|
if (block.canRenderInPass(pass)) {
|
||||||
}
|
renderHack = false
|
||||||
RenderHelper.enableStandardItemLighting()
|
renderBlocks.renderBlockByRenderType(block, x, y, z)
|
||||||
mc.entityRenderer.disableLightmap(frame)
|
renderHack = true
|
||||||
mc.gameSettings.ambientOcclusion = oldOcclusion
|
}
|
||||||
|
|
||||||
|
tess.setTranslation(0, 0, 0)
|
||||||
|
tess.draw()
|
||||||
|
}
|
||||||
|
RenderHelper.enableStandardItemLighting()
|
||||||
|
mc.entityRenderer.disableLightmap(frame)
|
||||||
|
mc.gameSettings.ambientOcclusion = oldOcclusion
|
||||||
|
}
|
||||||
|
|
||||||
|
def onRenderWorldEvent() {
|
||||||
|
if (oldWorld != world) {
|
||||||
|
oldWorld = world
|
||||||
|
renderBlocks = new MovingRenderBlocks(new MovingWorld(world))
|
||||||
|
renderBlocks.renderAllFaces = true
|
||||||
}
|
}
|
||||||
|
|
||||||
def onRenderWorldEvent()
|
MovementManager2.getWorldStructs(world).foreachStruct(renderStruct)
|
||||||
{
|
}
|
||||||
if (oldWorld != world)
|
|
||||||
{
|
|
||||||
oldWorld = world
|
|
||||||
renderBlocks = new MovingRenderBlocks(new MovingWorld(world))
|
|
||||||
renderBlocks.renderAllFaces = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for (s <- MovementManager2.getWorldStructs(world).structs) for (b <- s.preMoveBlocks)
|
def onTick() = {
|
||||||
render(b.x, b.y, b.z, renderPos(s, frame))
|
if (oldWorld != null && world == null) {
|
||||||
|
oldWorld = null
|
||||||
|
renderBlocks = null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def onPreRenderTick(time:Float)
|
def onPreRenderTick(time: Float) {
|
||||||
{
|
isRendering = true
|
||||||
isRendering = true
|
frame = time
|
||||||
frame = time
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def onPostRenderTick()
|
def onPostRenderTick() {
|
||||||
{
|
isRendering = false
|
||||||
isRendering = false
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def renderPos(s:BlockStruct, partial:Float) =
|
def renderPos(s: BlockStruct, partial: Float) = {
|
||||||
{
|
new Vector3(BlockCoord.sideOffsets(s.moveDir))
|
||||||
new Vector3(BlockCoord.sideOffsets(s.moveDir))
|
.multiply(s.progress + s.speed * partial)
|
||||||
.multiply(s.progress+s.speed*partial)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
class MovingRenderBlocks(w:IBlockAccess) extends RenderBlocks(w)
|
class MovingRenderBlocks(w: IBlockAccess) extends RenderBlocks(w) {
|
||||||
{
|
val eps = 1.0 / 0x10000
|
||||||
val eps = 1.0/0x10000
|
|
||||||
|
|
||||||
override def renderStandardBlock(block:Block, x:Int, y:Int, z:Int) =
|
override def renderStandardBlock(block: Block, x: Int, y: Int, z: Int) = {
|
||||||
{
|
if (MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) {
|
||||||
if (MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z))
|
if (renderMinX == 0.0d) renderMinX += eps
|
||||||
{
|
if (renderMinY == 0.0d) renderMinY += eps
|
||||||
if (renderMinX == 0.0D) renderMinX += eps
|
if (renderMinZ == 0.0d) renderMinZ += eps
|
||||||
if (renderMinY == 0.0D) renderMinY += eps
|
if (renderMaxX == 1.0d) renderMaxX -= eps
|
||||||
if (renderMinZ == 0.0D) renderMinZ += eps
|
if (renderMaxY == 1.0d) renderMaxY -= eps
|
||||||
if (renderMaxX == 1.0D) renderMaxX -= eps
|
if (renderMaxZ == 1.0d) renderMaxZ -= eps
|
||||||
if (renderMaxY == 1.0D) renderMaxY -= eps
|
|
||||||
if (renderMaxZ == 1.0D) renderMaxZ -= eps
|
|
||||||
}
|
|
||||||
super.renderStandardBlock(block, x, y, z)
|
|
||||||
}
|
}
|
||||||
|
super.renderStandardBlock(block, x, y, z)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MovingWorld(val world:World) extends IBlockAccess
|
class MovingWorld(val world: World) extends IBlockAccess {
|
||||||
{
|
override def getBlock(x: Int, y: Int, z: Int) = world.getBlock(x, y, z)
|
||||||
override def getBlock(x:Int, y:Int, z:Int) = world.getBlock(x, y, z)
|
|
||||||
|
|
||||||
override def getTileEntity(x:Int, y:Int, z:Int) = world.getTileEntity(x, y, z)
|
override def getTileEntity(x: Int, y: Int, z: Int) =
|
||||||
|
world.getTileEntity(x, y, z)
|
||||||
|
|
||||||
def computeLightValue(x:Int, y:Int, z:Int, tpe:EnumSkyBlock) =
|
def computeLightValue(x: Int, y: Int, z: Int, tpe: EnumSkyBlock) = {
|
||||||
{
|
(for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s))
|
||||||
(for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s))
|
yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max
|
||||||
yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def getLightBrightnessForSkyBlocks(
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
z: Int,
|
||||||
|
light: Int
|
||||||
|
) =
|
||||||
|
MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match {
|
||||||
|
case true =>
|
||||||
|
val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky)
|
||||||
|
val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block)
|
||||||
|
l1 << 20 | Seq(l2, light).max << 4
|
||||||
|
case false => world.getLightBrightnessForSkyBlocks(x, y, z, light)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
override def getBlockMetadata(x: Int, y: Int, z: Int) =
|
||||||
override def getLightBrightnessForSkyBlocks(x:Int, y:Int, z:Int, light:Int) =
|
world.getBlockMetadata(x, y, z)
|
||||||
MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match
|
|
||||||
{
|
|
||||||
case true =>
|
|
||||||
val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky)
|
|
||||||
val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block)
|
|
||||||
l1<<20|Seq(l2, light).max<<4
|
|
||||||
case false => world.getLightBrightnessForSkyBlocks(x, y, z, light)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def getBlockMetadata(x:Int, y:Int, z:Int) = world.getBlockMetadata(x, y, z)
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def isAirBlock(x: Int, y: Int, z: Int) = world.isAirBlock(x, y, z)
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def isAirBlock(x:Int, y:Int, z:Int) = world.isAirBlock(x, y, z)
|
override def getBiomeGenForCoords(x: Int, z: Int) =
|
||||||
|
world.getBiomeGenForCoords(x, z)
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def getBiomeGenForCoords(x:Int, z:Int) = world.getBiomeGenForCoords(x, z)
|
override def getHeight = world.getHeight
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
override def getHeight = world.getHeight
|
override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache()
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
override def isBlockProvidingPowerTo(x: Int, y: Int, z: Int, side: Int) =
|
||||||
override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache()
|
world.isBlockProvidingPowerTo(x, y, z, side)
|
||||||
|
|
||||||
override def isBlockProvidingPowerTo(x:Int, y:Int, z:Int, side:Int) =
|
override def isSideSolid(
|
||||||
world.isBlockProvidingPowerTo(x, y, z, side)
|
x: Int,
|
||||||
|
y: Int,
|
||||||
override def isSideSolid(x:Int, y:Int, z:Int, side:ForgeDirection, _default:Boolean) =
|
z: Int,
|
||||||
world.isSideSolid(x, y, z, side, _default)
|
side: ForgeDirection,
|
||||||
}
|
_default: Boolean
|
||||||
|
) =
|
||||||
|
world.isSideSolid(x, y, z, side, _default)
|
||||||
|
}
|
||||||
@@ -5,7 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
package mrtjp.relocation
|
package mrtjp.relocation
|
||||||
|
|
||||||
import java.util.{ArrayList => JAList, List => JList, Set => JSet, TreeSet => JTreeSet}
|
import java.util.{
|
||||||
|
ArrayList => JAList,
|
||||||
|
List => JList,
|
||||||
|
Set => JSet,
|
||||||
|
TreeSet => JTreeSet
|
||||||
|
}
|
||||||
|
|
||||||
import codechicken.lib.vec.BlockCoord
|
import codechicken.lib.vec.BlockCoord
|
||||||
import cpw.mods.fml.common.ObfuscationReflectionHelper
|
import cpw.mods.fml.common.ObfuscationReflectionHelper
|
||||||
@@ -19,78 +24,94 @@ import net.minecraft.world._
|
|||||||
import scala.collection.JavaConversions._
|
import scala.collection.JavaConversions._
|
||||||
import scala.collection.immutable.HashSet
|
import scala.collection.immutable.HashSet
|
||||||
|
|
||||||
object Utils
|
object Utils {
|
||||||
{
|
def rescheduleTicks(
|
||||||
def rescheduleTicks(world:World, blocks:Set[BlockCoord], allBlocks:Set[BlockCoord], dir:Int) = world match
|
world: World,
|
||||||
{
|
blocks: Set[BlockCoord],
|
||||||
case world:WorldServer =>
|
allBlocks: Set[BlockCoord],
|
||||||
val hash = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73064_N",
|
dir: Int
|
||||||
"pendingTickListEntriesHashSet").asInstanceOf[JSet[NextTickListEntry]]
|
) = world match {
|
||||||
|
case world: WorldServer =>
|
||||||
|
val hash = ObfuscationReflectionHelper
|
||||||
|
.getPrivateValue(
|
||||||
|
classOf[WorldServer],
|
||||||
|
world,
|
||||||
|
"field_73064_N",
|
||||||
|
"pendingTickListEntriesHashSet"
|
||||||
|
)
|
||||||
|
.asInstanceOf[JSet[NextTickListEntry]]
|
||||||
|
|
||||||
val tree = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73065_O",
|
val tree = ObfuscationReflectionHelper
|
||||||
"pendingTickListEntriesTreeSet").asInstanceOf[JTreeSet[NextTickListEntry]]
|
.getPrivateValue(
|
||||||
|
classOf[WorldServer],
|
||||||
|
world,
|
||||||
|
"field_73065_O",
|
||||||
|
"pendingTickListEntriesTreeSet"
|
||||||
|
)
|
||||||
|
.asInstanceOf[JTreeSet[NextTickListEntry]]
|
||||||
|
|
||||||
val list = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_94579_S",
|
val list = ObfuscationReflectionHelper
|
||||||
"pendingTickListEntriesThisTick").asInstanceOf[JAList[NextTickListEntry]]
|
.getPrivateValue(
|
||||||
|
classOf[WorldServer],
|
||||||
|
world,
|
||||||
|
"field_94579_S",
|
||||||
|
"pendingTickListEntriesThisTick"
|
||||||
|
)
|
||||||
|
.asInstanceOf[JAList[NextTickListEntry]]
|
||||||
|
|
||||||
val isOptifine = world.getClass.getName == "WorldServerOF"
|
val isOptifine = world.getClass.getName == "WorldServerOF"
|
||||||
|
|
||||||
val chunks = allBlocks.map(b => world.getChunkFromBlockCoords(b.x, b.z)).filter(_ != null)
|
val chunks = allBlocks
|
||||||
|
.map(b => world.getChunkFromBlockCoords(b.x, b.z))
|
||||||
|
.filter(_ != null)
|
||||||
|
|
||||||
val scheduledTicks = chunks.flatMap(ch => world.getPendingBlockUpdates(ch, !isOptifine)
|
val scheduledTicks = chunks.flatMap(ch =>
|
||||||
.asInstanceOf[JAList[NextTickListEntry]] match
|
world
|
||||||
{
|
.getPendingBlockUpdates(ch, !isOptifine)
|
||||||
case null => HashSet[NextTickListEntry]()
|
.asInstanceOf[JAList[NextTickListEntry]] match {
|
||||||
case tList => tList.toSet
|
case null => HashSet[NextTickListEntry]()
|
||||||
})
|
case tList => tList.toSet
|
||||||
|
|
||||||
if (isOptifine) for (tick <- scheduledTicks)
|
|
||||||
{
|
|
||||||
tree.remove(tick)
|
|
||||||
hash.remove(tick)
|
|
||||||
list.remove(tick)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tick <- scheduledTicks)
|
|
||||||
{
|
|
||||||
val bc = new BlockCoord(tick.xCoord, tick.yCoord, tick.zCoord)
|
|
||||||
if (blocks(bc))
|
|
||||||
{
|
|
||||||
bc.offset(dir)
|
|
||||||
tick.xCoord = bc.x
|
|
||||||
tick.yCoord = bc.y
|
|
||||||
tick.zCoord = bc.z
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tick <- scheduledTicks) if (!hash.contains(tick))
|
|
||||||
{
|
|
||||||
hash.add(tick)
|
|
||||||
tree.add(tick)
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
|
|
||||||
def rerenderBlocks(world:World, blocks:Set[BlockCoord])
|
|
||||||
{
|
|
||||||
if (world.isRemote)
|
|
||||||
{
|
|
||||||
val mc = Minecraft.getMinecraft
|
|
||||||
val teList = mc.renderGlobal.tileEntities.asInstanceOf[JList[TileEntity]]
|
|
||||||
|
|
||||||
for (pass <- 0 to 1)
|
|
||||||
{
|
|
||||||
for(c <- blocks; te = world.getTileEntity(c.x, c.y, c.z))
|
|
||||||
{
|
|
||||||
if (te != null) pass match
|
|
||||||
{
|
|
||||||
case 0 => teList.remove(te)
|
|
||||||
case 1 => teList.add(te)
|
|
||||||
}
|
|
||||||
mc.renderGlobal.markBlockForRenderUpdate(c.x, c.y, c.z)
|
|
||||||
}
|
|
||||||
mc.renderGlobal.updateRenderers(mc.renderViewEntity, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isOptifine) for (tick <- scheduledTicks) {
|
||||||
|
tree.remove(tick)
|
||||||
|
hash.remove(tick)
|
||||||
|
list.remove(tick)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tick <- scheduledTicks) {
|
||||||
|
val bc = new BlockCoord(tick.xCoord, tick.yCoord, tick.zCoord)
|
||||||
|
if (blocks(bc)) {
|
||||||
|
bc.offset(dir)
|
||||||
|
tick.xCoord = bc.x
|
||||||
|
tick.yCoord = bc.y
|
||||||
|
tick.zCoord = bc.z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tick <- scheduledTicks) if (!hash.contains(tick)) {
|
||||||
|
hash.add(tick)
|
||||||
|
tree.add(tick)
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
|
||||||
|
def rerenderBlocks(world: World, blocks: Set[BlockCoord]) {
|
||||||
|
if (world.isRemote) {
|
||||||
|
val mc = Minecraft.getMinecraft
|
||||||
|
val teList = mc.renderGlobal.tileEntities.asInstanceOf[JList[TileEntity]]
|
||||||
|
|
||||||
|
for (pass <- 0 to 1) {
|
||||||
|
for (c <- blocks; te = world.getTileEntity(c.x, c.y, c.z)) {
|
||||||
|
if (te != null) pass match {
|
||||||
|
case 0 => teList.remove(te)
|
||||||
|
case 1 => teList.add(te)
|
||||||
|
}
|
||||||
|
mc.renderGlobal.markBlockForRenderUpdate(c.x, c.y, c.z)
|
||||||
|
}
|
||||||
|
mc.renderGlobal.updateRenderers(mc.renderViewEntity, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||