Zeroth pass on 1.13

This commit is contained in:
cpw 2018-08-27 13:10:07 -04:00 committed by LexManos
parent 6e99f84e91
commit 77c3310711
176 changed files with 603 additions and 16145 deletions

View File

@ -1,477 +1,116 @@
buildscript {
repositories {
mavenLocal()
maven { url = 'http://files.minecraftforge.net/maven' }
jcenter()
mavenCentral()
maven {
name = "forge"
url = "http://files.minecraftforge.net/maven"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.+'
}
}
plugins {
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
}
}
}
apply plugin: 'eclipse'
group = 'net.minecraftforge'
version = getVersionFromJava(file("src/main/java/net/minecraftforge/common/ForgeVersion.java"))
version = '1.0.0'
extractForgeSources { exclude "**/SideOnly.java", "**/Side.java" }
extractForgeResources { exclude "**/log4j2.xml" }
genGradleProjects {
addTestCompileDep "junit:junit:4.12" // TODO update unit tests to junit 5 and remove this
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") }
project(':mcp') {
apply plugin: 'net.minecraftforge.gradle.forgedev.mcp'
mcp {
config = 'de.oceanlabs.mcp:mcp_config:1.13@zip'
pipeline = 'joined'
}
}
processJson {
releaseJson = "jsons/${minecraft.version}-rel.json"
addReplacements([
"@minecraft_version@": project.minecraft.version,
"@version@": project.version,
"@project@": "forge",
"@artifact@": "net.minecraftforge:forge:${project.version}",
"@universal_jar@": { outputJar.archiveName },
"@timestamp@": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
])
project(':clean') {
evaluationDependsOn(':mcp')
apply plugin: 'eclipse'
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
repositories {
mavenCentral()
}
patcher {
parent = project(':mcp')
patchedSrc = file('src/main/java')
mappings channel: 'snapshot', version: '20180813-1.12'
mcVersion = '1.13'
}
}
license {
header = project.file('LICENSE-header.txt')
include 'net/minecraftforge/'
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 {
project(':forge') {
evaluationDependsOn(':clean')
apply plugin: 'eclipse'
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
sourceSets {
main {
files = project.files('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.
java {
srcDir "$rootDir/src/main/java"
}
}
else
{
// 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' }
}
}
resources {
srcDir "$rootDir/src/main/resources"
}
}
}
}
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)
{
def node = new JsonSlurper().parse(file);
def out = new StringBuilder()
node.versionInfo.libraries.each { lib ->
if (lib.serverreq)
{
// 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 "
compileJava {
options.fork = true
options.failOnError = false
options.forkOptions.with {
executable = 'java'
jvmArgs = ['-classpath', project.configurations.ecj.asPath, 'org.eclipse.jdt.internal.compiler.batch.Main', '-nowarn']
}
}
out += "minecraft_server.${minecraft.version}.jar"
return out.toString();
}
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];
}
task runclient(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main 'net.minecraftforge.fml.LaunchTesting'
systemProperties target:'fmldevclient'
}
build = System.getenv("BUILD_NUMBER") ?: project.ext.properties.buildNumber ?: 0
String branch = null;
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()
task runserver(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main 'net.minecraftforge.fml.LaunchTesting'
systemProperties target:'fmldevserver'
}
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 {
extraSrg = [
'MD: net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry/getKeys ()Ljava/util/Set; net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry/getKeys ()Ljava/util/Set;'
]
//evaluationDependsOnChildren()
task setup() {
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.

View File

@ -1,6 +1,5 @@
#Sat Mar 10 11:15:39 EST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
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

26
gradlew vendored
View File

@ -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.
MAX_FD="maximum"
warn ( ) {
warn () {
echo "$*"
}
die ( ) {
die () {
echo
echo "$*"
echo
@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
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" "$@"

6
gradlew.bat vendored
View File

@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

View File

@ -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")

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -46,7 +46,7 @@ import static net.minecraft.util.text.TextFormatting.*;
* client, the client takes precedence!
*
*/
public class ClientCommandHandler extends CommandHandler
public class ClientCommandHandler {} /*extends CommandHandler
{
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,
* 0 if it doesn't exist or it was canceled (it's sent to the server)
*/
* /
@Override
public int executeCommand(ICommandSender sender, String message)
{
@ -165,3 +165,4 @@ public class ClientCommandHandler extends CommandHandler
return Minecraft.getMinecraft().getIntegratedServer();
}
}
*/

View File

@ -26,11 +26,9 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.InventoryEffectRenderer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.input.Mouse;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraftforge.eventbus.api.Cancelable;
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 allows drawing next to Guis, above the background but below any tooltips.
*/
/*
public static class BackgroundDrawnEvent extends GuiScreenEvent
{
private final int mouseX;
@ -193,22 +192,27 @@ public class GuiScreenEvent extends Event
this.mouseY = scaledHeight - Mouse.getY() * scaledHeight / gui.mc.displayHeight - 1;
}
/**
*/
/**
* The x coordinate of the mouse pointer on the screen.
*/
*//*
public int getMouseX()
{
return mouseX;
}
/**
*/
/**
* The y coordinate of the mouse pointer on the screen.
*/
*//*
public int getMouseY()
{
return mouseY;
}
}
*/
/**
* This event fires in {@link InventoryEffectRenderer#updateActivePotionEffects()}

View File

@ -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; }
}

View File

@ -24,9 +24,8 @@ import java.util.ArrayList;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraft.client.gui.BossInfoClient;
import net.minecraft.client.gui.ScaledResolution;
@net.minecraftforge.eventbus.api.Cancelable
@Cancelable
public class RenderGameOverlayEvent extends Event
{
public float getPartialTicks()
@ -34,11 +33,6 @@ public class RenderGameOverlayEvent extends Event
return partialTicks;
}
public ScaledResolution getResolution()
{
return resolution;
}
public ElementType getType()
{
return type;
@ -71,20 +65,17 @@ public class RenderGameOverlayEvent extends Event
}
private final float partialTicks;
private final ScaledResolution resolution;
private final ElementType type;
public RenderGameOverlayEvent(float partialTicks, ScaledResolution resolution)
public RenderGameOverlayEvent(float partialTicks, Void resolution)
{
this.partialTicks = partialTicks;
this.resolution = resolution;
this.type = null;
}
private RenderGameOverlayEvent(RenderGameOverlayEvent parent, ElementType type)
{
this.partialTicks = parent.getPartialTicks();
this.resolution = parent.getResolution();
this.type = type;
}

View File

@ -38,7 +38,7 @@ public class PlaySoundEvent extends SoundEvent
{
super(manager);
this.sound = sound;
this.name = sound.getSoundLocation().getResourcePath();
this.name = sound.getSoundLocation().getPath();
this.setResultSound(sound);
}

View File

@ -45,7 +45,7 @@ public class SoundEvent extends net.minecraftforge.eventbus.api.Event
public SoundSourceEvent(SoundManager manager, ISound sound, String uuid)
{
super(manager);
this.name = sound.getSoundLocation().getResourcePath();
this.name = sound.getSoundLocation().getPath();
this.sound = sound;
this.uuid = uuid;
}

View File

@ -223,12 +223,14 @@ public class ForgeGuiFactory implements IModGuiFactory
Property global = ForgeMod.getConfig().get(VERSION_CHECK_CAT, "Global", true);
List<Property> props = new ArrayList<Property>();
// TODO
/*
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
{
values.remove(mod.getModId());
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.sort(Comparator.comparing(Property::getName));
@ -378,12 +380,15 @@ public class ForgeGuiFactory implements IModGuiFactory
private static Map<Object, String> getSelectableValues()
{
Map<Object, String> selectableValues = new TreeMap<Object, String>();
// TODO
/*
for (ModContainer mod : Loader.instance().getActiveModList())
// only add mods to the list that have a non-immutable ModContainer
if (!mod.isImmutable() && mod.getMod() != null)
selectableValues.put(mod.getModId(), mod.getName());
*/
return selectableValues;
}

View File

@ -28,7 +28,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.ForgeVersion.Status;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.client.ClientModLoader;
import net.minecraftforge.api.distmarker.Dist;
@ -85,7 +84,7 @@ public class NotificationModUpdateScreen extends GuiScreen
public static NotificationModUpdateScreen init(GuiMainMenu guiMainMenu, GuiButton modButton)
{
NotificationModUpdateScreen notificationModUpdateScreen = new NotificationModUpdateScreen(modButton);
notificationModUpdateScreen.setGuiSize(guiMainMenu.width, guiMainMenu.height);
notificationModUpdateScreen.setWorldAndResolution(guiMainMenu.mc, guiMainMenu.width, guiMainMenu.height);
notificationModUpdateScreen.initGui();
return notificationModUpdateScreen;
}

View File

@ -108,15 +108,17 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
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.Nullable;
import static net.minecraftforge.fml.Logging.MODELLOADING;
import static net.minecraftforge.fml.Logging.fmlLog;
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, ModelBlockDefinition> multipartDefinitions = 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
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 IBakedModel model = modelRegistry.getObject(location);
if(model == null)
@ -953,7 +955,7 @@ public final class ModelLoader extends ModelBakery
IBakedModel model = modelRegistry.getObject(missing);
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)
{

View File

@ -66,7 +66,7 @@ import javax.annotation.Nullable;
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 class Dimension
{

View File

@ -49,7 +49,7 @@ import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
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.FMLLog;
import net.minecraftforge.fml.common.Loader;

View File

@ -170,7 +170,7 @@ import org.apache.logging.log4j.MarkerManager;
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");
//TODO: Loot tables?
static class SeedEntry extends WeightedRandom.Item

View File

@ -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_GENERAL;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
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.WorldPersistenceHooks;
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
import net.minecraftforge.fml.javafmlmod.FMLModLoadingContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.StatList;
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.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
@ -76,7 +73,7 @@ import org.apache.logging.log4j.MarkerManager;
public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
{
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");
public static int clumpingThreshold = 64;
public static boolean removeErroringEntities = false;
@ -113,9 +110,9 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
public ForgeMod()
{
INSTANCE = this;
ModLoadingContext.get().getModEventBus().addListener(this::preInit);
ModLoadingContext.get().getModEventBus().addListener(this::postInit);
ModLoadingContext.get().getModEventBus().addListener(this::onAvailable);
FMLModLoadingContext.get().getModEventBus().addListener(this::preInit);
FMLModLoadingContext.get().getModEventBus().addListener(this::postInit);
FMLModLoadingContext.get().getModEventBus().addListener(this::onAvailable);
MinecraftForge.EVENT_BUS.addListener(this::serverStarting);
MinecraftForge.EVENT_BUS.addListener(this::playerLogin);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
@ -336,10 +333,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
if (event.isWorldRunning() && tmpStairs != disableStairSlabCulling)
{
SidedExecutor.runOn(Dist.CLIENT,()->{
Minecraft.getMinecraft().renderGlobal.loadRenderers();
return null;
});
DistExecutor.runWhenOn(Dist.CLIENT,()->()-> Minecraft.getMinecraft().renderGlobal.loadRenderers());
}
}
@ -438,7 +432,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
}
@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);
FluidRegistry.loadFluidDefaults(tag);
@ -449,10 +443,9 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
OreDictionary.rebakeMap();
StatList.reinit();
Ingredient.invalidateAll();
SidedExecutor.runOn(Dist.CLIENT, ()-> {
DistExecutor.runWhenOn(Dist.CLIENT, ()-> () -> {
Minecraft.getMinecraft().populateSearchTreeManager();
Minecraft.getMinecraft().getSearchTreeManager().onResourceManagerReload(Minecraft.getMinecraft().getResourceManager());
return null;
});
}

View File

@ -58,7 +58,7 @@ public class MinecraftForge
public static final IEventBus ORE_GEN_BUS = IEventBus.create();
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");
/**

View File

@ -22,7 +22,7 @@ package net.minecraftforge.common.brewing;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionHelper;
import net.minecraft.potion.PotionBrewing;
import javax.annotation.Nonnull;
@ -49,7 +49,7 @@ public class VanillaBrewingRecipe implements IBrewingRecipe {
@Override
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))
{
ItemStack result = PotionHelper.doReaction(ingredient, input);
ItemStack result = PotionBrewing.doReaction(ingredient, input);
if (result != input)
{
return result;

View File

@ -23,7 +23,7 @@ import java.util.concurrent.Callable;
import com.google.common.base.Throwables;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.INBTBase;
import net.minecraft.util.EnumFacing;
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.
*/
@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.
@ -79,7 +79,7 @@ public class Capability<T>
* @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...
*/
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.
* 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);
}
@ -107,7 +107,7 @@ public class Capability<T>
* See {@link IStorage#writeNBT(Capability, Object, EnumFacing)} for documentation.
*/
@Nullable
public NBTBase writeNBT(T instance, EnumFacing side)
public INBTBase writeNBT(T instance, EnumFacing side)
{
return storage.writeNBT(this, instance, side);
}

View File

@ -26,7 +26,7 @@ import java.util.Map;
import com.google.common.collect.Lists;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
@ -45,7 +45,7 @@ import net.minecraftforge.common.util.INBTSerializable;
public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompound>, ICapabilityProvider
{
private ICapabilityProvider[] caps;
private INBTSerializable<NBTBase>[] writers;
private INBTSerializable<INBTBase>[] writers;
private String[] names;
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)
{
List<ICapabilityProvider> lstCaps = Lists.newArrayList();
List<INBTSerializable<NBTBase>> lstWriters = Lists.newArrayList();
List<INBTSerializable<INBTBase>> lstWriters = Lists.newArrayList();
List<String> lstNames = Lists.newArrayList();
if (parent != null) // Parents go first!
@ -65,7 +65,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
lstCaps.add(parent);
if (parent instanceof INBTSerializable)
{
lstWriters.add((INBTSerializable<NBTBase>)parent);
lstWriters.add((INBTSerializable<INBTBase>)parent);
lstNames.add("Parent");
}
}
@ -76,7 +76,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
lstCaps.add(prov);
if (prov instanceof INBTSerializable)
{
lstWriters.add((INBTSerializable<NBTBase>)prov);
lstWriters.add((INBTSerializable<INBTBase>)prov);
lstNames.add(entry.getKey().toString());
}
}

View File

@ -45,7 +45,7 @@ import static net.minecraftforge.fml.Logging.CAPABILITIES;
public enum CapabilityManager
{
INSTANCE;
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Logger LOGGER = LogManager.getLogger();
/**
* Registers a capability to be consumed by others.

View File

@ -19,8 +19,8 @@
package net.minecraftforge.common.capabilities;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.INBTBase;
import net.minecraftforge.common.util.INBTSerializable;
//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>{}

View File

@ -37,7 +37,7 @@ import javax.annotation.Nonnull;
import net.minecraft.client.util.RecipeBookClient;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.SidedExecutor;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import org.apache.commons.io.FilenameUtils;
@ -81,7 +81,7 @@ import org.apache.logging.log4j.MarkerManager;
public class CraftingHelper {
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 Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private static Map<ResourceLocation, IConditionFactory> conditions = new HashMap<>();
@ -619,10 +619,7 @@ public class CraftingHelper {
GameData.fireRegistryEvents(rl -> rl.equals(GameData.RECIPES));
//reg.freeze();
SidedExecutor.runOn(Dist.CLIENT, ()-> {
RecipeBookClient.rebuildTable();
return null;
});
DistExecutor.runWhenOn(Dist.CLIENT, ()-> RecipeBookClient::rebuildTable);
}
private static void loadFactories(final ModFile modFile)

View File

@ -19,13 +19,13 @@
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
* 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();
void deserializeNBT(T nbt);

View File

@ -58,7 +58,7 @@ import javax.annotation.Nullable;
*/
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");
static int maxID = 0;

View File

@ -43,7 +43,7 @@ import static net.minecraftforge.fml.Logging.LOADING;
*/
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)
{
if (scanData == null) return;

View File

@ -25,9 +25,9 @@ import net.minecraftforge.fml.loading.FMLEnvironment;
import java.util.concurrent.Callable;
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}
@ -37,7 +37,7 @@ public final class SidedExecutor
* @param <T> The return type from the callable
* @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) {
try
{
@ -51,7 +51,12 @@ public final class SidedExecutor
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)
{
case CLIENT:

View File

@ -21,7 +21,7 @@ package net.minecraftforge.fml;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.resources.IResourcePack;
import net.minecraftforge.fml.client.ModFileResourcePack;
import java.util.function.BiFunction;

View File

@ -25,7 +25,7 @@ import java.util.Map.Entry;
import java.util.Optional;
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.NBTTagList;
import net.minecraft.util.ResourceLocation;
@ -47,7 +47,7 @@ import org.apache.logging.log4j.MarkerManager;
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");
@Override
@ -66,7 +66,7 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
final NBTTagCompound mod = new NBTTagCompound();
mod.setString("ModId", mi.getModId());
mod.setString("ModVersion", mi.getVersion().getVersionString());
modList.appendTag(mod);
modList.add(mod);
});
fmlData.setTag("LoadingModList", modList);
@ -82,12 +82,12 @@ public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.Worl
}
@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"))
{
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);
String modId = mod.getString("ModId");

View File

@ -19,33 +19,37 @@
package net.minecraftforge.fml;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import static net.minecraftforge.fml.Logging.CORE;
import static net.minecraftforge.fml.Logging.fmlLog;
public class FileUtils
{
private static final Logger LOGGER = LogManager.getLogger();
public static Path getOrCreateDirectory(Path dirPath, String dirLabel) {
if (!Files.isDirectory(dirPath))
{
fmlLog.debug(CORE,"Making {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE,"Making {} directory : {}", dirLabel, dirPath);
try {
Files.createDirectory(dirPath);
} catch (IOException e) {
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 {
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);
}
fmlLog.debug(CORE,"Created {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE,"Created {} directory : {}", dirLabel, dirPath);
} else {
fmlLog.debug(CORE,"Found existing {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE,"Found existing {} directory : {}", dirLabel, dirPath);
}
return dirPath;
}

View File

@ -21,29 +21,15 @@ package net.minecraftforge.fml;
import com.google.common.base.Strings;
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.MarkerManager;
import org.apache.logging.log4j.core.Filter;
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.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 java.io.File;
import java.lang.reflect.Field;
import static cpw.mods.modlauncher.Logging.CLASSLOADING;
import static net.minecraftforge.fml.Logging.fmlLog;
public class LaunchTesting
{
public static void main(String... args) throws InterruptedException

View File

@ -28,8 +28,6 @@ import org.apache.logging.log4j.core.config.Configurator;
public class Logging
{
public static final Logger fmlLog = LogManager.getLogger("FML");
// Lots of markers
public static final Marker CORE = MarkerManager.getMarker("CORE");
public static final Marker LOADING = MarkerManager.getMarker("LOADING");

View File

@ -34,7 +34,7 @@ import java.util.function.Supplier;
* The container that wraps around mods in the system.
* <p>
* 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
* facilities can treat mods at arms length.
* </p>

View File

@ -20,11 +20,9 @@
package net.minecraftforge.fml;
import com.google.common.collect.Streams;
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.DefaultModInfos;
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.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
@ -51,7 +49,7 @@ import static net.minecraftforge.fml.Logging.LOADING;
*/
public class ModList
{
private static Logger LOGGER = LogManager.getLogger("FML");
private static Logger LOGGER = LogManager.getLogger();
private static ModList INSTANCE;
private final List<ModFileInfo> modFiles;
private final List<ModInfo> sortedList;

View File

@ -47,7 +47,7 @@ import static net.minecraftforge.fml.Logging.CORE;
public class ModLoader
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Logger LOGGER = LogManager.getLogger();
private static ModLoader INSTANCE;
private final ClassLoader launchClassLoader;
private final LoadingModList loadingModList;
@ -97,7 +97,7 @@ public class ModLoader
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
LifecycleEventProvider.PREINIT.dispatch();
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();
}

View File

@ -21,6 +21,7 @@ package net.minecraftforge.fml;
import net.minecraftforge.fml.loading.FMLLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.URL;
@ -32,6 +33,9 @@ import static net.minecraftforge.fml.Logging.LOADING;
public class ModLoadingClassLoader extends SecureClassLoader
{
private static final Logger LOGGER = LogManager.getLogger();
static {
ClassLoader.registerAsParallelCapable();
}
@ -49,7 +53,7 @@ public class ModLoadingClassLoader extends SecureClassLoader
@Override
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 Path classResource = FMLLoader.getLoadingModList().findResource(className);
if (classResource != null) {

View File

@ -23,7 +23,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraftforge.api.distmarker.Dist;
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.FMLServerInitEvent;
import net.minecraftforge.fml.loading.FMLEnvironment;
@ -34,12 +34,12 @@ import java.util.function.Supplier;
public enum SidedProvider
{
// 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),
(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),
@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));
private static Supplier<Minecraft> client;

View File

@ -33,6 +33,7 @@ import net.minecraftforge.fml.client.gui.GuiConfirmation;
import net.minecraftforge.fml.client.gui.GuiNotification;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
@ -42,7 +43,7 @@ import javax.annotation.Nullable;
public class StartupQuery {
// 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");
public static boolean confirm(String text)
@ -236,8 +237,6 @@ public class StartupQuery {
throw new RuntimeException();
}
client.loadingScreen.displayLoadingString("");
try
{
Thread.sleep(50);
@ -247,8 +246,6 @@ public class StartupQuery {
query.exception = ie;
}
}
client.loadingScreen.displayLoadingString(""); // make sure the blank screen is being drawn at the end
}
};
}

View File

@ -19,16 +19,13 @@
package net.minecraftforge.fml;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WorldPersistenceHooks
{
@ -47,9 +44,7 @@ public class WorldPersistenceHooks
{
if (EffectiveSide.get() == LogicalSide.SERVER)
{
Map<String, NBTBase> additionalProperties = new HashMap<>();
worldInfo.setAdditionalProperties(additionalProperties);
worldPersistenceHooks.forEach(wac->wac.readData(handler, worldInfo, additionalProperties, tagCompound.getCompoundTag(wac.getModId())));
worldPersistenceHooks.forEach(wac->wac.readData(handler, worldInfo, tagCompound.getCompoundTag(wac.getModId())));
}
}
@ -76,6 +71,6 @@ public class WorldPersistenceHooks
{
String getModId();
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);
}
}

View File

@ -19,6 +19,7 @@
package net.minecraftforge.fml.client;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonArray;
@ -26,10 +27,10 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiConnecting;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiWorldSelection;
import net.minecraft.client.gui.ServerListEntryNormal;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.network.NetworkManager;
@ -39,7 +40,6 @@ import net.minecraft.world.storage.WorldSummary;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.client.gui.GuiAccessDenied;
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
import net.minecraftforge.registries.GameData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -55,8 +55,11 @@ import java.util.concurrent.CountDownLatch;
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");
// 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<ServerData, ExtendedServerListData> serverDataTag;
@ -77,6 +80,7 @@ public class ClientHooks
}
public static void bindServerListData(ServerData data, ServerStatusResponse originalResponse)
{
/*
if (extraServerListData.containsKey(originalResponse))
{
JsonObject jsonData = extraServerListData.get(originalResponse);
@ -104,6 +108,7 @@ public class ClientHooks
}
serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, ImmutableMap.of(), !moddedClientAllowed));
}
*/
startupConnectionData.countDown();
}
@ -167,7 +172,7 @@ public class ClientHooks
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)
@ -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));
}
}

View File

@ -20,11 +20,10 @@
package net.minecraftforge.fml.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.resources.IResourcePack;
import net.minecraft.resources.data.IMetadataSectionSerializer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.LogicalSidedProvider;
@ -33,7 +32,6 @@ import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.client.gui.GuiNotification;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import org.lwjgl.input.Mouse;
import java.io.IOException;
import java.util.List;
@ -44,13 +42,12 @@ public class ClientModLoader
private static boolean loading;
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;
ClientModLoader.mc = minecraft;
SidedProvider.setClient(()->minecraft);
LogicalSidedProvider.setClient(()->minecraft);
SplashProgress.start();
ModLoader.get().loadMods();
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
minecraft.refreshResources();
@ -61,7 +58,6 @@ public class ClientModLoader
ModLoader.get().finishMods();
loading = false;
mc.gameSettings.loadOptions();
SplashProgress.finish();
}
public static VersionChecker.Status checkForUpdates()
@ -75,27 +71,6 @@ public class ClientModLoader
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()
{
return false;

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -19,15 +19,19 @@
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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class ModFileResourcePack extends AbstractResourcePack
@ -45,32 +49,57 @@ public class ModFileResourcePack extends AbstractResourcePack
}
@Override
public String getPackName()
public String func_195762_a()
{
return modFile.getFileName();
}
@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));
}
@Override
protected boolean hasResourceName(String name)
protected boolean func_195768_c(String name)
{
return Files.exists(modFile.getLocator().findPath(modFile, name));
}
@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 {
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)
{
return Collections.emptySet();
}
}
@Override
public void close() throws IOException
{
}
}

View File

@ -19,10 +19,10 @@
package net.minecraftforge.fml.client;
import net.minecraft.client.resources.AbstractResourcePack;
import net.minecraft.client.resources.FileResourcePack;
import net.minecraft.client.resources.FolderResourcePack;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.resources.AbstractResourcePack;
import net.minecraft.resources.FilePack;
import net.minecraft.resources.FolderPack;
import net.minecraft.resources.IResourcePack;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
@ -48,8 +48,8 @@ public class ResourcePackLoader
map(mf -> new ModFileResourcePack(mf.getFile())).
collect(Collectors.toMap(ModFileResourcePack::getModFile, Function.identity()));
forgePack = Files.isDirectory(FMLLoader.getForgePath()) ?
new FolderResourcePack(FMLLoader.getForgePath().toFile()) :
new FileResourcePack(FMLLoader.getForgePath().toFile());
new FolderPack(FMLLoader.getForgePath().toFile()) :
new FilePack(FMLLoader.getForgePath().toFile());
resourcePacks.add(forgePack);
resourcePacks.addAll(modResourcePacks.values());
}

View File

@ -18,7 +18,7 @@
*/
package net.minecraftforge.fml.client;
/*
import static net.minecraftforge.fml.Logging.SPLASH;
import static net.minecraftforge.fml.Logging.fmlLog;
import static org.lwjgl.opengl.GL11.*;
@ -86,6 +86,7 @@ import org.lwjgl.util.glu.GLU;
@SuppressWarnings("serial")
public class SplashProgress
{
/*
private static Drawable d;
private static volatile boolean pause = false;
private static volatile boolean done = false;
@ -613,7 +614,7 @@ public class SplashProgress
* Resource loading doesn't usually require this call.
* Call {@link #resume()} when you're done.
* @deprecated not a stable API, will break, don't use this yet
*/
* /
@Deprecated
public static void pause()
{
@ -635,7 +636,7 @@ public class SplashProgress
/**
* @deprecated not a stable API, will break, don't use this yet
*/
* /
@Deprecated
public static void resume()
{
@ -980,4 +981,5 @@ public class SplashProgress
{
return (int) (bytes / 1024L / 1024L);
}
*/
}

View File

@ -20,27 +20,13 @@
package net.minecraftforge.fml.client;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
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.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;
public class TextureTracker
@ -51,24 +37,25 @@ public class TextureTracker
public static void trackMissingTexture(ResourceLocation resourceLocation)
{
badTextureDomains.add(resourceLocation.getResourceDomain());
missingTextures.put(resourceLocation.getResourceDomain(),resourceLocation);
badTextureDomains.add(resourceLocation.getNamespace());
missingTextures.put(resourceLocation.getNamespace(),resourceLocation);
}
public static void trackBrokenTexture(ResourceLocation resourceLocation, String error)
{
badTextureDomains.add(resourceLocation.getResourceDomain());
Set<ResourceLocation> badType = brokenTextures.get(resourceLocation.getResourceDomain(), error);
badTextureDomains.add(resourceLocation.getNamespace());
Set<ResourceLocation> badType = brokenTextures.get(resourceLocation.getNamespace(), error);
if (badType == null)
{
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);
}
public static void logMissingTextureErrors()
{
/*
if (missingTextures.isEmpty() && brokenTextures.isEmpty())
{
return;
@ -141,6 +128,7 @@ public class TextureTracker
logger.error(Strings.repeat("=", 50));
}
logger.error(Strings.repeat("+=", 25));
*/
}

View File

@ -34,8 +34,6 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.text.TextComponentString;
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.event.ConfigChangedEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
@ -85,51 +83,6 @@ public class GuiConfig extends GuiScreen
protected HoverChecker resetHoverChecker;
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,
* 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.configElements = configElements;
this.entryList = new GuiConfigEntries(this, mc);
this.initEntries = new ArrayList<IConfigEntry>(entryList.listEntries);
this.initEntries = new ArrayList<>(entryList.listEntries);
this.allRequireWorldRestart = allRequireWorldRestart;
IF:if (!allRequireWorldRestart)
{

View File

@ -27,7 +27,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import net.minecraft.client.Minecraft;
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.resources.I18n;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.ModList;
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;
/**
@ -150,10 +150,7 @@ public class GuiConfigEntries extends GuiListExtended
}
else if (configElement.getType() == ConfigGuiType.MOD_ID)
{
Map<Object, String> values = new TreeMap<Object, String>();
for (ModContainer mod : Loader.instance().getActiveModList())
values.put(mod.getModId(), mod.getName());
values.put("minecraft", "Minecraft");
Map<Object, String> values = ModList.get().getMods().stream().collect(Collectors.toMap(ModInfo::getModId, ModInfo::getDisplayName));
this.listEntries.add(new SelectValueEntry(this.owningScreen, this, configElement, values));
}
else if (configElement.getType() == ConfigGuiType.STRING)

View File

@ -20,13 +20,13 @@
package net.minecraftforge.fml.client.registry;
import com.google.common.collect.Maps;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import org.apache.commons.lang3.ArrayUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.fml.common.registry.GameRegistry;
@ -45,13 +45,13 @@ public class ClientRegistry
* @param id
* @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);
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);
specialRenderer.setRendererDispatcher(TileEntityRendererDispatcher.instance);

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -21,22 +21,23 @@ package net.minecraftforge.fml.common;
import cpw.mods.modlauncher.api.IEnvironment;
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.Paths;
import java.util.Arrays;
import java.util.Objects;
import static net.minecraftforge.fml.Logging.CORE;
import static net.minecraftforge.fml.Logging.fmlLog;
public enum FMLPaths
{
GAMEDIR(),
MODSDIR("mods"),
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 boolean isDirectory;
private Path absolutePath;
@ -71,7 +72,7 @@ public enum FMLPaths
for (FMLPaths path : FMLPaths.values())
{
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)
{
FileUtils.getOrCreateDirectory(path.absolutePath, path.name());

View File

@ -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);
}

View File

@ -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(){}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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());
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -26,14 +26,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
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.client.SplashProgress;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MessageFormatMessage;
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.
@ -41,7 +39,9 @@ import static net.minecraftforge.fml.Logging.fmlLog;
*/
public class ProgressManager
{
private static final Logger LOGGER = LogManager.getLogger();
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<ProgressBar>();
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
@ -62,13 +62,10 @@ public class ProgressManager
{
bar.timeEachStep();
}
SidedExecutor.runOn(Dist.CLIENT, ()->SplashProgress::processMessages);
// DistExecutor.runWhenOn(Dist.CLIENT, ()->SplashProgress::processMessages);
return bar;
}
public static boolean isDisplayVSyncForced() {
return FMLCommonHandler.instance().isDisplayVSyncForced();
}
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
@ -81,13 +78,13 @@ public class ProgressManager
{
long newTime = System.nanoTime();
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)
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
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)
{
step(ClassNameUtils.shortName(classToName)+ Arrays.stream(extra).collect(Collectors.joining(" ")));
step(ClassNameUtils.shortName(classToName)+ String.join(" ", extra));
}
public void step(String message)
@ -130,7 +127,7 @@ public class ProgressManager
if (timeEachStep && step != 0)
{
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;
}
step += 1;

View File

@ -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
{
}

View File

@ -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() + "]: ";
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}
}

View File

@ -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('/','.');
}
}

View File

@ -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"));
}
}

View File

@ -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();
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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 {
}

View File

@ -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();
}
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -19,8 +19,6 @@
package net.minecraftforge.fml.common.event;
import net.minecraft.command.CommandHandler;
import net.minecraft.command.ICommand;
import net.minecraft.server.MinecraftServer;
/**
@ -36,10 +34,4 @@ public class FMLServerStartingEvent extends ServerLifecycleEvent
{
super(server);
}
public void registerServerCommand(ICommand command)
{
CommandHandler ch = (CommandHandler) getServer().getCommandManager();
ch.registerCommand(command);
}
}

View File

@ -50,289 +50,6 @@ import com.google.common.collect.ImmutableList;
*
*/
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)
{

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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
{
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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