Zeroth pass on 1.13
This commit is contained in:
parent
6e99f84e91
commit
77c3310711
525
build.gradle
525
build.gradle
|
@ -1,477 +1,116 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
maven { url = 'http://files.minecraftforge.net/maven' }
|
||||||
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
|
||||||
name = "forge"
|
|
||||||
url = "http://files.minecraftforge.net/maven"
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name = "sonatype"
|
|
||||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
|
classpath 'net.minecraftforge.gradle:ForgeGradle:3.+'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
apply plugin: 'eclipse'
|
||||||
id 'net.minecrell.licenser' version '0.4'
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: "maven"
|
|
||||||
def patcher_plugin = plugins.apply('net.minecraftforge.gradle.patcher')
|
|
||||||
apply plugin: "net.minecraftforge.gradle.launch4j"
|
|
||||||
|
|
||||||
minecraft.version = "1.12.2"
|
|
||||||
|
|
||||||
minecraft {
|
|
||||||
mappings = 'snapshot_nodoc_20171003'
|
|
||||||
workspaceDir = "projects"
|
|
||||||
versionJson = "jsons/${minecraft.version}-dev.json"
|
|
||||||
buildUserdev = true
|
|
||||||
buildInstaller = true
|
|
||||||
installerVersion = "1.5"
|
|
||||||
|
|
||||||
def common = {
|
|
||||||
patchPrefixOriginal "../src-base/minecraft"
|
|
||||||
patchPrefixChanged "../src-work/minecraft"
|
|
||||||
mainClassClient "net.minecraft.launchwrapper.Launch"
|
|
||||||
tweakClassClient "net.minecraftforge.fml.common.launcher.FMLTweaker"
|
|
||||||
mainClassServer "net.minecraft.launchwrapper.Launch"
|
|
||||||
tweakClassServer "net.minecraftforge.fml.common.launcher.FMLServerTweaker"
|
|
||||||
}
|
|
||||||
|
|
||||||
projects {
|
|
||||||
forge {
|
|
||||||
rootDir "."
|
|
||||||
patchDir "patches/minecraft"
|
|
||||||
patchAfter "clean"
|
|
||||||
genPatchesFrom "clean"
|
|
||||||
genMcpPatches = false
|
|
||||||
applyMcpPatches = false
|
|
||||||
s2sKeepImports = true
|
|
||||||
with common
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'net.minecraftforge'
|
group = 'net.minecraftforge'
|
||||||
version = getVersionFromJava(file("src/main/java/net/minecraftforge/common/ForgeVersion.java"))
|
version = '1.0.0'
|
||||||
|
|
||||||
extractForgeSources { exclude "**/SideOnly.java", "**/Side.java" }
|
project(':mcp') {
|
||||||
extractForgeResources { exclude "**/log4j2.xml" }
|
apply plugin: 'net.minecraftforge.gradle.forgedev.mcp'
|
||||||
|
mcp {
|
||||||
genGradleProjects {
|
config = 'de.oceanlabs.mcp:mcp_config:1.13@zip'
|
||||||
addTestCompileDep "junit:junit:4.12" // TODO update unit tests to junit 5 and remove this
|
pipeline = 'joined'
|
||||||
addTestCompileDep "org.junit.jupiter:junit-jupiter-api:5.0.0"
|
}
|
||||||
addTestCompileDep "org.opentest4j:opentest4j:1.0.0" // needed for junit 5
|
|
||||||
addTestCompileDep "org.hamcrest:hamcrest-core:1.3"
|
|
||||||
filter { dep -> !dep.contains("scala") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processJson {
|
project(':clean') {
|
||||||
releaseJson = "jsons/${minecraft.version}-rel.json"
|
evaluationDependsOn(':mcp')
|
||||||
addReplacements([
|
apply plugin: 'eclipse'
|
||||||
"@minecraft_version@": project.minecraft.version,
|
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
|
||||||
"@version@": project.version,
|
repositories {
|
||||||
"@project@": "forge",
|
mavenCentral()
|
||||||
"@artifact@": "net.minecraftforge:forge:${project.version}",
|
}
|
||||||
"@universal_jar@": { outputJar.archiveName },
|
patcher {
|
||||||
"@timestamp@": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
parent = project(':mcp')
|
||||||
])
|
patchedSrc = file('src/main/java')
|
||||||
|
mappings channel: 'snapshot', version: '20180813-1.12'
|
||||||
|
mcVersion = '1.13'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project(':forge') {
|
||||||
license {
|
evaluationDependsOn(':clean')
|
||||||
header = project.file('LICENSE-header.txt')
|
apply plugin: 'eclipse'
|
||||||
|
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
|
||||||
include 'net/minecraftforge/'
|
sourceSets {
|
||||||
exclude 'net/minecraftforge/fml/repackage/'
|
|
||||||
exclude 'net/minecraftforge/server/terminalconsole/'
|
|
||||||
exclude 'net/minecraftforge/fml/common/versioning/ComparableVersion.java'
|
|
||||||
exclude 'net/minecraftforge/fml/common/versioning/InvalidVersionSpecificationException.java'
|
|
||||||
exclude 'net/minecraftforge/fml/common/versioning/Restriction.java'
|
|
||||||
exclude 'net/minecraftforge/fml/common/versioning/VersionRange.java'
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
main {
|
main {
|
||||||
files = project.files('src/main/java')
|
java {
|
||||||
}
|
srcDir "$rootDir/src/main/java"
|
||||||
test {
|
|
||||||
files = project.files('src/test/java')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task changelog(type: JenkinsChangelog) {
|
|
||||||
|
|
||||||
// skip if there is no forge jenkins pass
|
|
||||||
onlyIf {
|
|
||||||
project.hasProperty('forgeJenkinsPass')
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs.upToDateWhen { false } // never up to date
|
|
||||||
serverRoot = "http://ci.jenkins.minecraftforge.net/"
|
|
||||||
jobName = "minecraftforge"
|
|
||||||
targetBuild = System.env['BUILD_NUMBER'] ?: project.ext.properties.buildNumber ?:0;
|
|
||||||
authName = "console_script"
|
|
||||||
authPassword = project.hasProperty('forgeJenkinsPass') ? project.getProperty('forgeJenkinsPass') : "";
|
|
||||||
output = "build/distributions/${project.name}-${project.version}-changelog.txt"
|
|
||||||
}
|
|
||||||
|
|
||||||
task crowdin(type: CrowdinDownload) {
|
|
||||||
output = "build/crowdin.zip"
|
|
||||||
projectId = 'minecraft-forge'
|
|
||||||
extract = false // we wanna keep it as a zip. not extract it to a folder named "crowdin.zip"
|
|
||||||
|
|
||||||
// task auomatically skips if this is null
|
|
||||||
if (project.hasProperty('crowdinKey'))
|
|
||||||
apiKey = project.crowdinKey
|
|
||||||
}
|
|
||||||
|
|
||||||
def extraTxts = [
|
|
||||||
"CREDITS.txt",
|
|
||||||
"LICENSE.txt",
|
|
||||||
"LICENSE-Paulscode SoundSystem CodecIBXM.txt",
|
|
||||||
"LICENSE-Paulscode IBXM Library.txt"
|
|
||||||
]
|
|
||||||
if (project.hasProperty('forgeJenkinsPass'))
|
|
||||||
extraTxts += changelog
|
|
||||||
|
|
||||||
import groovy.json.JsonSlurper;
|
|
||||||
import groovy.json.JsonBuilder;
|
|
||||||
|
|
||||||
task extractAnnotationsVanilla(type: net.minecraftforge.gradle.tasks.TaskExtractAnnotationsText, dependsOn: deobfuscateJar) {
|
|
||||||
jar = deobfuscateJar.outJar
|
|
||||||
output = 'build/vanilla_annotations_raw.json'
|
|
||||||
doLast { //Re-dump it so it's in groovy's sorted order. Because I like being able to do diffs against things.
|
|
||||||
def json = new JsonSlurper().parseText(file(output).text)
|
|
||||||
file(output).write(new JsonBuilder(json).toPrettyString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task reobfToSRG(type: net.minecraftforge.gradle.patcher.TaskReobfuscate, dependsOn: reobfuscate) {
|
|
||||||
srg = patcher_plugin.delayedFile('{CACHE_DIR}/de/oceanlabs/mcp/mcp_{MAPPING_CHANNEL}/{MAPPING_VERSION}/{MC_VERSION}/srgs/mcp-srg.srg')
|
|
||||||
exc = reobfuscate.exc
|
|
||||||
preFFJar = reobfuscate.preFFJar
|
|
||||||
methodsCsv = reobfuscate.methodsCsv
|
|
||||||
fieldsCsv = reobfuscate.fieldsCsv
|
|
||||||
addLibs reobfuscate.libs
|
|
||||||
inJar = patcher_plugin.delayedFile('{BUILD_DIR}/localCache/Forge/recompiled.jar')
|
|
||||||
outJar = 'build/forge_srg.jar'
|
|
||||||
}
|
|
||||||
|
|
||||||
task extractAnnotationsForgeSRG(type: net.minecraftforge.gradle.tasks.TaskExtractAnnotationsText, dependsOn: reobfToSRG) {
|
|
||||||
jar = reobfToSRG.outJar
|
|
||||||
output = 'build/forge_annotations.json'
|
|
||||||
doLast { //Re-dump it so it's in groovy's sorted order. Because I like being able to do diffs against things.
|
|
||||||
def json = new JsonSlurper().parseText(file(output).text)
|
|
||||||
json.entrySet().removeIf{e -> (!e.key.startsWith('net/minecraft/') && !e.key.startsWith('net/minecraftforge/')) || e.key.endsWith('/package-info')}
|
|
||||||
file(output).write(new JsonBuilder(json).toPrettyString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task fixAnnotationsJson(dependsOn: [extractAnnotationsVanilla, extractAnnotationsForgeSRG, genPatches]) {
|
|
||||||
inputs.file(extractAnnotationsVanilla.output)
|
|
||||||
inputs.file(extractAnnotationsForgeSRG.output)
|
|
||||||
outputs.file('build/vanilla_annotations.json')
|
|
||||||
doLast {
|
|
||||||
def json_vanilla = new JsonSlurper().parseText(file(extractAnnotationsVanilla.output).text) as TreeMap
|
|
||||||
def json_forge = new JsonSlurper().parseText(file(extractAnnotationsForgeSRG.output).text) as TreeMap
|
|
||||||
def start = minecraft.projects.forge.patchDir.absolutePath.length()
|
|
||||||
file(minecraft.projects.forge.patchDir).traverse(type: groovy.io.FileType.FILES, nameFilter: {nf -> nf.endsWith('.java.patch')}) { f ->
|
|
||||||
def cls = f.absolutePath.substring(start+1).replace('\\', '/').replace('.java.patch', '')
|
|
||||||
json_vanilla.entrySet().removeIf{e -> e.key == cls || e.key.startsWith(cls + '$')}
|
|
||||||
json_forge.entrySet().stream().filter{e -> e.key == cls || e.key.startsWith(cls + '$')}.forEach{e -> json_vanilla.put(e.key, e.value)}
|
|
||||||
}
|
|
||||||
json_forge.entrySet().stream().filter{e -> e.key.startsWith('net/minecraftforge/')}.forEach{e -> json_vanilla.put(e.key, e.value)}
|
|
||||||
outputs.files.singleFile.write(new JsonBuilder(json_vanilla).toPrettyString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
outputJar {
|
|
||||||
classifier = 'universal'
|
|
||||||
from extraTxts
|
|
||||||
from(fixAnnotationsJson){
|
|
||||||
into 'META-INF'
|
|
||||||
}
|
|
||||||
dependsOn fixAnnotationsJson
|
|
||||||
|
|
||||||
// add crowdin locales
|
|
||||||
from { crowdin.getDidWork() ? zipTree(crowdin.output) : null}
|
|
||||||
dependsOn 'crowdin'
|
|
||||||
|
|
||||||
manifest.attributes([
|
|
||||||
"Main-Class": "net.minecraftforge.fml.relauncher.ServerLaunchWrapper",
|
|
||||||
"TweakClass": "net.minecraftforge.fml.common.launcher.FMLTweaker",
|
|
||||||
"Class-Path": getServerClasspath(file("jsons/${minecraft.version}-rel.json"))
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
installer {
|
|
||||||
classifier = 'installer'
|
|
||||||
from extraTxts
|
|
||||||
from "src/main/resources/forge_logo.png"
|
|
||||||
from "src/main/resources/url.png"
|
|
||||||
rename "forge_logo\\.png", "big_logo.png"
|
|
||||||
}
|
|
||||||
|
|
||||||
task signUniversal(type: SignJar, dependsOn: 'outputJar') {
|
|
||||||
onlyIf {
|
|
||||||
project.hasProperty('jarsigner')
|
|
||||||
}
|
|
||||||
|
|
||||||
def jarsigner = [:];
|
|
||||||
|
|
||||||
if (project.hasProperty('jarsigner'))
|
|
||||||
jarsigner = project.jarsigner;
|
|
||||||
|
|
||||||
alias = 'forge'
|
|
||||||
exclude "paulscode/**"
|
|
||||||
storePass = jarsigner.storepass
|
|
||||||
keyPass = jarsigner.keypass
|
|
||||||
keyStore = jarsigner.keystore
|
|
||||||
inputFile = outputJar.archivePath
|
|
||||||
outputFile = outputJar.archivePath
|
|
||||||
}
|
|
||||||
uploadArchives.dependsOn signUniversal
|
|
||||||
build.dependsOn signUniversal
|
|
||||||
installer.dependsOn signUniversal
|
|
||||||
|
|
||||||
// MDK package
|
|
||||||
|
|
||||||
import org.apache.tools.ant.filters.ReplaceTokens
|
|
||||||
task makeMdk(type: Zip) {
|
|
||||||
baseName = project.name
|
|
||||||
classifier = "mdk"
|
|
||||||
version = project.version
|
|
||||||
destinationDir = file('build/distributions')
|
|
||||||
|
|
||||||
from 'gradlew'
|
|
||||||
from 'gradlew.bat'
|
|
||||||
from extraTxts
|
|
||||||
into ('gradle') {
|
|
||||||
from 'gradle'
|
|
||||||
}
|
|
||||||
into ('eclipse') {
|
|
||||||
from 'mdk/eclipse'
|
|
||||||
}
|
|
||||||
from ('mdk') {
|
|
||||||
filter(ReplaceTokens, tokens: [
|
|
||||||
VERSION: project.version,
|
|
||||||
MAPPINGS: minecraft.mappings.replace('nodoc_', '')
|
|
||||||
])
|
|
||||||
exclude 'eclipse'
|
|
||||||
rename 'gitignore\\.txt', '.gitignore'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tasks.build.dependsOn makeMdk
|
|
||||||
|
|
||||||
// launch4j
|
|
||||||
|
|
||||||
launch4j {
|
|
||||||
jar = installer.archivePath.canonicalPath
|
|
||||||
outfile = file("build/distributions/${project.name}-${project.version}-installer-win.exe").canonicalPath
|
|
||||||
icon = file('icon.ico').canonicalPath
|
|
||||||
manifest = file('l4jManifest.xml').canonicalPath
|
|
||||||
jreMinVersion = '1.8.0'
|
|
||||||
initialHeapPercent = 5;
|
|
||||||
maxHeapPercent = 100;
|
|
||||||
}
|
|
||||||
tasks.generateXmlConfig.dependsOn installer
|
|
||||||
tasks.build.dependsOn 'launch4j'
|
|
||||||
|
|
||||||
// MAVEN
|
|
||||||
|
|
||||||
artifacts {
|
|
||||||
if (project.hasProperty('forgeJenkinsPass'))
|
|
||||||
archives changelog.output
|
|
||||||
archives file("build/distributions/${project.name}-${project.version}-installer-win.exe")
|
|
||||||
archives makeMdk
|
|
||||||
}
|
|
||||||
|
|
||||||
task ciWriteBuildNumber << {
|
|
||||||
def file = file("src/main/java/net/minecraftforge/common/ForgeVersion.java");
|
|
||||||
def bn = System.getenv("BUILD_NUMBER")?:project.ext.properties.buildNumber?:0;
|
|
||||||
def outfile = "";
|
|
||||||
def ln = "\n"; //Linux line endings because we're on git!
|
|
||||||
|
|
||||||
file.eachLine{ String s ->
|
|
||||||
if (s.matches("^ public static final int buildVersion = [\\d]+;\$"))
|
|
||||||
s = " public static final int buildVersion = ${bn};";
|
|
||||||
if (s.matches('^ public static final String mcVersion = "[^\\"]+";'))
|
|
||||||
s = " public static final String mcVersion = \"${minecraft.version}\";";
|
|
||||||
outfile += (s+ln);
|
|
||||||
}
|
|
||||||
file.write(outfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadArchives {
|
|
||||||
repositories.mavenDeployer {
|
|
||||||
|
|
||||||
dependsOn 'build'
|
|
||||||
|
|
||||||
if (project.hasProperty('forgeMavenPass'))
|
|
||||||
{
|
|
||||||
repository(url: "http://files.minecraftforge.net/maven/manage/upload") {
|
|
||||||
authentication(userName: "forge", password: project.getProperty('forgeMavenPass')) // the elvis operator. look it up.
|
|
||||||
}
|
}
|
||||||
}
|
resources {
|
||||||
else
|
srcDir "$rootDir/src/main/resources"
|
||||||
{
|
|
||||||
// local repo folder. Might wanna juset use gradle install if you wanans end it to maven-local
|
|
||||||
repository(url: 'file://localhost/' + project.file('repo').getAbsolutePath())
|
|
||||||
}
|
|
||||||
|
|
||||||
pom {
|
|
||||||
groupId = project.group
|
|
||||||
version = project.version
|
|
||||||
artifactId = project.archivesBaseName
|
|
||||||
project {
|
|
||||||
name project.archivesBaseName
|
|
||||||
packaging 'jar'
|
|
||||||
description 'Minecraft Forge API'
|
|
||||||
url 'https://github.com/MinecraftForge/MinecraftForge'
|
|
||||||
|
|
||||||
scm {
|
|
||||||
url 'https://github.com/MinecraftForge/MinecraftForge'
|
|
||||||
connection 'scm:git:git://github.com/MinecraftForge/MinecraftForge.git'
|
|
||||||
developerConnection 'scm:git:git@github.com:MinecraftForge/MinecraftForge.git'
|
|
||||||
}
|
|
||||||
|
|
||||||
issueManagement {
|
|
||||||
system 'github'
|
|
||||||
url 'https://github.com/MinecraftForge/MinecraftForge/issues'
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name 'Forge Public License'
|
|
||||||
url 'https://raw.github.com/MinecraftForge/MinecraftForge/master/MinecraftForge-License.txt'
|
|
||||||
distribution 'repo'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id 'cpw'
|
|
||||||
name 'cpw'
|
|
||||||
roles { role 'developer' }
|
|
||||||
}
|
|
||||||
developer {
|
|
||||||
id 'LexManos'
|
|
||||||
name 'Lex Manos'
|
|
||||||
roles { role 'developer' }
|
|
||||||
}
|
|
||||||
developer {
|
|
||||||
id 'AbrarSyed'
|
|
||||||
name 'Abrar Syed'
|
|
||||||
roles { role 'contributor' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
patcher {
|
||||||
|
parent = project(':clean')
|
||||||
|
patches = file("$rootDir/patches/minecraft")
|
||||||
|
patchedSrc = file('src/main/java')
|
||||||
|
accessTransformer = file("$rootDir/src/main/resources/forge_at.cfg")
|
||||||
|
srgPatches = false
|
||||||
|
}
|
||||||
|
applyPatches {
|
||||||
|
canonicalizeAccess true
|
||||||
|
canonicalizeWhitespace true
|
||||||
|
maxFuzz 3
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
implementation project(':clean')
|
||||||
|
implementation 'cpw.mods:modlauncher:0.1+'
|
||||||
|
implementation 'net.minecraftforge:accesstransformers:0.10+:shadowed'
|
||||||
|
implementation 'net.minecraftforge:eventbus:0.1+:service'
|
||||||
|
implementation 'net.minecraftforge:forgespi:0.1+'
|
||||||
|
implementation 'net.minecraftforge:coremods:0.1+'
|
||||||
|
implementation 'com.electronwill.night-config:core:3.4.0'
|
||||||
|
implementation 'com.electronwill.night-config:toml:3.4.0'
|
||||||
|
}
|
||||||
|
|
||||||
// HELPER METHODS
|
configurations {
|
||||||
|
ecj
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
ecj 'org.eclipse.jdt.core.compiler:ecj:4.6.1'
|
||||||
|
}
|
||||||
|
|
||||||
String getServerClasspath(File file)
|
compileJava {
|
||||||
{
|
options.fork = true
|
||||||
def node = new JsonSlurper().parse(file);
|
options.failOnError = false
|
||||||
def out = new StringBuilder()
|
options.forkOptions.with {
|
||||||
node.versionInfo.libraries.each { lib ->
|
executable = 'java'
|
||||||
if (lib.serverreq)
|
jvmArgs = ['-classpath', project.configurations.ecj.asPath, 'org.eclipse.jdt.internal.compiler.batch.Main', '-nowarn']
|
||||||
{
|
|
||||||
// group : artifact : version
|
|
||||||
def split = lib.name.split(':')
|
|
||||||
def group = split[0].replace('.', '/')
|
|
||||||
def artifact = split[1]
|
|
||||||
def version = split[2]
|
|
||||||
out += "libraries/$group/$artifact/$version/$artifact-${version}.jar "
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out += "minecraft_server.${minecraft.version}.jar"
|
task runclient(type: JavaExec) {
|
||||||
|
classpath sourceSets.main.runtimeClasspath
|
||||||
return out.toString();
|
main 'net.minecraftforge.fml.LaunchTesting'
|
||||||
}
|
systemProperties target:'fmldevclient'
|
||||||
|
|
||||||
String getVersionFromJava(File file)
|
|
||||||
{
|
|
||||||
String major = "0";
|
|
||||||
String minor = "0";
|
|
||||||
String revision = "0";
|
|
||||||
String build = "0";
|
|
||||||
|
|
||||||
String prefix = "public static final int";
|
|
||||||
file.eachLine{ String s ->
|
|
||||||
s = s.trim();
|
|
||||||
if (s.startsWith(prefix))
|
|
||||||
{
|
|
||||||
s = s.substring(prefix.length(), s.length() - 1);
|
|
||||||
s = s.replace('=', ' ').replace("Version", "").replaceAll(" +", " ").trim();
|
|
||||||
String[] pts = s.split(" ");
|
|
||||||
|
|
||||||
if (pts[0].equals("major")) major = pts[pts.length - 1];
|
|
||||||
else if (pts[0] == "minor") minor = pts[pts.length - 1];
|
|
||||||
else if (pts[0] == "revision") revision = pts[pts.length - 1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build = System.getenv("BUILD_NUMBER") ?: project.ext.properties.buildNumber ?: 0
|
task runserver(type: JavaExec) {
|
||||||
|
classpath sourceSets.main.runtimeClasspath
|
||||||
|
main 'net.minecraftforge.fml.LaunchTesting'
|
||||||
String branch = null;
|
systemProperties target:'fmldevserver'
|
||||||
if (!System.getenv().containsKey("GIT_BRANCH"))
|
|
||||||
{
|
|
||||||
// TODO: use grgit - Tried to switch 07/07/16 - jgit broken on windows?
|
|
||||||
branch = "git rev-parse --abbrev-ref HEAD".execute().text.trim()
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
branch = System.getenv("GIT_BRANCH");
|
|
||||||
branch = branch.substring(branch.lastIndexOf('/') + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
def out = "${minecraft.version.replace('-', '_')}-$major.$minor.$revision.$build"
|
|
||||||
|
|
||||||
if (branch && branch != 'master' && branch != 'HEAD' && branch != minecraft.version && branch != minecraft.version + '.0')
|
|
||||||
{
|
|
||||||
if (!(branch.endsWith('.x') && minecraft.version.startsWith(branch.substring(0, branch.length() -2))))
|
|
||||||
out += "-$branch"
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reobfuscate {
|
//evaluationDependsOnChildren()
|
||||||
extraSrg = [
|
task setup() {
|
||||||
'MD: net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry/getKeys ()Ljava/util/Set; net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry/getKeys ()Ljava/util/Set;'
|
dependsOn ':clean:extractMapped'
|
||||||
]
|
dependsOn ':forge:extractMapped' //These must be strings so that we can do lazy resolution. Else we need evaluationDependsOnChildren above
|
||||||
}
|
}
|
||||||
|
|
||||||
task resetBuildNumber << {
|
|
||||||
project.ext.properties.buildNumber = 0;
|
|
||||||
ciWriteBuildNumber.execute()
|
|
||||||
}
|
|
||||||
// re-add old tasks for jenkins compat
|
|
||||||
// should be removed, and the jenkins fixed when no longer building with FG 1.2
|
|
||||||
task setupForge { dependsOn 'setup', 'ciWriteBuildNumber' }
|
|
||||||
task buildPackages { dependsOn 'build' }
|
|
||||||
|
|
||||||
//Temporary hack to fix compile errors caused by mappings shading in Bootstrap
|
|
||||||
/*
|
|
||||||
task fixParams << {
|
|
||||||
logger.lifecycle('Fixing param names!')
|
|
||||||
def params = new File(extractMcpMappings.destinationDir, 'params.csv')
|
|
||||||
def text = params.text
|
|
||||||
text = text.replaceAll('p_180276_1_,biome,', 'p_180276_1_,biomeIn,')
|
|
||||||
params.write(text)
|
|
||||||
}
|
|
||||||
fixParams.dependsOn('extractMcpMappings')
|
|
||||||
extractMcpMappings.finalizedBy('fixParams')
|
|
||||||
*/
|
|
||||||
|
|
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
#Sat Mar 10 11:15:39 EST 2018
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
|
@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
|
||||||
# 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 "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
die ( ) {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
|
@ -154,11 +154,19 @@ if $cygwin ; then
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
|
|
@ -49,7 +49,6 @@ goto fail
|
||||||
@rem Get command-line arguments, handling Windows variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
|
@ -60,11 +59,6 @@ set _SKIP=2
|
||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
|
@ -1 +1,9 @@
|
||||||
rootProject.name = 'forge'
|
rootProject.name = 'Forge'
|
||||||
|
|
||||||
|
include ':mcp'
|
||||||
|
include ':clean'
|
||||||
|
include ':forge'
|
||||||
|
|
||||||
|
project(":mcp").projectDir = file("projects/mcp")
|
||||||
|
project(":clean").projectDir = file("projects/clean")
|
||||||
|
project(":forge").projectDir = file("projects/forge")
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.advancements.critereon;
|
|
||||||
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import net.minecraft.util.JsonUtils;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
|
|
||||||
import net.minecraft.advancements.critereon.ItemPredicate;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraftforge.oredict.OreDictionary;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An {@link ItemPredicate} that matches oredicts.
|
|
||||||
*/
|
|
||||||
public class OredictItemPredicate extends ItemPredicate
|
|
||||||
{
|
|
||||||
private final String ore;
|
|
||||||
|
|
||||||
public OredictItemPredicate(String ore)
|
|
||||||
{
|
|
||||||
this.ore = ore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OredictItemPredicate(JsonObject jsonObject) { this(JsonUtils.getString(jsonObject, "ore")); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(ItemStack stack)
|
|
||||||
{
|
|
||||||
return !stack.isEmpty() && ArrayUtils.contains(OreDictionary.getOreIDs(stack), OreDictionary.getOreID(ore));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.classloading;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class FMLForgePlugin
|
|
||||||
{
|
|
||||||
public static boolean RUNTIME_DEOBF = false;
|
|
||||||
}
|
|
|
@ -46,7 +46,7 @@ import static net.minecraft.util.text.TextFormatting.*;
|
||||||
* client, the client takes precedence!
|
* client, the client takes precedence!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ClientCommandHandler extends CommandHandler
|
public class ClientCommandHandler {} /*extends CommandHandler
|
||||||
{
|
{
|
||||||
public static final ClientCommandHandler instance = new ClientCommandHandler();
|
public static final ClientCommandHandler instance = new ClientCommandHandler();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public class ClientCommandHandler extends CommandHandler
|
||||||
/**
|
/**
|
||||||
* @return 1 if successfully executed, -1 if no permission or wrong usage,
|
* @return 1 if successfully executed, -1 if no permission or wrong usage,
|
||||||
* 0 if it doesn't exist or it was canceled (it's sent to the server)
|
* 0 if it doesn't exist or it was canceled (it's sent to the server)
|
||||||
*/
|
* /
|
||||||
@Override
|
@Override
|
||||||
public int executeCommand(ICommandSender sender, String message)
|
public int executeCommand(ICommandSender sender, String message)
|
||||||
{
|
{
|
||||||
|
@ -165,3 +165,4 @@ public class ClientCommandHandler extends CommandHandler
|
||||||
return Minecraft.getMinecraft().getIntegratedServer();
|
return Minecraft.getMinecraft().getIntegratedServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -26,11 +26,9 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import org.lwjgl.input.Mouse;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiButton;
|
import net.minecraft.client.gui.GuiButton;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.gui.ScaledResolution;
|
|
||||||
|
|
||||||
import net.minecraftforge.eventbus.api.Cancelable;
|
import net.minecraftforge.eventbus.api.Cancelable;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
@ -178,6 +176,7 @@ public class GuiScreenEvent extends Event
|
||||||
* This event fires at the end of {@link GuiScreen#drawDefaultBackground()} and before the rest of the Gui draws.
|
* This event fires at the end of {@link GuiScreen#drawDefaultBackground()} and before the rest of the Gui draws.
|
||||||
* This allows drawing next to Guis, above the background but below any tooltips.
|
* This allows drawing next to Guis, above the background but below any tooltips.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
public static class BackgroundDrawnEvent extends GuiScreenEvent
|
public static class BackgroundDrawnEvent extends GuiScreenEvent
|
||||||
{
|
{
|
||||||
private final int mouseX;
|
private final int mouseX;
|
||||||
|
@ -193,22 +192,27 @@ public class GuiScreenEvent extends Event
|
||||||
this.mouseY = scaledHeight - Mouse.getY() * scaledHeight / gui.mc.displayHeight - 1;
|
this.mouseY = scaledHeight - Mouse.getY() * scaledHeight / gui.mc.displayHeight - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
*/
|
||||||
|
/**
|
||||||
* The x coordinate of the mouse pointer on the screen.
|
* The x coordinate of the mouse pointer on the screen.
|
||||||
*/
|
*//*
|
||||||
|
|
||||||
public int getMouseX()
|
public int getMouseX()
|
||||||
{
|
{
|
||||||
return mouseX;
|
return mouseX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
*/
|
||||||
|
/**
|
||||||
* The y coordinate of the mouse pointer on the screen.
|
* The y coordinate of the mouse pointer on the screen.
|
||||||
*/
|
*//*
|
||||||
|
|
||||||
public int getMouseY()
|
public int getMouseY()
|
||||||
{
|
{
|
||||||
return mouseY;
|
return mouseY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event fires in {@link InventoryEffectRenderer#updateActivePotionEffects()}
|
* This event fires in {@link InventoryEffectRenderer#updateActivePotionEffects()}
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.client.event;
|
|
||||||
|
|
||||||
import org.lwjgl.input.Mouse;
|
|
||||||
|
|
||||||
import net.minecraftforge.eventbus.api.Cancelable;
|
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Author: MachineMuse (Claire Semple)
|
|
||||||
* Created: 2:46 PM, 9/4/13
|
|
||||||
*/
|
|
||||||
@net.minecraftforge.eventbus.api.Cancelable
|
|
||||||
public class MouseEvent extends net.minecraftforge.eventbus.api.Event
|
|
||||||
{
|
|
||||||
private final int x;
|
|
||||||
private final int y;
|
|
||||||
private final int dx;
|
|
||||||
private final int dy;
|
|
||||||
private final int dwheel;
|
|
||||||
private final int button;
|
|
||||||
private final boolean buttonstate;
|
|
||||||
private final long nanoseconds;
|
|
||||||
|
|
||||||
public MouseEvent()
|
|
||||||
{
|
|
||||||
this.x = Mouse.getEventX();
|
|
||||||
this.y = Mouse.getEventY();
|
|
||||||
this.dx = Mouse.getEventDX();
|
|
||||||
this.dy = Mouse.getEventDY();
|
|
||||||
this.dwheel = Mouse.getEventDWheel();
|
|
||||||
this.button = Mouse.getEventButton();
|
|
||||||
this.buttonstate = Mouse.getEventButtonState();
|
|
||||||
this.nanoseconds = Mouse.getEventNanoseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() { return x; }
|
|
||||||
public int getY() { return y; }
|
|
||||||
public int getDx() { return dx; }
|
|
||||||
public int getDy() { return dy; }
|
|
||||||
public int getDwheel() { return dwheel; }
|
|
||||||
public int getButton() { return button; }
|
|
||||||
public boolean isButtonstate() { return buttonstate; }
|
|
||||||
public long getNanoseconds() { return nanoseconds; }
|
|
||||||
}
|
|
|
@ -24,9 +24,8 @@ import java.util.ArrayList;
|
||||||
import net.minecraftforge.eventbus.api.Cancelable;
|
import net.minecraftforge.eventbus.api.Cancelable;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
import net.minecraft.client.gui.BossInfoClient;
|
import net.minecraft.client.gui.BossInfoClient;
|
||||||
import net.minecraft.client.gui.ScaledResolution;
|
|
||||||
|
|
||||||
@net.minecraftforge.eventbus.api.Cancelable
|
@Cancelable
|
||||||
public class RenderGameOverlayEvent extends Event
|
public class RenderGameOverlayEvent extends Event
|
||||||
{
|
{
|
||||||
public float getPartialTicks()
|
public float getPartialTicks()
|
||||||
|
@ -34,11 +33,6 @@ public class RenderGameOverlayEvent extends Event
|
||||||
return partialTicks;
|
return partialTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScaledResolution getResolution()
|
|
||||||
{
|
|
||||||
return resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ElementType getType()
|
public ElementType getType()
|
||||||
{
|
{
|
||||||
return type;
|
return type;
|
||||||
|
@ -71,20 +65,17 @@ public class RenderGameOverlayEvent extends Event
|
||||||
}
|
}
|
||||||
|
|
||||||
private final float partialTicks;
|
private final float partialTicks;
|
||||||
private final ScaledResolution resolution;
|
|
||||||
private final ElementType type;
|
private final ElementType type;
|
||||||
|
|
||||||
public RenderGameOverlayEvent(float partialTicks, ScaledResolution resolution)
|
public RenderGameOverlayEvent(float partialTicks, Void resolution)
|
||||||
{
|
{
|
||||||
this.partialTicks = partialTicks;
|
this.partialTicks = partialTicks;
|
||||||
this.resolution = resolution;
|
|
||||||
this.type = null;
|
this.type = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RenderGameOverlayEvent(RenderGameOverlayEvent parent, ElementType type)
|
private RenderGameOverlayEvent(RenderGameOverlayEvent parent, ElementType type)
|
||||||
{
|
{
|
||||||
this.partialTicks = parent.getPartialTicks();
|
this.partialTicks = parent.getPartialTicks();
|
||||||
this.resolution = parent.getResolution();
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class PlaySoundEvent extends SoundEvent
|
||||||
{
|
{
|
||||||
super(manager);
|
super(manager);
|
||||||
this.sound = sound;
|
this.sound = sound;
|
||||||
this.name = sound.getSoundLocation().getResourcePath();
|
this.name = sound.getSoundLocation().getPath();
|
||||||
this.setResultSound(sound);
|
this.setResultSound(sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class SoundEvent extends net.minecraftforge.eventbus.api.Event
|
||||||
public SoundSourceEvent(SoundManager manager, ISound sound, String uuid)
|
public SoundSourceEvent(SoundManager manager, ISound sound, String uuid)
|
||||||
{
|
{
|
||||||
super(manager);
|
super(manager);
|
||||||
this.name = sound.getSoundLocation().getResourcePath();
|
this.name = sound.getSoundLocation().getPath();
|
||||||
this.sound = sound;
|
this.sound = sound;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,12 +223,14 @@ public class ForgeGuiFactory implements IModGuiFactory
|
||||||
Property global = ForgeMod.getConfig().get(VERSION_CHECK_CAT, "Global", true);
|
Property global = ForgeMod.getConfig().get(VERSION_CHECK_CAT, "Global", true);
|
||||||
|
|
||||||
List<Property> props = new ArrayList<Property>();
|
List<Property> props = new ArrayList<Property>();
|
||||||
|
// TODO
|
||||||
|
/*
|
||||||
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
|
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
|
||||||
{
|
{
|
||||||
values.remove(mod.getModId());
|
values.remove(mod.getModId());
|
||||||
props.add(ForgeMod.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
|
props.add(ForgeMod.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
props.addAll(values.values()); // Add any left overs from the config
|
props.addAll(values.values()); // Add any left overs from the config
|
||||||
props.sort(Comparator.comparing(Property::getName));
|
props.sort(Comparator.comparing(Property::getName));
|
||||||
|
|
||||||
|
@ -378,12 +380,15 @@ public class ForgeGuiFactory implements IModGuiFactory
|
||||||
private static Map<Object, String> getSelectableValues()
|
private static Map<Object, String> getSelectableValues()
|
||||||
{
|
{
|
||||||
Map<Object, String> selectableValues = new TreeMap<Object, String>();
|
Map<Object, String> selectableValues = new TreeMap<Object, String>();
|
||||||
|
// TODO
|
||||||
|
/*
|
||||||
|
|
||||||
for (ModContainer mod : Loader.instance().getActiveModList())
|
for (ModContainer mod : Loader.instance().getActiveModList())
|
||||||
// only add mods to the list that have a non-immutable ModContainer
|
// only add mods to the list that have a non-immutable ModContainer
|
||||||
if (!mod.isImmutable() && mod.getMod() != null)
|
if (!mod.isImmutable() && mod.getMod() != null)
|
||||||
selectableValues.put(mod.getModId(), mod.getName());
|
selectableValues.put(mod.getModId(), mod.getName());
|
||||||
|
|
||||||
|
*/
|
||||||
return selectableValues;
|
return selectableValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.common.ForgeMod;
|
import net.minecraftforge.common.ForgeMod;
|
||||||
import net.minecraftforge.common.ForgeVersion;
|
import net.minecraftforge.common.ForgeVersion;
|
||||||
import net.minecraftforge.common.ForgeVersion.Status;
|
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
import net.minecraftforge.fml.VersionChecker;
|
||||||
import net.minecraftforge.fml.client.ClientModLoader;
|
import net.minecraftforge.fml.client.ClientModLoader;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
@ -85,7 +84,7 @@ public class NotificationModUpdateScreen extends GuiScreen
|
||||||
public static NotificationModUpdateScreen init(GuiMainMenu guiMainMenu, GuiButton modButton)
|
public static NotificationModUpdateScreen init(GuiMainMenu guiMainMenu, GuiButton modButton)
|
||||||
{
|
{
|
||||||
NotificationModUpdateScreen notificationModUpdateScreen = new NotificationModUpdateScreen(modButton);
|
NotificationModUpdateScreen notificationModUpdateScreen = new NotificationModUpdateScreen(modButton);
|
||||||
notificationModUpdateScreen.setGuiSize(guiMainMenu.width, guiMainMenu.height);
|
notificationModUpdateScreen.setWorldAndResolution(guiMainMenu.mc, guiMainMenu.width, guiMainMenu.height);
|
||||||
notificationModUpdateScreen.initGui();
|
notificationModUpdateScreen.initGui();
|
||||||
return notificationModUpdateScreen;
|
return notificationModUpdateScreen;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,15 +108,17 @@ import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.MODELLOADING;
|
import static net.minecraftforge.fml.Logging.MODELLOADING;
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
|
||||||
|
|
||||||
public final class ModelLoader extends ModelBakery
|
public final class ModelLoader extends ModelBakery
|
||||||
{
|
{
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private final Map<ModelResourceLocation, IModel> stateModels = Maps.newHashMap();
|
private final Map<ModelResourceLocation, IModel> stateModels = Maps.newHashMap();
|
||||||
private final Map<ModelResourceLocation, ModelBlockDefinition> multipartDefinitions = Maps.newHashMap();
|
private final Map<ModelResourceLocation, ModelBlockDefinition> multipartDefinitions = Maps.newHashMap();
|
||||||
private final Map<ModelBlockDefinition, IModel> multipartModels = Maps.newHashMap();
|
private final Map<ModelBlockDefinition, IModel> multipartModels = Maps.newHashMap();
|
||||||
|
@ -939,7 +941,7 @@ public final class ModelLoader extends ModelBakery
|
||||||
// ignoring pure ResourceLocation arguments, all things we care about pass ModelResourceLocation
|
// ignoring pure ResourceLocation arguments, all things we care about pass ModelResourceLocation
|
||||||
if(entry.getKey() instanceof ModelResourceLocation)
|
if(entry.getKey() instanceof ModelResourceLocation)
|
||||||
{
|
{
|
||||||
fmlLog.debug(MODELLOADING, ()-> new ModelLoaderErrorMessage((ModelResourceLocation)entry.getKey(), entry.getValue(), modelRegistry, this.blockModelShapes, this::getVariantNames));
|
LOGGER.debug(MODELLOADING, ()-> new ModelLoaderErrorMessage((ModelResourceLocation)entry.getKey(), entry.getValue(), modelRegistry, this.blockModelShapes, this::getVariantNames));
|
||||||
final ModelResourceLocation location = (ModelResourceLocation)entry.getKey();
|
final ModelResourceLocation location = (ModelResourceLocation)entry.getKey();
|
||||||
final IBakedModel model = modelRegistry.getObject(location);
|
final IBakedModel model = modelRegistry.getObject(location);
|
||||||
if(model == null)
|
if(model == null)
|
||||||
|
@ -953,7 +955,7 @@ public final class ModelLoader extends ModelBakery
|
||||||
IBakedModel model = modelRegistry.getObject(missing);
|
IBakedModel model = modelRegistry.getObject(missing);
|
||||||
if(model == null || model == missingModel)
|
if(model == null || model == missingModel)
|
||||||
{
|
{
|
||||||
fmlLog.debug(MODELLOADING, ()-> new ModelLoaderErrorMessage(missing, null, modelRegistry, this.blockModelShapes, this::getVariantNames));
|
LOGGER.debug(MODELLOADING, ()-> new ModelLoaderErrorMessage(missing, null, modelRegistry, this.blockModelShapes, this::getVariantNames));
|
||||||
}
|
}
|
||||||
if(model == null)
|
if(model == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,7 +66,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class DimensionManager
|
public class DimensionManager
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker DIMMGR = MarkerManager.getMarker("DIMS");
|
private static final Marker DIMMGR = MarkerManager.getMarker("DIMS");
|
||||||
private static class Dimension
|
private static class Dimension
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,7 +49,7 @@ import net.minecraftforge.common.config.ConfigCategory;
|
||||||
import net.minecraftforge.common.config.Configuration;
|
import net.minecraftforge.common.config.Configuration;
|
||||||
import net.minecraftforge.common.config.Property;
|
import net.minecraftforge.common.config.Property;
|
||||||
import net.minecraftforge.common.util.Constants;
|
import net.minecraftforge.common.util.Constants;
|
||||||
import net.minecraftforge.fml.ServerLifecycleHooks;
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
import net.minecraftforge.fml.common.Loader;
|
import net.minecraftforge.fml.common.Loader;
|
||||||
|
|
|
@ -170,7 +170,7 @@ import org.apache.logging.log4j.MarkerManager;
|
||||||
|
|
||||||
public class ForgeHooks
|
public class ForgeHooks
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker FORGEHOOKS = MarkerManager.getMarker("FORGEHOOKS");
|
private static final Marker FORGEHOOKS = MarkerManager.getMarker("FORGEHOOKS");
|
||||||
//TODO: Loot tables?
|
//TODO: Loot tables?
|
||||||
static class SeedEntry extends WeightedRandom.Item
|
static class SeedEntry extends WeightedRandom.Item
|
||||||
|
|
|
@ -25,22 +25,21 @@ import net.minecraft.world.biome.Biome;
|
||||||
import static net.minecraftforge.common.config.Configuration.CATEGORY_CLIENT;
|
import static net.minecraftforge.common.config.Configuration.CATEGORY_CLIENT;
|
||||||
import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL;
|
import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.fml.SidedExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
import net.minecraftforge.fml.VersionChecker;
|
||||||
import net.minecraftforge.fml.WorldPersistenceHooks;
|
import net.minecraftforge.fml.WorldPersistenceHooks;
|
||||||
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
|
import net.minecraftforge.fml.javafmlmod.FMLModLoadingContext;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.stats.StatList;
|
import net.minecraft.stats.StatList;
|
||||||
import net.minecraft.world.storage.SaveHandler;
|
import net.minecraft.world.storage.SaveHandler;
|
||||||
|
@ -66,9 +65,7 @@ import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
|
||||||
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
|
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
|
||||||
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||||
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
|
||||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||||
import org.apache.logging.log4j.Marker;
|
import org.apache.logging.log4j.Marker;
|
||||||
import org.apache.logging.log4j.MarkerManager;
|
import org.apache.logging.log4j.MarkerManager;
|
||||||
|
@ -76,7 +73,7 @@ import org.apache.logging.log4j.MarkerManager;
|
||||||
public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
{
|
{
|
||||||
public static final String VERSION_CHECK_CAT = "version_checking";
|
public static final String VERSION_CHECK_CAT = "version_checking";
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker FORGEMOD = MarkerManager.getMarker("FORGEMOD");
|
private static final Marker FORGEMOD = MarkerManager.getMarker("FORGEMOD");
|
||||||
public static int clumpingThreshold = 64;
|
public static int clumpingThreshold = 64;
|
||||||
public static boolean removeErroringEntities = false;
|
public static boolean removeErroringEntities = false;
|
||||||
|
@ -113,9 +110,9 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
public ForgeMod()
|
public ForgeMod()
|
||||||
{
|
{
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
ModLoadingContext.get().getModEventBus().addListener(this::preInit);
|
FMLModLoadingContext.get().getModEventBus().addListener(this::preInit);
|
||||||
ModLoadingContext.get().getModEventBus().addListener(this::postInit);
|
FMLModLoadingContext.get().getModEventBus().addListener(this::postInit);
|
||||||
ModLoadingContext.get().getModEventBus().addListener(this::onAvailable);
|
FMLModLoadingContext.get().getModEventBus().addListener(this::onAvailable);
|
||||||
MinecraftForge.EVENT_BUS.addListener(this::serverStarting);
|
MinecraftForge.EVENT_BUS.addListener(this::serverStarting);
|
||||||
MinecraftForge.EVENT_BUS.addListener(this::playerLogin);
|
MinecraftForge.EVENT_BUS.addListener(this::playerLogin);
|
||||||
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
|
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
|
||||||
|
@ -336,10 +333,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
|
|
||||||
if (event.isWorldRunning() && tmpStairs != disableStairSlabCulling)
|
if (event.isWorldRunning() && tmpStairs != disableStairSlabCulling)
|
||||||
{
|
{
|
||||||
SidedExecutor.runOn(Dist.CLIENT,()->{
|
DistExecutor.runWhenOn(Dist.CLIENT,()->()-> Minecraft.getMinecraft().renderGlobal.loadRenderers());
|
||||||
Minecraft.getMinecraft().renderGlobal.loadRenderers();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -438,7 +432,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
|
public void readData(SaveHandler handler, WorldInfo info, Map<String, INBTBase> propertyMap, NBTTagCompound tag)
|
||||||
{
|
{
|
||||||
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
|
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
|
||||||
FluidRegistry.loadFluidDefaults(tag);
|
FluidRegistry.loadFluidDefaults(tag);
|
||||||
|
@ -449,10 +443,9 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
OreDictionary.rebakeMap();
|
OreDictionary.rebakeMap();
|
||||||
StatList.reinit();
|
StatList.reinit();
|
||||||
Ingredient.invalidateAll();
|
Ingredient.invalidateAll();
|
||||||
SidedExecutor.runOn(Dist.CLIENT, ()-> {
|
DistExecutor.runWhenOn(Dist.CLIENT, ()-> () -> {
|
||||||
Minecraft.getMinecraft().populateSearchTreeManager();
|
Minecraft.getMinecraft().populateSearchTreeManager();
|
||||||
Minecraft.getMinecraft().getSearchTreeManager().onResourceManagerReload(Minecraft.getMinecraft().getResourceManager());
|
Minecraft.getMinecraft().getSearchTreeManager().onResourceManagerReload(Minecraft.getMinecraft().getResourceManager());
|
||||||
return null;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class MinecraftForge
|
||||||
public static final IEventBus ORE_GEN_BUS = IEventBus.create();
|
public static final IEventBus ORE_GEN_BUS = IEventBus.create();
|
||||||
|
|
||||||
static final ForgeInternalHandler INTERNAL_HANDLER = new ForgeInternalHandler();
|
static final ForgeInternalHandler INTERNAL_HANDLER = new ForgeInternalHandler();
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker FORGE = MarkerManager.getMarker("FORGE");
|
private static final Marker FORGE = MarkerManager.getMarker("FORGE");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@ package net.minecraftforge.common.brewing;
|
||||||
import net.minecraft.init.Items;
|
import net.minecraft.init.Items;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.potion.PotionHelper;
|
import net.minecraft.potion.PotionBrewing;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public class VanillaBrewingRecipe implements IBrewingRecipe {
|
||||||
@Override
|
@Override
|
||||||
public boolean isIngredient(@Nonnull ItemStack stack)
|
public boolean isIngredient(@Nonnull ItemStack stack)
|
||||||
{
|
{
|
||||||
return PotionHelper.isReagent(stack);
|
return PotionBrewing.isReagent(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ public class VanillaBrewingRecipe implements IBrewingRecipe {
|
||||||
{
|
{
|
||||||
if (!input.isEmpty() && !ingredient.isEmpty() && isIngredient(ingredient))
|
if (!input.isEmpty() && !ingredient.isEmpty() && isIngredient(ingredient))
|
||||||
{
|
{
|
||||||
ItemStack result = PotionHelper.doReaction(ingredient, input);
|
ItemStack result = PotionBrewing.doReaction(ingredient, input);
|
||||||
if (result != input)
|
if (result != input)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -58,7 +58,7 @@ public class Capability<T>
|
||||||
* @return a NBT holding the data. Null if no data needs to be stored.
|
* @return a NBT holding the data. Null if no data needs to be stored.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
NBTBase writeNBT(Capability<T> capability, T instance, EnumFacing side);
|
INBTBase writeNBT(Capability<T> capability, T instance, EnumFacing side);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the capability instance from a NBT tag.
|
* Read the capability instance from a NBT tag.
|
||||||
|
@ -79,7 +79,7 @@ public class Capability<T>
|
||||||
* @param side The side of the object the instance is associated with.
|
* @param side The side of the object the instance is associated with.
|
||||||
* @param nbt A NBT holding the data. Must not be null, as doesn't make sense to call this function with nothing to read...
|
* @param nbt A NBT holding the data. Must not be null, as doesn't make sense to call this function with nothing to read...
|
||||||
*/
|
*/
|
||||||
void readNBT(Capability<T> capability, T instance, EnumFacing side, NBTBase nbt);
|
void readNBT(Capability<T> capability, T instance, EnumFacing side, INBTBase nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +97,7 @@ public class Capability<T>
|
||||||
* Quick access to the IStorage's readNBT.
|
* Quick access to the IStorage's readNBT.
|
||||||
* See {@link IStorage#readNBT(Capability, Object, EnumFacing, NBTBase)} for documentation.
|
* See {@link IStorage#readNBT(Capability, Object, EnumFacing, NBTBase)} for documentation.
|
||||||
*/
|
*/
|
||||||
public void readNBT(T instance, EnumFacing side, NBTBase nbt)
|
public void readNBT(T instance, EnumFacing side, INBTBase nbt)
|
||||||
{
|
{
|
||||||
storage.readNBT(this, instance, side, nbt);
|
storage.readNBT(this, instance, side, nbt);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ public class Capability<T>
|
||||||
* See {@link IStorage#writeNBT(Capability, Object, EnumFacing)} for documentation.
|
* See {@link IStorage#writeNBT(Capability, Object, EnumFacing)} for documentation.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public NBTBase writeNBT(T instance, EnumFacing side)
|
public INBTBase writeNBT(T instance, EnumFacing side)
|
||||||
{
|
{
|
||||||
return storage.writeNBT(this, instance, side);
|
return storage.writeNBT(this, instance, side);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
@ -45,7 +45,7 @@ import net.minecraftforge.common.util.INBTSerializable;
|
||||||
public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompound>, ICapabilityProvider
|
public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompound>, ICapabilityProvider
|
||||||
{
|
{
|
||||||
private ICapabilityProvider[] caps;
|
private ICapabilityProvider[] caps;
|
||||||
private INBTSerializable<NBTBase>[] writers;
|
private INBTSerializable<INBTBase>[] writers;
|
||||||
private String[] names;
|
private String[] names;
|
||||||
|
|
||||||
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list)
|
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list)
|
||||||
|
@ -57,7 +57,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
|
||||||
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, @Nullable ICapabilityProvider parent)
|
public CapabilityDispatcher(Map<ResourceLocation, ICapabilityProvider> list, @Nullable ICapabilityProvider parent)
|
||||||
{
|
{
|
||||||
List<ICapabilityProvider> lstCaps = Lists.newArrayList();
|
List<ICapabilityProvider> lstCaps = Lists.newArrayList();
|
||||||
List<INBTSerializable<NBTBase>> lstWriters = Lists.newArrayList();
|
List<INBTSerializable<INBTBase>> lstWriters = Lists.newArrayList();
|
||||||
List<String> lstNames = Lists.newArrayList();
|
List<String> lstNames = Lists.newArrayList();
|
||||||
|
|
||||||
if (parent != null) // Parents go first!
|
if (parent != null) // Parents go first!
|
||||||
|
@ -65,7 +65,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
|
||||||
lstCaps.add(parent);
|
lstCaps.add(parent);
|
||||||
if (parent instanceof INBTSerializable)
|
if (parent instanceof INBTSerializable)
|
||||||
{
|
{
|
||||||
lstWriters.add((INBTSerializable<NBTBase>)parent);
|
lstWriters.add((INBTSerializable<INBTBase>)parent);
|
||||||
lstNames.add("Parent");
|
lstNames.add("Parent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
|
||||||
lstCaps.add(prov);
|
lstCaps.add(prov);
|
||||||
if (prov instanceof INBTSerializable)
|
if (prov instanceof INBTSerializable)
|
||||||
{
|
{
|
||||||
lstWriters.add((INBTSerializable<NBTBase>)prov);
|
lstWriters.add((INBTSerializable<INBTBase>)prov);
|
||||||
lstNames.add(entry.getKey().toString());
|
lstNames.add(entry.getKey().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import static net.minecraftforge.fml.Logging.CAPABILITIES;
|
||||||
public enum CapabilityManager
|
public enum CapabilityManager
|
||||||
{
|
{
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a capability to be consumed by others.
|
* Registers a capability to be consumed by others.
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.capabilities;
|
package net.minecraftforge.common.capabilities;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraftforge.common.util.INBTSerializable;
|
import net.minecraftforge.common.util.INBTSerializable;
|
||||||
|
|
||||||
//Just a mix of the two, useful in patches to lower the size.
|
//Just a mix of the two, useful in patches to lower the size.
|
||||||
public interface ICapabilitySerializable<T extends NBTBase> extends ICapabilityProvider, INBTSerializable<T>{}
|
public interface ICapabilitySerializable<T extends INBTBase> extends ICapabilityProvider, INBTSerializable<T>{}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import javax.annotation.Nonnull;
|
||||||
import net.minecraft.client.util.RecipeBookClient;
|
import net.minecraft.client.util.RecipeBookClient;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.SidedExecutor;
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ import org.apache.logging.log4j.MarkerManager;
|
||||||
public class CraftingHelper {
|
public class CraftingHelper {
|
||||||
|
|
||||||
private static final boolean DEBUG_LOAD_MINECRAFT = false;
|
private static final boolean DEBUG_LOAD_MINECRAFT = false;
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker CRAFTHELPER = MarkerManager.getMarker("CRAFTHELPER");
|
private static final Marker CRAFTHELPER = MarkerManager.getMarker("CRAFTHELPER");
|
||||||
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
private static Map<ResourceLocation, IConditionFactory> conditions = new HashMap<>();
|
private static Map<ResourceLocation, IConditionFactory> conditions = new HashMap<>();
|
||||||
|
@ -619,10 +619,7 @@ public class CraftingHelper {
|
||||||
GameData.fireRegistryEvents(rl -> rl.equals(GameData.RECIPES));
|
GameData.fireRegistryEvents(rl -> rl.equals(GameData.RECIPES));
|
||||||
|
|
||||||
//reg.freeze();
|
//reg.freeze();
|
||||||
SidedExecutor.runOn(Dist.CLIENT, ()-> {
|
DistExecutor.runWhenOn(Dist.CLIENT, ()-> RecipeBookClient::rebuildTable);
|
||||||
RecipeBookClient.rebuildTable();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadFactories(final ModFile modFile)
|
private static void loadFactories(final ModFile modFile)
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.util;
|
package net.minecraftforge.common.util;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface designed to unify various things in the Minecraft
|
* An interface designed to unify various things in the Minecraft
|
||||||
* code base that can be serialized to and from a NBT tag.
|
* code base that can be serialized to and from a NBT tag.
|
||||||
*/
|
*/
|
||||||
public interface INBTSerializable<T extends NBTBase>
|
public interface INBTSerializable<T extends INBTBase>
|
||||||
{
|
{
|
||||||
T serializeNBT();
|
T serializeNBT();
|
||||||
void deserializeNBT(T nbt);
|
void deserializeNBT(T nbt);
|
||||||
|
|
|
@ -58,7 +58,7 @@ import javax.annotation.Nullable;
|
||||||
*/
|
*/
|
||||||
public abstract class FluidRegistry
|
public abstract class FluidRegistry
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker FLUIDS = MarkerManager.getMarker("FLUIDS");
|
private static final Marker FLUIDS = MarkerManager.getMarker("FLUIDS");
|
||||||
static int maxID = 0;
|
static int maxID = 0;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ import static net.minecraftforge.fml.Logging.LOADING;
|
||||||
*/
|
*/
|
||||||
public class AutomaticEventSubscriber
|
public class AutomaticEventSubscriber
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
public static void inject(final ModContainer mod, final ModFileScanData scanData, final ClassLoader loader)
|
public static void inject(final ModContainer mod, final ModFileScanData scanData, final ClassLoader loader)
|
||||||
{
|
{
|
||||||
if (scanData == null) return;
|
if (scanData == null) return;
|
||||||
|
|
|
@ -25,9 +25,9 @@ import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public final class SidedExecutor
|
public final class DistExecutor
|
||||||
{
|
{
|
||||||
private SidedExecutor() {}
|
private DistExecutor() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the callable in the supplier only on the specified {@link Side}
|
* Run the callable in the supplier only on the specified {@link Side}
|
||||||
|
@ -37,7 +37,7 @@ public final class SidedExecutor
|
||||||
* @param <T> The return type from the callable
|
* @param <T> The return type from the callable
|
||||||
* @return The callable's result
|
* @return The callable's result
|
||||||
*/
|
*/
|
||||||
public static <T> T runOn(Dist dist, Supplier<Callable<T>> toRun) {
|
public static <T> T callWhenOn(Dist dist, Supplier<Callable<T>> toRun) {
|
||||||
if (dist == FMLEnvironment.dist) {
|
if (dist == FMLEnvironment.dist) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,12 @@ public final class SidedExecutor
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T runSided(Supplier<Supplier<T>> clientTarget, Supplier<Supplier<T>> serverTarget) {
|
public static void runWhenOn(Dist dist, Supplier<Runnable> toRun) {
|
||||||
|
if (dist == FMLEnvironment.dist) {
|
||||||
|
toRun.get().run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static <T> T runForDist(Supplier<Supplier<T>> clientTarget, Supplier<Supplier<T>> serverTarget) {
|
||||||
switch (FMLEnvironment.dist)
|
switch (FMLEnvironment.dist)
|
||||||
{
|
{
|
||||||
case CLIENT:
|
case CLIENT:
|
|
@ -21,7 +21,7 @@ package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.resources.IResourcePack;
|
import net.minecraft.resources.IResourcePack;
|
||||||
import net.minecraftforge.fml.client.ModFileResourcePack;
|
import net.minecraftforge.fml.client.ModFileResourcePack;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.Map.Entry;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
@ -47,7 +47,7 @@ import org.apache.logging.log4j.MarkerManager;
|
||||||
public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.WorldPersistenceHook
|
public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker WORLDPERSISTENCE = MarkerManager.getMarker("WP");
|
private static final Marker WORLDPERSISTENCE = MarkerManager.getMarker("WP");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,7 +66,7 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
|
||||||
final NBTTagCompound mod = new NBTTagCompound();
|
final NBTTagCompound mod = new NBTTagCompound();
|
||||||
mod.setString("ModId", mi.getModId());
|
mod.setString("ModId", mi.getModId());
|
||||||
mod.setString("ModVersion", mi.getVersion().getVersionString());
|
mod.setString("ModVersion", mi.getVersion().getVersionString());
|
||||||
modList.appendTag(mod);
|
modList.add(mod);
|
||||||
});
|
});
|
||||||
fmlData.setTag("LoadingModList", modList);
|
fmlData.setTag("LoadingModList", modList);
|
||||||
|
|
||||||
|
@ -82,12 +82,12 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
|
public void readData(SaveHandler handler, WorldInfo info, NBTTagCompound tag)
|
||||||
{
|
{
|
||||||
if (tag.hasKey("LoadingModList"))
|
if (tag.hasKey("LoadingModList"))
|
||||||
{
|
{
|
||||||
NBTTagList modList = tag.getTagList("LoadingModList", (byte)10);
|
NBTTagList modList = tag.getTagList("LoadingModList", (byte)10);
|
||||||
for (int i = 0; i < modList.tagCount(); i++)
|
for (int i = 0; i < modList.size(); i++)
|
||||||
{
|
{
|
||||||
NBTTagCompound mod = modList.getCompoundTagAt(i);
|
NBTTagCompound mod = modList.getCompoundTagAt(i);
|
||||||
String modId = mod.getString("ModId");
|
String modId = mod.getString("ModId");
|
||||||
|
|
|
@ -19,33 +19,37 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.CORE;
|
import static net.minecraftforge.fml.Logging.CORE;
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
|
||||||
|
|
||||||
public class FileUtils
|
public class FileUtils
|
||||||
{
|
{
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
public static Path getOrCreateDirectory(Path dirPath, String dirLabel) {
|
public static Path getOrCreateDirectory(Path dirPath, String dirLabel) {
|
||||||
if (!Files.isDirectory(dirPath))
|
if (!Files.isDirectory(dirPath))
|
||||||
{
|
{
|
||||||
fmlLog.debug(CORE,"Making {} directory : {}", dirLabel, dirPath);
|
LOGGER.debug(CORE,"Making {} directory : {}", dirLabel, dirPath);
|
||||||
try {
|
try {
|
||||||
Files.createDirectory(dirPath);
|
Files.createDirectory(dirPath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (e instanceof FileAlreadyExistsException) {
|
if (e instanceof FileAlreadyExistsException) {
|
||||||
fmlLog.error(CORE,"Failed to create {} directory - there is a file in the way", dirLabel);
|
LOGGER.error(CORE,"Failed to create {} directory - there is a file in the way", dirLabel);
|
||||||
} else {
|
} else {
|
||||||
fmlLog.error(CORE,"Problem with creating {} directory (Permissions?)", dirLabel, e);
|
LOGGER.error(CORE,"Problem with creating {} directory (Permissions?)", dirLabel, e);
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Problem creating directory", e);
|
throw new RuntimeException("Problem creating directory", e);
|
||||||
}
|
}
|
||||||
fmlLog.debug(CORE,"Created {} directory : {}", dirLabel, dirPath);
|
LOGGER.debug(CORE,"Created {} directory : {}", dirLabel, dirPath);
|
||||||
} else {
|
} else {
|
||||||
fmlLog.debug(CORE,"Found existing {} directory : {}", dirLabel, dirPath);
|
LOGGER.debug(CORE,"Found existing {} directory : {}", dirLabel, dirPath);
|
||||||
}
|
}
|
||||||
return dirPath;
|
return dirPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,29 +21,15 @@ package net.minecraftforge.fml;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import cpw.mods.modlauncher.Launcher;
|
import cpw.mods.modlauncher.Launcher;
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.block.properties.PropertyEnum;
|
|
||||||
import net.minecraft.block.state.BlockStateContainer;
|
|
||||||
import net.minecraft.item.EnumDyeColor;
|
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.MarkerManager;
|
|
||||||
import org.apache.logging.log4j.core.Filter;
|
import org.apache.logging.log4j.core.Filter;
|
||||||
import org.apache.logging.log4j.core.LoggerContext;
|
import org.apache.logging.log4j.core.LoggerContext;
|
||||||
import org.apache.logging.log4j.core.config.Configuration;
|
|
||||||
import org.apache.logging.log4j.core.config.ConfigurationFactory;
|
|
||||||
import org.apache.logging.log4j.core.config.Configurator;
|
import org.apache.logging.log4j.core.config.Configurator;
|
||||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
|
|
||||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
|
|
||||||
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
|
|
||||||
import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
|
|
||||||
import org.apache.logging.log4j.core.filter.MarkerFilter;
|
import org.apache.logging.log4j.core.filter.MarkerFilter;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import static cpw.mods.modlauncher.Logging.CLASSLOADING;
|
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
|
||||||
|
|
||||||
public class LaunchTesting
|
public class LaunchTesting
|
||||||
{
|
{
|
||||||
public static void main(String... args) throws InterruptedException
|
public static void main(String... args) throws InterruptedException
|
||||||
|
|
|
@ -28,8 +28,6 @@ import org.apache.logging.log4j.core.config.Configurator;
|
||||||
|
|
||||||
public class Logging
|
public class Logging
|
||||||
{
|
{
|
||||||
public static final Logger fmlLog = LogManager.getLogger("FML");
|
|
||||||
|
|
||||||
// Lots of markers
|
// Lots of markers
|
||||||
public static final Marker CORE = MarkerManager.getMarker("CORE");
|
public static final Marker CORE = MarkerManager.getMarker("CORE");
|
||||||
public static final Marker LOADING = MarkerManager.getMarker("LOADING");
|
public static final Marker LOADING = MarkerManager.getMarker("LOADING");
|
||||||
|
|
|
@ -34,7 +34,7 @@ import java.util.function.Supplier;
|
||||||
* The container that wraps around mods in the system.
|
* The container that wraps around mods in the system.
|
||||||
* <p>
|
* <p>
|
||||||
* The philosophy is that individual mod implementation technologies should not
|
* The philosophy is that individual mod implementation technologies should not
|
||||||
* impact the actual loading and management of mod code. This interface provides
|
* impact the actual loading and management of mod code. This class provides
|
||||||
* a mechanism by which we can wrap actual mod code so that the loader and other
|
* a mechanism by which we can wrap actual mod code so that the loader and other
|
||||||
* facilities can treat mods at arms length.
|
* facilities can treat mods at arms length.
|
||||||
* </p>
|
* </p>
|
||||||
|
|
|
@ -20,11 +20,9 @@
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import com.google.common.collect.Streams;
|
import com.google.common.collect.Streams;
|
||||||
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
|
|
||||||
import net.minecraftforge.fml.language.ModFileScanData;
|
import net.minecraftforge.fml.language.ModFileScanData;
|
||||||
import net.minecraftforge.fml.loading.DefaultModInfos;
|
import net.minecraftforge.fml.loading.DefaultModInfos;
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
|
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
|
@ -51,7 +49,7 @@ import static net.minecraftforge.fml.Logging.LOADING;
|
||||||
*/
|
*/
|
||||||
public class ModList
|
public class ModList
|
||||||
{
|
{
|
||||||
private static Logger LOGGER = LogManager.getLogger("FML");
|
private static Logger LOGGER = LogManager.getLogger();
|
||||||
private static ModList INSTANCE;
|
private static ModList INSTANCE;
|
||||||
private final List<ModFileInfo> modFiles;
|
private final List<ModFileInfo> modFiles;
|
||||||
private final List<ModInfo> sortedList;
|
private final List<ModInfo> sortedList;
|
||||||
|
|
|
@ -47,7 +47,7 @@ import static net.minecraftforge.fml.Logging.CORE;
|
||||||
|
|
||||||
public class ModLoader
|
public class ModLoader
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static ModLoader INSTANCE;
|
private static ModLoader INSTANCE;
|
||||||
private final ClassLoader launchClassLoader;
|
private final ClassLoader launchClassLoader;
|
||||||
private final LoadingModList loadingModList;
|
private final LoadingModList loadingModList;
|
||||||
|
@ -97,7 +97,7 @@ public class ModLoader
|
||||||
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
||||||
LifecycleEventProvider.PREINIT.dispatch();
|
LifecycleEventProvider.PREINIT.dispatch();
|
||||||
GameData.fireRegistryEvents(rl -> !Objects.equals(rl, GameData.RECIPES));
|
GameData.fireRegistryEvents(rl -> !Objects.equals(rl, GameData.RECIPES));
|
||||||
SidedExecutor.runOn(Dist.CLIENT, ModLoader::fireClientEvents);
|
Boolean result = DistExecutor.callWhenOn(Dist.CLIENT, ModLoader::fireClientEvents);
|
||||||
LifecycleEventProvider.SIDEDINIT.dispatch();
|
LifecycleEventProvider.SIDEDINIT.dispatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -32,6 +33,9 @@ import static net.minecraftforge.fml.Logging.LOADING;
|
||||||
|
|
||||||
public class ModLoadingClassLoader extends SecureClassLoader
|
public class ModLoadingClassLoader extends SecureClassLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ClassLoader.registerAsParallelCapable();
|
ClassLoader.registerAsParallelCapable();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +53,7 @@ public class ModLoadingClassLoader extends SecureClassLoader
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> findClass(String name) throws ClassNotFoundException
|
protected Class<?> findClass(String name) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
LogManager.getLogger("FML").debug(LOADING, "Loading class {}", name);
|
LOGGER.debug(LOADING, "Loading class {}", name);
|
||||||
final String className = name.replace('.','/').concat(".class");
|
final String className = name.replace('.','/').concat(".class");
|
||||||
final Path classResource = FMLLoader.getLoadingModList().findResource(className);
|
final Path classResource = FMLLoader.getLoadingModList().findResource(className);
|
||||||
if (classResource != null) {
|
if (classResource != null) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
import net.minecraftforge.fml.client.SplashProgress;
|
import net.minecraftforge.fml.client.ClientHooks;
|
||||||
import net.minecraftforge.fml.common.event.FMLClientInitEvent;
|
import net.minecraftforge.fml.common.event.FMLClientInitEvent;
|
||||||
import net.minecraftforge.fml.common.event.FMLServerInitEvent;
|
import net.minecraftforge.fml.common.event.FMLServerInitEvent;
|
||||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||||
|
@ -34,12 +34,12 @@ import java.util.function.Supplier;
|
||||||
public enum SidedProvider
|
public enum SidedProvider
|
||||||
{
|
{
|
||||||
// All of these need to be careful not to directly dereference the client and server elements in their signatures
|
// All of these need to be careful not to directly dereference the client and server elements in their signatures
|
||||||
DATAFIXER(c->c.get().getDataFixer(), s->s.get().getDataFixer()),
|
DATAFIXER(c->c.get().getDataFixer(), s->s.get().func_195563_aC()),
|
||||||
SIDEDINIT((Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c, mc),
|
SIDEDINIT((Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c, mc),
|
||||||
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s, mc)),
|
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s, mc)),
|
||||||
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> SplashProgress::stripSpecialChars,
|
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> ClientHooks::stripSpecialChars,
|
||||||
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str),
|
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str),
|
||||||
@SuppressWarnings("Convert2MethodRef") // need to not be methodrefs to avoid classloading all of StartupQuery's data
|
@SuppressWarnings("Convert2MethodRef") // need to not be methodrefs to avoid classloading all of StartupQuery's data (supplier is coming from StartupQuery)
|
||||||
STARTUPQUERY(c->StartupQuery.QueryWrapper.clientQuery(c), s->StartupQuery.QueryWrapper.dedicatedServerQuery(s));
|
STARTUPQUERY(c->StartupQuery.QueryWrapper.clientQuery(c), s->StartupQuery.QueryWrapper.dedicatedServerQuery(s));
|
||||||
|
|
||||||
private static Supplier<Minecraft> client;
|
private static Supplier<Minecraft> client;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import net.minecraftforge.fml.client.gui.GuiConfirmation;
|
||||||
import net.minecraftforge.fml.client.gui.GuiNotification;
|
import net.minecraftforge.fml.client.gui.GuiNotification;
|
||||||
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
||||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||||
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.Marker;
|
import org.apache.logging.log4j.Marker;
|
||||||
|
@ -42,7 +43,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class StartupQuery {
|
public class StartupQuery {
|
||||||
// internal class/functionality, do not use
|
// internal class/functionality, do not use
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker SQ = MarkerManager.getMarker("STARTUPQUERY");
|
private static final Marker SQ = MarkerManager.getMarker("STARTUPQUERY");
|
||||||
|
|
||||||
public static boolean confirm(String text)
|
public static boolean confirm(String text)
|
||||||
|
@ -236,8 +237,6 @@ public class StartupQuery {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
client.loadingScreen.displayLoadingString("");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
|
@ -247,8 +246,6 @@ public class StartupQuery {
|
||||||
query.exception = ie;
|
query.exception = ie;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.loadingScreen.displayLoadingString(""); // make sure the blank screen is being drawn at the end
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,13 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.world.storage.SaveHandler;
|
import net.minecraft.world.storage.SaveHandler;
|
||||||
import net.minecraft.world.storage.WorldInfo;
|
import net.minecraft.world.storage.WorldInfo;
|
||||||
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class WorldPersistenceHooks
|
public class WorldPersistenceHooks
|
||||||
{
|
{
|
||||||
|
@ -47,9 +44,7 @@ public class WorldPersistenceHooks
|
||||||
{
|
{
|
||||||
if (EffectiveSide.get() == LogicalSide.SERVER)
|
if (EffectiveSide.get() == LogicalSide.SERVER)
|
||||||
{
|
{
|
||||||
Map<String, NBTBase> additionalProperties = new HashMap<>();
|
worldPersistenceHooks.forEach(wac->wac.readData(handler, worldInfo, tagCompound.getCompoundTag(wac.getModId())));
|
||||||
worldInfo.setAdditionalProperties(additionalProperties);
|
|
||||||
worldPersistenceHooks.forEach(wac->wac.readData(handler, worldInfo, additionalProperties, tagCompound.getCompoundTag(wac.getModId())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +71,6 @@ public class WorldPersistenceHooks
|
||||||
{
|
{
|
||||||
String getModId();
|
String getModId();
|
||||||
NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info);
|
NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info);
|
||||||
void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag);
|
void readData(SaveHandler handler, WorldInfo info, NBTTagCompound tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
@ -26,10 +27,10 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Gui;
|
import net.minecraft.client.gui.Gui;
|
||||||
|
import net.minecraft.client.gui.GuiConnecting;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.gui.GuiWorldSelection;
|
import net.minecraft.client.gui.GuiWorldSelection;
|
||||||
import net.minecraft.client.gui.ServerListEntryNormal;
|
import net.minecraft.client.gui.ServerListEntryNormal;
|
||||||
import net.minecraft.client.multiplayer.GuiConnecting;
|
|
||||||
import net.minecraft.client.multiplayer.ServerData;
|
import net.minecraft.client.multiplayer.ServerData;
|
||||||
import net.minecraft.client.multiplayer.WorldClient;
|
import net.minecraft.client.multiplayer.WorldClient;
|
||||||
import net.minecraft.network.NetworkManager;
|
import net.minecraft.network.NetworkManager;
|
||||||
|
@ -39,7 +40,6 @@ import net.minecraft.world.storage.WorldSummary;
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
import net.minecraftforge.fml.LogicalSide;
|
||||||
import net.minecraftforge.fml.StartupQuery;
|
import net.minecraftforge.fml.StartupQuery;
|
||||||
import net.minecraftforge.fml.client.gui.GuiAccessDenied;
|
import net.minecraftforge.fml.client.gui.GuiAccessDenied;
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
|
|
||||||
import net.minecraftforge.registries.GameData;
|
import net.minecraftforge.registries.GameData;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
@ -55,8 +55,11 @@ import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
public class ClientHooks
|
public class ClientHooks
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger("FML");
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final Marker CLIENTHOOKS = MarkerManager.getMarker("CLIENTHOOKS");
|
private static final Marker CLIENTHOOKS = MarkerManager.getMarker("CLIENTHOOKS");
|
||||||
|
// From FontRenderer.renderCharAtPos
|
||||||
|
private static final String ALLOWED_CHARS = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
|
||||||
|
private static final CharMatcher DISALLOWED_CHAR_MATCHER = CharMatcher.anyOf(ALLOWED_CHARS).negate();
|
||||||
|
|
||||||
private static Map<ServerStatusResponse,JsonObject> extraServerListData;
|
private static Map<ServerStatusResponse,JsonObject> extraServerListData;
|
||||||
private static Map<ServerData, ExtendedServerListData> serverDataTag;
|
private static Map<ServerData, ExtendedServerListData> serverDataTag;
|
||||||
|
@ -77,6 +80,7 @@ public class ClientHooks
|
||||||
}
|
}
|
||||||
public static void bindServerListData(ServerData data, ServerStatusResponse originalResponse)
|
public static void bindServerListData(ServerData data, ServerStatusResponse originalResponse)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (extraServerListData.containsKey(originalResponse))
|
if (extraServerListData.containsKey(originalResponse))
|
||||||
{
|
{
|
||||||
JsonObject jsonData = extraServerListData.get(originalResponse);
|
JsonObject jsonData = extraServerListData.get(originalResponse);
|
||||||
|
@ -104,6 +108,7 @@ public class ClientHooks
|
||||||
}
|
}
|
||||||
serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, ImmutableMap.of(), !moddedClientAllowed));
|
serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, ImmutableMap.of(), !moddedClientAllowed));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
startupConnectionData.countDown();
|
startupConnectionData.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +172,7 @@ public class ClientHooks
|
||||||
|
|
||||||
static File getSavesDir()
|
static File getSavesDir()
|
||||||
{
|
{
|
||||||
return new File(Minecraft.getMinecraft().mcDataDir, "saves");
|
return new File(Minecraft.getMinecraft().gameDir, "saves");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tryLoadExistingWorld(GuiWorldSelection selectWorldGUI, WorldSummary comparator)
|
public static void tryLoadExistingWorld(GuiWorldSelection selectWorldGUI, WorldSummary comparator)
|
||||||
|
@ -210,4 +215,9 @@ public class ClientHooks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String stripSpecialChars(String message)
|
||||||
|
{
|
||||||
|
// We can't handle many unicode points in the splash renderer
|
||||||
|
return DISALLOWED_CHAR_MATCHER.removeFrom(net.minecraft.util.StringUtils.stripControlCodes(message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,10 @@
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.ScaledResolution;
|
|
||||||
import net.minecraft.client.renderer.GlStateManager;
|
import net.minecraft.client.renderer.GlStateManager;
|
||||||
import net.minecraft.client.resources.IReloadableResourceManager;
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
import net.minecraft.client.resources.IResourcePack;
|
import net.minecraft.resources.IResourcePack;
|
||||||
import net.minecraft.client.resources.data.MetadataSerializer;
|
import net.minecraft.resources.data.IMetadataSectionSerializer;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.LogicalSidedProvider;
|
import net.minecraftforge.fml.LogicalSidedProvider;
|
||||||
|
@ -33,7 +32,6 @@ import net.minecraftforge.fml.VersionChecker;
|
||||||
import net.minecraftforge.fml.ModLoader;
|
import net.minecraftforge.fml.ModLoader;
|
||||||
import net.minecraftforge.fml.client.gui.GuiNotification;
|
import net.minecraftforge.fml.client.gui.GuiNotification;
|
||||||
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||||
import org.lwjgl.input.Mouse;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -44,13 +42,12 @@ public class ClientModLoader
|
||||||
private static boolean loading;
|
private static boolean loading;
|
||||||
private static Minecraft mc;
|
private static Minecraft mc;
|
||||||
|
|
||||||
public static void begin(final Minecraft minecraft, final List<IResourcePack> defaultResourcePacks, final IReloadableResourceManager mcResourceManager, MetadataSerializer metadataSerializer_)
|
public static void begin(final Minecraft minecraft, final List<IResourcePack> defaultResourcePacks, final IReloadableResourceManager mcResourceManager, IMetadataSectionSerializer metadataSerializer)
|
||||||
{
|
{
|
||||||
loading = true;
|
loading = true;
|
||||||
ClientModLoader.mc = minecraft;
|
ClientModLoader.mc = minecraft;
|
||||||
SidedProvider.setClient(()->minecraft);
|
SidedProvider.setClient(()->minecraft);
|
||||||
LogicalSidedProvider.setClient(()->minecraft);
|
LogicalSidedProvider.setClient(()->minecraft);
|
||||||
SplashProgress.start();
|
|
||||||
ModLoader.get().loadMods();
|
ModLoader.get().loadMods();
|
||||||
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
|
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
|
||||||
minecraft.refreshResources();
|
minecraft.refreshResources();
|
||||||
|
@ -61,7 +58,6 @@ public class ClientModLoader
|
||||||
ModLoader.get().finishMods();
|
ModLoader.get().finishMods();
|
||||||
loading = false;
|
loading = false;
|
||||||
mc.gameSettings.loadOptions();
|
mc.gameSettings.loadOptions();
|
||||||
SplashProgress.finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VersionChecker.Status checkForUpdates()
|
public static VersionChecker.Status checkForUpdates()
|
||||||
|
@ -75,27 +71,6 @@ public class ClientModLoader
|
||||||
GlStateManager.enableTexture2D();
|
GlStateManager.enableTexture2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the startup screen has a notification on it, render that instead of the loading screen
|
|
||||||
public static boolean drawNotificationOverProgressScreen(final Minecraft client, final ScaledResolution scaledResolution) throws IOException
|
|
||||||
{
|
|
||||||
if (client.currentScreen instanceof GuiNotification)
|
|
||||||
{
|
|
||||||
int width = scaledResolution.getScaledWidth();
|
|
||||||
int height = scaledResolution.getScaledHeight();
|
|
||||||
int mouseX = Mouse.getX() * width / client.displayWidth;
|
|
||||||
int mouseZ = height - Mouse.getY() * height / client.displayHeight - 1;
|
|
||||||
|
|
||||||
client.currentScreen.drawScreen(mouseX, mouseZ, 0);
|
|
||||||
client.currentScreen.handleInput();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isErrored()
|
public static boolean isErrored()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
|
||||||
import net.minecraftforge.fml.client.config.GuiConfig;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
|
|
||||||
public class DefaultGuiFactory implements IModGuiFactory
|
|
||||||
{
|
|
||||||
|
|
||||||
protected String modid, title;
|
|
||||||
protected Minecraft minecraft;
|
|
||||||
|
|
||||||
protected DefaultGuiFactory(String modid, String title)
|
|
||||||
{
|
|
||||||
this.modid = modid;
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasConfigGui()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(Minecraft minecraftInstance)
|
|
||||||
{
|
|
||||||
this.minecraft = minecraftInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GuiScreen createConfigGui(GuiScreen parentScreen)
|
|
||||||
{
|
|
||||||
return new GuiConfig(parentScreen, modid, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IModGuiFactory forMod(ModContainer mod)
|
|
||||||
{
|
|
||||||
return new DefaultGuiFactory(mod.getModId(), mod.getName());
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,86 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
import net.minecraft.client.resources.FileResourcePack;
|
|
||||||
import net.minecraftforge.fml.common.FMLContainerHolder;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
|
|
||||||
public class FMLFileResourcePack extends FileResourcePack implements FMLContainerHolder {
|
|
||||||
|
|
||||||
private ModContainer container;
|
|
||||||
|
|
||||||
public FMLFileResourcePack(ModContainer container)
|
|
||||||
{
|
|
||||||
super(container.getSource());
|
|
||||||
this.container = container;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPackName()
|
|
||||||
{
|
|
||||||
return "FMLFileResourcePack:"+container.getName();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected InputStream getInputStreamByName(String resourceName) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return super.getInputStreamByName(resourceName);
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
if ("pack.mcmeta".equals(resourceName))
|
|
||||||
{
|
|
||||||
FMLLog.log.debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
|
|
||||||
return new ByteArrayInputStream(("{\n" +
|
|
||||||
" \"pack\": {\n"+
|
|
||||||
" \"description\": \"dummy FML pack for "+container.getName()+"\",\n"+
|
|
||||||
" \"pack_format\": 2\n"+
|
|
||||||
"}\n" +
|
|
||||||
"}").getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
else throw ioe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BufferedImage getPackImage() throws IOException
|
|
||||||
{
|
|
||||||
return ImageIO.read(getInputStreamByName(container.getMetadata().logoFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModContainer getFMLContainer()
|
|
||||||
{
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
import net.minecraft.client.resources.FolderResourcePack;
|
|
||||||
import net.minecraftforge.fml.common.FMLContainerHolder;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
|
|
||||||
public class FMLFolderResourcePack extends FolderResourcePack implements FMLContainerHolder {
|
|
||||||
|
|
||||||
private ModContainer container;
|
|
||||||
|
|
||||||
public FMLFolderResourcePack(ModContainer container)
|
|
||||||
{
|
|
||||||
super(container.getSource());
|
|
||||||
this.container = container;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean hasResourceName(String p_110593_1_)
|
|
||||||
{
|
|
||||||
return super.hasResourceName(p_110593_1_);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String getPackName()
|
|
||||||
{
|
|
||||||
return "FMLFileResourcePack:"+container.getName();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected InputStream getInputStreamByName(String resourceName) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return super.getInputStreamByName(resourceName);
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
if ("pack.mcmeta".equals(resourceName))
|
|
||||||
{
|
|
||||||
FMLLog.log.debug("Mod {} is missing a pack.mcmeta file, substituting a dummy one", container.getName());
|
|
||||||
return new ByteArrayInputStream(("{\n" +
|
|
||||||
" \"pack\": {\n"+
|
|
||||||
" \"description\": \"dummy FML pack for "+container.getName()+"\",\n"+
|
|
||||||
" \"pack_format\": 2\n"+
|
|
||||||
"}\n" +
|
|
||||||
"}").getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
else throw ioe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BufferedImage getPackImage() throws IOException
|
|
||||||
{
|
|
||||||
return ImageIO.read(getInputStreamByName(container.getMetadata().logoFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModContainer getFMLContainer()
|
|
||||||
{
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,15 +19,19 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
import net.minecraft.client.resources.AbstractResourcePack;
|
import net.minecraft.resources.AbstractResourcePack;
|
||||||
|
import net.minecraft.resources.ResourcePackType;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ModFileResourcePack extends AbstractResourcePack
|
public class ModFileResourcePack extends AbstractResourcePack
|
||||||
|
@ -45,32 +49,57 @@ public class ModFileResourcePack extends AbstractResourcePack
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPackName()
|
public String func_195762_a()
|
||||||
{
|
{
|
||||||
return modFile.getFileName();
|
return modFile.getFileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InputStream getInputStreamByName(String name) throws IOException
|
protected InputStream func_195766_a(String name) throws IOException
|
||||||
{
|
{
|
||||||
return Files.newInputStream(modFile.getLocator().findPath(modFile, name));
|
return Files.newInputStream(modFile.getLocator().findPath(modFile, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasResourceName(String name)
|
protected boolean func_195768_c(String name)
|
||||||
{
|
{
|
||||||
return Files.exists(modFile.getLocator().findPath(modFile, name));
|
return Files.exists(modFile.getLocator().findPath(modFile, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getResourceDomains()
|
public Collection<ResourceLocation> func_195758_a(ResourcePackType p_195758_1_, String p_195758_2_, int p_195758_3_, Predicate<String> p_195758_4_)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Files.walk(modFile.getLocator().findPath(modFile, p_195758_1_.func_198956_a())).
|
||||||
|
filter(path -> !path.toString().endsWith(".mcmeta")).
|
||||||
|
filter(path -> path.getNameCount() > 2 && p_195758_2_.equals(path.getName(2).toString())).
|
||||||
|
filter(path -> p_195758_4_.test(path.subpath(3, Math.min(p_195758_3_+3, path.getNameCount())).toString())).
|
||||||
|
map(path -> new ResourceLocation(path.getName(1).toString(),path.subpath(3,Math.min(p_195758_3_+3, path.getNameCount())).toString())).
|
||||||
|
collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> func_195759_a(ResourcePackType p_195759_1_)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Files.walk(modFile.getLocator().findPath(modFile, "assets"),1).map(p->p.getFileName().toString()).collect(Collectors.toSet());
|
return Files.walk(modFile.getLocator().findPath(modFile, p_195759_1_.func_198956_a()),1).map(p->p.getFileName().toString()).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
import net.minecraft.client.resources.AbstractResourcePack;
|
import net.minecraft.resources.AbstractResourcePack;
|
||||||
import net.minecraft.client.resources.FileResourcePack;
|
import net.minecraft.resources.FilePack;
|
||||||
import net.minecraft.client.resources.FolderResourcePack;
|
import net.minecraft.resources.FolderPack;
|
||||||
import net.minecraft.client.resources.IResourcePack;
|
import net.minecraft.resources.IResourcePack;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.loading.FMLLoader;
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||||
|
@ -48,8 +48,8 @@ public class ResourcePackLoader
|
||||||
map(mf -> new ModFileResourcePack(mf.getFile())).
|
map(mf -> new ModFileResourcePack(mf.getFile())).
|
||||||
collect(Collectors.toMap(ModFileResourcePack::getModFile, Function.identity()));
|
collect(Collectors.toMap(ModFileResourcePack::getModFile, Function.identity()));
|
||||||
forgePack = Files.isDirectory(FMLLoader.getForgePath()) ?
|
forgePack = Files.isDirectory(FMLLoader.getForgePath()) ?
|
||||||
new FolderResourcePack(FMLLoader.getForgePath().toFile()) :
|
new FolderPack(FMLLoader.getForgePath().toFile()) :
|
||||||
new FileResourcePack(FMLLoader.getForgePath().toFile());
|
new FilePack(FMLLoader.getForgePath().toFile());
|
||||||
resourcePacks.add(forgePack);
|
resourcePacks.add(forgePack);
|
||||||
resourcePacks.addAll(modResourcePacks.values());
|
resourcePacks.addAll(modResourcePacks.values());
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
/*
|
||||||
import static net.minecraftforge.fml.Logging.SPLASH;
|
import static net.minecraftforge.fml.Logging.SPLASH;
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
import static net.minecraftforge.fml.Logging.fmlLog;
|
||||||
import static org.lwjgl.opengl.GL11.*;
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
@ -86,6 +86,7 @@ import org.lwjgl.util.glu.GLU;
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class SplashProgress
|
public class SplashProgress
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
private static Drawable d;
|
private static Drawable d;
|
||||||
private static volatile boolean pause = false;
|
private static volatile boolean pause = false;
|
||||||
private static volatile boolean done = false;
|
private static volatile boolean done = false;
|
||||||
|
@ -613,7 +614,7 @@ public class SplashProgress
|
||||||
* Resource loading doesn't usually require this call.
|
* Resource loading doesn't usually require this call.
|
||||||
* Call {@link #resume()} when you're done.
|
* Call {@link #resume()} when you're done.
|
||||||
* @deprecated not a stable API, will break, don't use this yet
|
* @deprecated not a stable API, will break, don't use this yet
|
||||||
*/
|
* /
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static void pause()
|
public static void pause()
|
||||||
{
|
{
|
||||||
|
@ -635,7 +636,7 @@ public class SplashProgress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated not a stable API, will break, don't use this yet
|
* @deprecated not a stable API, will break, don't use this yet
|
||||||
*/
|
* /
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static void resume()
|
public static void resume()
|
||||||
{
|
{
|
||||||
|
@ -980,4 +981,5 @@ public class SplashProgress
|
||||||
{
|
{
|
||||||
return (int) (bytes / 1024L / 1024L);
|
return (int) (bytes / 1024L / 1024L);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
|
@ -20,27 +20,13 @@
|
||||||
package net.minecraftforge.fml.client;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.HashBasedTable;
|
import com.google.common.collect.HashBasedTable;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.SetMultimap;
|
import com.google.common.collect.SetMultimap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.collect.Table;
|
import com.google.common.collect.Table;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.resources.AbstractResourcePack;
|
|
||||||
import net.minecraft.client.resources.FallbackResourceManager;
|
|
||||||
import net.minecraft.client.resources.IResourcePack;
|
|
||||||
import net.minecraft.client.resources.SimpleReloadableResourceManager;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.fml.common.FMLContainerHolder;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class TextureTracker
|
public class TextureTracker
|
||||||
|
@ -51,24 +37,25 @@ public class TextureTracker
|
||||||
|
|
||||||
public static void trackMissingTexture(ResourceLocation resourceLocation)
|
public static void trackMissingTexture(ResourceLocation resourceLocation)
|
||||||
{
|
{
|
||||||
badTextureDomains.add(resourceLocation.getResourceDomain());
|
badTextureDomains.add(resourceLocation.getNamespace());
|
||||||
missingTextures.put(resourceLocation.getResourceDomain(),resourceLocation);
|
missingTextures.put(resourceLocation.getNamespace(),resourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void trackBrokenTexture(ResourceLocation resourceLocation, String error)
|
public static void trackBrokenTexture(ResourceLocation resourceLocation, String error)
|
||||||
{
|
{
|
||||||
badTextureDomains.add(resourceLocation.getResourceDomain());
|
badTextureDomains.add(resourceLocation.getNamespace());
|
||||||
Set<ResourceLocation> badType = brokenTextures.get(resourceLocation.getResourceDomain(), error);
|
Set<ResourceLocation> badType = brokenTextures.get(resourceLocation.getNamespace(), error);
|
||||||
if (badType == null)
|
if (badType == null)
|
||||||
{
|
{
|
||||||
badType = Sets.newHashSet();
|
badType = Sets.newHashSet();
|
||||||
brokenTextures.put(resourceLocation.getResourceDomain(), MoreObjects.firstNonNull(error, "Unknown error"), badType);
|
brokenTextures.put(resourceLocation.getNamespace(), MoreObjects.firstNonNull(error, "Unknown error"), badType);
|
||||||
}
|
}
|
||||||
badType.add(resourceLocation);
|
badType.add(resourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logMissingTextureErrors()
|
public static void logMissingTextureErrors()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (missingTextures.isEmpty() && brokenTextures.isEmpty())
|
if (missingTextures.isEmpty() && brokenTextures.isEmpty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -141,6 +128,7 @@ public class TextureTracker
|
||||||
logger.error(Strings.repeat("=", 50));
|
logger.error(Strings.repeat("=", 50));
|
||||||
}
|
}
|
||||||
logger.error(Strings.repeat("+=", 25));
|
logger.error(Strings.repeat("+=", 25));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.resources.I18n;
|
import net.minecraft.client.resources.I18n;
|
||||||
import net.minecraft.util.text.TextComponentString;
|
import net.minecraft.util.text.TextComponentString;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.common.config.ConfigElement;
|
|
||||||
import net.minecraftforge.common.config.ConfigManager;
|
|
||||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
|
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
|
||||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
|
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
|
||||||
|
@ -85,51 +83,6 @@ public class GuiConfig extends GuiScreen
|
||||||
protected HoverChecker resetHoverChecker;
|
protected HoverChecker resetHoverChecker;
|
||||||
protected HoverChecker checkBoxHoverChecker;
|
protected HoverChecker checkBoxHoverChecker;
|
||||||
|
|
||||||
/**
|
|
||||||
* This constructor handles the {@code @Config} configuration classes
|
|
||||||
* @param parentScreen the parent GuiScreen object
|
|
||||||
* @param mod the mod for which to create a screen
|
|
||||||
*/
|
|
||||||
public GuiConfig(GuiScreen parentScreen, String modid, String title)
|
|
||||||
{
|
|
||||||
this(parentScreen, modid, false, false, title, ConfigManager.getModConfigClasses(modid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param parentScreen the parrent GuiScreen object
|
|
||||||
* @param modID the mod ID for the mod whose config settings will be editted
|
|
||||||
* @param allRequireWorldRestart whether all config elements on this screen require a world restart
|
|
||||||
* @param allRequireMcRestart whether all config elements on this screen require a game restart
|
|
||||||
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
|
|
||||||
* edited.
|
|
||||||
* @param configClasses an array of classes annotated with {@code @Config} providing the configuration
|
|
||||||
*/
|
|
||||||
public GuiConfig(GuiScreen parentScreen, String modID, boolean allRequireWorldRestart, boolean allRequireMcRestart, String title,
|
|
||||||
Class<?>... configClasses)
|
|
||||||
{
|
|
||||||
this(parentScreen, collectConfigElements(configClasses), modID, null, allRequireWorldRestart, allRequireMcRestart, title, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<IConfigElement> collectConfigElements(Class<?>[] configClasses)
|
|
||||||
{
|
|
||||||
List<IConfigElement> toReturn;
|
|
||||||
if(configClasses.length == 1)
|
|
||||||
{
|
|
||||||
toReturn = ConfigElement.from(configClasses[0]).getChildElements();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toReturn = new ArrayList<IConfigElement>();
|
|
||||||
for(Class<?> clazz : configClasses)
|
|
||||||
{
|
|
||||||
toReturn.add(ConfigElement.from(clazz));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toReturn.sort(Comparator.comparing(e -> I18n.format(e.getLanguageKey())));
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. If a non-null value is passed for configID,
|
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. If a non-null value is passed for configID,
|
||||||
* the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed if any configElements were changed
|
* the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed if any configElements were changed
|
||||||
|
@ -214,7 +167,7 @@ public class GuiConfig extends GuiScreen
|
||||||
this.parentScreen = parentScreen;
|
this.parentScreen = parentScreen;
|
||||||
this.configElements = configElements;
|
this.configElements = configElements;
|
||||||
this.entryList = new GuiConfigEntries(this, mc);
|
this.entryList = new GuiConfigEntries(this, mc);
|
||||||
this.initEntries = new ArrayList<IConfigEntry>(entryList.listEntries);
|
this.initEntries = new ArrayList<>(entryList.listEntries);
|
||||||
this.allRequireWorldRestart = allRequireWorldRestart;
|
this.allRequireWorldRestart = allRequireWorldRestart;
|
||||||
IF:if (!allRequireWorldRestart)
|
IF:if (!allRequireWorldRestart)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiListExtended;
|
import net.minecraft.client.gui.GuiListExtended;
|
||||||
|
@ -35,10 +35,10 @@ import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.gui.GuiTextField;
|
import net.minecraft.client.gui.GuiTextField;
|
||||||
import net.minecraft.client.resources.I18n;
|
import net.minecraft.client.resources.I18n;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
import net.minecraftforge.fml.common.Loader;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,10 +150,7 @@ public class GuiConfigEntries extends GuiListExtended
|
||||||
}
|
}
|
||||||
else if (configElement.getType() == ConfigGuiType.MOD_ID)
|
else if (configElement.getType() == ConfigGuiType.MOD_ID)
|
||||||
{
|
{
|
||||||
Map<Object, String> values = new TreeMap<Object, String>();
|
Map<Object, String> values = ModList.get().getMods().stream().collect(Collectors.toMap(ModInfo::getModId, ModInfo::getDisplayName));
|
||||||
for (ModContainer mod : Loader.instance().getActiveModList())
|
|
||||||
values.put(mod.getModId(), mod.getName());
|
|
||||||
values.put("minecraft", "Minecraft");
|
|
||||||
this.listEntries.add(new SelectValueEntry(this.owningScreen, this, configElement, values));
|
this.listEntries.add(new SelectValueEntry(this.owningScreen, this, configElement, values));
|
||||||
}
|
}
|
||||||
else if (configElement.getType() == ConfigGuiType.STRING)
|
else if (configElement.getType() == ConfigGuiType.STRING)
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
package net.minecraftforge.fml.client.registry;
|
package net.minecraftforge.fml.client.registry;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
|
||||||
import net.minecraft.client.settings.KeyBinding;
|
import net.minecraft.client.settings.KeyBinding;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||||
|
@ -45,13 +45,13 @@ public class ClientRegistry
|
||||||
* @param id
|
* @param id
|
||||||
* @param specialRenderer
|
* @param specialRenderer
|
||||||
*/
|
*/
|
||||||
public static <T extends TileEntity> void registerTileEntity(Class<T> tileEntityClass, String id, TileEntitySpecialRenderer<? super T> specialRenderer)
|
public static <T extends TileEntity> void registerTileEntity(Class<T> tileEntityClass, String id, TileEntityRenderer<? super T> specialRenderer)
|
||||||
{
|
{
|
||||||
GameRegistry.registerTileEntity(tileEntityClass, id);
|
GameRegistry.registerTileEntity(tileEntityClass, id);
|
||||||
bindTileEntitySpecialRenderer(tileEntityClass, specialRenderer);
|
bindTileEntitySpecialRenderer(tileEntityClass, specialRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends TileEntity> void bindTileEntitySpecialRenderer(Class<T> tileEntityClass, TileEntitySpecialRenderer<? super T> specialRenderer)
|
public static <T extends TileEntity> void bindTileEntitySpecialRenderer(Class<T> tileEntityClass, TileEntityRenderer<? super T> specialRenderer)
|
||||||
{
|
{
|
||||||
TileEntityRendererDispatcher.instance.renderers.put(tileEntityClass, specialRenderer);
|
TileEntityRendererDispatcher.instance.renderers.put(tileEntityClass, specialRenderer);
|
||||||
specialRenderer.setRendererDispatcher(TileEntityRendererDispatcher.instance);
|
specialRenderer.setRendererDispatcher(TileEntityRendererDispatcher.instance);
|
||||||
|
|
|
@ -1,677 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.FutureTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import net.minecraft.entity.item.EntityItem;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.inventory.IInventory;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.nbt.NBTBase;
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
|
||||||
import net.minecraft.network.EnumConnectionState;
|
|
||||||
import net.minecraft.network.INetHandler;
|
|
||||||
import net.minecraft.network.NetworkManager;
|
|
||||||
import net.minecraft.network.handshake.client.C00Handshake;
|
|
||||||
import net.minecraft.network.login.server.SPacketDisconnect;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.util.IThreadListener;
|
|
||||||
import net.minecraft.util.text.TextComponentString;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraft.world.storage.SaveHandler;
|
|
||||||
import net.minecraft.world.storage.WorldInfo;
|
|
||||||
import net.minecraftforge.client.model.animation.Animation;
|
|
||||||
import net.minecraftforge.common.ForgeVersion;
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
|
||||||
import net.minecraftforge.common.util.CompoundDataFixer;
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
|
||||||
import net.minecraftforge.fml.StartupQuery;
|
|
||||||
import net.minecraftforge.fml.WorldPersistenceHooks;
|
|
||||||
import net.minecraftforge.fml.BrandingControl;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
|
||||||
import net.minecraftforge.fml.common.gameevent.InputEvent;
|
|
||||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
|
|
||||||
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
|
|
||||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
|
||||||
import net.minecraftforge.fml.common.thread.SidedThreadGroup;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.server.FMLServerHandler;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main class for non-obfuscated hook handling code
|
|
||||||
*
|
|
||||||
* Anything that doesn't require obfuscated or client/server specific code should
|
|
||||||
* go in this handler
|
|
||||||
*
|
|
||||||
* It also contains a reference to the sided handler instance that is valid
|
|
||||||
* allowing for common code to access specific properties from the obfuscated world
|
|
||||||
* without a direct dependency
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FMLCommonHandler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The singleton
|
|
||||||
*/
|
|
||||||
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
|
|
||||||
/**
|
|
||||||
* The delegate for side specific data and functions
|
|
||||||
*/
|
|
||||||
private IFMLSidedHandler sidedDelegate;
|
|
||||||
|
|
||||||
private boolean noForge;
|
|
||||||
private List<String> brandings;
|
|
||||||
private List<String> brandingsNoMC;
|
|
||||||
private Set<SaveHandler> handlerSet = Collections.newSetFromMap(new MapMaker().weakKeys().<SaveHandler,Boolean>makeMap());
|
|
||||||
private WeakReference<SaveHandler> handlerToCheck;
|
|
||||||
private IEventBus eventBus = MinecraftForge.EVENT_BUS;
|
|
||||||
private volatile CountDownLatch exitLatch = null;
|
|
||||||
|
|
||||||
private FMLCommonHandler()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* The FML event bus. Subscribe here for FML related events
|
|
||||||
*
|
|
||||||
* @Deprecated Use {@link MinecraftForge#EVENT_BUS} they're the same thing now
|
|
||||||
* @return the event bus
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public IEventBus bus()
|
|
||||||
{
|
|
||||||
return eventBus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> beginLoading(IFMLSidedHandler handler)
|
|
||||||
{
|
|
||||||
sidedDelegate = handler;
|
|
||||||
MinecraftForge.initialize();
|
|
||||||
// MinecraftForge.registerCrashCallable();
|
|
||||||
return ImmutableList.<String>of();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the instance
|
|
||||||
*/
|
|
||||||
public static FMLCommonHandler instance()
|
|
||||||
{
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Find the container that associates with the supplied mod object
|
|
||||||
* @param mod
|
|
||||||
*/
|
|
||||||
public ModContainer findContainerFor(Object mod)
|
|
||||||
{
|
|
||||||
if (mod instanceof String)
|
|
||||||
{
|
|
||||||
return Loader.instance().getIndexedModList().get(mod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Loader.instance().getReversedModObjectList().get(mod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the forge mod loader logging instance (goes to the forgemodloader log file)
|
|
||||||
* @return The log instance for the FML log file
|
|
||||||
*
|
|
||||||
* @deprecated Not used in FML, Mods use your own logger, see {@link FMLPreInitializationEvent#getModLog()}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Logger getFMLLogger()
|
|
||||||
{
|
|
||||||
return FMLLog.log;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Side getSide()
|
|
||||||
{
|
|
||||||
return sidedDelegate.getSide();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the effective side for the context in the game. This is dependent
|
|
||||||
* on thread analysis to try and determine whether the code is running in the
|
|
||||||
* server or not. Use at your own risk
|
|
||||||
*/
|
|
||||||
public Side getEffectiveSide()
|
|
||||||
{
|
|
||||||
final ThreadGroup group = Thread.currentThread().getThreadGroup();
|
|
||||||
return group instanceof SidedThreadGroup ? ((SidedThreadGroup) group).getSide() : Side.CLIENT;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Raise an exception
|
|
||||||
*/
|
|
||||||
public void raiseException(Throwable exception, String message, boolean stopGame)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("Something raised an exception. The message was '{}'. 'stopGame' is {}", stopGame, exception);
|
|
||||||
if (stopGame)
|
|
||||||
{
|
|
||||||
getSidedDelegate().haltGame(message,exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public List<String> getBrandings(boolean includeMC)
|
|
||||||
{
|
|
||||||
if (brandings == null)
|
|
||||||
{
|
|
||||||
BrandingControl.computeBranding();
|
|
||||||
}
|
|
||||||
return includeMC ? ImmutableList.copyOf(brandings) : ImmutableList.copyOf(brandingsNoMC);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFMLSidedHandler getSidedDelegate()
|
|
||||||
{
|
|
||||||
return sidedDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPostServerTick()
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.ServerTickEvent(Phase.END));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Every tick just after world and other ticks occur
|
|
||||||
*/
|
|
||||||
public void onPostWorldTick(World world)
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.WorldTickEvent(Side.SERVER, Phase.END, world));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPreServerTick()
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.ServerTickEvent(Phase.START));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Every tick just before world and other ticks occur
|
|
||||||
*/
|
|
||||||
public void onPreWorldTick(World world)
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.WorldTickEvent(Side.SERVER, Phase.START, world));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleServerAboutToStart(MinecraftServer server)
|
|
||||||
{
|
|
||||||
return Loader.instance().serverAboutToStart(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleServerStarting(MinecraftServer server)
|
|
||||||
{
|
|
||||||
return Loader.instance().serverStarting(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleServerStarted()
|
|
||||||
{
|
|
||||||
Loader.instance().serverStarted();
|
|
||||||
sidedDelegate.allowLogins();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleServerStopping()
|
|
||||||
{
|
|
||||||
Loader.instance().serverStopping();
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getSavesDirectory() {
|
|
||||||
return sidedDelegate.getSavesDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MinecraftServer getMinecraftServerInstance()
|
|
||||||
{
|
|
||||||
return sidedDelegate.getServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showGuiScreen(Object clientGuiElement)
|
|
||||||
{
|
|
||||||
sidedDelegate.showGuiScreen(clientGuiElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void queryUser(StartupQuery query) throws InterruptedException
|
|
||||||
{
|
|
||||||
sidedDelegate.queryUser(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onServerStart(MinecraftServer dedicatedServer)
|
|
||||||
{
|
|
||||||
FMLServerHandler.instance();
|
|
||||||
sidedDelegate.beginServerLoading(dedicatedServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onServerStarted()
|
|
||||||
{
|
|
||||||
sidedDelegate.finishServerLoading();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void onPreClientTick()
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.ClientTickEvent(Phase.START));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPostClientTick()
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.ClientTickEvent(Phase.END));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRenderTickStart(float timer)
|
|
||||||
{
|
|
||||||
Animation.setClientPartialTickTime(timer);
|
|
||||||
bus().post(new TickEvent.RenderTickEvent(Phase.START, timer));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRenderTickEnd(float timer)
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.RenderTickEvent(Phase.END, timer));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPlayerPreTick(EntityPlayer player)
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.PlayerTickEvent(Phase.START, player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPlayerPostTick(EntityPlayer player)
|
|
||||||
{
|
|
||||||
bus().post(new TickEvent.PlayerTickEvent(Phase.END, player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleWorldDataSave(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
|
|
||||||
{
|
|
||||||
for (ModContainer mc : Loader.instance().getModList())
|
|
||||||
{
|
|
||||||
if (mc instanceof InjectedModContainer)
|
|
||||||
{
|
|
||||||
WorldPersistenceHooks.WorldPersistenceHook wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
|
|
||||||
if (wac != null)
|
|
||||||
{
|
|
||||||
NBTTagCompound dataForWriting = wac.getDataForWriting(handler, worldInfo);
|
|
||||||
tagCompound.setTag(mc.getModId(), dataForWriting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleWorldDataLoad(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
|
|
||||||
{
|
|
||||||
if (getEffectiveSide()!=LogicalSide.SERVER)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (handlerSet.contains(handler))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handlerSet.add(handler);
|
|
||||||
handlerToCheck = new WeakReference<SaveHandler>(handler); // for confirmBackupLevelDatUse
|
|
||||||
Map<String,NBTBase> additionalProperties = Maps.newHashMap();
|
|
||||||
worldInfo.setAdditionalProperties(additionalProperties);
|
|
||||||
for (ModContainer mc : Loader.instance().getModList())
|
|
||||||
{
|
|
||||||
if (mc instanceof InjectedModContainer)
|
|
||||||
{
|
|
||||||
WorldPersistenceHooks.WorldPersistenceHook wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
|
|
||||||
if (wac != null)
|
|
||||||
{
|
|
||||||
wac.readData(handler, worldInfo, additionalProperties, tagCompound.getCompoundTag(mc.getModId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void confirmBackupLevelDatUse(SaveHandler handler)
|
|
||||||
{
|
|
||||||
if (handlerToCheck == null || handlerToCheck.get() != handler) {
|
|
||||||
// only run if the save has been initially loaded
|
|
||||||
handlerToCheck = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String text = "Forge Mod Loader detected that the backup level.dat is being used.\n\n" +
|
|
||||||
"This may happen due to a bug or corruption, continuing can damage\n" +
|
|
||||||
"your world beyond repair or lose data / progress.\n\n" +
|
|
||||||
"It's recommended to create a world backup before continuing.";
|
|
||||||
|
|
||||||
boolean confirmed = StartupQuery.confirm(text);
|
|
||||||
if (!confirmed) StartupQuery.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDisplayCloseRequested()
|
|
||||||
{
|
|
||||||
return sidedDelegate != null && sidedDelegate.isDisplayCloseRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldServerBeKilledQuietly()
|
|
||||||
{
|
|
||||||
if (sidedDelegate == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return sidedDelegate.shouldServerShouldBeKilledQuietly();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make handleExit() wait for handleServerStopped().
|
|
||||||
*
|
|
||||||
* For internal use only!
|
|
||||||
*/
|
|
||||||
public void expectServerStopped()
|
|
||||||
{
|
|
||||||
exitLatch = new CountDownLatch(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delayed System.exit() until the server is actually stopped/done saving.
|
|
||||||
*
|
|
||||||
* For internal use only!
|
|
||||||
*
|
|
||||||
* @param retVal Exit code for System.exit()
|
|
||||||
*/
|
|
||||||
public void handleExit(int retVal)
|
|
||||||
{
|
|
||||||
CountDownLatch latch = exitLatch;
|
|
||||||
|
|
||||||
if (latch != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FMLLog.log.info("Waiting for the server to terminate/save.");
|
|
||||||
if (!latch.await(10, TimeUnit.SECONDS))
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("The server didn't stop within 10 seconds, exiting anyway.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FMLLog.log.info("Server terminated.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("Interrupted wait, exiting.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.exit(retVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleServerStopped()
|
|
||||||
{
|
|
||||||
sidedDelegate.serverStopped();
|
|
||||||
MinecraftServer server = getMinecraftServerInstance();
|
|
||||||
Loader.instance().serverStopped();
|
|
||||||
// FORCE the internal server to stop: hello optifine workaround!
|
|
||||||
if (server!=null) ObfuscationReflectionHelper.setPrivateValue(MinecraftServer.class, server, false, "field_71316"+"_v", "u", "serverStopped");
|
|
||||||
|
|
||||||
// allow any pending exit to continue, clear exitLatch
|
|
||||||
CountDownLatch latch = exitLatch;
|
|
||||||
|
|
||||||
if (latch != null)
|
|
||||||
{
|
|
||||||
latch.countDown();
|
|
||||||
exitLatch = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModName()
|
|
||||||
{
|
|
||||||
List<String> modNames = Lists.newArrayListWithExpectedSize(3);
|
|
||||||
modNames.add("fml");
|
|
||||||
if (!noForge)
|
|
||||||
{
|
|
||||||
modNames.add(ForgeVersion.MOD_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Loader.instance().getFMLBrandingProperties().containsKey("snooperbranding"))
|
|
||||||
{
|
|
||||||
modNames.add(Loader.instance().getFMLBrandingProperties().get("snooperbranding"));
|
|
||||||
}
|
|
||||||
return Joiner.on(',').join(modNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addModToResourcePack(ModContainer container)
|
|
||||||
{
|
|
||||||
sidedDelegate.addModAsResource(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrentLanguage()
|
|
||||||
{
|
|
||||||
|
|
||||||
return sidedDelegate.getCurrentLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bootstrap()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetworkManager getClientToServerNetworkManager()
|
|
||||||
{
|
|
||||||
return sidedDelegate.getClientToServerNetworkManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireMouseInput()
|
|
||||||
{
|
|
||||||
bus().post(new InputEvent.MouseInputEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireKeyInput()
|
|
||||||
{
|
|
||||||
bus().post(new InputEvent.KeyInputEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerChangedDimensionEvent(EntityPlayer player, int fromDim, int toDim)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.PlayerChangedDimensionEvent(player, fromDim, toDim));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerLoggedIn(EntityPlayer player)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.PlayerLoggedInEvent(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerLoggedOut(EntityPlayer player)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.PlayerLoggedOutEvent(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerRespawnEvent(EntityPlayer player, boolean endConquered)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.PlayerRespawnEvent(player, endConquered));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerItemPickupEvent(EntityPlayer player, EntityItem item, ItemStack clone)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.ItemPickupEvent(player, item, clone));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerCraftingEvent(EntityPlayer player, ItemStack crafted, IInventory craftMatrix)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.ItemCraftedEvent(player, crafted, craftMatrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void firePlayerSmeltedEvent(EntityPlayer player, ItemStack smelted)
|
|
||||||
{
|
|
||||||
bus().post(new PlayerEvent.ItemSmeltedEvent(player, smelted));
|
|
||||||
}
|
|
||||||
|
|
||||||
public INetHandler getClientPlayHandler()
|
|
||||||
{
|
|
||||||
return sidedDelegate.getClientPlayHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireNetRegistrationEvent(NetworkManager manager, Set<String> channelSet, String channel, Side side)
|
|
||||||
{
|
|
||||||
sidedDelegate.fireNetRegistrationEvent(bus(), manager, channelSet, channel, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldAllowPlayerLogins()
|
|
||||||
{
|
|
||||||
return sidedDelegate.shouldAllowPlayerLogins();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireServerConnectionEvent(NetworkManager manager)
|
|
||||||
{
|
|
||||||
bus().post(new FMLNetworkEvent.ServerConnectionFromClientEvent(manager));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process initial Handshake packet, kicks players from the server if they are connecting while we are starting up.
|
|
||||||
* Also verifies the client has the FML marker.
|
|
||||||
*
|
|
||||||
* @param packet Handshake Packet
|
|
||||||
* @param manager NetworkDirection connection
|
|
||||||
* @return True to allow connection, otherwise False.
|
|
||||||
*/
|
|
||||||
public boolean handleServerHandshake(C00Handshake packet, NetworkManager manager)
|
|
||||||
{
|
|
||||||
if (!shouldAllowPlayerLogins())
|
|
||||||
{
|
|
||||||
TextComponentString text = new TextComponentString("Server is still starting! Please wait before reconnecting.");
|
|
||||||
LOGGER.info("Disconnecting Player: {}", text.getUnformattedText());
|
|
||||||
manager.sendPacket(new SPacketDisconnect(text));
|
|
||||||
manager.closeChannel(text);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet.getRequestedState() == EnumConnectionState.LOGIN && (!NetworkRegistry.INSTANCE.isVanillaAccepted(Side.CLIENT) && !packet.hasFMLMarker()))
|
|
||||||
{
|
|
||||||
manager.setConnectionState(EnumConnectionState.LOGIN);
|
|
||||||
TextComponentString text = new TextComponentString("This server has mods that require FML/Forge to be installed on the client. Contact your server admin for more details.");
|
|
||||||
Collection<String> modNames = NetworkRegistry.INSTANCE.getRequiredMods(Side.CLIENT);
|
|
||||||
FMLLog.log.info("Disconnecting Player: This server has mods that require FML/Forge to be installed on the client: {}", modNames);
|
|
||||||
manager.sendPacket(new SPacketDisconnect(text));
|
|
||||||
manager.closeChannel(text);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.channel().attr(net.minecraftforge.fml.network.NetworkRegistry.FML_MARKER).set(packet.hasFMLMarker());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void processWindowMessages()
|
|
||||||
{
|
|
||||||
if (sidedDelegate == null) return;
|
|
||||||
sidedDelegate.processWindowMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to exit from java, with system exit preventions in place. Will be tidy about it and just log a message,
|
|
||||||
* unless debugging is enabled
|
|
||||||
*
|
|
||||||
* @param exitCode The exit code
|
|
||||||
* @param hardExit Perform a halt instead of an exit (only use when the world is unsavable) - read the warnings at {@link Runtime#halt(int)}
|
|
||||||
*/
|
|
||||||
public void exitJava(int exitCode, boolean hardExit)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("Java has been asked to exit (code {})", exitCode);
|
|
||||||
if (hardExit)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("This is an abortive exit and could cause world corruption or other things");
|
|
||||||
}
|
|
||||||
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
|
|
||||||
FMLLog.log.warn("Exit trace:");
|
|
||||||
//The first 2 elements are Thread#getStackTrace and FMLCommonHandler#exitJava and aren't relevant
|
|
||||||
for (int i = 2; i < stack.length; i++)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("\t{}", stack[i]);
|
|
||||||
}
|
|
||||||
if (hardExit)
|
|
||||||
{
|
|
||||||
Runtime.getRuntime().halt(exitCode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Runtime.getRuntime().exit(exitCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IThreadListener getWorldThread(INetHandler net)
|
|
||||||
{
|
|
||||||
return sidedDelegate.getWorldThread(net);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void callFuture(FutureTask<?> task)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
task.run();
|
|
||||||
task.get(); // Forces the exception to be thrown if any
|
|
||||||
}
|
|
||||||
catch (InterruptedException | ExecutionException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.fatal("Exception caught executing FutureTask: {}", e.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String stripSpecialChars(String message)
|
|
||||||
{
|
|
||||||
return sidedDelegate != null ? sidedDelegate.stripSpecialChars(message) : message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadRenderers() {
|
|
||||||
sidedDelegate.reloadRenderers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireSidedRegistryEvents()
|
|
||||||
{
|
|
||||||
sidedDelegate.fireSidedRegistryEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompoundDataFixer getDataFixer()
|
|
||||||
{
|
|
||||||
return (CompoundDataFixer)sidedDelegate.getDataFixer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDisplayVSyncForced() { return sidedDelegate.isDisplayVSyncForced(); }
|
|
||||||
public void resetClientRecipeBook() {
|
|
||||||
this.sidedDelegate.resetClientRecipeBook();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadSearchTrees() {
|
|
||||||
this.sidedDelegate.reloadSearchTrees();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reloadCreativeSettings()
|
|
||||||
{
|
|
||||||
this.sidedDelegate.reloadCreativeSettings();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Level;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.ThreadContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FMLs logging class. <b>Internal use only, NOT FOR MOD LOGGING!</b> Mods use your own log, see {@link FMLPreInitializationEvent#getModLog()}.
|
|
||||||
* TODO 1.13 remove all the deprecated methods
|
|
||||||
*/
|
|
||||||
public class FMLLog
|
|
||||||
{
|
|
||||||
|
|
||||||
public static final Logger log = LogManager.getLogger("FML");
|
|
||||||
|
|
||||||
public static void bigWarning(String format, Object... data)
|
|
||||||
{
|
|
||||||
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
|
||||||
log.warn("****************************************");
|
|
||||||
log.warn("* "+format, data);
|
|
||||||
for (int i = 2; i < 8 && i < trace.length; i++)
|
|
||||||
{
|
|
||||||
log.warn("* at {}{}", trace[i].toString(), i == 7 ? "..." : "");
|
|
||||||
}
|
|
||||||
log.warn("****************************************");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void log(String targetLog, Level level, String format, Object... data)
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.log(targetLog, level, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void log(Level level, String format, Object... data)
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.log(level, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void log(String targetLog, Level level, Throwable ex, String format, Object... data)
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.log(targetLog, level, ex, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void log(Level level, Throwable ex, String format, Object... data)
|
|
||||||
{
|
|
||||||
FMLRelaunchLog.log(level, ex, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void severe(String format, Object... data)
|
|
||||||
{
|
|
||||||
log(Level.ERROR, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void warning(String format, Object... data)
|
|
||||||
{
|
|
||||||
log(Level.WARN, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void info(String format, Object... data)
|
|
||||||
{
|
|
||||||
log(Level.INFO, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void fine(String format, Object... data)
|
|
||||||
{
|
|
||||||
log(Level.DEBUG, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void finer(String format, Object... data)
|
|
||||||
{
|
|
||||||
log(Level.TRACE, format, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static Logger getLogger()
|
|
||||||
{
|
|
||||||
return log;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,22 +21,23 @@ package net.minecraftforge.fml.common;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.IEnvironment;
|
import cpw.mods.modlauncher.api.IEnvironment;
|
||||||
import net.minecraftforge.fml.FileUtils;
|
import net.minecraftforge.fml.FileUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.CORE;
|
import static net.minecraftforge.fml.Logging.CORE;
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
|
||||||
|
|
||||||
public enum FMLPaths
|
public enum FMLPaths
|
||||||
{
|
{
|
||||||
GAMEDIR(),
|
GAMEDIR(),
|
||||||
MODSDIR("mods"),
|
MODSDIR("mods"),
|
||||||
CONFIGDIR("config"),
|
CONFIGDIR("config"),
|
||||||
FMLCONFIG(false, CONFIGDIR, "fml.cfg");
|
FMLCONFIG(false, CONFIGDIR, "fml.toml");
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private final Path relativePath;
|
private final Path relativePath;
|
||||||
private final boolean isDirectory;
|
private final boolean isDirectory;
|
||||||
private Path absolutePath;
|
private Path absolutePath;
|
||||||
|
@ -71,7 +72,7 @@ public enum FMLPaths
|
||||||
for (FMLPaths path : FMLPaths.values())
|
for (FMLPaths path : FMLPaths.values())
|
||||||
{
|
{
|
||||||
path.absolutePath = rootPath.resolve(path.relativePath).toAbsolutePath();
|
path.absolutePath = rootPath.resolve(path.relativePath).toAbsolutePath();
|
||||||
fmlLog.debug(CORE,"Path {} is {}", ()-> path, ()-> path.absolutePath);
|
LOGGER.debug(CORE,"Path {} is {}", ()-> path, ()-> path.absolutePath);
|
||||||
if (path.isDirectory)
|
if (path.isDirectory)
|
||||||
{
|
{
|
||||||
FileUtils.getOrCreateDirectory(path.absolutePath, path.name());
|
FileUtils.getOrCreateDirectory(path.absolutePath, path.name());
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import net.minecraft.command.EntitySelector;
|
|
||||||
import net.minecraft.command.ICommandSender;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows mods to create custom selectors in commands.
|
|
||||||
* Registered in {@link net.minecraftforge.fml.common.registry.GameRegistry#registerEntitySelector(IEntitySelectorFactory, String...)}
|
|
||||||
* For an example implementation, see CustomEntitySelectorTest
|
|
||||||
*/
|
|
||||||
public interface IEntitySelectorFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called every time a command that contains entity selectors is executed
|
|
||||||
*
|
|
||||||
* @param arguments A map with all arguments and their values
|
|
||||||
* @param mainSelector The main selector string (e.g. 'a' for all players or 'e' for all entities)
|
|
||||||
* @param sender The sender of the command
|
|
||||||
* @param position A position either specified in the selector arguments or by the players position. See {@link EntitySelector#getPosFromArguments(Map, Vec3d)}
|
|
||||||
* @return A list of new predicates, can be empty ({@link Collections#emptyList()} but not null.
|
|
||||||
*/
|
|
||||||
@Nonnull List<Predicate<Entity>> createPredicates(Map<String, String> arguments, String mainSelector, ICommandSender sender, Vec3d position);
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.network.INetHandler;
|
|
||||||
import net.minecraft.network.NetworkManager;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.util.IThreadListener;
|
|
||||||
import net.minecraftforge.common.util.CompoundDataFixer;
|
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.StartupQuery;
|
|
||||||
|
|
||||||
public interface IFMLSidedHandler
|
|
||||||
{
|
|
||||||
List<String> getAdditionalBrandingInformation();
|
|
||||||
|
|
||||||
Side getSide();
|
|
||||||
|
|
||||||
void haltGame(String message, Throwable exception);
|
|
||||||
|
|
||||||
void showGuiScreen(Object clientGuiElement);
|
|
||||||
|
|
||||||
void queryUser(StartupQuery query) throws InterruptedException;
|
|
||||||
|
|
||||||
void beginServerLoading(MinecraftServer server);
|
|
||||||
|
|
||||||
void finishServerLoading();
|
|
||||||
|
|
||||||
File getSavesDirectory();
|
|
||||||
|
|
||||||
MinecraftServer getServer();
|
|
||||||
|
|
||||||
boolean isDisplayCloseRequested();
|
|
||||||
|
|
||||||
boolean shouldServerShouldBeKilledQuietly();
|
|
||||||
|
|
||||||
void addModAsResource(ModContainer container);
|
|
||||||
|
|
||||||
String getCurrentLanguage();
|
|
||||||
|
|
||||||
void serverStopped();
|
|
||||||
|
|
||||||
NetworkManager getClientToServerNetworkManager();
|
|
||||||
|
|
||||||
INetHandler getClientPlayHandler();
|
|
||||||
|
|
||||||
void fireNetRegistrationEvent(IEventBus bus, NetworkManager manager, Set<String> channelSet, String channel, Side side);
|
|
||||||
|
|
||||||
boolean shouldAllowPlayerLogins();
|
|
||||||
|
|
||||||
void allowLogins();
|
|
||||||
|
|
||||||
IThreadListener getWorldThread(INetHandler net);
|
|
||||||
|
|
||||||
void processWindowMessages();
|
|
||||||
|
|
||||||
String stripSpecialChars(String message);
|
|
||||||
|
|
||||||
void reloadRenderers();
|
|
||||||
|
|
||||||
void fireSidedRegistryEvents();
|
|
||||||
|
|
||||||
CompoundDataFixer getDataFixer();
|
|
||||||
|
|
||||||
boolean isDisplayVSyncForced();
|
|
||||||
|
|
||||||
default void resetClientRecipeBook(){}
|
|
||||||
|
|
||||||
default void reloadSearchTrees(){}
|
|
||||||
|
|
||||||
default void reloadCreativeSettings(){}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraftforge.event.furnace.FurnaceFuelBurnTimeEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated set your item's {@link Item#getItemBurnTime(ItemStack)} or subscribe to {@link FurnaceFuelBurnTimeEvent} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface IFuelHandler
|
|
||||||
{
|
|
||||||
int getBurnTime(ItemStack fuel);
|
|
||||||
}
|
|
|
@ -1,382 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import net.minecraftforge.common.util.TextTable;
|
|
||||||
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
|
|
||||||
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLLoadEvent;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLModDisabledEvent;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
|
||||||
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.ThreadContext;
|
|
||||||
import org.apache.logging.log4j.message.FormattedMessage;
|
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
|
||||||
import com.google.common.collect.BiMap;
|
|
||||||
import com.google.common.collect.ImmutableBiMap;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.ListMultimap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class LoadController
|
|
||||||
{
|
|
||||||
private Loader loader;
|
|
||||||
private EventBus masterChannel;
|
|
||||||
private ImmutableMap<String, EventBus> eventChannels;
|
|
||||||
private LoaderState state;
|
|
||||||
private Multimap<String, ModState> modStates = ArrayListMultimap.create();
|
|
||||||
private List<ModContainer> activeModList = Lists.newArrayList();
|
|
||||||
private ModContainer activeContainer;
|
|
||||||
private BiMap<ModContainer, Object> modObjectList;
|
|
||||||
private ListMultimap<String, ModContainer> packageOwners;
|
|
||||||
|
|
||||||
public LoadController(Loader loader)
|
|
||||||
{
|
|
||||||
this.loader = loader;
|
|
||||||
this.masterChannel = new FMLThrowingEventBus((exception, context) -> {
|
|
||||||
Throwables.throwIfUnchecked(exception);
|
|
||||||
// should not happen, but add some extra context for checked exceptions
|
|
||||||
Method method = context.getSubscriberMethod();
|
|
||||||
String parameterNames = Stream.of(method.getParameterTypes()).map(Class::getName).collect(Collectors.joining(", "));
|
|
||||||
String message = "Exception thrown during LoadController." + method.getName() + '(' + parameterNames + ')';
|
|
||||||
throw new LoaderExceptionModCrash(message, exception);
|
|
||||||
});
|
|
||||||
this.masterChannel.register(this);
|
|
||||||
|
|
||||||
state = LoaderState.NOINIT;
|
|
||||||
packageOwners = ArrayListMultimap.create();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void disableMod(ModContainer mod)
|
|
||||||
{
|
|
||||||
HashMap<String, EventBus> temporary = Maps.newHashMap(eventChannels);
|
|
||||||
String modId = mod.getModId();
|
|
||||||
EventBus bus = temporary.remove(modId);
|
|
||||||
bus.post(new FMLModDisabledEvent());
|
|
||||||
eventChannels = ImmutableMap.copyOf(temporary);
|
|
||||||
modStates.put(modId, ModState.DISABLED);
|
|
||||||
modObjectList.remove(mod);
|
|
||||||
activeModList.remove(mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void buildModList(FMLLoadEvent event)
|
|
||||||
{
|
|
||||||
Builder<String, EventBus> eventBus = ImmutableMap.builder();
|
|
||||||
|
|
||||||
for (final ModContainer mod : loader.getModList())
|
|
||||||
{
|
|
||||||
EventBus bus = new FMLThrowingEventBus((exception, context) -> this.errorOccurred(mod, exception));
|
|
||||||
|
|
||||||
boolean isActive = mod.registerBus(bus, this);
|
|
||||||
if (isActive)
|
|
||||||
{
|
|
||||||
activeModList.add(mod);
|
|
||||||
modStates.put(mod.getModId(), ModState.UNLOADED);
|
|
||||||
eventBus.put(mod.getModId(), bus);
|
|
||||||
FMLCommonHandler.instance().addModToResourcePack(mod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("Mod {} has been disabled through configuration", mod.getModId());
|
|
||||||
modStates.put(mod.getModId(), ModState.UNLOADED);
|
|
||||||
modStates.put(mod.getModId(), ModState.DISABLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eventChannels = eventBus.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void distributeStateMessage(LoaderState state, Object... eventData)
|
|
||||||
{
|
|
||||||
if (state.hasEvent())
|
|
||||||
{
|
|
||||||
masterChannel.post(state.getEvent(eventData));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void transition(LoaderState desiredState, boolean forceState)
|
|
||||||
{
|
|
||||||
if (FMLCommonHandler.instance().isDisplayCloseRequested())
|
|
||||||
{
|
|
||||||
FMLLog.log.info("The game window is being closed by the player, exiting.");
|
|
||||||
FMLCommonHandler.instance().exitJava(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoaderState oldState = state;
|
|
||||||
state = state.transition(false);
|
|
||||||
if (state != desiredState)
|
|
||||||
{
|
|
||||||
if (!forceState)
|
|
||||||
{
|
|
||||||
FormattedMessage message = new FormattedMessage("A fatal error occurred during the state transition from {} to {}. State became {} instead. Loading cannot continue.", oldState, desiredState, state);
|
|
||||||
throw new LoaderException(message.getFormattedMessage());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FMLLog.log.info("The state engine was in incorrect state {} and forced into state {}. Errors may have been discarded.", state, desiredState);
|
|
||||||
forceState(desiredState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ModContainer activeContainer()
|
|
||||||
{
|
|
||||||
return activeContainer != null ? activeContainer : findActiveContainerFromStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
void forceActiveContainer(@Nullable ModContainer container)
|
|
||||||
{
|
|
||||||
activeContainer = container;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void propogateStateMessage(ModLifecycleEvent stateEvent)
|
|
||||||
{
|
|
||||||
if (stateEvent instanceof FMLPreInitializationEvent)
|
|
||||||
{
|
|
||||||
modObjectList = buildModObjectList();
|
|
||||||
}
|
|
||||||
ProgressBar bar = ProgressManager.push(stateEvent.description(), activeModList.size(), true);
|
|
||||||
for (ModContainer mc : activeModList)
|
|
||||||
{
|
|
||||||
bar.step(mc.getName());
|
|
||||||
sendEventToModContainer(stateEvent, mc);
|
|
||||||
}
|
|
||||||
ProgressManager.pop(bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendEventToModContainer(ModLifecycleEvent stateEvent, ModContainer mc)
|
|
||||||
{
|
|
||||||
String modId = mc.getModId();
|
|
||||||
Collection<String> requirements = mc.getRequirements().stream().map(ArtifactVersion::getLabel).collect(Collectors.toCollection(HashSet::new));
|
|
||||||
for (ArtifactVersion av : mc.getDependencies())
|
|
||||||
{
|
|
||||||
if (av.getLabel() != null && requirements.contains(av.getLabel()) && modStates.containsEntry(av.getLabel(), ModState.ERRORED))
|
|
||||||
{
|
|
||||||
LogManager.getLogger(modId).error("Skipping event {} and marking errored mod {} since required dependency {} has errored", stateEvent.getEventType(), modId, av.getLabel());
|
|
||||||
modStates.put(modId, ModState.ERRORED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
activeContainer = mc;
|
|
||||||
stateEvent.applyModContainer(mc);
|
|
||||||
ThreadContext.put("mod", modId);
|
|
||||||
LogManager.getLogger(modId).trace("Sending event {} to mod {}", stateEvent.getEventType(), modId);
|
|
||||||
eventChannels.get(modId).post(stateEvent);
|
|
||||||
LogManager.getLogger(modId).trace("Sent event {} to mod {}", stateEvent.getEventType(), modId);
|
|
||||||
ThreadContext.remove("mod");
|
|
||||||
activeContainer = null;
|
|
||||||
if (stateEvent instanceof FMLStateEvent)
|
|
||||||
{
|
|
||||||
if (!errors.containsKey(modId))
|
|
||||||
{
|
|
||||||
modStates.put(modId, ((FMLStateEvent)stateEvent).getModState());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
modStates.put(modId, ModState.ERRORED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImmutableBiMap<ModContainer, Object> buildModObjectList()
|
|
||||||
{
|
|
||||||
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.builder();
|
|
||||||
for (ModContainer mc : activeModList)
|
|
||||||
{
|
|
||||||
if (!mc.isImmutable() && mc.getMod() != null)
|
|
||||||
{
|
|
||||||
builder.put(mc, mc.getMod());
|
|
||||||
List<String> packages = mc.getOwnedPackages();
|
|
||||||
for (String pkg : packages)
|
|
||||||
{
|
|
||||||
packageOwners.put(pkg, mc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mc.getMod() == null && !mc.isImmutable() && state != LoaderState.CONSTRUCTING)
|
|
||||||
{
|
|
||||||
FormattedMessage message = new FormattedMessage("There is a severe problem with {} ({}) - it appears not to have constructed correctly", mc.getName(), mc.getModId());
|
|
||||||
this.errorOccurred(mc, new RuntimeException(message.getFormattedMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void errorOccurred(ModContainer modContainer, Throwable exception)
|
|
||||||
{
|
|
||||||
String modId = modContainer.getModId();
|
|
||||||
String modName = modContainer.getName();
|
|
||||||
modStates.put(modId, ModState.ERRORED);
|
|
||||||
if (exception instanceof InvocationTargetException)
|
|
||||||
{
|
|
||||||
exception = exception.getCause();
|
|
||||||
}
|
|
||||||
if (exception instanceof LoaderException) // avoid wrapping loader exceptions multiple times
|
|
||||||
{
|
|
||||||
throw (LoaderException) exception;
|
|
||||||
}
|
|
||||||
FormattedMessage message = new FormattedMessage("Caught exception from {} ({})", modName, modId);
|
|
||||||
throw new LoaderExceptionModCrash(message.getFormattedMessage(), exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printModStates(StringBuilder ret)
|
|
||||||
{
|
|
||||||
ret.append("\n\tStates:");
|
|
||||||
for (ModState state : ModState.values())
|
|
||||||
ret.append(" '").append(state.getMarker()).append("' = ").append(state.toString());
|
|
||||||
|
|
||||||
TextTable table = new TextTable(Lists.newArrayList(
|
|
||||||
TextTable.column("State"),
|
|
||||||
TextTable.column("ID"),
|
|
||||||
TextTable.column("Version"),
|
|
||||||
TextTable.column("Source"),
|
|
||||||
TextTable.column("Signature"))
|
|
||||||
);
|
|
||||||
for (ModContainer mc : loader.getModList())
|
|
||||||
{
|
|
||||||
table.add(
|
|
||||||
modStates.get(mc.getModId()).stream().map(ModState::getMarker).reduce("", (a, b) -> a + b),
|
|
||||||
mc.getModId(),
|
|
||||||
mc.getVersion(),
|
|
||||||
mc.getSource().getName(),
|
|
||||||
mc.getSigningCertificate() != null ? CertificateHelper.getFingerprint(mc.getSigningCertificate()) : "None"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.append("\n");
|
|
||||||
ret.append("\n\t");
|
|
||||||
table.append(ret, "\n\t");
|
|
||||||
ret.append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ModContainer> getActiveModList()
|
|
||||||
{
|
|
||||||
return activeModList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModState getModState(ModContainer selectedMod)
|
|
||||||
{
|
|
||||||
return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void distributeStateMessage(Class<?> customEvent)
|
|
||||||
{
|
|
||||||
Object eventInstance;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
eventInstance = customEvent.newInstance();
|
|
||||||
}
|
|
||||||
catch (InstantiationException | IllegalAccessException e)
|
|
||||||
{
|
|
||||||
throw new LoaderException("Failed to create new event instance for " + customEvent.getName(), e);
|
|
||||||
}
|
|
||||||
masterChannel.post(eventInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BiMap<ModContainer, Object> getModObjectList()
|
|
||||||
{
|
|
||||||
if (modObjectList == null)
|
|
||||||
{
|
|
||||||
FMLLog.log.fatal("Detected an attempt by a mod {} to perform game activity during mod construction. This is a serious programming error.", activeContainer);
|
|
||||||
return buildModObjectList();
|
|
||||||
}
|
|
||||||
return ImmutableBiMap.copyOf(modObjectList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInState(LoaderState state)
|
|
||||||
{
|
|
||||||
return this.state == state;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasReachedState(LoaderState state)
|
|
||||||
{
|
|
||||||
return this.state.ordinal() >= state.ordinal() && this.state != LoaderState.ERRORED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void forceState(LoaderState newState)
|
|
||||||
{
|
|
||||||
this.state = newState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private ModContainer findActiveContainerFromStack()
|
|
||||||
{
|
|
||||||
for (Class<?> c : getCallingStack())
|
|
||||||
{
|
|
||||||
int idx = c.getName().lastIndexOf('.');
|
|
||||||
if (idx == -1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String pkg = c.getName().substring(0, idx);
|
|
||||||
if (packageOwners.containsKey(pkg))
|
|
||||||
{
|
|
||||||
return packageOwners.get(pkg).get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FMLSecurityManager accessibleManager = new FMLSecurityManager();
|
|
||||||
|
|
||||||
class FMLSecurityManager extends SecurityManager
|
|
||||||
{
|
|
||||||
Class<?>[] getStackClasses()
|
|
||||||
{
|
|
||||||
return getClassContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?>[] getCallingStack()
|
|
||||||
{
|
|
||||||
return accessibleManager.getStackClasses();
|
|
||||||
}
|
|
||||||
|
|
||||||
LoaderState getState()
|
|
||||||
{
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,127 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
|
|
||||||
import net.minecraftforge.fml.common.versioning.VersionParser;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonParseException;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import com.google.gson.TypeAdapter;
|
|
||||||
import com.google.gson.stream.JsonReader;
|
|
||||||
import com.google.gson.stream.JsonWriter;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class MetadataCollection
|
|
||||||
{
|
|
||||||
private String modListVersion;
|
|
||||||
private ModMetadata[] modList;
|
|
||||||
private Map<String, ModMetadata> metadatas = Maps.newHashMap();
|
|
||||||
|
|
||||||
public static MetadataCollection from(@Nullable InputStream inputStream, String sourceName)
|
|
||||||
{
|
|
||||||
if (inputStream == null)
|
|
||||||
{
|
|
||||||
return new MetadataCollection();
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MetadataCollection collection;
|
|
||||||
Gson gson = new GsonBuilder().registerTypeAdapter(ArtifactVersion.class, new ArtifactVersionAdapter()).create();
|
|
||||||
JsonParser parser = new JsonParser();
|
|
||||||
JsonElement rootElement = parser.parse(reader);
|
|
||||||
if (rootElement.isJsonArray())
|
|
||||||
{
|
|
||||||
collection = new MetadataCollection();
|
|
||||||
JsonArray jsonList = rootElement.getAsJsonArray();
|
|
||||||
collection.modList = new ModMetadata[jsonList.size()];
|
|
||||||
int i = 0;
|
|
||||||
for (JsonElement mod : jsonList)
|
|
||||||
{
|
|
||||||
collection.modList[i++]=gson.fromJson(mod, ModMetadata.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
collection = gson.fromJson(rootElement, MetadataCollection.class);
|
|
||||||
}
|
|
||||||
collection.parseModMetadataList();
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
catch (JsonParseException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("The mcmod.info file in {} cannot be parsed as valid JSON. It will be ignored", sourceName, e);
|
|
||||||
return new MetadataCollection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseModMetadataList()
|
|
||||||
{
|
|
||||||
for (ModMetadata modMetadata : modList)
|
|
||||||
{
|
|
||||||
metadatas.put(modMetadata.modId, modMetadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModMetadata getMetadataForId(String modId, Map<String, Object> extraData)
|
|
||||||
{
|
|
||||||
if (!metadatas.containsKey(modId))
|
|
||||||
{
|
|
||||||
ModMetadata dummy = new ModMetadata();
|
|
||||||
dummy.modId = modId;
|
|
||||||
dummy.name = (String) extraData.get("name");
|
|
||||||
dummy.version = (String) extraData.get("version");
|
|
||||||
dummy.autogenerated = true;
|
|
||||||
metadatas.put(modId, dummy);
|
|
||||||
}
|
|
||||||
return metadatas.get(modId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ArtifactVersionAdapter extends TypeAdapter<ArtifactVersion>
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(JsonWriter out, ArtifactVersion value) throws IOException
|
|
||||||
{
|
|
||||||
// no op - we never write these out
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArtifactVersion read(JsonReader in) throws IOException
|
|
||||||
{
|
|
||||||
return VersionParser.parseVersionReference(in.nextString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
|
||||||
import net.minecraftforge.fml.client.GuiModsMissing;
|
|
||||||
import net.minecraftforge.fml.client.IDisplayableError;
|
|
||||||
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
|
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
||||||
|
|
||||||
public class MissingModsException extends EnhancedRuntimeException implements IDisplayableError
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
private final String id;
|
|
||||||
private final String name;
|
|
||||||
/** @deprecated use {@link #getMissingModInfos()} */
|
|
||||||
@Deprecated // TODO remove in 1.13
|
|
||||||
public final Set<ArtifactVersion> missingMods;
|
|
||||||
private final List<MissingModInfo> missingModsInfos;
|
|
||||||
private final String modName;
|
|
||||||
|
|
||||||
public MissingModsException(String id, String name)
|
|
||||||
{
|
|
||||||
this(new HashSet<>(), id, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated use {@link #MissingModsException(String, String)}
|
|
||||||
*/
|
|
||||||
@Deprecated // TODO remove in 1.13
|
|
||||||
public MissingModsException(Set<ArtifactVersion> missingMods, String id, String name)
|
|
||||||
{
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.missingMods = missingMods;
|
|
||||||
this.missingModsInfos = new ArrayList<>();
|
|
||||||
for (ArtifactVersion artifactVersion : missingMods)
|
|
||||||
{
|
|
||||||
missingModsInfos.add(new MissingModInfo(artifactVersion, null, true));
|
|
||||||
}
|
|
||||||
this.modName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage()
|
|
||||||
{
|
|
||||||
Set<ArtifactVersion> missingMods = missingModsInfos.stream().map(MissingModInfo::getAcceptedVersion).collect(Collectors.toSet());
|
|
||||||
return String.format("Mod %s (%s) requires %s", id, name, missingMods);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMissingMod(ArtifactVersion acceptedVersion, @Nullable ArtifactVersion currentVersion, boolean required)
|
|
||||||
{
|
|
||||||
MissingModInfo missingModInfo = new MissingModInfo(acceptedVersion, currentVersion, required);
|
|
||||||
this.missingModsInfos.add(missingModInfo);
|
|
||||||
this.missingMods.add(acceptedVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModName()
|
|
||||||
{
|
|
||||||
return modName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MissingModInfo> getMissingModInfos()
|
|
||||||
{
|
|
||||||
return Collections.unmodifiableList(this.missingModsInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void printStackTrace(WrappedPrintStream stream)
|
|
||||||
{
|
|
||||||
stream.println("Missing Mods:");
|
|
||||||
for (MissingModInfo info : this.missingModsInfos)
|
|
||||||
{
|
|
||||||
ArtifactVersion acceptedVersion = info.getAcceptedVersion();
|
|
||||||
ArtifactVersion currentVersion = info.getCurrentVersion();
|
|
||||||
String currentString = currentVersion != null ? currentVersion.getVersionString() : "missing";
|
|
||||||
stream.println(String.format("\t%s : need %s: have %s", acceptedVersion.getVersionString(), acceptedVersion.getRangeString(), currentString));
|
|
||||||
}
|
|
||||||
stream.println("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
public GuiScreen createGui()
|
|
||||||
{
|
|
||||||
return new GuiModsMissing(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MissingModInfo
|
|
||||||
{
|
|
||||||
private final ArtifactVersion acceptedVersion;
|
|
||||||
@Nullable
|
|
||||||
private final ArtifactVersion currentVersion;
|
|
||||||
private final boolean required;
|
|
||||||
|
|
||||||
private MissingModInfo(ArtifactVersion acceptedVersion, @Nullable ArtifactVersion currentVersion, boolean required)
|
|
||||||
{
|
|
||||||
Preconditions.checkNotNull(acceptedVersion, "acceptedVersion");
|
|
||||||
this.acceptedVersion = acceptedVersion;
|
|
||||||
this.currentVersion = currentVersion;
|
|
||||||
this.required = required;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ArtifactVersion getCurrentVersion()
|
|
||||||
{
|
|
||||||
return currentVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtifactVersion getAcceptedVersion()
|
|
||||||
{
|
|
||||||
return acceptedVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRequired()
|
|
||||||
{
|
|
||||||
return required;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,187 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.IClassTransformer;
|
|
||||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple delegating class loader used to load mods into the system
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ModClassLoader extends URLClassLoader
|
|
||||||
{
|
|
||||||
private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar", "rt.jar");
|
|
||||||
private LaunchClassLoader mainClassLoader;
|
|
||||||
private List<File> sources;
|
|
||||||
|
|
||||||
public ModClassLoader(ClassLoader parent) {
|
|
||||||
super(new URL[0], null);
|
|
||||||
if (parent instanceof LaunchClassLoader)
|
|
||||||
{
|
|
||||||
this.mainClassLoader = (LaunchClassLoader)parent;
|
|
||||||
}
|
|
||||||
this.sources = Lists.newArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addFile(File modFile) throws MalformedURLException
|
|
||||||
{
|
|
||||||
URL url = modFile.toURI().toURL();
|
|
||||||
mainClassLoader.addURL(url);
|
|
||||||
this.sources.add(modFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
|
||||||
{
|
|
||||||
return mainClassLoader.loadClass(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public File[] getParentSources() {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<File> files=new ArrayList<File>();
|
|
||||||
for(URL url : mainClassLoader.getSources())
|
|
||||||
{
|
|
||||||
URI uri = url.toURI();
|
|
||||||
if(uri.getScheme().equals("file"))
|
|
||||||
{
|
|
||||||
files.add(new File(uri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files.toArray(new File[]{});
|
|
||||||
}
|
|
||||||
catch (URISyntaxException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("Unable to process our input to locate the minecraft code", e);
|
|
||||||
throw new LoaderException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getDefaultLibraries()
|
|
||||||
{
|
|
||||||
return STANDARD_LIBRARIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDefaultLibrary(File file)
|
|
||||||
{
|
|
||||||
String home = System.getProperty("java.home"); // Nullcheck just in case some JVM decides to be stupid
|
|
||||||
if (home != null && file.getAbsolutePath().startsWith(home)) return true;
|
|
||||||
// Should really pull this from the json somehow, but we dont have that at runtime.
|
|
||||||
String name = file.getName();
|
|
||||||
if (!name.endsWith(".jar")) return false;
|
|
||||||
String[] prefixes =
|
|
||||||
{
|
|
||||||
"launchwrapper-",
|
|
||||||
"asm-all-",
|
|
||||||
"akka-actor_2.11-",
|
|
||||||
"config-",
|
|
||||||
"scala-",
|
|
||||||
"jopt-simple-",
|
|
||||||
"lzma-",
|
|
||||||
"realms-",
|
|
||||||
"httpclient-",
|
|
||||||
"httpcore-",
|
|
||||||
"vecmath-",
|
|
||||||
"trove4j-",
|
|
||||||
"icu4j-core-mojang-",
|
|
||||||
"codecjorbis-",
|
|
||||||
"codecwav-",
|
|
||||||
"libraryjavawound-",
|
|
||||||
"librarylwjglopenal-",
|
|
||||||
"soundsystem-",
|
|
||||||
"netty-all-",
|
|
||||||
"guava-",
|
|
||||||
"commons-lang3-",
|
|
||||||
"commons-compress-",
|
|
||||||
"commons-logging-",
|
|
||||||
"commons-io-",
|
|
||||||
"commons-codec-",
|
|
||||||
"jinput-",
|
|
||||||
"jutils-",
|
|
||||||
"gson-",
|
|
||||||
"authlib-",
|
|
||||||
"log4j-api-",
|
|
||||||
"log4j-core-",
|
|
||||||
"lwjgl-",
|
|
||||||
"lwjgl_util-",
|
|
||||||
"twitch-",
|
|
||||||
"jline-",
|
|
||||||
"jna-",
|
|
||||||
"platform-",
|
|
||||||
"oshi-core-",
|
|
||||||
"netty-",
|
|
||||||
"libraryjavasound-",
|
|
||||||
"fastutil-"
|
|
||||||
};
|
|
||||||
for (String s : prefixes)
|
|
||||||
{
|
|
||||||
if (name.startsWith(s)) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearNegativeCacheFor(Set<String> classList)
|
|
||||||
{
|
|
||||||
mainClassLoader.clearNegativeEntries(classList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModAPITransformer addModAPITransformer(ASMDataTable dataTable)
|
|
||||||
{
|
|
||||||
mainClassLoader.registerTransformer("net.minecraftforge.fml.common.asm.transformers.ModAPITransformer");
|
|
||||||
List<IClassTransformer> transformers = mainClassLoader.getTransformers();
|
|
||||||
ModAPITransformer modAPI = (ModAPITransformer) transformers.get(transformers.size()-1);
|
|
||||||
modAPI.initTable(dataTable);
|
|
||||||
return modAPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<URL> parentURLs = null;
|
|
||||||
public boolean containsSource(File source)
|
|
||||||
{
|
|
||||||
if (parentURLs == null) {
|
|
||||||
parentURLs = Arrays.asList(mainClassLoader.getURLs());
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return parentURLs.contains(source.toURI().toURL());
|
|
||||||
} catch (MalformedURLException e)
|
|
||||||
{
|
|
||||||
// shouldn't happen
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Repeatable;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classes annotated with this will have the named interface or method removed from the runtime definition of the class
|
|
||||||
* if the modid specified is missing.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class Optional {
|
|
||||||
/**
|
|
||||||
* Not constructable
|
|
||||||
*/
|
|
||||||
private Optional() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a list of interfaces as removable
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface InterfaceList {
|
|
||||||
/**
|
|
||||||
* Mark a list of interfaces for optional removal.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Interface[] value();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Used to remove optional interfaces
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Repeatable(InterfaceList.class)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface Interface {
|
|
||||||
/**
|
|
||||||
* The fully qualified name of the interface to be stripped
|
|
||||||
* @return the interface name
|
|
||||||
*/
|
|
||||||
String iface();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The modid that is required to be present for stripping NOT to occur
|
|
||||||
* @return the modid
|
|
||||||
*/
|
|
||||||
String modid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strip references to this interface in method declarations? (Useful to kill synthetic methods from scala f.e.)
|
|
||||||
*
|
|
||||||
* @return if references should be stripped
|
|
||||||
*/
|
|
||||||
boolean striprefs() default false;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Used to remove optional methods
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
public @interface Method {
|
|
||||||
/**
|
|
||||||
* The modid that is required to be present for stripping NOT to occur
|
|
||||||
* @return the modid
|
|
||||||
*/
|
|
||||||
String modid();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,14 +26,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.fml.SidedExecutor;
|
|
||||||
import net.minecraftforge.fml.SidedProvider;
|
import net.minecraftforge.fml.SidedProvider;
|
||||||
import net.minecraftforge.fml.client.SplashProgress;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.message.MessageFormatMessage;
|
import org.apache.logging.log4j.message.MessageFormatMessage;
|
||||||
|
|
||||||
import static net.minecraftforge.fml.Logging.SPLASH;
|
import static net.minecraftforge.fml.Logging.SPLASH;
|
||||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not a fully fleshed out API, may change in future MC versions.
|
* Not a fully fleshed out API, may change in future MC versions.
|
||||||
|
@ -41,7 +39,9 @@ import static net.minecraftforge.fml.Logging.fmlLog;
|
||||||
*/
|
*/
|
||||||
public class ProgressManager
|
public class ProgressManager
|
||||||
{
|
{
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<ProgressBar>();
|
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<ProgressBar>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not a fully fleshed out API, may change in future MC versions.
|
* Not a fully fleshed out API, may change in future MC versions.
|
||||||
* However feel free to use and suggest additions.
|
* However feel free to use and suggest additions.
|
||||||
|
@ -62,13 +62,10 @@ public class ProgressManager
|
||||||
{
|
{
|
||||||
bar.timeEachStep();
|
bar.timeEachStep();
|
||||||
}
|
}
|
||||||
SidedExecutor.runOn(Dist.CLIENT, ()->SplashProgress::processMessages);
|
// DistExecutor.runWhenOn(Dist.CLIENT, ()->SplashProgress::processMessages);
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDisplayVSyncForced() {
|
|
||||||
return FMLCommonHandler.instance().isDisplayVSyncForced();
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Not a fully fleshed out API, may change in future MC versions.
|
* Not a fully fleshed out API, may change in future MC versions.
|
||||||
* However feel free to use and suggest additions.
|
* However feel free to use and suggest additions.
|
||||||
|
@ -81,13 +78,13 @@ public class ProgressManager
|
||||||
{
|
{
|
||||||
long newTime = System.nanoTime();
|
long newTime = System.nanoTime();
|
||||||
if (bar.timeEachStep)
|
if (bar.timeEachStep)
|
||||||
fmlLog.debug(SPLASH, () -> new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
|
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
|
||||||
if (bar.getSteps() == 1)
|
if (bar.getSteps() == 1)
|
||||||
fmlLog.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
|
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
|
||||||
else
|
else
|
||||||
fmlLog.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} took {1,number,0.000}ms", bar.getTitle(), (newTime - bar.lastTime) / 1.0e6));
|
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} took {1,number,0.000}ms", bar.getTitle(), (newTime - bar.lastTime) / 1.0e6));
|
||||||
}
|
}
|
||||||
SidedExecutor.runOn(Dist.CLIENT, ()->SplashProgress::processMessages);
|
// DistExecutor.runWhenOn(Dist.CLIENT, ()->SplashProgress::processMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -121,7 +118,7 @@ public class ProgressManager
|
||||||
|
|
||||||
public void step(Class<?> classToName, String... extra)
|
public void step(Class<?> classToName, String... extra)
|
||||||
{
|
{
|
||||||
step(ClassNameUtils.shortName(classToName)+ Arrays.stream(extra).collect(Collectors.joining(" ")));
|
step(ClassNameUtils.shortName(classToName)+ String.join(" ", extra));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void step(String message)
|
public void step(String message)
|
||||||
|
@ -130,7 +127,7 @@ public class ProgressManager
|
||||||
if (timeEachStep && step != 0)
|
if (timeEachStep && step != 0)
|
||||||
{
|
{
|
||||||
long newTime = System.nanoTime();
|
long newTime = System.nanoTime();
|
||||||
fmlLog.debug(SPLASH,new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", getTitle(), getMessage(), (newTime - lastTime) / 1.0e6));
|
LOGGER.debug(SPLASH,new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", getTitle(), getMessage(), (newTime - lastTime) / 1.0e6));
|
||||||
lastTime = newTime;
|
lastTime = newTime;
|
||||||
}
|
}
|
||||||
step += 1;
|
step += 1;
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method annotated with this on the {@link Mod} will be called whenever a local save is listed in
|
|
||||||
* the save games list.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
public @interface SaveInspectionHandler
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PrintStream which redirects it's output to a given logger.
|
|
||||||
*
|
|
||||||
* @author Arkan
|
|
||||||
*/
|
|
||||||
public class TracingPrintStream extends PrintStream {
|
|
||||||
|
|
||||||
private Logger logger;
|
|
||||||
private int BASE_DEPTH = 3;
|
|
||||||
|
|
||||||
public TracingPrintStream(Logger logger, PrintStream original) {
|
|
||||||
super(original);
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void println(Object o) {
|
|
||||||
logger.info("{}{}", getPrefix(), o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void println(String s) {
|
|
||||||
logger.info("{}{}", getPrefix(), s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getPrefix() {
|
|
||||||
StackTraceElement[] elems = Thread.currentThread().getStackTrace();
|
|
||||||
StackTraceElement elem = elems[BASE_DEPTH]; // The caller is always at BASE_DEPTH, including this call.
|
|
||||||
if (elem.getClassName().startsWith("kotlin.io.")) {
|
|
||||||
elem = elems[BASE_DEPTH + 2]; // Kotlins IoPackage masks origins 2 deeper in the stack.
|
|
||||||
} else if (elem.getClassName().startsWith("java.lang.Throwable")) {
|
|
||||||
elem = elems[BASE_DEPTH + 4];
|
|
||||||
}
|
|
||||||
return "[" + elem.getClassName() + ":" + elem.getMethodName() + ":" + elem.getLineNumber() + "]: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
|
||||||
import net.minecraftforge.fml.client.GuiWrongMinecraft;
|
|
||||||
import net.minecraftforge.fml.client.IDisplayableError;
|
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
|
|
||||||
public class WrongMinecraftVersionException extends EnhancedRuntimeException implements IDisplayableError
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
public ModContainer mod;
|
|
||||||
private String mcVersion;
|
|
||||||
|
|
||||||
public WrongMinecraftVersionException(ModContainer mod, String mcver)
|
|
||||||
{
|
|
||||||
super(String.format("Wrong Minecraft version for %s", mod.getModId()));
|
|
||||||
this.mod = mod;
|
|
||||||
this.mcVersion = mcver;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void printStackTrace(WrappedPrintStream stream) {
|
|
||||||
stream.println("Wrong Minecraft Versions!");
|
|
||||||
stream.println("Mod: " + mod.getModId());
|
|
||||||
stream.println("Location: " + mod.getSource().toString());
|
|
||||||
stream.println("Expected: " + mod.acceptableMinecraftVersionRange().toString());
|
|
||||||
stream.println("Current: " + mcVersion);
|
|
||||||
stream.println("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SideOnly(Side.CLIENT)
|
|
||||||
public GuiScreen createGui()
|
|
||||||
{
|
|
||||||
return new GuiWrongMinecraft(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Level;
|
|
||||||
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copied from http://stackoverflow.com/questions/1399126/java-util-zip-recreating-directory-structure
|
|
||||||
* because the code looked very tidy and neat. Thanks, McDowell!
|
|
||||||
*
|
|
||||||
* @author McDowell
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ZipperUtil {
|
|
||||||
public static void zip(File directory, File zipfile) throws IOException
|
|
||||||
{
|
|
||||||
URI base = directory.toURI();
|
|
||||||
Deque<File> queue = new LinkedList<File>();
|
|
||||||
queue.push(directory);
|
|
||||||
OutputStream out = new FileOutputStream(zipfile);
|
|
||||||
Closeable res = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ZipOutputStream zout = new ZipOutputStream(out);
|
|
||||||
res = zout;
|
|
||||||
while (!queue.isEmpty())
|
|
||||||
{
|
|
||||||
directory = queue.pop();
|
|
||||||
for (File kid : directory.listFiles())
|
|
||||||
{
|
|
||||||
String name = base.relativize(kid.toURI()).getPath();
|
|
||||||
if (kid.isDirectory())
|
|
||||||
{
|
|
||||||
queue.push(kid);
|
|
||||||
name = name.endsWith("/") ? name : name + "/";
|
|
||||||
zout.putNextEntry(new ZipEntry(name));
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
zout.putNextEntry(new ZipEntry(name));
|
|
||||||
Files.copy(kid, zout);
|
|
||||||
zout.closeEntry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
res.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void backupWorld() throws IOException
|
|
||||||
{
|
|
||||||
String dirName = FMLCommonHandler.instance().getMinecraftServerInstance().getFolderName();
|
|
||||||
|
|
||||||
backupWorld(dirName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static void backupWorld(String dirName, String saveName) throws IOException
|
|
||||||
{
|
|
||||||
backupWorld(dirName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void backupWorld(String dirName) throws IOException
|
|
||||||
{
|
|
||||||
File dstFolder = FMLCommonHandler.instance().getSavesDirectory();
|
|
||||||
File zip = new File(dstFolder, String.format("%s-%2$tY%2$tm%2$td-%2$tH%2$tM%2$tS.zip", dirName, System.currentTimeMillis()));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ZipperUtil.zip(new File(dstFolder, dirName), zip);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("World backup failed.", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
FMLLog.log.info("World backup created at {}.", zip.getCanonicalPath());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,284 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.net.URLStreamHandler;
|
|
||||||
import java.security.Permission;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.IClassTransformer;
|
|
||||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassVisitor;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.FieldVisitor;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
|
||||||
import org.objectweb.asm.commons.Method;
|
|
||||||
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class ASMTransformerWrapper
|
|
||||||
{
|
|
||||||
private static final Map<String, String> wrapperModMap = Maps.newHashMap();
|
|
||||||
private static final Map<String, String> wrapperParentMap = Maps.newHashMap();
|
|
||||||
|
|
||||||
private static final LoadingCache<String, byte[]> wrapperCache = CacheBuilder.newBuilder()
|
|
||||||
.maximumSize(30)
|
|
||||||
.weakValues()
|
|
||||||
.build(new CacheLoader<String, byte[]>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public byte[] load(String file) throws Exception
|
|
||||||
{
|
|
||||||
return makeWrapper(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static final URL asmGenRoot;
|
|
||||||
private static boolean injected = false;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
asmGenRoot = new URL("asmgen", null, -1, "/", new ASMGenHandler());
|
|
||||||
}
|
|
||||||
catch(MalformedURLException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ASMGenHandler extends URLStreamHandler
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected URLConnection openConnection(URL url) throws IOException
|
|
||||||
{
|
|
||||||
String file = url.getFile();
|
|
||||||
if(file.equals("/"))
|
|
||||||
{
|
|
||||||
return new URLConnection(url)
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void connect() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if(!file.startsWith("/")) throw new RuntimeException("Malformed URL: " + url);
|
|
||||||
file = file.substring(1);
|
|
||||||
if(wrapperModMap.containsKey(file))
|
|
||||||
{
|
|
||||||
return new ASMGenConnection(url, file);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ASMGenConnection extends URLConnection
|
|
||||||
{
|
|
||||||
private final String file;
|
|
||||||
|
|
||||||
protected ASMGenConnection(URL url, String file)
|
|
||||||
{
|
|
||||||
super(url);
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream()
|
|
||||||
{
|
|
||||||
return new ByteArrayInputStream(wrapperCache.getUnchecked(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public Permission getPermission()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getTransformerWrapper(LaunchClassLoader launchLoader, String parentClass, String coreMod)
|
|
||||||
{
|
|
||||||
if(!injected)
|
|
||||||
{
|
|
||||||
injected = true;
|
|
||||||
launchLoader.addURL(asmGenRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = getWrapperName(parentClass);
|
|
||||||
String fileName = name.replace('.', '/') + ".class";
|
|
||||||
wrapperModMap.put(fileName, coreMod);
|
|
||||||
wrapperParentMap.put(fileName, parentClass);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] makeWrapper(String fileName)
|
|
||||||
{
|
|
||||||
if(!wrapperModMap.containsKey(fileName) || !wrapperParentMap.containsKey(fileName) || !fileName.endsWith(".class"))
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("makeWrapper called with strange argument: " + fileName);
|
|
||||||
}
|
|
||||||
String name = fileName.substring(0, fileName.length() - ".class".length());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Type wrapper = Type.getType(TransformerWrapper.class);
|
|
||||||
|
|
||||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
||||||
|
|
||||||
writer.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, name, null, wrapper.getInternalName(), null);
|
|
||||||
|
|
||||||
Method m = Method.getMethod("void <init> ()");
|
|
||||||
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, m, null, null, writer);
|
|
||||||
mg.loadThis();
|
|
||||||
mg.invokeConstructor(wrapper, m);
|
|
||||||
mg.returnValue();
|
|
||||||
mg.endMethod();
|
|
||||||
|
|
||||||
m = Method.getMethod("java.lang.String getParentClass ()");
|
|
||||||
mg = new GeneratorAdapter(Opcodes.ACC_PROTECTED, m, null, null, writer);
|
|
||||||
mg.push(wrapperParentMap.get(fileName));
|
|
||||||
mg.returnValue();
|
|
||||||
mg.endMethod();
|
|
||||||
|
|
||||||
m = Method.getMethod("java.lang.String getCoreMod ()");
|
|
||||||
mg = new GeneratorAdapter(Opcodes.ACC_PROTECTED, m, null, null, writer);
|
|
||||||
mg.push(wrapperModMap.get(fileName));
|
|
||||||
mg.returnValue();
|
|
||||||
mg.endMethod();
|
|
||||||
|
|
||||||
writer.visitEnd();
|
|
||||||
|
|
||||||
return writer.toByteArray();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getWrapperName(String parentClass)
|
|
||||||
{
|
|
||||||
return "$wrapper." + parentClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private static class WrapperVisitor extends ClassVisitor
|
|
||||||
{
|
|
||||||
private final String name;
|
|
||||||
private final String parentClass;
|
|
||||||
|
|
||||||
public WrapperVisitor(ClassVisitor cv, String name, String parentClass)
|
|
||||||
{
|
|
||||||
super(Opcodes.ASM5, cv);
|
|
||||||
this.name = name.replace('.', '/');
|
|
||||||
this.parentClass = parentClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
|
||||||
{
|
|
||||||
super.visit(version, access, this.name, signature, superName, interfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
|
|
||||||
{
|
|
||||||
if(name.equals("parentClass"))
|
|
||||||
{
|
|
||||||
return super.visitField(access, name, desc, signature, parentClass);
|
|
||||||
}
|
|
||||||
return super.visitField(access, name, desc, signature, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class TransformerWrapper implements IClassTransformer
|
|
||||||
{
|
|
||||||
private final IClassTransformer parent;
|
|
||||||
|
|
||||||
public TransformerWrapper()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.parent = (IClassTransformer)this.getClass().getClassLoader().loadClass(getParentClass()).newInstance();
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(String name, String transformedName, byte[] basicClass)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return parent.transform(name, transformedName, basicClass);
|
|
||||||
}
|
|
||||||
catch(Throwable e)
|
|
||||||
{
|
|
||||||
throw new TransformerException("Exception in class transformer " + parent + " from coremod " + getCoreMod(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return "TransformerWrapper(" + getParentClass() + ", " + getCoreMod() + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract String getParentClass();
|
|
||||||
|
|
||||||
protected abstract String getCoreMod();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TransformerException extends RuntimeException
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -6616232415696157218L;
|
|
||||||
|
|
||||||
public TransformerException(String message, Throwable cause)
|
|
||||||
{
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.IClassNameTransformer;
|
|
||||||
import net.minecraft.launchwrapper.IClassTransformer;
|
|
||||||
import net.minecraftforge.fml.common.asm.deobf.FMLDeobfuscatingRemapper;
|
|
||||||
import net.minecraftforge.fml.common.asm.deobf.FMLRemappingAdapter;
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassReader;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.commons.RemappingClassAdapter;
|
|
||||||
|
|
||||||
public class DeobfuscationTransformer implements IClassTransformer, IClassNameTransformer {
|
|
||||||
|
|
||||||
private static final boolean RECALC_FRAMES = Boolean.parseBoolean(System.getProperty("FORGE_FORCE_FRAME_RECALC", "false"));
|
|
||||||
private static final int WRITER_FLAGS = ClassWriter.COMPUTE_MAXS | (RECALC_FRAMES ? ClassWriter.COMPUTE_FRAMES : 0);
|
|
||||||
private static final int READER_FLAGS = RECALC_FRAMES ? ClassReader.SKIP_FRAMES : ClassReader.EXPAND_FRAMES;
|
|
||||||
// COMPUTE_FRAMES causes classes to be loaded, which could cause issues if the classes do not exist.
|
|
||||||
// However in testing this has not happened. {As we run post RuntimeDistCleaner}
|
|
||||||
// If reported we need to add a custom implementation of ClassWriter.getCommonSuperClass
|
|
||||||
// that does not cause class loading.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ClassReader classReader = new ClassReader(bytes);
|
|
||||||
ClassWriter classWriter = new ClassWriter(WRITER_FLAGS);
|
|
||||||
RemappingClassAdapter remapAdapter = new FMLRemappingAdapter(classWriter);
|
|
||||||
classReader.accept(remapAdapter, READER_FLAGS);
|
|
||||||
return classWriter.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String remapClassName(String name)
|
|
||||||
{
|
|
||||||
return FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.','/')).replace('/', '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String unmapClassName(String name)
|
|
||||||
{
|
|
||||||
return FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/','.');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,188 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.CodeSource;
|
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
|
||||||
import net.minecraftforge.fml.common.CertificateHelper;
|
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
|
||||||
import net.minecraftforge.fml.common.asm.deobf.FMLDeobfuscatingRemapper;
|
|
||||||
import net.minecraftforge.fml.common.patcher.ClassPatchManager;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
|
||||||
|
|
||||||
public class FMLSanityChecker implements IFMLCallHook
|
|
||||||
{
|
|
||||||
private static final String FMLFINGERPRINT = "51:0A:FB:4C:AF:A4:A0:F2:F5:CF:C5:0E:B4:CC:3C:30:24:4A:E3:8E".toLowerCase().replace(":", "");
|
|
||||||
private static final String FORGEFINGERPRINT = "E3:C3:D5:0C:7C:98:6D:F7:4C:64:5C:0A:C5:46:39:74:1C:90:A5:57".toLowerCase().replace(":", "");
|
|
||||||
private static final String MCFINGERPRINT = "CD:99:95:96:56:F7:53:DC:28:D8:63:B4:67:69:F7:F8:FB:AE:FC:FC".toLowerCase().replace(":", "");
|
|
||||||
private LaunchClassLoader cl;
|
|
||||||
private boolean liveEnv;
|
|
||||||
public static File fmlLocation;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception
|
|
||||||
{
|
|
||||||
CodeSource codeSource = getClass().getProtectionDomain().getCodeSource();
|
|
||||||
boolean goodFML = false;
|
|
||||||
boolean fmlIsJar = false;
|
|
||||||
if (codeSource.getLocation().getProtocol().equals("jar"))
|
|
||||||
{
|
|
||||||
fmlIsJar = true;
|
|
||||||
Certificate[] certificates = codeSource.getCertificates();
|
|
||||||
if (certificates!=null)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (Certificate cert : certificates)
|
|
||||||
{
|
|
||||||
String fingerprint = CertificateHelper.getFingerprint(cert);
|
|
||||||
if (fingerprint.equals(FMLFINGERPRINT))
|
|
||||||
{
|
|
||||||
FMLLog.log.info("Found valid fingerprint for FML. Certificate fingerprint {}", fingerprint);
|
|
||||||
goodFML = true;
|
|
||||||
}
|
|
||||||
else if (fingerprint.equals(FORGEFINGERPRINT))
|
|
||||||
{
|
|
||||||
FMLLog.log.info("Found valid fingerprint for Minecraft Forge. Certificate fingerprint {}", fingerprint);
|
|
||||||
goodFML = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FMLLog.log.error("Found invalid fingerprint for FML: {}", fingerprint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goodFML = true;
|
|
||||||
}
|
|
||||||
// Server is not signed, so assume it's good - a deobf env is dev time so it's good too
|
|
||||||
boolean goodMC = FMLLaunchHandler.side() == Side.SERVER || !liveEnv;
|
|
||||||
int certCount = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Class<?> cbr = Class.forName("net.minecraft.client.ClientBrandRetriever",false, cl);
|
|
||||||
codeSource = cbr.getProtectionDomain().getCodeSource();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
// Probably a development environment, or the server (the server is not signed)
|
|
||||||
goodMC = true;
|
|
||||||
}
|
|
||||||
JarFile mcJarFile = null;
|
|
||||||
if (fmlIsJar && !goodMC && codeSource.getLocation().getProtocol().equals("jar"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String mcPath = codeSource.getLocation().getPath().substring(5);
|
|
||||||
mcPath = mcPath.substring(0, mcPath.lastIndexOf('!'));
|
|
||||||
mcPath = URLDecoder.decode(mcPath, StandardCharsets.UTF_8.name());
|
|
||||||
mcJarFile = new JarFile(mcPath,true);
|
|
||||||
mcJarFile.getManifest();
|
|
||||||
JarEntry cbrEntry = mcJarFile.getJarEntry("net/minecraft/client/ClientBrandRetriever.class");
|
|
||||||
InputStream mcJarFileInputStream = mcJarFile.getInputStream(cbrEntry);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ByteStreams.toByteArray(mcJarFileInputStream);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(mcJarFileInputStream);
|
|
||||||
}
|
|
||||||
Certificate[] certificates = cbrEntry.getCertificates();
|
|
||||||
certCount = certificates != null ? certificates.length : 0;
|
|
||||||
if (certificates!=null)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (Certificate cert : certificates)
|
|
||||||
{
|
|
||||||
String fingerprint = CertificateHelper.getFingerprint(cert);
|
|
||||||
if (fingerprint.equals(MCFINGERPRINT))
|
|
||||||
{
|
|
||||||
FMLLog.log.info("Found valid fingerprint for Minecraft. Certificate fingerprint {}", fingerprint);
|
|
||||||
goodMC = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("A critical error occurred trying to read the minecraft jar file", e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtils.closeQuietly(mcJarFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goodMC = true;
|
|
||||||
}
|
|
||||||
if (!goodMC)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("The minecraft jar {} appears to be corrupt! There has been CRITICAL TAMPERING WITH MINECRAFT, it is highly unlikely minecraft will work! STOP NOW, get a clean copy and try again!", codeSource.getLocation().getFile());
|
|
||||||
if (!Boolean.parseBoolean(System.getProperty("fml.ignoreInvalidMinecraftCertificates","false")))
|
|
||||||
{
|
|
||||||
FMLLog.log.error("For your safety, FML will not launch minecraft. You will need to fetch a clean version of the minecraft jar file");
|
|
||||||
FMLLog.log.error("Technical information: The class net.minecraft.client.ClientBrandRetriever should have been associated with the minecraft jar file, " +
|
|
||||||
"and should have returned us a valid, intact minecraft jar location. This did not work. Either you have modified the minecraft jar file (if so " +
|
|
||||||
"run the forge installer again), or you are using a base editing jar that is changing this class (and likely others too). If you REALLY " +
|
|
||||||
"want to run minecraft in this configuration, add the flag -Dfml.ignoreInvalidMinecraftCertificates=true to the 'JVM settings' in your launcher profile.");
|
|
||||||
FMLCommonHandler.instance().exitJava(1, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FMLLog.log.error("FML has been ordered to ignore the invalid or missing minecraft certificate. This is very likely to cause a problem!");
|
|
||||||
FMLLog.log.error("Technical information: ClientBrandRetriever was at {}, there were {} certificates for it", codeSource.getLocation(), certCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!goodFML)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("FML appears to be missing any signature data. This is not a good thing");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void injectData(Map<String, Object> data)
|
|
||||||
{
|
|
||||||
liveEnv = (Boolean)data.get("runtimeDeobfuscationEnabled");
|
|
||||||
cl = (LaunchClassLoader) data.get("classLoader");
|
|
||||||
File mcDir = (File)data.get("mcLocation");
|
|
||||||
fmlLocation = (File)data.get("coremodLocation");
|
|
||||||
ClassPatchManager.INSTANCE.setup(FMLLaunchHandler.side());
|
|
||||||
FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import java.util.ListIterator;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.IClassTransformer;
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassReader;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
import org.objectweb.asm.tree.FieldInsnNode;
|
|
||||||
import org.objectweb.asm.tree.FieldNode;
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode;
|
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
|
||||||
|
|
||||||
public class FieldRedirectTransformer implements IClassTransformer
|
|
||||||
{
|
|
||||||
private final String clsName;
|
|
||||||
private final String TYPE;
|
|
||||||
private final String DESC;
|
|
||||||
private final String bypass;
|
|
||||||
|
|
||||||
protected FieldRedirectTransformer(String cls, String type, String bypass)
|
|
||||||
{
|
|
||||||
this.clsName = cls;
|
|
||||||
this.TYPE = type;
|
|
||||||
this.DESC = "()" + type;
|
|
||||||
this.bypass = bypass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(String name, String transformedName, byte[] basicClass)
|
|
||||||
{
|
|
||||||
if (!this.clsName.equals(transformedName))
|
|
||||||
return basicClass;
|
|
||||||
|
|
||||||
ClassNode classNode = new ClassNode();
|
|
||||||
ClassReader classReader = new ClassReader(basicClass);
|
|
||||||
classReader.accept(classNode, 0);
|
|
||||||
|
|
||||||
FieldNode fieldRef = null;
|
|
||||||
for (FieldNode f : classNode.fields)
|
|
||||||
{
|
|
||||||
if (this.TYPE.equals(f.desc) && fieldRef == null)
|
|
||||||
{
|
|
||||||
fieldRef = f;
|
|
||||||
}
|
|
||||||
else if (this.TYPE.equals(f.desc))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Error processing " + clsName + " - found a duplicate holder field");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fieldRef == null)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Error processing " + clsName + " - no holder field declared (is the code somehow obfuscated?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodNode getMethod = null;
|
|
||||||
for (MethodNode m: classNode.methods)
|
|
||||||
{
|
|
||||||
if (m.name.equals(this.bypass)) continue;
|
|
||||||
if (this.DESC.equals(m.desc) && getMethod == null)
|
|
||||||
{
|
|
||||||
getMethod = m;
|
|
||||||
}
|
|
||||||
else if (this.DESC.equals(m.desc))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Error processing " + clsName + " - duplicate get method found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (getMethod == null)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Error processing " + clsName + " - no get method found (is the code somehow obfuscated?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MethodNode m: classNode.methods)
|
|
||||||
{
|
|
||||||
if (m.name.equals(this.bypass)) continue;
|
|
||||||
for (ListIterator<AbstractInsnNode> it = m.instructions.iterator(); it.hasNext(); )
|
|
||||||
{
|
|
||||||
AbstractInsnNode insnNode = it.next();
|
|
||||||
if (insnNode.getType() == AbstractInsnNode.FIELD_INSN)
|
|
||||||
{
|
|
||||||
FieldInsnNode fi = (FieldInsnNode)insnNode;
|
|
||||||
if (fieldRef.name.equals(fi.name) && fi.getOpcode() == Opcodes.GETFIELD)
|
|
||||||
{
|
|
||||||
it.remove();
|
|
||||||
MethodInsnNode replace = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classNode.name, getMethod.name, getMethod.desc, false);
|
|
||||||
it.add(replace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
|
||||||
classNode.accept(writer);
|
|
||||||
return writer.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
public class ItemBlockSpecialTransformer extends FieldRedirectTransformer
|
|
||||||
{
|
|
||||||
public ItemBlockSpecialTransformer()
|
|
||||||
{
|
|
||||||
super("net.minecraft.item.ItemBlockSpecial", "Lnet/minecraft/block/Block;", "getBlockRaw");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
public class ItemBlockTransformer extends FieldRedirectTransformer
|
|
||||||
{
|
|
||||||
public ItemBlockTransformer()
|
|
||||||
{
|
|
||||||
super("net.minecraft.item.ItemBlock", "Lnet/minecraft/block/Block;", "getBlockRaw");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
public class ItemStackTransformer extends FieldRedirectTransformer
|
|
||||||
{
|
|
||||||
public ItemStackTransformer()
|
|
||||||
{
|
|
||||||
super("net.minecraft.item.ItemStack", "Lnet/minecraft/item/Item;", "getItemRaw");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to force certain classes to reobfuscate
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.TYPE})
|
|
||||||
public @interface ReobfuscationMarker {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm;
|
|
||||||
|
|
||||||
import org.objectweb.asm.*;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.IClassTransformer;
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.relauncher.FMLSecurityManager.ExitTrappedException;
|
|
||||||
|
|
||||||
public class TerminalTransformer implements IClassTransformer
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public byte[] transform(String name, String transformedName, byte[] basicClass)
|
|
||||||
{
|
|
||||||
if (basicClass == null) return null;
|
|
||||||
ClassReader reader = new ClassReader(basicClass);
|
|
||||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
|
||||||
|
|
||||||
ClassVisitor visitor = writer;
|
|
||||||
visitor = new ExitVisitor(visitor);
|
|
||||||
|
|
||||||
reader.accept(visitor, 0);
|
|
||||||
return writer.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExitVisitor extends ClassVisitor
|
|
||||||
{
|
|
||||||
private String clsName = null;
|
|
||||||
private static final String callbackOwner = org.objectweb.asm.Type.getInternalName(ExitVisitor.class);
|
|
||||||
|
|
||||||
private ExitVisitor(ClassVisitor cv)
|
|
||||||
{
|
|
||||||
super(Opcodes.ASM5, cv);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
|
||||||
{
|
|
||||||
super.visit(version, access, name, signature, superName, interfaces);
|
|
||||||
this.clsName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int mAccess, final String mName, final String mDesc, String mSignature, String[] mExceptions)
|
|
||||||
{
|
|
||||||
final boolean warn = !(clsName.equals("net/minecraft/client/Minecraft") ||
|
|
||||||
clsName.equals("net/minecraft/server/dedicated/DedicatedServer") ||
|
|
||||||
clsName.equals("net/minecraft/server/dedicated/ServerHangWatchdog") ||
|
|
||||||
clsName.equals("net/minecraft/server/dedicated/ServerHangWatchdog$1") ||
|
|
||||||
clsName.equals("net/minecraftforge/fml/common/FMLCommonHandler") ||
|
|
||||||
clsName.startsWith("com/jcraft/jogg/") ||
|
|
||||||
clsName.startsWith("scala/sys/") ||
|
|
||||||
clsName.startsWith("net/minecraft/server/gui/MinecraftServerGui") ||
|
|
||||||
clsName.startsWith("com/sun/jna/")
|
|
||||||
);
|
|
||||||
|
|
||||||
return new MethodVisitor(Opcodes.ASM5, super.visitMethod(mAccess, mName, mDesc, mSignature, mExceptions))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isIntf)
|
|
||||||
{
|
|
||||||
if (opcode == Opcodes.INVOKESTATIC && owner.equals("java/lang/System") && name.equals("exit") && desc.equals("(I)V"))
|
|
||||||
{
|
|
||||||
if (warn)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
FMLLog.log.warn("MOD HAS DIRECT REFERENCE System.exit() THIS IS NOT ALLOWED REROUTING TO FML!");
|
|
||||||
FMLLog.log.warn("Offender: {}.{}{}", ExitVisitor.this.clsName, mName, mDesc);
|
|
||||||
FMLLog.log.warn("Use FMLCommonHandler.exitJava instead");
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
}
|
|
||||||
owner = ExitVisitor.callbackOwner;
|
|
||||||
name = "systemExitCalled";
|
|
||||||
}
|
|
||||||
else if (opcode == Opcodes.INVOKEVIRTUAL && owner.equals("java/lang/Runtime") && name.equals("exit") && desc.equals("(I)V"))
|
|
||||||
{
|
|
||||||
if (warn)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
FMLLog.log.warn("MOD HAS DIRECT REFERENCE Runtime.exit() THIS IS NOT ALLOWED REROUTING TO FML!");
|
|
||||||
FMLLog.log.warn("Offender: {}.{}{}", ExitVisitor.this.clsName, mName, mDesc);
|
|
||||||
FMLLog.log.warn("Use FMLCommonHandler.exitJava instead");
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
}
|
|
||||||
opcode = Opcodes.INVOKESTATIC;
|
|
||||||
owner = ExitVisitor.callbackOwner;
|
|
||||||
name = "runtimeExitCalled";
|
|
||||||
desc = "(Ljava/lang/Runtime;I)V";
|
|
||||||
}
|
|
||||||
else if (opcode == Opcodes.INVOKEVIRTUAL && owner.equals("java/lang/Runtime") && name.equals("halt") && desc.equals("(I)V"))
|
|
||||||
{
|
|
||||||
if (warn)
|
|
||||||
{
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
FMLLog.log.warn("MOD HAS DIRECT REFERENCE Runtime.halt() THIS IS NOT ALLOWED REROUTING TO FML!");
|
|
||||||
FMLLog.log.warn("Offendor: {}.{}{}", ExitVisitor.this.clsName, mName, mDesc);
|
|
||||||
FMLLog.log.warn("Use FMLCommonHandler.exitJava instead");
|
|
||||||
FMLLog.log.warn("=============================================================");
|
|
||||||
}
|
|
||||||
opcode = Opcodes.INVOKESTATIC;
|
|
||||||
owner = ExitVisitor.callbackOwner;
|
|
||||||
name = "runtimeHaltCalled";
|
|
||||||
desc = "(Ljava/lang/Runtime;I)V";
|
|
||||||
}
|
|
||||||
|
|
||||||
super.visitMethodInsn(opcode, owner, name, desc, isIntf);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intercept System.exit, and check if the caller is allowed to use it, if not wrap it in a ExitTrappedException
|
|
||||||
public static void systemExitCalled(int status)
|
|
||||||
{
|
|
||||||
ExitVisitor.checkAccess();
|
|
||||||
System.exit(status);
|
|
||||||
}
|
|
||||||
// Intercept Runtime.getRuntime().exit, and check if the caller is allowed to use it, if not wrap it in a ExitTrappedException
|
|
||||||
public static void runtimeExitCalled(Runtime runtime, int status)
|
|
||||||
{
|
|
||||||
ExitVisitor.checkAccess();
|
|
||||||
runtime.exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intercept Runtime.getRuntime().halt, and check if the caller is allowed to use it, if not wrap it in a ExitTrappedException
|
|
||||||
public static void runtimeHaltCalled(Runtime runtime, int status)
|
|
||||||
{
|
|
||||||
ExitVisitor.checkAccess();
|
|
||||||
runtime.halt(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkAccess()
|
|
||||||
{
|
|
||||||
StackTraceElement[] cause = Thread.currentThread().getStackTrace();
|
|
||||||
|
|
||||||
String callingClass = cause.length > 2 ? cause[3].getClassName() : "none";
|
|
||||||
String callingParent = cause.length > 3 ? cause[4].getClassName() : "none";
|
|
||||||
// FML is allowed to call system exit and the Minecraft applet (from the quit button), and the dedicated server (from itself)
|
|
||||||
boolean allowed = false;
|
|
||||||
allowed |= callingClass.startsWith("net.minecraftforge.fml.");
|
|
||||||
allowed |= callingClass.equals("net.minecraft.client.Minecraft") && callingParent.equals("net.minecraft.client.Minecraft");
|
|
||||||
allowed |= callingClass.equals("net.minecraft.server.gui.MinecraftServerGui$1") && callingParent.equals("java.awt.AWTEventMulticaster");
|
|
||||||
allowed |= callingClass.equals("net.minecraft.server.dedicated.DedicatedServer") && callingParent.equals("net.minecraft.server.MinecraftServer");
|
|
||||||
allowed |= callingClass.equals("net.minecraft.server.dedicated.ServerHangWatchdog");
|
|
||||||
allowed |= callingClass.equals("net.minecraft.server.dedicated.ServerHangWatchdog$1");
|
|
||||||
|
|
||||||
if (!allowed)
|
|
||||||
{
|
|
||||||
throw new ExitTrappedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,501 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm.deobf;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.common.patcher.ClassPatchManager;
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassReader;
|
|
||||||
import org.objectweb.asm.commons.Remapper;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
import org.objectweb.asm.tree.FieldNode;
|
|
||||||
|
|
||||||
import com.google.common.base.CharMatcher;
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.BiMap;
|
|
||||||
import com.google.common.collect.ImmutableBiMap;
|
|
||||||
import com.google.common.collect.ImmutableBiMap.Builder;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.io.CharSource;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class FMLDeobfuscatingRemapper extends Remapper {
|
|
||||||
public static final FMLDeobfuscatingRemapper INSTANCE = new FMLDeobfuscatingRemapper();
|
|
||||||
|
|
||||||
private BiMap<String, String> classNameBiMap;
|
|
||||||
|
|
||||||
private Map<String,Map<String,String>> rawFieldMaps;
|
|
||||||
private Map<String,Map<String,String>> rawMethodMaps;
|
|
||||||
|
|
||||||
private Map<String,Map<String,String>> fieldNameMaps;
|
|
||||||
private Map<String,Map<String,String>> methodNameMaps;
|
|
||||||
|
|
||||||
private LaunchClassLoader classLoader;
|
|
||||||
|
|
||||||
|
|
||||||
private static final boolean DEBUG_REMAPPING = Boolean.parseBoolean(System.getProperty("fml.remappingDebug", "false"));
|
|
||||||
private static final boolean DUMP_FIELD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpFieldMaps", "false")) && DEBUG_REMAPPING;
|
|
||||||
private static final boolean DUMP_METHOD_MAPS = Boolean.parseBoolean(System.getProperty("fml.remappingDebug.dumpMethodMaps", "false")) && DEBUG_REMAPPING;
|
|
||||||
|
|
||||||
private FMLDeobfuscatingRemapper()
|
|
||||||
{
|
|
||||||
classNameBiMap=ImmutableBiMap.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setupLoadOnly(String deobfFileName, boolean loadAll)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File mapData = new File(deobfFileName);
|
|
||||||
LZMAInputSupplier zis = new LZMAInputSupplier(new FileInputStream(mapData));
|
|
||||||
CharSource srgSource = zis.asCharSource(StandardCharsets.UTF_8);
|
|
||||||
List<String> srgList = srgSource.readLines();
|
|
||||||
rawMethodMaps = Maps.newHashMap();
|
|
||||||
rawFieldMaps = Maps.newHashMap();
|
|
||||||
Builder<String, String> builder = ImmutableBiMap.builder();
|
|
||||||
Splitter splitter = Splitter.on(CharMatcher.anyOf(": ")).omitEmptyStrings().trimResults();
|
|
||||||
for (String line : srgList)
|
|
||||||
{
|
|
||||||
String[] parts = Iterables.toArray(splitter.split(line),String.class);
|
|
||||||
String typ = parts[0];
|
|
||||||
if ("CL".equals(typ))
|
|
||||||
{
|
|
||||||
parseClass(builder, parts);
|
|
||||||
}
|
|
||||||
else if ("MD".equals(typ) && loadAll)
|
|
||||||
{
|
|
||||||
parseMethod(parts);
|
|
||||||
}
|
|
||||||
else if ("FD".equals(typ) && loadAll)
|
|
||||||
{
|
|
||||||
parseField(parts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classNameBiMap = builder.build();
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("An error occurred loading the deobfuscation map data", ioe);
|
|
||||||
}
|
|
||||||
methodNameMaps = Maps.newHashMapWithExpectedSize(rawMethodMaps.size());
|
|
||||||
fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size());
|
|
||||||
|
|
||||||
}
|
|
||||||
public void setup(File mcDir, LaunchClassLoader classLoader, String deobfFileName)
|
|
||||||
{
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<String> srgList;
|
|
||||||
final String gradleStartProp = System.getProperty("net.minecraftforge.gradle.GradleStart.srg.srg-mcp");
|
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(gradleStartProp))
|
|
||||||
{
|
|
||||||
// get as a resource
|
|
||||||
InputStream classData = getClass().getResourceAsStream(deobfFileName);
|
|
||||||
LZMAInputSupplier zis = new LZMAInputSupplier(classData);
|
|
||||||
CharSource srgSource = zis.asCharSource(StandardCharsets.UTF_8);
|
|
||||||
srgList = srgSource.readLines();
|
|
||||||
FMLLog.log.debug("Loading deobfuscation resource {} with {} records", deobfFileName, srgList.size());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
srgList = Files.readLines(new File(gradleStartProp), StandardCharsets.UTF_8);
|
|
||||||
FMLLog.log.debug("Loading deobfuscation resource {} with {} records", gradleStartProp, srgList.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
rawMethodMaps = Maps.newHashMap();
|
|
||||||
rawFieldMaps = Maps.newHashMap();
|
|
||||||
Builder<String, String> builder = ImmutableBiMap.builder();
|
|
||||||
Splitter splitter = Splitter.on(CharMatcher.anyOf(": ")).omitEmptyStrings().trimResults();
|
|
||||||
for (String line : srgList)
|
|
||||||
{
|
|
||||||
String[] parts = Iterables.toArray(splitter.split(line),String.class);
|
|
||||||
String typ = parts[0];
|
|
||||||
if ("CL".equals(typ))
|
|
||||||
{
|
|
||||||
parseClass(builder, parts);
|
|
||||||
}
|
|
||||||
else if ("MD".equals(typ))
|
|
||||||
{
|
|
||||||
parseMethod(parts);
|
|
||||||
}
|
|
||||||
else if ("FD".equals(typ))
|
|
||||||
{
|
|
||||||
parseField(parts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classNameBiMap = builder.build();
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("An error occurred loading the deobfuscation map data", ioe);
|
|
||||||
}
|
|
||||||
methodNameMaps = Maps.newHashMapWithExpectedSize(rawMethodMaps.size());
|
|
||||||
fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRemappedClass(String className)
|
|
||||||
{
|
|
||||||
return !map(className).equals(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseField(String[] parts)
|
|
||||||
{
|
|
||||||
String oldSrg = parts[1];
|
|
||||||
int lastOld = oldSrg.lastIndexOf('/');
|
|
||||||
String cl = oldSrg.substring(0,lastOld);
|
|
||||||
String oldName = oldSrg.substring(lastOld+1);
|
|
||||||
String newSrg = parts[2];
|
|
||||||
int lastNew = newSrg.lastIndexOf('/');
|
|
||||||
String newName = newSrg.substring(lastNew+1);
|
|
||||||
if (!rawFieldMaps.containsKey(cl))
|
|
||||||
{
|
|
||||||
rawFieldMaps.put(cl, Maps.<String,String>newHashMap());
|
|
||||||
}
|
|
||||||
String fieldType = getFieldType(cl, oldName);
|
|
||||||
// We might be in mcp named land, where in fact the name is "new"
|
|
||||||
if (fieldType == null) fieldType = getFieldType(cl, newName);
|
|
||||||
rawFieldMaps.get(cl).put(oldName + ":" + fieldType, newName);
|
|
||||||
rawFieldMaps.get(cl).put(oldName + ":null", newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache the field descriptions for classes so we don't repeatedly reload the same data again and again
|
|
||||||
*/
|
|
||||||
private final Map<String,Map<String,String>> fieldDescriptions = Maps.newHashMap();
|
|
||||||
|
|
||||||
// Cache null values so we don't waste time trying to recompute classes with no field or method maps
|
|
||||||
private Set<String> negativeCacheMethods = Sets.newHashSet();
|
|
||||||
private Set<String> negativeCacheFields = Sets.newHashSet();
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String getFieldType(String owner, String name)
|
|
||||||
{
|
|
||||||
if (fieldDescriptions.containsKey(owner))
|
|
||||||
{
|
|
||||||
return fieldDescriptions.get(owner).get(name);
|
|
||||||
}
|
|
||||||
synchronized (fieldDescriptions)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(owner, map(owner).replace('/', '.'), classLoader);
|
|
||||||
if (classBytes == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ClassReader cr = new ClassReader(classBytes);
|
|
||||||
ClassNode classNode = new ClassNode();
|
|
||||||
cr.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
|
||||||
Map<String,String> resMap = Maps.newHashMap();
|
|
||||||
for (FieldNode fieldNode : classNode.fields) {
|
|
||||||
resMap.put(fieldNode.name, fieldNode.desc);
|
|
||||||
}
|
|
||||||
fieldDescriptions.put(owner, resMap);
|
|
||||||
return resMap.get(name);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("A critical exception occurred reading a class file {}", owner, e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseClass(Builder<String, String> builder, String[] parts)
|
|
||||||
{
|
|
||||||
builder.put(parts[1],parts[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseMethod(String[] parts)
|
|
||||||
{
|
|
||||||
String oldSrg = parts[1];
|
|
||||||
int lastOld = oldSrg.lastIndexOf('/');
|
|
||||||
String cl = oldSrg.substring(0,lastOld);
|
|
||||||
String oldName = oldSrg.substring(lastOld+1);
|
|
||||||
String sig = parts[2];
|
|
||||||
String newSrg = parts[3];
|
|
||||||
int lastNew = newSrg.lastIndexOf('/');
|
|
||||||
String newName = newSrg.substring(lastNew+1);
|
|
||||||
if (!rawMethodMaps.containsKey(cl))
|
|
||||||
{
|
|
||||||
rawMethodMaps.put(cl, Maps.<String,String>newHashMap());
|
|
||||||
}
|
|
||||||
rawMethodMaps.get(cl).put(oldName+sig, newName);
|
|
||||||
}
|
|
||||||
|
|
||||||
String mapMemberFieldName(String owner, String name, String desc)
|
|
||||||
{
|
|
||||||
String remappedName = mapFieldName(owner, name, desc, true);
|
|
||||||
storeMemberFieldMapping(owner, name, desc, remappedName);
|
|
||||||
return remappedName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void storeMemberFieldMapping(String owner, String name, String desc, String remappedName) {
|
|
||||||
Map<String, String> fieldMap = getRawFieldMap(owner);
|
|
||||||
|
|
||||||
String key = name + ":" + desc;
|
|
||||||
String altKey = name + ":null";
|
|
||||||
|
|
||||||
if (!fieldMap.containsKey(key)) {
|
|
||||||
fieldMap.put(key, remappedName);
|
|
||||||
fieldMap.put(altKey, remappedName);
|
|
||||||
|
|
||||||
// Alternatively, maps could be made mutable and we could just set the relevant entry, saving
|
|
||||||
// the need to regenerate the super map each time
|
|
||||||
fieldNameMaps.remove(owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String mapFieldName(String owner, String name, @Nullable String desc)
|
|
||||||
{
|
|
||||||
return mapFieldName(owner, name, desc, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
String mapFieldName(String owner, String name, @Nullable String desc, boolean raw)
|
|
||||||
{
|
|
||||||
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
Map<String, String> fieldMap = getFieldMap(owner, raw);
|
|
||||||
return fieldMap!=null && fieldMap.containsKey(name+":"+desc) ? fieldMap.get(name+":"+desc) : fieldMap!=null && fieldMap.containsKey(name+":null") ? fieldMap.get(name+":null") :name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String map(String typeName)
|
|
||||||
{
|
|
||||||
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
|
||||||
{
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
if (classNameBiMap.containsKey(typeName))
|
|
||||||
{
|
|
||||||
return classNameBiMap.get(typeName);
|
|
||||||
}
|
|
||||||
int dollarIdx = typeName.lastIndexOf('$');
|
|
||||||
if (dollarIdx > -1)
|
|
||||||
{
|
|
||||||
return map(typeName.substring(0, dollarIdx)) + "$" + typeName.substring(dollarIdx + 1);
|
|
||||||
}
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String unmap(String typeName)
|
|
||||||
{
|
|
||||||
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
|
||||||
{
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classNameBiMap.containsValue(typeName))
|
|
||||||
{
|
|
||||||
return classNameBiMap.inverse().get(typeName);
|
|
||||||
}
|
|
||||||
int dollarIdx = typeName.lastIndexOf('$');
|
|
||||||
if (dollarIdx > -1)
|
|
||||||
{
|
|
||||||
return unmap(typeName.substring(0, dollarIdx)) + "$" + typeName.substring(dollarIdx + 1);
|
|
||||||
}
|
|
||||||
return typeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String mapMethodName(String owner, String name, String desc)
|
|
||||||
{
|
|
||||||
if (classNameBiMap==null || classNameBiMap.isEmpty())
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
Map<String, String> methodMap = getMethodMap(owner);
|
|
||||||
String methodDescriptor = name+desc;
|
|
||||||
return methodMap!=null && methodMap.containsKey(methodDescriptor) ? methodMap.get(methodDescriptor) : name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public String mapSignature(String signature, boolean typeSignature)
|
|
||||||
{
|
|
||||||
// JDT decorates some lambdas with this and SignatureReader chokes on it
|
|
||||||
if (signature != null && signature.contains("!*"))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return super.mapSignature(signature, typeSignature);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String,String> getRawFieldMap(String className)
|
|
||||||
{
|
|
||||||
if (!rawFieldMaps.containsKey(className))
|
|
||||||
{
|
|
||||||
rawFieldMaps.put(className, Maps.<String,String>newHashMap());
|
|
||||||
}
|
|
||||||
return rawFieldMaps.get(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String,String> getFieldMap(String className, boolean raw)
|
|
||||||
{
|
|
||||||
if (raw)
|
|
||||||
{
|
|
||||||
return getRawFieldMap(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fieldNameMaps.containsKey(className) && !negativeCacheFields.contains(className))
|
|
||||||
{
|
|
||||||
findAndMergeSuperMaps(className);
|
|
||||||
if (!fieldNameMaps.containsKey(className))
|
|
||||||
{
|
|
||||||
negativeCacheFields.add(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DUMP_FIELD_MAPS)
|
|
||||||
{
|
|
||||||
FMLLog.log.trace("Field map for {} : {}", className, fieldNameMaps.get(className));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fieldNameMaps.get(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String,String> getMethodMap(String className)
|
|
||||||
{
|
|
||||||
if (!methodNameMaps.containsKey(className) && !negativeCacheMethods.contains(className))
|
|
||||||
{
|
|
||||||
findAndMergeSuperMaps(className);
|
|
||||||
if (!methodNameMaps.containsKey(className))
|
|
||||||
{
|
|
||||||
negativeCacheMethods.add(className);
|
|
||||||
}
|
|
||||||
if (DUMP_METHOD_MAPS)
|
|
||||||
{
|
|
||||||
FMLLog.log.trace("Method map for {} : {}", className, methodNameMaps.get(className));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return methodNameMaps.get(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void findAndMergeSuperMaps(String name)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String superName = null;
|
|
||||||
String[] interfaces = new String[0];
|
|
||||||
byte[] classBytes = ClassPatchManager.INSTANCE.getPatchedResource(name, map(name), classLoader);
|
|
||||||
if (classBytes != null)
|
|
||||||
{
|
|
||||||
ClassReader cr = new ClassReader(classBytes);
|
|
||||||
superName = cr.getSuperName();
|
|
||||||
interfaces = cr.getInterfaces();
|
|
||||||
}
|
|
||||||
mergeSuperMaps(name, superName, interfaces);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("Error getting patched resource:", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void mergeSuperMaps(String name, @Nullable String superName, String[] interfaces)
|
|
||||||
{
|
|
||||||
// System.out.printf("Computing super maps for %s: %s %s\n", name, superName, Arrays.asList(interfaces));
|
|
||||||
if (classNameBiMap == null || classNameBiMap.isEmpty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Skip Object
|
|
||||||
if (Strings.isNullOrEmpty(superName))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> allParents = ImmutableList.<String>builder().add(superName).addAll(Arrays.asList(interfaces)).build();
|
|
||||||
// generate maps for all parent objects
|
|
||||||
for (String parentThing : allParents)
|
|
||||||
{
|
|
||||||
if (!fieldNameMaps.containsKey(parentThing))
|
|
||||||
{
|
|
||||||
findAndMergeSuperMaps(parentThing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Map<String, String> methodMap = Maps.newHashMap();
|
|
||||||
Map<String, String> fieldMap = Maps.newHashMap();
|
|
||||||
for (String parentThing : allParents)
|
|
||||||
{
|
|
||||||
if (methodNameMaps.containsKey(parentThing))
|
|
||||||
{
|
|
||||||
methodMap.putAll(methodNameMaps.get(parentThing));
|
|
||||||
}
|
|
||||||
if (fieldNameMaps.containsKey(parentThing))
|
|
||||||
{
|
|
||||||
fieldMap.putAll(fieldNameMaps.get(parentThing));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rawMethodMaps.containsKey(name))
|
|
||||||
{
|
|
||||||
methodMap.putAll(rawMethodMaps.get(name));
|
|
||||||
}
|
|
||||||
if (rawFieldMaps.containsKey(name))
|
|
||||||
{
|
|
||||||
fieldMap.putAll(rawFieldMaps.get(name));
|
|
||||||
}
|
|
||||||
methodNameMaps.put(name, ImmutableMap.copyOf(methodMap));
|
|
||||||
fieldNameMaps.put(name, ImmutableMap.copyOf(fieldMap));
|
|
||||||
// System.out.printf("Maps: %s %s\n", name, methodMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getObfedClasses()
|
|
||||||
{
|
|
||||||
return ImmutableSet.copyOf(classNameBiMap.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getStaticFieldType(String oldType, String oldName, String newType, String newName)
|
|
||||||
{
|
|
||||||
String fType = getFieldType(newType, newName);
|
|
||||||
if (oldType.equals(newType))
|
|
||||||
{
|
|
||||||
return fType;
|
|
||||||
}
|
|
||||||
Map<String, String> newClassMap = fieldDescriptions.computeIfAbsent(newType, k -> Maps.newHashMap());
|
|
||||||
newClassMap.put(newName, fType);
|
|
||||||
return fType;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,121 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm.deobf;
|
|
||||||
|
|
||||||
import org.objectweb.asm.ClassVisitor;
|
|
||||||
import org.objectweb.asm.FieldVisitor;
|
|
||||||
import org.objectweb.asm.Handle;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
import org.objectweb.asm.commons.Remapper;
|
|
||||||
import org.objectweb.asm.commons.RemappingClassAdapter;
|
|
||||||
import org.objectweb.asm.commons.RemappingMethodAdapter;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FMLRemappingAdapter extends RemappingClassAdapter {
|
|
||||||
public FMLRemappingAdapter(ClassVisitor cv)
|
|
||||||
{
|
|
||||||
super(cv, FMLDeobfuscatingRemapper.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final List<Handle> META_FACTORIES = Arrays.asList(
|
|
||||||
new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory",
|
|
||||||
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
|
|
||||||
false),
|
|
||||||
new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "altMetafactory",
|
|
||||||
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;",
|
|
||||||
false)
|
|
||||||
);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
|
||||||
{
|
|
||||||
if (interfaces == null)
|
|
||||||
{
|
|
||||||
interfaces = new String[0];
|
|
||||||
}
|
|
||||||
FMLDeobfuscatingRemapper.INSTANCE.mergeSuperMaps(name, superName, interfaces);
|
|
||||||
super.visit(version, access, name, signature, superName, interfaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
|
||||||
FMLDeobfuscatingRemapper remapper = FMLDeobfuscatingRemapper.INSTANCE;
|
|
||||||
FieldVisitor fv = cv.visitField(access,
|
|
||||||
remapper.mapMemberFieldName(className, name, desc),
|
|
||||||
remapper.mapDesc(desc), remapper.mapSignature(signature, true),
|
|
||||||
remapper.mapValue(value));
|
|
||||||
return createRemappingFieldAdapter(fv);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MethodVisitor createRemappingMethodAdapter(int access, String newDesc, MethodVisitor mv)
|
|
||||||
{
|
|
||||||
return new StaticFixingMethodVisitor(access, newDesc, mv, remapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class StaticFixingMethodVisitor extends RemappingMethodAdapter
|
|
||||||
{
|
|
||||||
|
|
||||||
public StaticFixingMethodVisitor(int access, String desc, MethodVisitor mv, Remapper remapper)
|
|
||||||
{
|
|
||||||
super(access, desc, mv, remapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitFieldInsn(int opcode, String originalType, String originalName, String desc)
|
|
||||||
{
|
|
||||||
// This method solves the problem of a static field reference changing type. In all probability it is a
|
|
||||||
// compatible change, however we need to fix up the desc to point at the new type
|
|
||||||
String type = remapper.mapType(originalType);
|
|
||||||
String fieldName = remapper.mapFieldName(originalType, originalName, desc);
|
|
||||||
String newDesc = remapper.mapDesc(desc);
|
|
||||||
if (opcode == Opcodes.GETSTATIC && type.startsWith("net/minecraft/") && newDesc.startsWith("Lnet/minecraft/"))
|
|
||||||
{
|
|
||||||
String replDesc = FMLDeobfuscatingRemapper.INSTANCE.getStaticFieldType(originalType, originalName, type, fieldName);
|
|
||||||
if (replDesc != null)
|
|
||||||
{
|
|
||||||
newDesc = remapper.mapDesc(replDesc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// super.super
|
|
||||||
if (mv != null) {
|
|
||||||
mv.visitFieldInsn(opcode, type, fieldName, newDesc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)
|
|
||||||
{
|
|
||||||
// Special case lambda metaFactory to get new name
|
|
||||||
if (META_FACTORIES.contains(bsm))
|
|
||||||
{
|
|
||||||
String owner = Type.getReturnType(desc).getInternalName();
|
|
||||||
String odesc = ((Type) bsmArgs[0]).getDescriptor(); // First constant argument is "samMethodType - Signature and return type of method to be implemented by the function object."
|
|
||||||
name = remapper.mapMethodName(owner, name, odesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.asm.deobf;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import LZMA.LzmaInputStream;
|
|
||||||
|
|
||||||
import com.google.common.io.ByteSource;
|
|
||||||
|
|
||||||
public class LZMAInputSupplier extends ByteSource {
|
|
||||||
private InputStream compressedData;
|
|
||||||
|
|
||||||
public LZMAInputSupplier(InputStream compressedData)
|
|
||||||
{
|
|
||||||
this.compressedData = compressedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream openStream() throws IOException
|
|
||||||
{
|
|
||||||
return new LzmaInputStream(this.compressedData);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,192 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.discovery.json;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder;
|
|
||||||
|
|
||||||
//Package private, modders shouldn't access this. Do it through ASMDataTable.
|
|
||||||
class ASMInfo
|
|
||||||
{
|
|
||||||
String name;
|
|
||||||
String[] interfaces;
|
|
||||||
List<Annotation> annotations;
|
|
||||||
private Map<Integer, Annotation> byID;
|
|
||||||
|
|
||||||
public Annotation getSubAnnotation(int id)
|
|
||||||
{
|
|
||||||
if (byID == null)
|
|
||||||
{
|
|
||||||
byID = Maps.newHashMap();
|
|
||||||
annotations.forEach(a -> { if (a.id != null) byID.put(a.id, a); });
|
|
||||||
}
|
|
||||||
return byID.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return MoreObjects.toStringHelper("")
|
|
||||||
.add("name", name)
|
|
||||||
.add("itf", interfaces)
|
|
||||||
.add("ann", annotations)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TargetType { CLASS, FIELD, METHOD, SUBTYPE };
|
|
||||||
public enum ValueType
|
|
||||||
{
|
|
||||||
BOOL(Boolean::valueOf, v -> {boolean[] ret = new boolean[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Boolean.parseBoolean(v[x]); return ret; }),
|
|
||||||
BYTE(Byte::valueOf, v -> {byte[] ret = new byte[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Byte.parseByte(v[x]); return ret; }),
|
|
||||||
CHAR(x -> x.charAt(0), v -> {char[] ret = new char[v.length]; for (int x = 0; x < v.length; x++) ret[x] = v[x].charAt(0); return ret; }),
|
|
||||||
SHORT(Short::valueOf, v -> {short[] ret = new short[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Short.parseShort(v[x]); return ret; }),
|
|
||||||
INT(Integer::valueOf, v -> {int[] ret = new int[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Integer.parseInt(v[x]); return ret; }),
|
|
||||||
LONG(Long::valueOf, v -> {long[] ret = new long[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Long.parseLong(v[x]); return ret; }),
|
|
||||||
FLOAT(Float::valueOf, v -> {float[] ret = new float[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Float.parseFloat(v[x]); return ret; }),
|
|
||||||
DOUBLE(Double::valueOf, v -> {double[] ret = new double[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Double.parseDouble(v[x]); return ret; }),
|
|
||||||
STRING(x -> x, x -> x),
|
|
||||||
CLASS(Type::getType, v -> {Type[] ret = new Type[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Type.getType(v[x]); return ret; }),
|
|
||||||
ENUM(ValueType::getEnumHolder, v -> {List<EnumHolder> ret = Lists.newArrayList(); for (int x = 0; x < v.length; x++) ret.add(ValueType.getEnumHolder(v[x])); return ret; }),
|
|
||||||
ANNOTATION(null, null),
|
|
||||||
NULL(x -> null, x -> null);
|
|
||||||
|
|
||||||
public final Function<String, Object> single;
|
|
||||||
public final Function<String[], Object> array;
|
|
||||||
|
|
||||||
private ValueType(Function<String, Object> single, Function<String[], Object> array)
|
|
||||||
{
|
|
||||||
this.single = single;
|
|
||||||
this.array = array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EnumHolder getEnumHolder(String value)
|
|
||||||
{
|
|
||||||
int idx = value.lastIndexOf('/');
|
|
||||||
if (idx <= 1)
|
|
||||||
throw new IllegalArgumentException("Can not create a EnumHolder for value: " + value);
|
|
||||||
String field = value.substring(idx + 1);
|
|
||||||
value = value.substring(0, idx);
|
|
||||||
idx = value.indexOf(';'); //Legacy internal name.
|
|
||||||
value = value.substring(1, idx);
|
|
||||||
return new EnumHolder(value, field);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static class Annotation
|
|
||||||
{
|
|
||||||
TargetType type;
|
|
||||||
String name;
|
|
||||||
String target;
|
|
||||||
Integer id;
|
|
||||||
ValueHolder value;
|
|
||||||
Map<String, ValueHolder> values;
|
|
||||||
private Map<String, Object> _values;
|
|
||||||
|
|
||||||
public Map<String, Object> getValues(ASMInfo pool)
|
|
||||||
{
|
|
||||||
if (_values == null)
|
|
||||||
{
|
|
||||||
_values = Maps.newHashMap();
|
|
||||||
if (values != null)
|
|
||||||
values.forEach((k, v) -> _values.put(k, v.get(pool)));
|
|
||||||
else
|
|
||||||
_values.put("value", value == null ? null : value.get(pool));
|
|
||||||
}
|
|
||||||
|
|
||||||
return _values;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return MoreObjects.toStringHelper("")
|
|
||||||
.add("type", type)
|
|
||||||
.add("name", name)
|
|
||||||
.add("target", target)
|
|
||||||
.add("id", id)
|
|
||||||
.add("value", value)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ValueHolder
|
|
||||||
{
|
|
||||||
ValueType type;
|
|
||||||
String value;
|
|
||||||
String[] values;
|
|
||||||
|
|
||||||
private Object _value;
|
|
||||||
|
|
||||||
private ValueType getType()
|
|
||||||
{
|
|
||||||
return type == null ? ValueType.STRING : type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object get(ASMInfo pool)
|
|
||||||
{
|
|
||||||
if (_value == null)
|
|
||||||
{
|
|
||||||
if (values != null)
|
|
||||||
{
|
|
||||||
if (type == ValueType.ANNOTATION)
|
|
||||||
{
|
|
||||||
List<Map<String, Object>> list = Lists.newArrayList();
|
|
||||||
_value = list;
|
|
||||||
|
|
||||||
for (String s : values)
|
|
||||||
{
|
|
||||||
Annotation sub = pool.getSubAnnotation(Integer.parseInt(s));
|
|
||||||
if (sub == null)
|
|
||||||
FMLLog.log.error("Invalid Sub-Annotation in Annotation JSON: " + s);
|
|
||||||
else
|
|
||||||
list.add(sub.getValues(pool));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_value = getType().array.apply(values);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (type == ValueType.ANNOTATION)
|
|
||||||
{
|
|
||||||
Annotation sub = pool.getSubAnnotation(Integer.parseInt(value));
|
|
||||||
if (sub == null)
|
|
||||||
FMLLog.log.error("Invalid Sub-Annotation in Annotation JSON: " + value);
|
|
||||||
else
|
|
||||||
_value = sub.getValues(pool);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_value = getType().single.apply(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.discovery.json;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
|
||||||
import com.google.common.collect.HashMultimap;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.discovery.json.ASMInfo.Annotation;
|
|
||||||
import net.minecraftforge.fml.common.discovery.json.ASMInfo.TargetType;
|
|
||||||
|
|
||||||
public class JsonAnnotationLoader
|
|
||||||
{
|
|
||||||
public static final String ANNOTATION_JSON = "META-INF/fml_cache_annotation.json";
|
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
|
||||||
private static final java.lang.reflect.Type INFO_TABLE = new TypeToken<Map<String, ASMInfo>>(){}.getType();
|
|
||||||
|
|
||||||
public static Multimap<String, ASMData> loadJson(InputStream data, ModCandidate candidate, ASMDataTable table)
|
|
||||||
{
|
|
||||||
Map<String, ASMInfo> map = GSON.fromJson(new InputStreamReader(data, StandardCharsets.UTF_8), INFO_TABLE);
|
|
||||||
Multimap<String, ASMData> ret = HashMultimap.create();
|
|
||||||
|
|
||||||
for (Entry<String, ASMInfo> entry : map.entrySet())
|
|
||||||
{
|
|
||||||
//TODO: Java9 Multi-Release Jars, picking the correct class for the current platform. For now we just ignore them.
|
|
||||||
if (entry.getKey().startsWith("META-INF/"))
|
|
||||||
continue;
|
|
||||||
//TODO: Remove in 1.13, some older mods have these in the entries due to FG issue. Basically filter out scala synthetic class.
|
|
||||||
if (entry.getKey().endsWith("$"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ASMInfo asm_info = entry.getValue();
|
|
||||||
if (asm_info.interfaces != null)
|
|
||||||
{
|
|
||||||
for (String type : asm_info.interfaces)
|
|
||||||
{
|
|
||||||
//Interfaces use internal name, but annotations use source names. See ASMModParser.sendToTable
|
|
||||||
table.addASMData(candidate, type, asm_info.name, null, null);
|
|
||||||
ret.put(type, new ASMData(candidate, type, asm_info.name, null, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String owner_name = asm_info.name.replace('/', '.');
|
|
||||||
if (asm_info.annotations != null)
|
|
||||||
{
|
|
||||||
for (Annotation anno : asm_info.annotations)
|
|
||||||
{
|
|
||||||
String name = anno.name.indexOf(';') > 0 ? Type.getType(anno.name).getClassName() : anno.name;
|
|
||||||
String target = anno.target != null && (anno.type == TargetType.CLASS || anno.type == TargetType.SUBTYPE) ? anno.target.replace('/', '.') : anno.target;
|
|
||||||
|
|
||||||
table.addASMData(candidate, name, owner_name, target, anno.getValues(asm_info));
|
|
||||||
ret.put(name, new ASMData(candidate, name, owner_name, target, anno.getValues(asm_info)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.event;
|
package net.minecraftforge.fml.common.event;
|
||||||
|
|
||||||
import net.minecraft.command.CommandHandler;
|
|
||||||
import net.minecraft.command.ICommand;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,10 +34,4 @@ public class FMLServerStartingEvent extends ServerLifecycleEvent
|
||||||
{
|
{
|
||||||
super(server);
|
super(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerServerCommand(ICommand command)
|
|
||||||
{
|
|
||||||
CommandHandler ch = (CommandHandler) getServer().getCommandManager();
|
|
||||||
ch.registerCommand(command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,289 +50,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ByteBufUtils {
|
public class ByteBufUtils {
|
||||||
/**
|
|
||||||
* The number of bytes to write the supplied int using the 7 bit varint encoding.
|
|
||||||
*
|
|
||||||
* @param toCount The number to analyse
|
|
||||||
* @return The number of bytes it will take to write it (maximum of 5)
|
|
||||||
*/
|
|
||||||
public static int varIntByteCount(int toCount)
|
|
||||||
{
|
|
||||||
return (toCount & 0xFFFFFF80) == 0 ? 1 : ((toCount & 0xFFFFC000) == 0 ? 2 : ((toCount & 0xFFE00000) == 0 ? 3 : ((toCount & 0xF0000000) == 0 ? 4 : 5)));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Read a varint from the supplied buffer.
|
|
||||||
*
|
|
||||||
* @param buf The buffer to read from
|
|
||||||
* @param maxSize The maximum length of bytes to read
|
|
||||||
* @return The integer
|
|
||||||
*/
|
|
||||||
public static int readVarInt(ByteBuf buf, int maxSize)
|
|
||||||
{
|
|
||||||
Validate.isTrue(maxSize < 6 && maxSize > 0, "Varint length is between 1 and 5, not %d", maxSize);
|
|
||||||
int i = 0;
|
|
||||||
int j = 0;
|
|
||||||
byte b0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
b0 = buf.readByte();
|
|
||||||
i |= (b0 & 127) << j++ * 7;
|
|
||||||
|
|
||||||
if (j > maxSize)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("VarInt too big");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((b0 & 128) == 128);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* An extended length short. Used by custom payload packets to extend size.
|
|
||||||
*
|
|
||||||
* @param buf
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static int readVarShort(ByteBuf buf)
|
|
||||||
{
|
|
||||||
int low = buf.readUnsignedShort();
|
|
||||||
int high = 0;
|
|
||||||
if ((low & 0x8000) != 0)
|
|
||||||
{
|
|
||||||
low = low & 0x7FFF;
|
|
||||||
high = buf.readUnsignedByte();
|
|
||||||
}
|
|
||||||
return ((high & 0xFF) << 15) | low;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeVarShort(ByteBuf buf, int toWrite)
|
|
||||||
{
|
|
||||||
int low = toWrite & 0x7FFF;
|
|
||||||
int high = ( toWrite & 0x7F8000 ) >> 15;
|
|
||||||
if (high != 0)
|
|
||||||
{
|
|
||||||
low = low | 0x8000;
|
|
||||||
}
|
|
||||||
buf.writeShort(low);
|
|
||||||
if (high != 0)
|
|
||||||
{
|
|
||||||
buf.writeByte(high);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Write an integer to the buffer using variable length encoding. The maxSize constrains
|
|
||||||
* how many bytes (and therefore the maximum number) that will be written.
|
|
||||||
*
|
|
||||||
* @param to The buffer to write to
|
|
||||||
* @param toWrite The integer to write
|
|
||||||
* @param maxSize The maximum number of bytes to use
|
|
||||||
*/
|
|
||||||
public static void writeVarInt(ByteBuf to, int toWrite, int maxSize)
|
|
||||||
{
|
|
||||||
Validate.isTrue(varIntByteCount(toWrite) <= maxSize, "Integer is too big for %d bytes", maxSize);
|
|
||||||
while ((toWrite & -128) != 0)
|
|
||||||
{
|
|
||||||
to.writeByte(toWrite & 127 | 128);
|
|
||||||
toWrite >>>= 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
to.writeByte(toWrite);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Read a UTF8 string from the byte buffer.
|
|
||||||
* It is encoded as <varint length>[<UTF8 char bytes>]
|
|
||||||
*
|
|
||||||
* @param from The buffer to read from
|
|
||||||
* @return The string
|
|
||||||
*/
|
|
||||||
public static String readUTF8String(ByteBuf from)
|
|
||||||
{
|
|
||||||
int len = readVarInt(from,2);
|
|
||||||
String str = from.toString(from.readerIndex(), len, StandardCharsets.UTF_8);
|
|
||||||
from.readerIndex(from.readerIndex() + len);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a String with UTF8 byte encoding to the buffer.
|
|
||||||
* It is encoded as <varint length>[<UTF8 char bytes>]
|
|
||||||
* @param to the buffer to write to
|
|
||||||
* @param string The string to write
|
|
||||||
*/
|
|
||||||
public static void writeUTF8String(ByteBuf to, String string)
|
|
||||||
{
|
|
||||||
byte[] utf8Bytes = string.getBytes(StandardCharsets.UTF_8);
|
|
||||||
Validate.isTrue(varIntByteCount(utf8Bytes.length) < 3, "The string is too long for this encoding.");
|
|
||||||
writeVarInt(to, utf8Bytes.length, 2);
|
|
||||||
to.writeBytes(utf8Bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an {@link ItemStack} using minecraft compatible encoding.
|
|
||||||
*
|
|
||||||
* @param to The buffer to write to
|
|
||||||
* @param stack The itemstack to write
|
|
||||||
*/
|
|
||||||
public static void writeItemStack(ByteBuf to, ItemStack stack)
|
|
||||||
{
|
|
||||||
PacketBuffer pb = new PacketBuffer(to);
|
|
||||||
pb.writeItemStack(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an {@link ItemStack} from the byte buffer provided. It uses the minecraft encoding.
|
|
||||||
*
|
|
||||||
* @param from The buffer to read from
|
|
||||||
* @return The itemstack read
|
|
||||||
*/
|
|
||||||
public static ItemStack readItemStack(ByteBuf from)
|
|
||||||
{
|
|
||||||
PacketBuffer pb = new PacketBuffer(from);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return pb.readItemStack();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
// Unpossible?
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an {@link NBTTagCompound} to the byte buffer. It uses the minecraft encoding.
|
|
||||||
*
|
|
||||||
* @param to The buffer to write to
|
|
||||||
* @param tag The tag to write
|
|
||||||
*/
|
|
||||||
public static void writeTag(ByteBuf to, NBTTagCompound tag)
|
|
||||||
{
|
|
||||||
PacketBuffer pb = new PacketBuffer(to);
|
|
||||||
pb.writeCompoundTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an {@link NBTTagCompound} from the byte buffer. It uses the minecraft encoding.
|
|
||||||
*
|
|
||||||
* @param from The buffer to read from
|
|
||||||
* @return The read tag
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public static NBTTagCompound readTag(ByteBuf from)
|
|
||||||
{
|
|
||||||
PacketBuffer pb = new PacketBuffer(from);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return pb.readCompoundTag();
|
|
||||||
} catch (IOException e)
|
|
||||||
{
|
|
||||||
// Unpossible?
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a registry entry to the stream. The serialized format is not specified and must not be relied upon.
|
|
||||||
* Do not use this to write to a file, it is used for client-server communication only.
|
|
||||||
* @param out the buffer to write to
|
|
||||||
* @param entry the registry entry
|
|
||||||
*/
|
|
||||||
public static <T extends IForgeRegistryEntry<T>> void writeRegistryEntry(@Nonnull ByteBuf out, @Nonnull T entry)
|
|
||||||
{
|
|
||||||
ForgeRegistry<T> registry = (ForgeRegistry<T>)GameRegistry.findRegistry(entry.getRegistryType());
|
|
||||||
writeUTF8String(out, RegistryManager.ACTIVE.getName(registry).toString());
|
|
||||||
writeVarInt(out, registry.getID(entry), 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a registry entry from the stream. The same format as in {@link #writeRegistryEntry(ByteBuf, IForgeRegistryEntry)} is used.
|
|
||||||
* @param in the buffer to read from
|
|
||||||
* @param registry the registry the entry belongs to
|
|
||||||
* @return the read registry entry
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static <T extends IForgeRegistryEntry<T>> T readRegistryEntry(@Nonnull ByteBuf in, @Nonnull IForgeRegistry<T> registry)
|
|
||||||
{
|
|
||||||
String registryName = readUTF8String(in);
|
|
||||||
int id = readVarInt(in, 5);
|
|
||||||
ResourceLocation expectedRegistryName = RegistryManager.ACTIVE.getName(registry);
|
|
||||||
|
|
||||||
if (!expectedRegistryName.toString().equals(registryName))
|
|
||||||
throw new IllegalArgumentException("Registry mismatch: " + registryName + " != " + expectedRegistryName);
|
|
||||||
|
|
||||||
T thing = ((ForgeRegistry<T>)registry).getRaw(id);
|
|
||||||
if (thing == null)
|
|
||||||
throw new IllegalArgumentException("Unknown ID " + id + " for registry " + expectedRegistryName + " received.");
|
|
||||||
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write multiple registry entries from the same registry to the stream. The serialized format may be more compact than using
|
|
||||||
* {@link #writeRegistryEntry(ByteBuf, IForgeRegistryEntry)} multiple times.
|
|
||||||
* @param out the buffer to write to
|
|
||||||
* @param entries the entries to write
|
|
||||||
*/
|
|
||||||
public static <T extends IForgeRegistryEntry<T>> void writeRegistryEntries(@Nonnull ByteBuf out, @Nonnull Collection<T> entries)
|
|
||||||
{
|
|
||||||
writeVarInt(out, entries.size(), 5);
|
|
||||||
|
|
||||||
Iterator<T> it = entries.iterator();
|
|
||||||
if (it.hasNext())
|
|
||||||
{
|
|
||||||
T first = it.next();
|
|
||||||
ForgeRegistry<T> registry = (ForgeRegistry<T>)GameRegistry.findRegistry(first.getRegistryType());
|
|
||||||
writeUTF8String(out, RegistryManager.ACTIVE.getName(registry).toString());
|
|
||||||
writeVarInt(out, registry.getID(first), 5);
|
|
||||||
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
int id = registry.getID(it.next());
|
|
||||||
if (id == -1)
|
|
||||||
throw new IllegalArgumentException("Unregistered IForgeRegistryEntry in collection " + entries + ".");
|
|
||||||
writeVarInt(out, id, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read multiple registry entries from the same registries from the stream. The list of entries must have been written by
|
|
||||||
* {@link #writeRegistryEntries(ByteBuf, Collection)}.
|
|
||||||
* @param in the buffer to read from
|
|
||||||
* @param registry the registry the entries belong to
|
|
||||||
* @return the immutable list of entries
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static <T extends IForgeRegistryEntry<T>> List<T> readRegistryEntries(@Nonnull ByteBuf in, @Nonnull IForgeRegistry<T> registry)
|
|
||||||
{
|
|
||||||
int size = readVarInt(in, 5);
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String registryName = readUTF8String(in);
|
|
||||||
ResourceLocation expectedRegistryName = RegistryManager.ACTIVE.getName(registry);
|
|
||||||
if (!expectedRegistryName.toString().equals(registryName))
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Registry mismatch: " + registryName + " != " + expectedRegistryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableList.Builder<T> b = ImmutableList.builder();
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
int id = readVarInt(in, 5);
|
|
||||||
T thing = ((ForgeRegistry<T>)registry).getRaw(id);
|
|
||||||
if (thing == null)
|
|
||||||
throw new IllegalArgumentException("Unknown ID " + id + " for registry " + expectedRegistryName + " received.");
|
|
||||||
|
|
||||||
b.add(thing);
|
|
||||||
}
|
|
||||||
return b.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getContentDump(ByteBuf buffer)
|
public static String getContentDump(ByteBuf buffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandler;
|
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import net.minecraft.network.Packet;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
|
||||||
import net.minecraftforge.fml.ModThreadContext;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;
|
|
||||||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility wrapper around {@link EmbeddedChannel}. Provides some convenience methods
|
|
||||||
* associated with the specific needs of FML network handling.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FMLEmbeddedChannel extends EmbeddedChannel {
|
|
||||||
public FMLEmbeddedChannel(String channelName, LogicalSide source, ChannelHandler... handlers)
|
|
||||||
{
|
|
||||||
this(ModThreadContext.get().getActiveContainer(), channelName, source, handlers);
|
|
||||||
}
|
|
||||||
public FMLEmbeddedChannel(ModContainer container, String channelName, LogicalSide source, ChannelHandler... handlers)
|
|
||||||
{
|
|
||||||
super(handlers);
|
|
||||||
this.attr(NetworkRegistry.FML_CHANNEL).set(channelName);
|
|
||||||
this.attr(NetworkRegistry.CHANNEL_SOURCE).set(source);
|
|
||||||
this.attr(NetworkRegistry.MOD_CONTAINER).setIfAbsent(container);
|
|
||||||
this.pipeline().addFirst("fml:outbound",new FMLOutboundHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method to generate a regular packet from a custom packet. Basically, it writes the packet through the
|
|
||||||
* outbound side which should have a message to message codec present (such as {@link FMLIndexedMessageToMessageCodec},
|
|
||||||
* transforming from mod packets to standard {@link FMLProxyPacket}s.
|
|
||||||
*
|
|
||||||
* This is mostly useful in cases where vanilla expects a packet, such as the TileEntity getDescriptionPacket.
|
|
||||||
*
|
|
||||||
* @param object The inbound packet
|
|
||||||
* @return A Packet suitable for passing to vanilla network code.
|
|
||||||
*/
|
|
||||||
public Packet<?> generatePacketFrom(Object object)
|
|
||||||
{
|
|
||||||
OutboundTarget outboundTarget = attr(FMLOutboundHandler.FML_MESSAGETARGET).getAndSet(OutboundTarget.NOWHERE);
|
|
||||||
writeOutbound(object);
|
|
||||||
Packet<?> pkt = (Packet<?>) outboundMessages().poll();
|
|
||||||
attr(FMLOutboundHandler.FML_MESSAGETARGET).set(outboundTarget);
|
|
||||||
return pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String findChannelHandlerNameForType(Class<? extends ChannelHandler> type)
|
|
||||||
{
|
|
||||||
String targetName = null;
|
|
||||||
for (Entry<String, ChannelHandler> entry : pipeline())
|
|
||||||
{
|
|
||||||
if (type.isInstance(entry.getValue()))
|
|
||||||
{
|
|
||||||
targetName = entry.getKey();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targetName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanAttributes()
|
|
||||||
{
|
|
||||||
this.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(null);
|
|
||||||
this.attr(NetworkRegistry.NET_HANDLER).set(null);
|
|
||||||
this.attr(NetworkDispatcher.FML_DISPATCHER).set(null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,229 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelFutureListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
|
|
||||||
import java.util.EnumMap;
|
|
||||||
|
|
||||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
|
||||||
import net.minecraft.network.NetHandlerPlayServer;
|
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An event driven network channel, using {@link FMLNetworkEvent.CustomPacketEvent} and {@link FMLNetworkEvent.CustomNetworkEvent}
|
|
||||||
* to deliver messages to an event listener. There is one "bus" for each channel, due to the
|
|
||||||
* impossibility of filtering a bus for specific events.
|
|
||||||
*
|
|
||||||
* This event driven system completely wraps the netty code. Mod code deals with FMLProxyPackets directly. It is not
|
|
||||||
* possible to enhance the netty pipeline, and I would expect highly unexpected results if it were modified reflectively.
|
|
||||||
* Use a real ChannelHandler if you want to use netty.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FMLEventChannel {
|
|
||||||
private EnumMap<Side, FMLEmbeddedChannel> channels;
|
|
||||||
private IEventBus eventBus;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is done this way so that the CLIENT specific code in the factory only loads on the client
|
|
||||||
*/
|
|
||||||
private enum EventFactory
|
|
||||||
{
|
|
||||||
SERVER()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
FMLNetworkEvent.CustomPacketEvent<?> make(FMLProxyPacket msg)
|
|
||||||
{
|
|
||||||
FMLNetworkEvent.CustomPacketEvent<?> event = null;
|
|
||||||
if (msg.handler() instanceof NetHandlerPlayServer)
|
|
||||||
{
|
|
||||||
NetHandlerPlayServer server = (NetHandlerPlayServer) msg.handler();
|
|
||||||
event = new FMLNetworkEvent.ServerCustomPacketEvent(server.getNetworkManager(), msg);
|
|
||||||
}
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CLIENT()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
FMLNetworkEvent.CustomPacketEvent<?> make(FMLProxyPacket msg)
|
|
||||||
{
|
|
||||||
FMLNetworkEvent.CustomPacketEvent<?> event = null;
|
|
||||||
if (msg.handler() instanceof NetHandlerPlayClient)
|
|
||||||
{
|
|
||||||
NetHandlerPlayClient client = (NetHandlerPlayClient) msg.handler();
|
|
||||||
event = new FMLNetworkEvent.ClientCustomPacketEvent(client.getNetworkManager(), msg);
|
|
||||||
}
|
|
||||||
else if (msg.handler() instanceof NetHandlerPlayServer)
|
|
||||||
{
|
|
||||||
NetHandlerPlayServer server = (NetHandlerPlayServer) msg.handler();
|
|
||||||
event = new FMLNetworkEvent.ServerCustomPacketEvent(server.getNetworkManager(), msg);
|
|
||||||
}
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@Nullable
|
|
||||||
abstract FMLNetworkEvent.CustomPacketEvent<?> make(FMLProxyPacket msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EventFactory factory = FMLCommonHandler.instance().getSide() == Side.CLIENT ? EventFactory.CLIENT : EventFactory.SERVER;
|
|
||||||
FMLEventChannel(String name)
|
|
||||||
{
|
|
||||||
this.channels = NetworkRegistry.INSTANCE.newChannel(name, new NetworkEventFiringHandler(this));
|
|
||||||
this.eventBus = IEventBus.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register an event listener with this channel and bus. See {@link SubscribeEvent}
|
|
||||||
*
|
|
||||||
* @param object
|
|
||||||
*/
|
|
||||||
public void register(Object object)
|
|
||||||
{
|
|
||||||
this.eventBus.register(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister an event listener from the bus.
|
|
||||||
* @param object
|
|
||||||
*/
|
|
||||||
public void unregister(Object object)
|
|
||||||
{
|
|
||||||
this.eventBus.unregister(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fireRead(FMLProxyPacket msg, ChannelHandlerContext ctx)
|
|
||||||
{
|
|
||||||
FMLNetworkEvent.CustomPacketEvent<?> event = factory.make(msg);
|
|
||||||
if (event != null)
|
|
||||||
{
|
|
||||||
this.eventBus.post(event);
|
|
||||||
if (event.getReply() != null)
|
|
||||||
{
|
|
||||||
ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.REPLY);
|
|
||||||
ctx.writeAndFlush(event.getReply()).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fireUserEvent(Object evt, ChannelHandlerContext ctx)
|
|
||||||
{
|
|
||||||
FMLNetworkEvent.CustomNetworkEvent event = new FMLNetworkEvent.CustomNetworkEvent(evt);
|
|
||||||
this.eventBus.post(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a packet to all on the server
|
|
||||||
*
|
|
||||||
* @param pkt
|
|
||||||
*/
|
|
||||||
public void sendToAll(FMLProxyPacket pkt)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to a specific player
|
|
||||||
*
|
|
||||||
* @param pkt
|
|
||||||
* @param player
|
|
||||||
*/
|
|
||||||
public void sendTo(FMLProxyPacket pkt, EntityPlayerMP player)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to all around a point
|
|
||||||
* @param pkt
|
|
||||||
* @param point
|
|
||||||
*/
|
|
||||||
public void sendToAllAround(FMLProxyPacket pkt, NetworkRegistry.TargetPoint point)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to all tracking the point
|
|
||||||
* The {@code range} field of the {@link NetworkRegistry.TargetPoint} is ignored.
|
|
||||||
* @param pkt
|
|
||||||
* @param point
|
|
||||||
*/
|
|
||||||
public void sendToAllTracking(FMLProxyPacket pkt, NetworkRegistry.TargetPoint point)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_POINT);
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to all tracking the entity
|
|
||||||
* This is not equivalent to {@link #sendToAllTracking(FMLProxyPacket, NetworkRegistry.TargetPoint)}
|
|
||||||
* because entities have different tracking distances based on their type.
|
|
||||||
* @param pkt
|
|
||||||
* @param entity
|
|
||||||
*/
|
|
||||||
public void sendToAllTracking(FMLProxyPacket pkt, Entity entity)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TRACKING_ENTITY);
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(entity);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to all in a dimension
|
|
||||||
* @param pkt
|
|
||||||
* @param dimensionId
|
|
||||||
*/
|
|
||||||
public void sendToDimension(FMLProxyPacket pkt, int dimensionId)
|
|
||||||
{
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION);
|
|
||||||
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId);
|
|
||||||
channels.get(Side.SERVER).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send to the server
|
|
||||||
* @param pkt
|
|
||||||
*/
|
|
||||||
public void sendToServer(FMLProxyPacket pkt)
|
|
||||||
{
|
|
||||||
channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
|
|
||||||
channels.get(Side.CLIENT).writeAndFlush(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import io.netty.channel.ChannelHandler.Sharable;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.handler.codec.MessageToMessageCodec;
|
|
||||||
import io.netty.util.AttributeKey;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ByteMap;
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap;
|
|
||||||
|
|
||||||
import net.minecraft.network.PacketBuffer;
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
|
|
||||||
@Sharable
|
|
||||||
public abstract class FMLIndexedMessageToMessageCodec<A> extends MessageToMessageCodec<FMLProxyPacket, A>
|
|
||||||
{
|
|
||||||
private final Byte2ObjectMap<Class<? extends A>> discriminators = new Byte2ObjectOpenHashMap<>();
|
|
||||||
private final Object2ByteMap<Class<? extends A>> types = new Object2ByteOpenHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make this accessible to subclasses
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static final AttributeKey<ThreadLocal<WeakReference<FMLProxyPacket>>> INBOUNDPACKETTRACKER = AttributeKey.valueOf("fml:inboundpacket");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
|
||||||
{
|
|
||||||
super.handlerAdded(ctx);
|
|
||||||
ctx.channel().attr(INBOUNDPACKETTRACKER).set(new ThreadLocal<WeakReference<FMLProxyPacket>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public FMLIndexedMessageToMessageCodec<A> addDiscriminator(int discriminator, Class<? extends A> type)
|
|
||||||
{
|
|
||||||
discriminators.put((byte)discriminator, type);
|
|
||||||
types.put(type, (byte)discriminator);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void encodeInto(ChannelHandlerContext ctx, A msg, ByteBuf target) throws Exception;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void encode(ChannelHandlerContext ctx, A msg, List<Object> out) throws Exception
|
|
||||||
{
|
|
||||||
String channel = ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get();
|
|
||||||
Class<?> clazz = msg.getClass();
|
|
||||||
if (!types.containsKey(clazz))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Undefined discriminator for message type " + clazz.getName() + " in channel " + channel);
|
|
||||||
}
|
|
||||||
byte discriminator = types.getByte(clazz);
|
|
||||||
PacketBuffer buffer = new PacketBuffer(Unpooled.buffer());
|
|
||||||
buffer.writeByte(discriminator);
|
|
||||||
encodeInto(ctx, msg, buffer);
|
|
||||||
FMLProxyPacket proxy = new FMLProxyPacket(buffer, channel);
|
|
||||||
WeakReference<FMLProxyPacket> ref = ctx.channel().attr(INBOUNDPACKETTRACKER).get().get();
|
|
||||||
FMLProxyPacket old = ref == null ? null : ref.get();
|
|
||||||
if (old != null)
|
|
||||||
{
|
|
||||||
proxy.setDispatcher(old.getDispatcher());
|
|
||||||
}
|
|
||||||
out.add(proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void decodeInto(ChannelHandlerContext ctx, ByteBuf source, A msg);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out) throws Exception
|
|
||||||
{
|
|
||||||
testMessageValidity(msg);
|
|
||||||
ByteBuf payload = msg.payload().duplicate();
|
|
||||||
if (payload.readableBytes() < 1)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("The FMLIndexedCodec has received an empty buffer on channel {}, likely a result of a LAN server issue. Pipeline parts : {}", ctx.channel().attr(NetworkRegistry.FML_CHANNEL), ctx.pipeline().toString());
|
|
||||||
}
|
|
||||||
byte discriminator = payload.readByte();
|
|
||||||
Class<? extends A> clazz = discriminators.get(discriminator);
|
|
||||||
if(clazz == null)
|
|
||||||
{
|
|
||||||
throw new NullPointerException("Undefined message for discriminator " + discriminator + " in channel " + msg.channel());
|
|
||||||
}
|
|
||||||
A newMsg = clazz.newInstance();
|
|
||||||
ctx.channel().attr(INBOUNDPACKETTRACKER).get().set(new WeakReference<FMLProxyPacket>(msg));
|
|
||||||
decodeInto(ctx, payload.slice(), newMsg);
|
|
||||||
out.add(newMsg);
|
|
||||||
payload.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to verify the message received. This can be used to hard disconnect in case of an unexpected packet,
|
|
||||||
* say due to a weird protocol mismatch. Use with caution.
|
|
||||||
* @param msg
|
|
||||||
*/
|
|
||||||
protected void testMessageValidity(FMLProxyPacket msg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
|
|
||||||
{
|
|
||||||
FMLLog.log.error("FMLIndexedMessageCodec exception caught", cause);
|
|
||||||
super.exceptionCaught(ctx, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,258 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
import net.minecraft.network.INetHandler;
|
|
||||||
import net.minecraft.network.NetworkManager;
|
|
||||||
import net.minecraft.network.play.INetHandlerPlayClient;
|
|
||||||
import net.minecraft.network.play.INetHandlerPlayServer;
|
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
public class FMLNetworkEvent<T extends INetHandler> extends Event {
|
|
||||||
private final T handler;
|
|
||||||
private final NetworkManager manager;
|
|
||||||
private final Class<T> type;
|
|
||||||
|
|
||||||
FMLNetworkEvent(T thing, Class<T> type, NetworkManager manager)
|
|
||||||
{
|
|
||||||
this.handler = thing;
|
|
||||||
this.type = type;
|
|
||||||
this.manager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<T> getHandlerType()
|
|
||||||
{
|
|
||||||
return getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getHandler()
|
|
||||||
{
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetworkManager getManager()
|
|
||||||
{
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<T> getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired at the client when a client connects to a server
|
|
||||||
*/
|
|
||||||
public static class ClientConnectedToServerEvent extends FMLNetworkEvent<INetHandlerPlayClient> {
|
|
||||||
private final boolean isLocal;
|
|
||||||
private final String connectionType;
|
|
||||||
public ClientConnectedToServerEvent(NetworkManager manager, String connectionType)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayClient) manager.getNetHandler(), INetHandlerPlayClient.class, manager);
|
|
||||||
this.isLocal = manager.isLocalChannel();
|
|
||||||
this.connectionType = connectionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocal()
|
|
||||||
{
|
|
||||||
return isLocal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getConnectionType()
|
|
||||||
{
|
|
||||||
return connectionType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired at the server when a client connects to the server.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class ServerConnectionFromClientEvent extends FMLNetworkEvent<INetHandlerPlayServer> {
|
|
||||||
private final boolean isLocal;
|
|
||||||
public ServerConnectionFromClientEvent(NetworkManager manager)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayServer) manager.getNetHandler(), INetHandlerPlayServer.class, manager);
|
|
||||||
this.isLocal = manager.isLocalChannel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLocal()
|
|
||||||
{
|
|
||||||
return isLocal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Fired at the server when a client disconnects.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class ServerDisconnectionFromClientEvent extends FMLNetworkEvent<INetHandlerPlayServer> {
|
|
||||||
public ServerDisconnectionFromClientEvent(NetworkManager manager)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayServer) manager.getNetHandler(), INetHandlerPlayServer.class, manager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Fired at the client when the client is disconnected from the server.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class ClientDisconnectionFromServerEvent extends FMLNetworkEvent<INetHandlerPlayClient> {
|
|
||||||
public ClientDisconnectionFromServerEvent(NetworkManager manager)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayClient) manager.getNetHandler(), INetHandlerPlayClient.class, manager);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the REGISTER/UNREGISTER for custom channels is received.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
* @param <S> The side
|
|
||||||
*/
|
|
||||||
public static class CustomPacketRegistrationEvent<S extends INetHandler> extends FMLNetworkEvent<S> {
|
|
||||||
private final ImmutableSet<String> registrations;
|
|
||||||
private final String operation;
|
|
||||||
private final Side side;
|
|
||||||
public CustomPacketRegistrationEvent(NetworkManager manager, Set<String> registrations, String operation, Side side, Class<S> type)
|
|
||||||
{
|
|
||||||
super(type.cast(manager.getNetHandler()), type, manager);
|
|
||||||
this.registrations = ImmutableSet.copyOf(registrations);
|
|
||||||
this.side = side;
|
|
||||||
this.operation = operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImmutableSet<String> getRegistrations()
|
|
||||||
{
|
|
||||||
return registrations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOperation()
|
|
||||||
{
|
|
||||||
return operation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Side getSide()
|
|
||||||
{
|
|
||||||
return side;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class CustomPacketEvent<S extends INetHandler> extends FMLNetworkEvent<S> {
|
|
||||||
private final FMLProxyPacket packet;
|
|
||||||
|
|
||||||
private FMLProxyPacket reply;
|
|
||||||
CustomPacketEvent(S thing, Class<S> type, NetworkManager manager, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
super(thing, type, manager);
|
|
||||||
this.packet = packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Side side();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The packet that generated the event
|
|
||||||
*/
|
|
||||||
public FMLProxyPacket getPacket()
|
|
||||||
{
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set this packet to reply to the originator
|
|
||||||
*/
|
|
||||||
public FMLProxyPacket getReply()
|
|
||||||
{
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReply(FMLProxyPacket reply)
|
|
||||||
{
|
|
||||||
this.reply = reply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a custom packet is received on the client for the channel
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class ClientCustomPacketEvent extends CustomPacketEvent<INetHandlerPlayClient> {
|
|
||||||
public ClientCustomPacketEvent(NetworkManager manager, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayClient) manager.getNetHandler(), INetHandlerPlayClient.class, manager, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Side side()
|
|
||||||
{
|
|
||||||
return Side.CLIENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a custom packet is received at the server for the channel
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class ServerCustomPacketEvent extends CustomPacketEvent<INetHandlerPlayServer> {
|
|
||||||
public ServerCustomPacketEvent(NetworkManager manager, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
super((INetHandlerPlayServer) manager.getNetHandler(), INetHandlerPlayServer.class, manager, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Side side()
|
|
||||||
{
|
|
||||||
return Side.SERVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when a custom event, such as {@link NetworkHandshakeEstablished} is fired for the channel
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class CustomNetworkEvent extends net.minecraftforge.eventbus.api.Event
|
|
||||||
{
|
|
||||||
private final Object wrappedEvent;
|
|
||||||
public CustomNetworkEvent(Object wrappedEvent)
|
|
||||||
{
|
|
||||||
this.wrappedEvent = wrappedEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getWrappedEvent()
|
|
||||||
{
|
|
||||||
return wrappedEvent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
public class FMLNetworkException extends RuntimeException
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public FMLNetworkException(Exception e)
|
|
||||||
{
|
|
||||||
super(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FMLNetworkException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public FMLNetworkException(String string)
|
|
||||||
{
|
|
||||||
super(string);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,394 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
|
||||||
import io.netty.channel.ChannelPromise;
|
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
|
||||||
import io.netty.util.AttributeKey;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
|
||||||
import net.minecraft.network.NetworkManager;
|
|
||||||
import net.minecraft.server.management.PlayerChunkMap;
|
|
||||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.world.WorldServer;
|
|
||||||
import net.minecraftforge.common.DimensionManager;
|
|
||||||
import net.minecraftforge.common.util.FakePlayer;
|
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
|
||||||
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;
|
|
||||||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
|
|
||||||
public static final AttributeKey<OutboundTarget> FML_MESSAGETARGET = AttributeKey.valueOf("fml:outboundTarget");
|
|
||||||
public static final AttributeKey<Object> FML_MESSAGETARGETARGS = AttributeKey.valueOf("fml:outboundTargetArgs");
|
|
||||||
public enum OutboundTarget {
|
|
||||||
/**
|
|
||||||
* The packet is sent nowhere. It will be on the {@link EmbeddedChannel#outboundMessages()} Queue.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
NOWHERE(Sets.immutableEnumSet(Side.CLIENT, Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to the {@link NetworkDispatcher} supplied as an argument.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
DISPATCHER(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof NetworkDispatcher))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("DISPATCHER expects a NetworkDispatcher");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
return ImmutableList.of((NetworkDispatcher)args);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to the originator of the packet. This requires the inbound packet
|
|
||||||
* to have it's originator information set.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
REPLY(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
return ImmutableList.of(packet.getDispatcher());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to the {@link EntityPlayerMP} supplied as an argument.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
PLAYER(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof EntityPlayerMP))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("PLAYER target expects a Player arg");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
EntityPlayerMP player = (EntityPlayerMP) args;
|
|
||||||
NetworkDispatcher dispatcher = (player == null || player instanceof FakePlayer) ? null : player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
return dispatcher == null ? ImmutableList.<NetworkDispatcher>of() : ImmutableList.of(dispatcher);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is dispatched to all players connected to the server.
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
ALL(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
|
|
||||||
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers())
|
|
||||||
{
|
|
||||||
NetworkDispatcher dispatcher = player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
if (dispatcher != null) builder.add(dispatcher);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to all players in the dimension identified by the integer argument.
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
DIMENSION(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof Integer))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("DIMENSION expects an integer argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
int dimension = (Integer)args;
|
|
||||||
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
|
|
||||||
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers())
|
|
||||||
{
|
|
||||||
if (dimension == player.dimension)
|
|
||||||
{
|
|
||||||
NetworkDispatcher dispatcher = player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
// Null dispatchers may exist for fake players - skip them
|
|
||||||
if (dispatcher != null) builder.add(dispatcher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to all players within range of the {@link TargetPoint} argument supplied.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
ALLAROUNDPOINT(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof TargetPoint))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("ALLAROUNDPOINT expects a TargetPoint argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
TargetPoint tp = (TargetPoint)args;
|
|
||||||
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
|
|
||||||
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers())
|
|
||||||
{
|
|
||||||
if (player.dimension == tp.dimension)
|
|
||||||
{
|
|
||||||
double d4 = tp.x - player.posX;
|
|
||||||
double d5 = tp.y - player.posY;
|
|
||||||
double d6 = tp.z - player.posZ;
|
|
||||||
|
|
||||||
if (d4 * d4 + d5 * d5 + d6 * d6 < tp.range * tp.range)
|
|
||||||
{
|
|
||||||
NetworkDispatcher dispatcher = player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
if (dispatcher != null) builder.add(dispatcher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to all players that are watching the Chunk containing the supplied {@link TargetPoint}.
|
|
||||||
* The {@code range} field of the {@link TargetPoint} is ignored.
|
|
||||||
*/
|
|
||||||
TRACKING_POINT(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof TargetPoint))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("TRACKING_POINT expects a TargetPoint argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
TargetPoint tp = (TargetPoint)args;
|
|
||||||
WorldServer world = DimensionManager.getWorld(tp.dimension);
|
|
||||||
if (world == null)
|
|
||||||
{
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerChunkMapEntry entry = world.getPlayerChunkMap().getEntry(MathHelper.floor(tp.x) >> 4, MathHelper.floor(tp.z) >> 4);
|
|
||||||
if (entry == null)
|
|
||||||
{
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
|
|
||||||
for (EntityPlayerMP player : entry.getWatchingPlayers())
|
|
||||||
{
|
|
||||||
NetworkDispatcher dispatcher = player.connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
if (dispatcher != null) builder.add(dispatcher);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to all players tracking the supplied {@link Entity}. This is different from {@link #TRACKING_POINT} because Entities
|
|
||||||
* can have different tracking distances depending on their type.
|
|
||||||
*/
|
|
||||||
TRACKING_ENTITY(Sets.immutableEnumSet(Side.SERVER))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
if (!(args instanceof Entity))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("TRACKING_ENTITY expects an Entity argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
Entity e = (Entity)args;
|
|
||||||
Set<? extends EntityPlayer> players = FMLCommonHandler.instance().getMinecraftServerInstance()
|
|
||||||
.getWorld(e.dimension).getEntityTracker().getTrackingPlayers(e);
|
|
||||||
|
|
||||||
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.builder();
|
|
||||||
for (EntityPlayer player : players)
|
|
||||||
{
|
|
||||||
NetworkDispatcher dispatcher = ((EntityPlayerMP) player).connection.netManager.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
if (dispatcher != null) builder.add(dispatcher);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The packet is sent to the server this client is currently conversing with.
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
TOSERVER(Sets.immutableEnumSet(Side.CLIENT))
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void validateArgs(Object args)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
|
|
||||||
{
|
|
||||||
NetworkManager clientConnection = FMLCommonHandler.instance().getClientToServerNetworkManager();
|
|
||||||
return clientConnection == null || clientConnection.channel().attr(NetworkDispatcher.FML_DISPATCHER).get() == null ? ImmutableList.<NetworkDispatcher>of() : ImmutableList.of(clientConnection.channel().attr(NetworkDispatcher.FML_DISPATCHER).get());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private OutboundTarget(ImmutableSet<Side> sides)
|
|
||||||
{
|
|
||||||
this.allowed = sides;
|
|
||||||
}
|
|
||||||
public final ImmutableSet<Side> allowed;
|
|
||||||
public abstract void validateArgs(Object args);
|
|
||||||
@Nullable
|
|
||||||
public abstract List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception
|
|
||||||
{
|
|
||||||
if (!(msg instanceof FMLProxyPacket))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FMLProxyPacket pkt = (FMLProxyPacket) msg;
|
|
||||||
OutboundTarget outboundTarget;
|
|
||||||
Object args = null;
|
|
||||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
|
||||||
// INTERNAL message callback - let it pass out
|
|
||||||
if (dispatcher != null)
|
|
||||||
{
|
|
||||||
ctx.write(msg, promise);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
outboundTarget = ctx.channel().attr(FML_MESSAGETARGET).get();
|
|
||||||
Side channelSide = ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get();
|
|
||||||
if (outboundTarget != null && outboundTarget.allowed.contains(channelSide))
|
|
||||||
{
|
|
||||||
args = ctx.channel().attr(FML_MESSAGETARGETARGS).get();
|
|
||||||
outboundTarget.validateArgs(args);
|
|
||||||
}
|
|
||||||
else if (channelSide == Side.CLIENT)
|
|
||||||
{
|
|
||||||
outboundTarget = OutboundTarget.TOSERVER;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new FMLNetworkException("Packet arrived at the outbound handler without a valid target!");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<NetworkDispatcher> dispatchers = outboundTarget.selectNetworks(args, ctx, pkt);
|
|
||||||
|
|
||||||
// This will drop the messages into the output queue at the embedded channel
|
|
||||||
if (dispatchers == null)
|
|
||||||
{
|
|
||||||
ctx.write(msg, promise);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (NetworkDispatcher targetDispatcher : dispatchers)
|
|
||||||
{
|
|
||||||
pkt.payload().retain();
|
|
||||||
targetDispatcher.sendProxy(pkt);
|
|
||||||
}
|
|
||||||
pkt.payload().release();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method annotated with this will be called when a remote network connection is offered.
|
|
||||||
* The method should have two parameters, of types Map<String,String> and {@link Side}. It should return a boolean
|
|
||||||
* true indicating that the remote party is acceptable, or false if not.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* When the method is invoked, the map will contain String keys and values listing all mods and their versions present.
|
|
||||||
* The side represents the side of the remote party. So if you're on the server, it'll be CLIENT, and vice versa.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This method will be invoked both when querying the status of the remote server, and when connecting to the remote server.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <strong>NOTE: the server will not be setup at any point when this method is called. Do not try and interact with the server
|
|
||||||
* or the client in any way, except to accept or reject the list of mods.</strong>
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
public @interface NetworkCheckHandler
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Level;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandler.Sharable;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this handler as the only thing in your channel, to receive network events
|
|
||||||
* whenever your channel receives a message.
|
|
||||||
* Note: it will not forward on to other handlers.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Sharable
|
|
||||||
public class NetworkEventFiringHandler extends SimpleChannelInboundHandler<FMLProxyPacket> {
|
|
||||||
private FMLEventChannel eventChannel;
|
|
||||||
|
|
||||||
NetworkEventFiringHandler(FMLEventChannel fmlEventChannel)
|
|
||||||
{
|
|
||||||
this.eventChannel = fmlEventChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception
|
|
||||||
{
|
|
||||||
eventChannel.fireRead(msg,ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
|
|
||||||
{
|
|
||||||
eventChannel.fireUserEvent(evt,ctx);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
|
|
||||||
{
|
|
||||||
FMLLog.log.error("NetworkEventFiringHandler exception", cause);
|
|
||||||
super.exceptionCaught(ctx, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import net.minecraft.network.INetHandler;
|
|
||||||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This message is sent through all channels affected by a currently occurring handshake. It is guaranteed to
|
|
||||||
* be able to send a custom payload packet, however, interaction with minecraft and world state is NOT assured
|
|
||||||
* as it is likely this is fired on a netty handler thread, not a world processing thread.
|
|
||||||
*
|
|
||||||
* If you wish to send an outbound message through your channel, bind the {@link FMLOutboundHandler#FML_MESSAGETARGET}
|
|
||||||
* property of your channel to the supplied dispatcher.
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NetworkHandshakeEstablished {
|
|
||||||
public final NetworkDispatcher dispatcher;
|
|
||||||
public final Side side;
|
|
||||||
public final INetHandler netHandler;
|
|
||||||
|
|
||||||
public NetworkHandshakeEstablished(NetworkDispatcher dispatcher, INetHandler netHandler, Side origin)
|
|
||||||
{
|
|
||||||
this.netHandler = netHandler;
|
|
||||||
this.dispatcher = dispatcher;
|
|
||||||
this.side = origin;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,358 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.network;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandler;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.handler.codec.MessageToMessageCodec;
|
|
||||||
import io.netty.util.AttributeKey;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
|
||||||
import net.minecraft.inventory.Container;
|
|
||||||
import net.minecraft.network.INetHandler;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
|
||||||
import net.minecraftforge.fml.ModContainer;
|
|
||||||
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
|
||||||
import net.minecraftforge.fml.common.network.internal.NetworkModHolder;
|
|
||||||
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NetworkRegistry
|
|
||||||
{
|
|
||||||
public static final NetworkRegistry INSTANCE = new NetworkRegistry();
|
|
||||||
private EnumMap<LogicalSide,Map<String,FMLEmbeddedChannel>> channels = Maps.newEnumMap(LogicalSide.class);
|
|
||||||
private Map<ModContainer, NetworkModHolder> registry = Maps.newHashMap();
|
|
||||||
private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap();
|
|
||||||
private Map<ModContainer, IGuiHandler> clientGuiHandlers = Maps.newHashMap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set in the {@link ChannelHandlerContext}
|
|
||||||
*/
|
|
||||||
public static final AttributeKey<String> FML_CHANNEL = AttributeKey.valueOf("fml:channelName");
|
|
||||||
public static final AttributeKey<LogicalSide> CHANNEL_SOURCE = AttributeKey.valueOf("fml:channelSource");
|
|
||||||
public static final AttributeKey<ModContainer> MOD_CONTAINER = AttributeKey.valueOf("fml:modContainer");
|
|
||||||
public static final AttributeKey<INetHandler> NET_HANDLER = AttributeKey.valueOf("fml:netHandler");
|
|
||||||
|
|
||||||
// Version 1: ServerHello only contains this value as a byte
|
|
||||||
// Version 2: ServerHello additionally contains a 4 byte (int) dimension for the logging in client
|
|
||||||
public static final byte FML_PROTOCOL = 2;
|
|
||||||
|
|
||||||
private NetworkRegistry()
|
|
||||||
{
|
|
||||||
channels.put(LogicalSide.CLIENT, Maps.<String,FMLEmbeddedChannel>newConcurrentMap());
|
|
||||||
channels.put(LogicalSide.SERVER, Maps.<String,FMLEmbeddedChannel>newConcurrentMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a target point for the ALLROUNDPOINT target.
|
|
||||||
*
|
|
||||||
* @author cpw
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class TargetPoint {
|
|
||||||
/**
|
|
||||||
* A target point
|
|
||||||
* @param dimension The dimension to target
|
|
||||||
* @param x The X coordinate
|
|
||||||
* @param y The Y coordinate
|
|
||||||
* @param z The Z coordinate
|
|
||||||
* @param range The range
|
|
||||||
*/
|
|
||||||
public TargetPoint(int dimension, double x, double y, double z, double range)
|
|
||||||
{
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.range = range;
|
|
||||||
this.dimension = dimension;
|
|
||||||
}
|
|
||||||
public final double x;
|
|
||||||
public final double y;
|
|
||||||
public final double z;
|
|
||||||
public final double range;
|
|
||||||
public final int dimension;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Create a new synchronous message channel pair based on netty.
|
|
||||||
*
|
|
||||||
* There are two preconstructed models available:
|
|
||||||
* <ul>
|
|
||||||
* <li> {@link #newSimpleChannel(String)} provides {@link SimpleNetworkWrapper}, a simple implementation of a netty handler, suitable for those who don't
|
|
||||||
* wish to dive too deeply into netty.
|
|
||||||
* <li> {@link #newEventDrivenChannel(String)} (String)} provides {@link FMLEventChannel} an event driven implementation, with lower level
|
|
||||||
* access to the network data stream, for those with advanced bitbanging needs that don't wish to poke netty too hard.
|
|
||||||
* <li> Alternatively, simply use the netty features provided here and implement the full power of the netty stack.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* There are two channels created : one for each logical Dist (conDistred as the source of an outbound message)
|
|
||||||
* The returned map will contain a value for each logical Dist, though both will only be working in the
|
|
||||||
* integrated server case.
|
|
||||||
*
|
|
||||||
* The channel expects to read and write using {@link FMLProxyPacket}. All operation is synchronous, as the
|
|
||||||
* asynchronous behaviour occurs at a lower level in netty.
|
|
||||||
*
|
|
||||||
* The first handler in the pipeline is special and should not be removed or moved from the head - it transforms
|
|
||||||
* packets from the outbound of this pipeline into custom packets, based on the current {@link AttributeKey} value
|
|
||||||
* {@link FMLOutboundHandler#FML_MESSAGETARGET} and {@link FMLOutboundHandler#FML_MESSAGETARGETARGS} set on the channel.
|
|
||||||
* For the client to server channel (source Dist : CLIENT) this is fixed as "TOSERVER". For SERVER to CLIENT packets,
|
|
||||||
* several possible values exist.
|
|
||||||
*
|
|
||||||
* Mod Messages should be transformed using a something akin to a {@link MessageToMessageCodec}. FML provides
|
|
||||||
* a utility codec, {@link FMLIndexedMessageToMessageCodec} that transforms from {@link FMLProxyPacket} to a mod
|
|
||||||
* message using a message discriminator byte. This is optional, but highly recommended for use.
|
|
||||||
*
|
|
||||||
* Note also that the handlers supplied need to be {@link ChannelHandler.Sharable} - they are injected into two
|
|
||||||
* channels.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @param handlers
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public EnumMap<LogicalSide,FMLEmbeddedChannel> newChannel(String name, ChannelHandler... handlers)
|
|
||||||
{
|
|
||||||
if (channels.get(LogicalSide.CLIENT).containsKey(name) || channels.get(LogicalSide.SERVER).containsKey(name) || name.startsWith("MC|") || name.startsWith("\u0001") || name.startsWith("FML"))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("That channel is already registered");
|
|
||||||
}
|
|
||||||
EnumMap<LogicalSide, FMLEmbeddedChannel> result = Maps.newEnumMap(LogicalSide.class);
|
|
||||||
|
|
||||||
for (LogicalSide side : LogicalSide.values())
|
|
||||||
{
|
|
||||||
FMLEmbeddedChannel channel = new FMLEmbeddedChannel(name, side, handlers);
|
|
||||||
channels.get(side).put(name,channel);
|
|
||||||
result.put(side, channel);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new {@link SimpleNetworkWrapper} for the channel.
|
|
||||||
*
|
|
||||||
* @param name The name of the channel
|
|
||||||
* @return A {@link SimpleNetworkWrapper} for handling this channel
|
|
||||||
*/
|
|
||||||
public SimpleNetworkWrapper newSimpleChannel(String name)
|
|
||||||
{
|
|
||||||
return new SimpleNetworkWrapper(name);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Construct a new {@link FMLEventChannel} for the channel.
|
|
||||||
*
|
|
||||||
* @param name The name of the channel
|
|
||||||
* @return An {@link FMLEventChannel} for handling this channel
|
|
||||||
*/
|
|
||||||
public FMLEventChannel newEventDrivenChannel(String name)
|
|
||||||
{
|
|
||||||
return new FMLEventChannel(name);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* INTERNAL Create a new channel pair with the specified name and channel handlers.
|
|
||||||
* This is used internally in forge and FML
|
|
||||||
*
|
|
||||||
* @param container The container to associate the channel with
|
|
||||||
* @param name The name for the channel
|
|
||||||
* @param handlers Some {@link ChannelHandler} for the channel
|
|
||||||
* @return an {@link EnumMap} of the pair of channels. keys are {@link Dist}. There will always be two entries.
|
|
||||||
*/
|
|
||||||
public EnumMap<LogicalSide,FMLEmbeddedChannel> newChannel(ModContainer container, String name, ChannelHandler... handlers)
|
|
||||||
{
|
|
||||||
if (channels.get(Dist.CLIENT).containsKey(name) || channels.get(Dist.DEDICATED_SERVER).containsKey(name) || name.startsWith("MC|") || name.startsWith("\u0001") || (name.startsWith("FML") && !("FML".equals(container.getModId()))))
|
|
||||||
{
|
|
||||||
throw new RuntimeException("That channel is already registered");
|
|
||||||
}
|
|
||||||
EnumMap<LogicalSide,FMLEmbeddedChannel> result = Maps.newEnumMap(LogicalSide.class);
|
|
||||||
|
|
||||||
for (LogicalSide Dist : LogicalSide.values())
|
|
||||||
{
|
|
||||||
FMLEmbeddedChannel channel = new FMLEmbeddedChannel(container, name, Dist, handlers);
|
|
||||||
channels.get(Dist).put(name,channel);
|
|
||||||
result.put(Dist, channel);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FMLEmbeddedChannel getChannel(String name, Dist source)
|
|
||||||
{
|
|
||||||
return channels.get(source).get(name);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Register an {@link IGuiHandler} for the supplied mod object.
|
|
||||||
*
|
|
||||||
* @param mod The mod to handle GUIs for
|
|
||||||
* @param handler A handler for creating GUI related objects
|
|
||||||
*/
|
|
||||||
public void registerGuiHandler(Object mod, IGuiHandler handler)
|
|
||||||
{
|
|
||||||
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
|
|
||||||
if (mc == null)
|
|
||||||
{
|
|
||||||
FMLLog.log.error("Mod of type {} attempted to register a gui network handler during a construction phase", mod.getClass().getName());
|
|
||||||
throw new RuntimeException("Invalid attempt to create a GUI during mod construction. Use an EventHandler instead");
|
|
||||||
}
|
|
||||||
serverGuiHandlers.put(mc, handler);
|
|
||||||
clientGuiHandlers.put(mc, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* INTERNAL method for accessing the Gui registry
|
|
||||||
* @param mc Mod Container
|
|
||||||
* @param player Player
|
|
||||||
* @param modGuiId guiId
|
|
||||||
* @param world World
|
|
||||||
* @param x X coord
|
|
||||||
* @param y Y coord
|
|
||||||
* @param z Z coord
|
|
||||||
* @return The server Dist GUI object (An instance of {@link Container})
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Container getRemoteGuiContainer(ModContainer mc, EntityPlayerMP player, int modGuiId, World world, int x, int y, int z)
|
|
||||||
{
|
|
||||||
IGuiHandler handler = serverGuiHandlers.get(mc);
|
|
||||||
|
|
||||||
if (handler != null)
|
|
||||||
{
|
|
||||||
return (Container)handler.getServerGuiElement(modGuiId, player, world, x, y, z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* INTERNAL method for accessing the Gui registry
|
|
||||||
* @param mc Mod Container
|
|
||||||
* @param player Player
|
|
||||||
* @param modGuiId guiId
|
|
||||||
* @param world World
|
|
||||||
* @param x X coord
|
|
||||||
* @param y Y coord
|
|
||||||
* @param z Z coord
|
|
||||||
* @return The client Dist GUI object (An instance of {@link net.minecraft.client.gui.Gui})
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public Object getLocalGuiContainer(ModContainer mc, EntityPlayer player, int modGuiId, World world, int x, int y, int z)
|
|
||||||
{
|
|
||||||
IGuiHandler handler = clientGuiHandlers.get(mc);
|
|
||||||
return handler.getClientGuiElement(modGuiId, player, world, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is there a channel with this name on this Dist?
|
|
||||||
* @param channelName The name
|
|
||||||
* @param source the Dist
|
|
||||||
* @return if there's a channel
|
|
||||||
*/
|
|
||||||
public boolean hasChannel(String channelName, Dist source)
|
|
||||||
{
|
|
||||||
return channels.get(source).containsKey(channelName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* INTERNAL method for registering a mod as a network capable thing
|
|
||||||
* @param fmlModContainer The fml mod container
|
|
||||||
* @param clazz a class
|
|
||||||
* @param remoteVersionRange the acceptable remote range
|
|
||||||
* @param asmHarvestedData internal data
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public void register(ModContainer fmlModContainer, Class<?> clazz, @Nullable String remoteVersionRange, ASMDataTable asmHarvestedData)
|
|
||||||
{
|
|
||||||
NetworkModHolder networkModHolder = new NetworkModHolder(fmlModContainer, clazz, remoteVersionRange, asmHarvestedData);
|
|
||||||
registry.put(fmlModContainer, networkModHolder);
|
|
||||||
networkModHolder.testVanillaAcceptance();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
public boolean isVanillaAccepted(Dist from)
|
|
||||||
{
|
|
||||||
return registry.values().stream()
|
|
||||||
.allMatch(mod -> mod.acceptsVanilla(from));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<String> getRequiredMods(Dist from)
|
|
||||||
{
|
|
||||||
return registry.values().stream()
|
|
||||||
.filter(mod -> !mod.acceptsVanilla(from))
|
|
||||||
.map(mod -> mod.getContainer().getModId())
|
|
||||||
.sorted()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Map<ModContainer,NetworkModHolder> registry()
|
|
||||||
{
|
|
||||||
return ImmutableMap.copyOf(registry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All the valid channel names for a Dist
|
|
||||||
* @param Dist the Dist
|
|
||||||
* @return the set of channel names
|
|
||||||
*/
|
|
||||||
public Set<String> channelNamesFor(Dist Dist)
|
|
||||||
{
|
|
||||||
return channels.get(Dist).keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* INTERNAL fire a handshake to all channels
|
|
||||||
* @param networkDispatcher The dispatcher firing
|
|
||||||
* @param origin which Dist the dispatcher is on
|
|
||||||
*/
|
|
||||||
public void fireNetworkHandshake(NetworkDispatcher networkDispatcher, Dist origin)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
NetworkHandshakeEstablished handshake = new NetworkHandshakeEstablished(networkDispatcher, networkDispatcher.getNetHandler(), origin);
|
|
||||||
for (FMLEmbeddedChannel channel : channels.get(origin).values())
|
|
||||||
{
|
|
||||||
channel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(OutboundTarget.DISPATCHER);
|
|
||||||
channel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(networkDispatcher);
|
|
||||||
channel.pipeline().fireUserEventTriggered(handshake);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanAttributes()
|
|
||||||
{
|
|
||||||
channels.values().forEach(map -> map.values().forEach(FMLEmbeddedChannel::cleanAttributes));
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue