Compare commits

...
61 Commits
Author SHA1 Message Date
LexManos f173bde812 1.16.5 Initial Update. 2021-01-15 11:33:11 -08:00
LexManos dd10933ab0 Update Coremods, ASM, and include standalone Nashorn to load on J15. 2021-01-14 15:48:53 -08:00
Ian Rehwinkel c3e84646db Added IWeatherParticleRenderHandler to allow a mod to take control over weather particles and sounds. (#7522) 2021-01-07 12:24:40 -08:00
covers1624 2094f99640 Allow Chunk loading Tickets to opt-into forcing chunk ticks. (#7525) 2021-01-07 12:13:47 -08:00
malte0811 94f3bdaa69 Fix crash when mods add goals to skeleton horses (MC-206338) (#7509) 2021-01-07 12:04:50 -08:00
Take Weiland 7220e9d0b0 Set WM_CLASS and WM_INSTANCE_NAME for early progress window (#7534) 2021-01-07 12:03:46 -08:00
Alex O'Neill 020102d87f Make UnboundedMapCodec more lenient in decoding dimensions. Fixes MC-197860 (#7527) 2021-01-05 19:17:24 -08:00
LexManos f101700969 Fix FML's Config Sync packet not allowing same length filenames in encoder and decoder. Closes #7584 2021-01-05 11:50:05 -08:00
LexManos c4b148b84b Prevent NPE and deprecated MissingMappings.getMappings function. Closes #6252 2021-01-05 11:47:00 -08:00
LexManos b6a9274870 Fix entities not correctly being able to be ridden under water. 2021-01-03 03:02:32 -08:00
Jonathan Coates 830d9699e3 Fix crash when beehive is broken by fake player (#7566) 2020-12-28 13:56:44 -08:00
Alex O'Neill fc68b81b21 Add supplier variant to AbstractBlock.Properties#lootFrom (#7563) 2020-12-28 13:42:15 -08:00
Take Weiland 2904772b16 Fix ModFileResourcePack.getAllResourceLocations ignoring resourceNamespace. (#7562)
Fixes #7405
2020-12-28 13:39:44 -08:00
Take Weiland e120b57032 Fix missing serializers when deserializing global loot modifiers (#7561) 2020-12-28 13:37:32 -08:00
Take Weiland b86b56260d Fix VanillaConnectionNetworkFilter sending out invalid entity properties packets without an entity ID (#7560) 2020-12-28 13:34:31 -08:00
Richard Freimer b222b23557 Make shear interactions extend to subclasses (#7544) 2020-12-28 13:10:35 -08:00
sciwhiz12 8ec4253068 Add a SoundType subclass that uses suppliers (#7538) 2020-12-28 13:09:03 -08:00
sciwhiz12 74ca88b7be Fix compound ingredient in shapeless recipes (#7537) Fixes #7530 2020-12-28 13:03:48 -08:00
Alex O'Neill a1119cd77a Fix potential NPE in ForgeHooks.onItemPlaceIntoWorld when passing in null player. (#7505) 2020-12-28 12:18:52 -08:00
mrp-v2 545723dc8c Fix modded PointOfInterestType's not populating blockstate map when registered (#7503) 2020-12-28 12:17:51 -08:00
poopoodice b64f4780c5 Add new LivingConversionEvent to control mobs turning into other mobs. (#7386) 2020-12-28 12:03:11 -08:00
KnightMiner 1c98b29087 Add ItemAttributeModifierEvent (#7484) 2020-12-28 11:59:09 -08:00
Brennan Ward 33880331d2 Fix RightClickBlock ALLOW not being implemented (#7426) 2020-12-28 11:54:30 -08:00
LexManos 74a43877e4 Quiet down errors related to modders not changing their update urls from the default. 2020-12-26 11:39:14 -08:00
LexManos 7542fbea48 Make mod data packs able to be disabled. It'll break things, but that's on you. Closes #6776 2020-12-26 11:38:45 -08:00
tterrag 2d9a1bc6f9 Add generated resource tracking to ExistingFileHelper 2020-12-12 12:33:56 -05:00
tterrag a57a240c13 Fix BlockStateProvider item models not knowing about block models
Add tests for this case
2020-12-10 21:37:13 -05:00
Richard Freimer b7fb6484d7 Override invalidateCaps instead of remove for vanilla TE capability invalidation (#7536)
Properly invalidate patched in vanilla TE caps in invalidateCaps instead of remove so that they get invalidated on chunk unload
2020-12-08 11:54:29 -08:00
Richard Freimer 1a539ffebc Make TEs invalidate capabilities when the chunk they are in unloads (#7529)
Fixed LazyOptional potentially notifying invalidation listeners multiple times.
2020-12-05 12:05:32 -08:00
Kevin G 27220a5ad8 Fixed entity navigation to stop entities spinning - MC-94054 (#7520) 2020-12-05 11:54:03 -08:00
Unbekannt1998 e975fc8252 Fix wrong function call in BlockStateProvider::horizontalFaceBlock (#7514) 2020-12-05 11:52:44 -08:00
tterrag d85ea5a3b0 Fix datagen order of multipart conditions being unstable 2020-11-28 21:10:49 -05:00
Alex O'Neill ccb7345084 Fix forge config option for default world type not applying unless you change the default world type (#7521) 2020-11-28 03:56:44 +01:00
David Quintana 93c00b67d9 Implement feature for mods to define new world types (#7448)
* Mods can now register world types via a new forge registry, and optionally register a settings screen to tweak them.
  * The default world type for dedicated servers and singleplayer world creation is configurable via forge's common config.
2020-11-28 00:57:15 +01:00
IzzelAliz cd393bbfdc Fix dimType not encode to registries (#7513) 2020-11-24 09:14:10 -08:00
Richard Freimer fd045d4628 Add support for referencing forge's resources and specifying existing mods to data generators (#7456) 2020-11-22 22:45:13 -05:00
cpw 47e076071b Fix #6692
Thanks @AterAnimAvis for help and suggestions

Signed-off-by: cpw <[email protected]>
2020-11-22 17:00:48 -05:00
Cyborgmas a73e003dd3 Fix translucent blocks not rendering properly when moved by pistons on fabulous (#7441) 2020-11-21 11:57:33 -08:00
LexManos 949984268d Bump version for RB. 2020-11-20 12:53:44 -08:00
Take Weiland 114acfca3b Fix food bar not rendering when non-living entities are mounted (#7446) 2020-11-20 10:24:43 -08:00
Alex O'Neill 56e538e8a9 Fix MC-194811 - Removing structures causes chunk save errors. 2020-11-20 10:23:50 -08:00
Take Weiland fa46f3dd49 Fix concurrency issue in StartupMessageManager (#7483) 2020-11-20 10:17:00 -08:00
Alex O'Neill 6ec5a8f2c1 Fix forge registry types that have private constructors (BlockStateProviderType, BlockPlacerType, FoliagePlacerType, TreeDecoratorType) (#7482) 2020-11-20 10:11:15 -08:00
cpw 49b596dda3 Fix problem where the absence of forge and MC in later loading triggered a weird crash.
Signed-off-by: cpw <[email protected]>
2020-11-15 11:08:34 -05:00
cpw 0c5ced1bbf Fix NPE problem when modid is mismatched.
Signed-off-by: cpw <[email protected]>
2020-11-13 20:41:20 -05:00
cpw 4a09a2420d Return the processed modlist data to the upstream system, not the raw unprocessed data. Should resolve the problem
that mixin complains about missing info when it's in a "crashed" situation.

Signed-off-by: cpw <[email protected]>
2020-11-13 19:12:43 -05:00
Cyborgmas 0ff8a596fc Fix dims on servers not loading the first run (#7445) 2020-11-11 01:09:35 -08:00
Take Weiland bca20ace4e Allow for custom argument types by filtering them on vanilla connections (#7463) 2020-11-10 12:24:25 -08:00
Brennan Ward f3b53001c9 Add Player context to AnvilUpdateEvent (#7442) 2020-11-10 12:05:47 -08:00
Jonathan Coates 15bac0eeaa Don't overwrite PlayerAdvancement's player with a fake one (#7454)
If a FakePlayer is constructed with the same UUID/GameProfile as a
currently active player, the player object within PlayerAdvancement is
set to the fake player.

As fake players cannot receive advancements (see grantCriterion), this
prevents the actual player from receiving any advancements until they
change dimension/relog.
2020-11-10 11:55:42 -08:00
Curle 1782973a29 Add BannerBlock.forColor to SAS to fix banner.toItem() on servers. 2020-11-10 11:38:20 -08:00
Boy132 9a4a501a95 Call Harvest check event even if the block doesn't require any tool (#7414) 2020-11-10 11:36:32 -08:00
LexManos 9bbfbd5479 Use linked collections to stabilize order when adding new registry entries. 2020-11-10 11:24:57 -08:00
Dennis C 8c68731838 Render local player when the renderViewEntity is not the local player (#7216) 2020-11-10 11:13:49 -08:00
cpw 0d7f507f4e Some help in ExtensionPoint regarding DISPLAYTEST. Let's improve those tick rates!
Signed-off-by: cpw <[email protected]>
2020-11-07 23:11:45 -05:00
cpw f78b943bdf Handle erroring during early mod construction phases, and actually report that into the error UI
by doing armslength exception handling and propagation.

Signed-off-by: cpw <[email protected]>
2020-11-07 22:30:19 -05:00
cpw 160f3f88f9 Support backwards loading 1.16.3 mods in 1.16.4, because we are able to do that. Tweak loading a bit to be smarter about dependency errors of various kinds.
Signed-off-by: cpw <[email protected]>
2020-11-07 20:48:02 -05:00
David Quintana 45e38859ed Add FluidStack codec, and a test mod that verifies its behaviour matches the existing write/read logic.
Add missing license headers.
2020-11-07 21:10:18 +01:00
cpw 38a5400a8c Update event bus version (should be 3.0.5)
Tweak MDK to automatically populate recommended values for things like forge version, loader version and minecraft version.

Signed-off-by: cpw <[email protected]>
2020-11-06 21:11:26 -05:00
diesieben07 acd18455c2 Workaround for modded attributes on vanilla entities logging warnings on vanilla clients
Switch to a handler-based approach per packet class, simplify patch, add some docs

Add license header and docs

Switch to a network handler based approach

Switch to a network handler based approach

revert build gradle change

Simplify Packet patch

Add license header to IForgePacket

Revert ForgeHooks changes

Less hacky and more generic way to filter packets for vanilla connections

_Actually_ Order SAS.
It's early

Order SAS

simplify vanilla connection check

Remove unneeded import change
2020-11-03 18:47:04 -05:00
cpw 5a7facc20f Fix early sorting bug that meant the file deduping was causing an error, to, well, not cause it, so we can get to an error screen.
Signed-off-by: cpw <[email protected]>
2020-11-02 14:57:23 -05:00
128 changed files with 3214 additions and 417 deletions

No files matched your search

+57 -49
View File
@@ -11,8 +11,8 @@ buildscript {
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.187'
classpath 'org.ow2.asm:asm:7.2'
classpath 'org.ow2.asm:asm-tree:7.2'
classpath 'org.ow2.asm:asm:9.0'
classpath 'org.ow2.asm:asm-tree:9.0'
}
}
@@ -54,8 +54,8 @@ ext {
}
MAPPING_CHANNEL = 'snapshot'
MAPPING_VERSION = '20201028-1.16.3'
MC_VERSION = '1.16.4'
MCP_VERSION = '20201102.104115'
MC_VERSION = '1.16.5'
MCP_VERSION = '20210115.111550'
}
project(':mcp') {
@@ -197,7 +197,7 @@ project(':forge') {
}
ext {
SPEC_VERSION = '35.0' // This is overwritten by git tag, but here so dev time doesnt explode
SPEC_VERSION = '36.0' // This is overwritten by git tag, but here so dev time doesnt explode
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
// ForgeMC is a unique identifier for every MC version we have supported.
// Essentially, the same as the old, except dropping the first number, and the builds are no longer unique.
@@ -432,17 +432,18 @@ project(':forge') {
fmllauncherImplementation.extendsFrom(installer)
}
dependencies {
installer 'org.ow2.asm:asm:7.2'
installer 'org.ow2.asm:asm-commons:7.2'
installer 'org.ow2.asm:asm-tree:7.2'
installer 'org.ow2.asm:asm-util:7.2'
installer 'org.ow2.asm:asm-analysis:7.2'
installer 'cpw.mods:modlauncher:8.0.6'
installer 'org.ow2.asm:asm:9.0'
installer 'org.ow2.asm:asm-commons:9.0'
installer 'org.ow2.asm:asm-tree:9.0'
installer 'org.ow2.asm:asm-util:9.0'
installer 'org.ow2.asm:asm-analysis:9.0'
installer 'cpw.mods:modlauncher:8.0.+'
installer 'cpw.mods:grossjava9hacks:1.3.+'
installer 'net.minecraftforge:accesstransformers:2.2.+:shadowed'
installer 'net.minecraftforge:eventbus:3.0.+:service'
installer 'net.minecraftforge:accesstransformers:3.0.+'
installer 'org.antlr:antlr4-runtime:4.9.1' //Dep of AccessTransformer
installer 'net.minecraftforge:eventbus:4.0.+'
installer 'net.minecraftforge:forgespi:3.2.+'
installer 'net.minecraftforge:coremods:3.0.+'
installer 'net.minecraftforge:coremods:4.0.+'
installer 'net.minecraftforge:unsafe:0.2.+'
installer 'com.electronwill.night-config:core:3.6.2'
installer 'com.electronwill.night-config:toml:3.6.2'
@@ -454,6 +455,9 @@ project(':forge') {
installer 'net.minecrell:terminalconsoleappender:1.2.+'
installer 'net.sf.jopt-simple:jopt-simple:5.0.4'
installer 'org.spongepowered:mixin:0.8.2'
// This is org.openjdk.nashorn:nashorn-core:15.1.1 repackaged so it doesn't crash on JREs < 15.
// See: https://github.com/LexManos/NashornLegacyPackager
installer 'net.minecraftforge:nashorn-core-compat:15.1.1'
fmllauncherImplementation 'com.google.guava:guava:21.0'
fmllauncherImplementation 'com.google.code.gson:gson:2.8.0'
fmllauncherImplementation 'org.lwjgl:lwjgl:3.2.2'
@@ -475,35 +479,35 @@ project(':forge') {
if (changelog.exists())
extraTxts += changelog
task crowdin(type: CrowdinTask) {
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
//TODO: Merge our english.json?
}
task crowdin(type: CrowdinTask) {
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
//TODO: Merge our english.json?
}
// We apply the bin patches we just created to make a jar that is JUST our changes
['Client', 'Server', 'Joined'].each { side ->
def gen = tasks.getByName("gen${side}BinPatches")
gen.tool = BINPATCH_TOOL
task "apply${side}BinPatches"(type: ApplyBinPatches, dependsOn: gen) {
clean = { gen.cleanJar }
input = gen.output
tool = BINPATCH_TOOL
}
if (side != 'Joined') {
// Create SRG named Vanilla jars, using the SpecialSource we have in the installer
task "create${side}SRG"(type: RenameJar, dependsOn: gen) {
tool = SPECIAL_SOURCE + ':shaded'
args = ['--stable', '--in-jar', '{input}', '--out-jar', '{output}', '--srg-in', '{mappings}']
mappings = { gen.srg }
input = { gen.cleanJar }
output = file("build/create${name}SRG/output.jar")
}
}
}
['Client', 'Server', 'Joined'].each { side ->
def gen = tasks.getByName("gen${side}BinPatches")
gen.tool = BINPATCH_TOOL
task "apply${side}BinPatches"(type: ApplyBinPatches, dependsOn: gen) {
clean = { gen.cleanJar }
input = gen.output
tool = BINPATCH_TOOL
}
if (side != 'Joined') {
// Create SRG named Vanilla jars, using the SpecialSource we have in the installer
task "create${side}SRG"(type: RenameJar, dependsOn: gen) {
tool = SPECIAL_SOURCE + ':shaded'
args = ['--stable', '--in-jar', '{input}', '--out-jar', '{output}', '--srg-in', '{mappings}']
mappings = { gen.srg }
input = { gen.cleanJar }
output = file("build/create${name}SRG/output.jar")
}
}
}
task downloadLibraries(type: DownloadLibrariesTask, dependsOn: ':mcp:setupMCP') {
input = VERSION_JSON
output = rootProject.file('build/libraries/')
input = VERSION_JSON
output = rootProject.file('build/libraries/')
}
task extractInheritance(type: ExtractInheritance, dependsOn: [genJoinedBinPatches, downloadLibraries]) {
@@ -511,23 +515,23 @@ project(':forge') {
input { genJoinedBinPatches.cleanJar }
doFirst { downloadLibraries.libraries.each{ addLibrary(it) } }
}
task checkATs(type: CheckATs, dependsOn: extractInheritance) {
inheritance = extractInheritance.output
ats = patcher.accessTransformers
ats = patcher.accessTransformers
}
task checkSAS(type: CheckSAS, dependsOn: extractInheritance) {
inheritance = extractInheritance.output
sass = patcher.sideAnnotationStrippers
sass = patcher.sideAnnotationStrippers
}
task checkExcs(type: CheckExcs, dependsOn: jar) {
binary = jar.archivePath
excs = patcher.excs
excs = patcher.excs
}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs]){}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs]){}
task checkPatchesAndFix(type: CheckPatches) {
patchDir = file("$rootDir/patches")
@@ -638,6 +642,7 @@ project(':forge') {
logo: '/big_logo.png',
minecraft: MC_VERSION,
welcome: "Welcome to the simple ${project.name.capitalize()} installer.",
mirrorList: "https://files.minecraftforge.net/mirrors-2.0.json",
data: [
MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]",
@@ -758,7 +763,7 @@ project(':forge') {
// add crowdin locales
from { crowdin.output.exists() ? zipTree(crowdin.output) : null}
dependsOn crowdin
duplicatesStrategy = 'exclude'
duplicatesStrategy = 'exclude'
doFirst {
MANIFESTS.each{ pkg, values ->
@@ -879,7 +884,9 @@ project(':forge') {
FORGE_NAME: project.name,
MC_VERSION: MC_VERSION,
MAPPING_CHANNEL: MAPPING_CHANNEL,
MAPPING_VERSION: MAPPING_VERSION
MAPPING_VERSION: MAPPING_VERSION,
FORGE_SPEC_VERSION: SPEC_VERSION.split("\\.")[0],
MC_NEXT_VERSION: "1."+((MC_VERSION.split("\\.")[1] as int)+1)
])
rename 'gitignore\\.txt', '.gitignore'
rename 'gitattributes\\.txt', '.gitattributes'
@@ -947,6 +954,7 @@ project(':forge') {
exclude 'net/minecraftforge/fml/common/versioning/InvalidVersionSpecificationException.java'
exclude 'net/minecraftforge/fml/common/versioning/Restriction.java'
exclude 'net/minecraftforge/fml/common/versioning/VersionRange.java'
exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java'
tasks {
main {
@@ -59,11 +59,12 @@ public class Util {
url = "https://files.minecraftforge.net/maven/${path}"
}
//TODO remove when Mojang launcher is updated
if (!classifiers && art.classifier != null) { //Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
if (!classifiers && art.classifier != null) {
//Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
// However, keep the path normal so that our mirror system works.
art.version = "${art.version}-${art.classifier}"
art.classifier = null
art.extension = 'jar'
path = "${art.group.replace('.', '/')}/${art.name}/${art.version}/${art.name}-${art.version}.jar"
}
ret[key] = [
name: "${art.group}:${art.name}:${art.version}" + (art.classifier == null ? '' : ":${art.classifier}") + (art.extension == 'jar' ? '' : "@${art.extension}"),
+10 -7
View File
@@ -6,24 +6,26 @@
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[34,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
loaderVersion="[@FORGE_SPEC_VERSION@,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="All rights reserved"
# A URL to refer people to when problems occur with this mod
issueTrackerURL="http://my.issue.tracker/" #optional
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId="examplemod" #mandatory
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
# see the associated build.gradle script for how to populate this completely automatically during a build
version="${file.jarVersion}" #mandatory
# A display name for the mod
displayName="Example Mod" #mandatory
# A URL to query for updates for this mod. See the JSON update specification <here>
updateJSONURL="http://myurl.me/" #optional
# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
displayURL="http://example.com/" #optional
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
logoFile="examplemod.png" #optional
# A text field displayed in the mod UI
@@ -45,7 +47,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magn
# Does this dependency have to exist - if not, ordering below must be specified
mandatory=true #mandatory
# The version range of the dependency
versionRange="[34,)" #mandatory
versionRange="[@FORGE_SPEC_VERSION@,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
@@ -54,6 +56,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magn
[[dependencies.examplemod]]
modId="minecraft"
mandatory=true
versionRange="[1.16.3]"
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[@MC_VERSION@,@MC_NEXT_VERSION@)"
ordering="NONE"
side="BOTH"
@@ -144,12 +144,22 @@
public AbstractBlock.Properties func_200941_a(float p_200941_1_) {
this.field_200961_i = p_200941_1_;
return this;
@@ -933,7 +971,7 @@
@@ -932,11 +970,17 @@
return this;
}
+ @Deprecated // FORGE: Use the variant that takes a Supplier below
public AbstractBlock.Properties func_222379_b(Block p_222379_1_) {
- this.field_222381_j = p_222379_1_.func_220068_i();
+ this.lootTableSupplier = () -> p_222379_1_.delegate.get().func_220068_i();
return this;
}
+ public AbstractBlock.Properties lootFrom(java.util.function.Supplier<? extends Block> blockIn) {
+ this.lootTableSupplier = () -> blockIn.get().func_220068_i();
+ return this;
+ }
+
public AbstractBlock.Properties func_235859_g_() {
this.field_235813_o_ = true;
return this;
@@ -0,0 +1,19 @@
--- a/net/minecraft/block/BeehiveBlock.java
+++ b/net/minecraft/block/BeehiveBlock.java
@@ -85,6 +85,7 @@
List<BeeEntity> list = p_226881_1_.func_217357_a(BeeEntity.class, (new AxisAlignedBB(p_226881_2_)).func_72314_b(8.0D, 6.0D, 8.0D));
if (!list.isEmpty()) {
List<PlayerEntity> list1 = p_226881_1_.func_217357_a(PlayerEntity.class, (new AxisAlignedBB(p_226881_2_)).func_72314_b(8.0D, 6.0D, 8.0D));
+ if (list1.isEmpty()) return; //Forge: Prevent Error when no players are around.
int i = list1.size();
for(BeeEntity beeentity : list) {
@@ -105,7 +106,7 @@
int i = p_225533_1_.func_177229_b(field_226873_c_);
boolean flag = false;
if (i >= 5) {
- if (itemstack.func_77973_b() == Items.field_151097_aZ) {
+ if (itemstack.func_77973_b() instanceof net.minecraft.item.ShearsItem) {
p_225533_2_.func_184148_a(p_225533_4_, p_225533_4_.func_226277_ct_(), p_225533_4_.func_226278_cu_(), p_225533_4_.func_226281_cx_(), SoundEvents.field_226133_ah_, SoundCategory.NEUTRAL, 1.0F, 1.0F);
func_226878_a_(p_225533_2_, p_225533_3_);
itemstack.func_222118_a(1, p_225533_4_, (p_226874_1_) -> {
@@ -0,0 +1,11 @@
--- a/net/minecraft/block/PumpkinBlock.java
+++ b/net/minecraft/block/PumpkinBlock.java
@@ -20,7 +20,7 @@
public ActionResultType func_225533_a_(BlockState p_225533_1_, World p_225533_2_, BlockPos p_225533_3_, PlayerEntity p_225533_4_, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
ItemStack itemstack = p_225533_4_.func_184586_b(p_225533_5_);
- if (itemstack.func_77973_b() == Items.field_151097_aZ) {
+ if (itemstack.func_77973_b() instanceof net.minecraft.item.ShearsItem) {
if (!p_225533_2_.field_72995_K) {
Direction direction = p_225533_6_.func_216354_b();
Direction direction1 = direction.func_176740_k() == Direction.Axis.Y ? p_225533_4_.func_174811_aO().func_176734_d() : direction;
@@ -0,0 +1,10 @@
--- a/net/minecraft/block/SoundType.java
+++ b/net/minecraft/block/SoundType.java
@@ -59,6 +59,7 @@
private final SoundEvent field_185865_r;
private final SoundEvent field_185866_s;
+ @Deprecated // Forge: Use {@link net.minecraftforge.common.util.ForgeSoundType} instead for suppliers
public SoundType(float p_i46679_1_, float p_i46679_2_, SoundEvent p_i46679_3_, SoundEvent p_i46679_4_, SoundEvent p_i46679_5_, SoundEvent p_i46679_6_, SoundEvent p_i46679_7_) {
this.field_185860_m = p_i46679_1_;
this.field_185861_n = p_i46679_2_;
@@ -0,0 +1,11 @@
--- a/net/minecraft/block/TripWireBlock.java
+++ b/net/minecraft/block/TripWireBlock.java
@@ -67,7 +67,7 @@
}
public void func_176208_a(World p_176208_1_, BlockPos p_176208_2_, BlockState p_176208_3_, PlayerEntity p_176208_4_) {
- if (!p_176208_1_.field_72995_K && !p_176208_4_.func_184614_ca().func_190926_b() && p_176208_4_.func_184614_ca().func_77973_b() == Items.field_151097_aZ) {
+ if (!p_176208_1_.field_72995_K && !p_176208_4_.func_184614_ca().func_190926_b() && p_176208_4_.func_184614_ca().func_77973_b() instanceof net.minecraft.item.ShearsItem) {
p_176208_1_.func_180501_a(p_176208_2_, p_176208_3_.func_206870_a(field_176295_N, Boolean.valueOf(true)), 4);
}
@@ -9,3 +9,11 @@
if (monitor != null) {
VideoMode videomode = monitor.func_197992_a(this.field_198125_l ? this.field_198124_k : Optional.empty());
this.field_198120_g = this.field_198127_n = monitor.func_197989_c() + videomode.func_198064_a() / 2 - this.field_198129_p / 2;
@@ -271,6 +271,7 @@
GLFW.glfwGetFramebufferSize(this.field_198119_f, aint, aint1);
this.field_198131_r = aint[0];
this.field_198132_s = aint1[0];
+ if (this.field_198132_s == 0 || this.field_198131_r==0) net.minecraftforge.fml.loading.progress.EarlyProgressVisualization.INSTANCE.updateFBSize(w->this.field_198131_r=w, h->this.field_198132_s=h);
}
private void func_198089_c(long p_198089_1_, int p_198089_3_, int p_198089_4_) {
@@ -0,0 +1,21 @@
--- a/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
+++ b/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
@@ -113,6 +113,9 @@
private BiomeGeneratorTypeScreens(String p_i232324_1_) {
this.field_239076_k_ = new TranslationTextComponent("generator." + p_i232324_1_);
}
+ public BiomeGeneratorTypeScreens(ITextComponent displayName) {
+ this.field_239076_k_ = displayName;
+ }
private static DimensionGeneratorSettings func_243452_a(DynamicRegistries p_243452_0_, DimensionGeneratorSettings p_243452_1_, BiomeGeneratorTypeScreens p_243452_2_, Biome p_243452_3_) {
BiomeProvider biomeprovider = new SingleBiomeProvider(p_243452_3_);
@@ -166,4 +169,8 @@
public interface IFactory {
Screen createEditScreen(CreateWorldScreen p_createEditScreen_1_, DimensionGeneratorSettings p_createEditScreen_2_);
}
+
+ // Forge start
+ // For internal use only, automatically called for all ForgeWorldTypes. Register your ForgeWorldType in the forge registry!
+ public static void registerGenerator(BiomeGeneratorTypeScreens gen) { field_239068_c_.add(gen); }
}
@@ -1,5 +1,14 @@
--- a/net/minecraft/client/gui/screen/CreateWorldScreen.java
+++ b/net/minecraft/client/gui/screen/CreateWorldScreen.java
@@ -110,7 +110,7 @@
public static CreateWorldScreen func_243425_a(@Nullable Screen p_243425_0_) {
DynamicRegistries.Impl dynamicregistries$impl = DynamicRegistries.func_239770_b_();
- return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar)), Optional.of(BiomeGeneratorTypeScreens.field_239066_a_), OptionalLong.empty()));
+ return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, net.minecraftforge.client.ForgeHooksClient.getDefaultWorldType().map(type -> type.func_241220_a_(dynamicregistries$impl, new java.util.Random().nextLong(), true, false)).orElseGet(() -> DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar))), net.minecraftforge.client.ForgeHooksClient.getDefaultWorldType(), OptionalLong.empty()));
}
private CreateWorldScreen(@Nullable Screen p_i242063_1_, DatapackCodec p_i242063_2_, WorldOptionsScreen p_i242063_3_) {
@@ -542,6 +542,7 @@
File file1 = path.toFile();
if (this.field_243416_G == null) {
@@ -0,0 +1,19 @@
--- a/net/minecraft/client/gui/screen/WorldOptionsScreen.java
+++ b/net/minecraft/client/gui/screen/WorldOptionsScreen.java
@@ -134,6 +134,7 @@
this.field_239035_i_.field_230693_o_ = this.field_239040_n_.isPresent();
this.field_239036_j_ = p_239048_1_.func_230480_a_(new Button(j, 120, 150, 20, new TranslationTextComponent("selectWorld.customizeType"), (p_239044_3_) -> {
BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory = BiomeGeneratorTypeScreens.field_239069_d_.get(this.field_239040_n_);
+ biomegeneratortypescreens$ifactory = net.minecraftforge.client.ForgeHooksClient.getBiomeGeneratorTypeScreenFactory(this.field_239040_n_, biomegeneratortypescreens$ifactory);
if (biomegeneratortypescreens$ifactory != null) {
p_239048_2_.func_147108_a(biomegeneratortypescreens$ifactory.createEditScreen(p_239048_1_, this.field_239039_m_));
}
@@ -292,7 +293,7 @@
} else {
this.field_239034_h_.field_230694_p_ = p_239059_1_;
this.field_239027_a_.field_230694_p_ = p_239059_1_;
- this.field_239036_j_.field_230694_p_ = p_239059_1_ && BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_);
+ this.field_239036_j_.field_230694_p_ = p_239059_1_ && (BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_) || net.minecraftforge.client.ForgeHooksClient.hasBiomeGeneratorSettingsOptionsScreen(this.field_239040_n_));
this.field_239037_k_.field_230694_p_ = p_239059_1_;
}
@@ -101,7 +101,7 @@
} else {
ItemStack itemstack = p_217292_1_.func_184586_b(p_217292_3_);
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks
+ .onRightClickBlock(p_217292_1_, p_217292_3_, blockpos, p_217292_4_.func_216354_b());
+ .onRightClickBlock(p_217292_1_, p_217292_3_, blockpos, p_217292_4_);
+ if (event.isCanceled()) {
+ this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
+ return event.getCancellationResult();
@@ -122,7 +122,7 @@
+ boolean flag = !p_217292_1_.func_184614_ca().doesSneakBypassUse(p_217292_2_,blockpos,p_217292_1_) || !p_217292_1_.func_184592_cb().doesSneakBypassUse(p_217292_2_,blockpos,p_217292_1_);
boolean flag1 = p_217292_1_.func_226563_dT_() && flag;
- if (!flag1) {
+ if (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1) {
+ if (event.getUseBlock() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1)) {
ActionResultType actionresulttype = p_217292_2_.func_180495_p(blockpos).func_227031_a_(p_217292_2_, p_217292_1_, p_217292_3_, p_217292_4_);
if (actionresulttype.func_226246_a_()) {
this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
@@ -130,9 +130,10 @@
}
this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
if (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b())) {
- if (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b())) {
- ItemUseContext itemusecontext = new ItemUseContext(p_217292_1_, p_217292_3_, p_217292_4_);
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b()))) {
ActionResultType actionresulttype1;
if (this.field_78779_k.func_77145_d()) {
int i = itemstack.func_190916_E();
@@ -12,7 +12,19 @@
float f = this.field_72777_q.field_71441_e.func_72867_j(p_228438_2_);
if (!(f <= 0.0F)) {
p_228438_1_.func_205109_c();
@@ -830,7 +835,7 @@
@@ -347,6 +352,11 @@
}
public void func_228436_a_(ActiveRenderInfo p_228436_1_) {
+ net.minecraftforge.client.IWeatherParticleRenderHandler renderHandler = field_72769_h.func_239132_a_().getWeatherParticleRenderHandler();
+ if (renderHandler != null) {
+ renderHandler.render(field_72773_u, field_72769_h, field_72777_q, p_228436_1_);
+ return;
+ }
float f = this.field_72777_q.field_71441_e.func_72867_j(1.0F) / (Minecraft.func_71375_t() ? 1.0F : 2.0F);
if (!(f <= 0.0F)) {
Random random = new Random((long)this.field_72773_u * 312987231L);
@@ -830,7 +840,7 @@
this.field_147595_R = true;
BlockPos blockpos2 = chunkrenderdispatcher$chunkrender4.func_178568_j().func_177982_a(8, 8, 8);
boolean flag1 = blockpos2.func_177951_i(blockpos) < 768.0D;
@@ -21,7 +33,7 @@
this.field_175009_l.add(chunkrenderdispatcher$chunkrender4);
} else {
this.field_72777_q.func_213239_aq().func_76320_a("build near");
@@ -915,13 +920,13 @@
@@ -915,13 +925,13 @@
float f = p_228426_7_.func_205001_m();
boolean flag1 = this.field_72777_q.field_71441_e.func_239132_a_().func_230493_a_(MathHelper.func_76128_c(d0), MathHelper.func_76128_c(d1)) || this.field_72777_q.field_71456_v.func_184046_j().func_184056_f();
if (this.field_72777_q.field_71474_y.field_151451_c >= 4) {
@@ -37,7 +49,7 @@
iprofiler.func_219895_b("terrain_setup");
this.func_228437_a_(p_228426_6_, clippinghelper, flag, this.field_228409_ai_++, this.field_72777_q.field_71439_g.func_175149_v());
iprofiler.func_219895_b("updatechunks");
@@ -942,7 +947,9 @@
@@ -942,7 +952,9 @@
this.func_174967_a(p_228426_3_ + l1);
iprofiler.func_219895_b("terrain");
this.func_228441_a_(RenderType.func_228639_c_(), p_228426_1_, d0, d1, d2);
@@ -47,7 +59,16 @@
this.func_228441_a_(RenderType.func_228643_e_(), p_228426_1_, d0, d1, d2);
if (this.field_72769_h.func_239132_a_().func_239217_c_()) {
RenderHelper.func_237533_a_(p_228426_1_.func_227866_c_().func_227870_a_());
@@ -1010,6 +1017,7 @@
@@ -972,7 +984,7 @@
IRenderTypeBuffer.Impl irendertypebuffer$impl = this.field_228415_m_.func_228487_b_();
for(Entity entity : this.field_72769_h.func_217416_b()) {
- if ((this.field_175010_j.func_229086_a_(entity, clippinghelper, d0, d1, d2) || entity.func_184215_y(this.field_72777_q.field_71439_g)) && (entity != p_228426_6_.func_216773_g() || p_228426_6_.func_216770_i() || p_228426_6_.func_216773_g() instanceof LivingEntity && ((LivingEntity)p_228426_6_.func_216773_g()).func_70608_bn()) && (!(entity instanceof ClientPlayerEntity) || p_228426_6_.func_216773_g() == entity)) {
+ if ((this.field_175010_j.func_229086_a_(entity, clippinghelper, d0, d1, d2) || entity.func_184215_y(this.field_72777_q.field_71439_g)) && (entity != p_228426_6_.func_216773_g() || p_228426_6_.func_216770_i() || p_228426_6_.func_216773_g() instanceof LivingEntity && ((LivingEntity)p_228426_6_.func_216773_g()).func_70608_bn()) && (!(entity instanceof ClientPlayerEntity) || p_228426_6_.func_216773_g() == entity || (entity == field_72777_q.field_71439_g && !field_72777_q.field_71439_g.func_175149_v()))) { //FORGE: render local player entity when it is not the renderViewEntity
++this.field_72749_I;
if (entity.field_70173_aa == 0) {
entity.field_70142_S = entity.func_226277_ct_();
@@ -1010,6 +1022,7 @@
List<TileEntity> list = worldrenderer$localrenderinformationcontainer.field_178036_a.func_178571_g().func_178485_b();
if (!list.isEmpty()) {
for(TileEntity tileentity1 : list) {
@@ -55,7 +76,7 @@
BlockPos blockpos3 = tileentity1.func_174877_v();
IRenderTypeBuffer irendertypebuffer1 = irendertypebuffer$impl;
p_228426_1_.func_227860_a_();
@@ -1035,6 +1043,7 @@
@@ -1035,6 +1048,7 @@
synchronized(this.field_181024_n) {
for(TileEntity tileentity : this.field_181024_n) {
@@ -63,7 +84,7 @@
BlockPos blockpos2 = tileentity.func_174877_v();
p_228426_1_.func_227860_a_();
p_228426_1_.func_227861_a_((double)blockpos2.func_177958_n() - d0, (double)blockpos2.func_177956_o() - d1, (double)blockpos2.func_177952_p() - d2);
@@ -1084,10 +1093,13 @@
@@ -1084,10 +1098,13 @@
iprofiler.func_219895_b("outline");
BlockPos blockpos = ((BlockRayTraceResult)raytraceresult).func_216350_a();
BlockState blockstate = this.field_72769_h.func_180495_p(blockpos);
@@ -78,7 +99,7 @@
}
RenderSystem.pushMatrix();
@@ -1119,7 +1131,7 @@
@@ -1119,7 +1136,7 @@
this.field_239224_H_.func_237506_a_(this.field_72777_q.func_147110_a());
RenderState.field_239237_T_.func_228547_a_();
iprofiler.func_219895_b("particles");
@@ -87,7 +108,7 @@
RenderState.field_239237_T_.func_228549_b_();
} else {
iprofiler.func_219895_b("translucent");
@@ -1129,7 +1141,7 @@
@@ -1129,7 +1146,7 @@
iprofiler.func_219895_b("string");
this.func_228441_a_(RenderType.func_241715_r_(), p_228426_1_, d0, d1, d2);
iprofiler.func_219895_b("particles");
@@ -96,7 +117,7 @@
}
RenderSystem.pushMatrix();
@@ -1481,6 +1493,11 @@
@@ -1481,6 +1498,11 @@
}
public void func_228424_a_(MatrixStack p_228424_1_, float p_228424_2_) {
@@ -108,7 +129,7 @@
if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.END) {
this.func_228444_b_(p_228424_1_);
} else if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.NORMAL) {
@@ -1609,6 +1626,11 @@
@@ -1609,6 +1631,11 @@
}
public void func_228425_a_(MatrixStack p_228425_1_, float p_228425_2_, double p_228425_3_, double p_228425_5_, double p_228425_7_) {
@@ -120,7 +141,7 @@
float f = this.field_72769_h.func_239132_a_().func_239213_a_();
if (!Float.isNaN(f)) {
RenderSystem.disableCull();
@@ -1792,7 +1814,7 @@
@@ -1792,7 +1819,7 @@
while(iterator.hasNext()) {
ChunkRenderDispatcher.ChunkRender chunkrenderdispatcher$chunkrender = iterator.next();
@@ -129,7 +150,7 @@
this.field_174995_M.func_228902_a_(chunkrenderdispatcher$chunkrender);
} else {
chunkrenderdispatcher$chunkrender.func_228929_a_(this.field_174995_M);
@@ -2076,7 +2098,12 @@
@@ -2076,7 +2103,12 @@
this.field_175008_n.func_217628_a(p_215319_1_, p_215319_2_, p_215319_3_, p_215319_4_);
}
@@ -142,7 +163,7 @@
ISound isound = this.field_147593_P.get(p_184377_2_);
if (isound != null) {
this.field_72777_q.func_147118_V().func_147683_b(isound);
@@ -2084,7 +2111,7 @@
@@ -2084,7 +2116,7 @@
}
if (p_184377_1_ != null) {
@@ -151,7 +172,7 @@
if (musicdiscitem != null) {
this.field_72777_q.field_71456_v.func_238451_a_(musicdiscitem.func_234801_g_());
}
@@ -2232,7 +2259,7 @@
@@ -2232,7 +2264,7 @@
break;
case 1010:
if (Item.func_150899_d(p_180439_4_) instanceof MusicDiscItem) {
@@ -160,7 +181,7 @@
} else {
this.func_184377_a((SoundEvent)null, p_180439_3_);
}
@@ -2382,8 +2409,8 @@
@@ -2382,8 +2414,8 @@
break;
case 2001:
BlockState blockstate = Block.func_196257_b(p_180439_4_);
@@ -171,7 +192,7 @@
this.field_72769_h.func_184156_a(p_180439_3_, soundtype.func_185845_c(), SoundCategory.BLOCKS, (soundtype.func_185843_a() + 1.0F) / 2.0F, soundtype.func_185847_b() * 0.8F, false);
}
@@ -2531,7 +2558,7 @@
@@ -2531,7 +2563,7 @@
} else {
int i = p_228420_0_.func_226658_a_(LightType.SKY, p_228420_2_);
int j = p_228420_0_.func_226658_a_(LightType.BLOCK, p_228420_2_);
@@ -180,7 +201,7 @@
if (j < k) {
j = k;
}
@@ -2570,6 +2597,11 @@
@@ -2570,6 +2602,11 @@
return this.field_239226_J_;
}
@@ -1,16 +1,14 @@
--- a/net/minecraft/client/renderer/tileentity/PistonTileEntityRenderer.java
+++ b/net/minecraft/client/renderer/tileentity/PistonTileEntityRenderer.java
@@ -61,8 +61,12 @@
@@ -61,8 +61,11 @@
}
private void func_228876_a_(BlockPos p_228876_1_, BlockState p_228876_2_, MatrixStack p_228876_3_, IRenderTypeBuffer p_228876_4_, World p_228876_5_, boolean p_228876_6_, int p_228876_7_) {
- RenderType rendertype = RenderTypeLookup.func_239221_b_(p_228876_2_);
+ net.minecraft.client.renderer.RenderType.func_228661_n_().stream().filter(t -> RenderTypeLookup.canRenderInLayer(p_228876_2_, t)).forEach(rendertype -> {
+ net.minecraftforge.client.ForgeHooksClient.setRenderLayer(rendertype);
+ net.minecraftforge.client.ForgeHooksClient.renderPistonMovedBlocks(p_228876_1_, p_228876_2_, p_228876_3_, p_228876_4_, p_228876_5_, p_228876_6_, p_228876_7_, field_178462_c == null ? field_178462_c = Minecraft.func_71410_x().func_175602_ab() : field_178462_c);
+ if(false) {
RenderType rendertype = RenderTypeLookup.func_239221_b_(p_228876_2_);
IVertexBuilder ivertexbuilder = p_228876_4_.getBuffer(rendertype);
+ if (field_178462_c == null) field_178462_c = Minecraft.func_71410_x().func_175602_ab();
this.field_178462_c.func_175019_b().func_228802_a_(p_228876_5_, this.field_178462_c.func_184389_a(p_228876_2_), p_228876_2_, p_228876_1_, p_228876_3_, ivertexbuilder, p_228876_6_, new Random(), p_228876_2_.func_209533_a(p_228876_1_), p_228876_7_);
+ });
+ net.minecraftforge.client.ForgeHooksClient.setRenderLayer(null);
+ }
}
}
@@ -1,22 +1,26 @@
--- a/net/minecraft/client/world/DimensionRenderInfo.java
+++ b/net/minecraft/client/world/DimensionRenderInfo.java
@@ -26,6 +26,9 @@
@@ -26,6 +26,10 @@
private final DimensionRenderInfo.FogType field_241680_e_;
private final boolean field_241681_f_;
private final boolean field_239212_e_;
+ private net.minecraftforge.client.IWeatherRenderHandler weatherRenderHandler = null;
+ private net.minecraftforge.client.IWeatherParticleRenderHandler weatherParticleRenderHandler = null;
+ private net.minecraftforge.client.ISkyRenderHandler skyRenderHandler = null;
+ private net.minecraftforge.client.ICloudRenderHandler cloudRenderHandler = null;
public DimensionRenderInfo(float p_i241259_1_, boolean p_i241259_2_, DimensionRenderInfo.FogType p_i241259_3_, boolean p_i241259_4_, boolean p_i241259_5_) {
this.field_239210_c_ = p_i241259_1_;
@@ -82,6 +85,28 @@
@@ -82,6 +86,35 @@
return this.field_239212_e_;
}
+ public void setWeatherRenderHandler(net.minecraftforge.client.IWeatherRenderHandler weatherRenderHandler) {
+ this.weatherRenderHandler = weatherRenderHandler;
+ }
+ public void setWeatherParticleRenderHandler(net.minecraftforge.client.IWeatherParticleRenderHandler weatherParticleRenderHandler) {
+ this.weatherParticleRenderHandler = weatherParticleRenderHandler;
+ }
+ public void setSkyRenderHandler(net.minecraftforge.client.ISkyRenderHandler skyRenderHandler) {
+ this.skyRenderHandler = skyRenderHandler;
+ }
@@ -32,6 +36,10 @@
+ return weatherRenderHandler;
+ }
+ @Nullable
+ public net.minecraftforge.client.IWeatherParticleRenderHandler getWeatherParticleRenderHandler() {
+ return weatherParticleRenderHandler;
+ }
+ @Nullable
+ public net.minecraftforge.client.ISkyRenderHandler getSkyRenderHandler() {
+ return skyRenderHandler;
+ }
@@ -0,0 +1,11 @@
--- a/net/minecraft/command/arguments/ArgumentTypes.java
+++ b/net/minecraft/command/arguments/ArgumentTypes.java
@@ -220,4 +220,8 @@
this.field_197481_c = p_i48088_3_;
}
}
+ @javax.annotation.Nullable public static ResourceLocation getId(ArgumentType<?> type) {
+ Entry<?> entry = func_201040_a(type);
+ return entry == null ? null : entry.field_197481_c;
+ }
}
@@ -1,10 +1,11 @@
--- a/net/minecraft/data/Main.java
+++ b/net/minecraft/data/Main.java
@@ -21,8 +21,12 @@
@@ -21,8 +21,13 @@
OptionSpec<Void> optionspec6 = optionparser.accepts("all", "Include all generators");
OptionSpec<String> optionspec7 = optionparser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
OptionSpec<String> optionspec8 = optionparser.accepts("input", "Input folder").withRequiredArg();
+ OptionSpec<String> existing = optionparser.accepts("existing", "Existing resource packs that generated resources can reference").withRequiredArg();
+ OptionSpec<String> existingMod = optionparser.accepts("existing-mod", "Existing mods that generated resources can reference the resource packs of").withRequiredArg();
+ OptionSpec<java.io.File> gameDir = optionparser.accepts("gameDir").withRequiredArg().ofType(java.io.File.class).defaultsTo(new java.io.File(".")).required(); //Need by modlauncher, so lets just eat it
+ OptionSpec<String> mod = optionparser.accepts("mod", "A modid to dump").withRequiredArg().withValuesSeparatedBy(",");
+ OptionSpec<Void> flat = optionparser.accepts("flat", "Do not append modid prefix to output directory when generating for multiple mods");
@@ -14,7 +15,7 @@
Path path = Paths.get(optionspec7.value(optionset));
boolean flag = optionset.has(optionspec6);
boolean flag1 = flag || optionset.has(optionspec2);
@@ -30,10 +34,13 @@
@@ -30,10 +35,14 @@
boolean flag3 = flag || optionset.has(optionspec3);
boolean flag4 = flag || optionset.has(optionspec4);
boolean flag5 = flag || optionset.has(optionspec5);
@@ -24,9 +25,10 @@
- datagenerator.func_200392_c();
+ Collection<Path> inputs = optionset.valuesOf(optionspec8).stream().map(Paths::get).collect(Collectors.toList());
+ Collection<Path> existingPacks = optionset.valuesOf(existing).stream().map(Paths::get).collect(Collectors.toList());
+ java.util.Set<String> existingMods = new java.util.HashSet<>(optionset.valuesOf(existingMod));
+ java.util.Set<String> mods = new java.util.HashSet<>(optionset.valuesOf(mod));
+ boolean isFlat = mods.isEmpty() || optionset.has(flat);
+ net.minecraftforge.fml.DatagenModLoader.begin(mods, path, inputs, existingPacks, flag2, flag1, flag3, flag4, flag5, isFlat);
+ net.minecraftforge.fml.DatagenModLoader.begin(mods, path, inputs, existingPacks, existingMods, flag2, flag1, flag3, flag4, flag5, isFlat);
+ if (mods.contains("minecraft") || mods.isEmpty())
+ func_200264_a(isFlat ? path : path.resolve("minecraft"), inputs, flag1, flag2, flag3, flag4, flag5).func_200392_c();
} else {
@@ -1,11 +1,12 @@
--- a/net/minecraft/data/TagsProvider.java
+++ b/net/minecraft/data/TagsProvider.java
@@ -28,10 +28,18 @@
@@ -28,10 +28,20 @@
protected final DataGenerator field_200433_a;
protected final Registry<T> field_200435_c;
protected final Map<ResourceLocation, ITag.Builder> field_200434_b = Maps.newLinkedHashMap();
+ protected final String modId;
+ protected final net.minecraftforge.common.data.ExistingFileHelper existingFileHelper;
+ private final net.minecraftforge.common.data.ExistingFileHelper.IResourceType resourceType;
+ @Deprecated//Forge, Use ModID version.
protected TagsProvider(DataGenerator p_i49827_1_, Registry<T> p_i49827_2_) {
@@ -16,10 +17,11 @@
this.field_200435_c = p_i49827_2_;
+ this.modId = modId;
+ this.existingFileHelper = existingFileHelper;
+ this.resourceType = new net.minecraftforge.common.data.ExistingFileHelper.ResourceType(net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder());
}
protected abstract void func_200432_c();
@@ -47,12 +55,14 @@
@@ -47,12 +57,14 @@
return this.field_200435_c.func_241873_b(p_240527_1_).orElse((T)null);
};
this.field_200434_b.forEach((p_240524_4_, p_240524_5_) -> {
@@ -35,7 +37,7 @@
try {
String s = field_200437_e.toJson((JsonElement)jsonobject);
@@ -74,11 +84,26 @@
@@ -74,20 +86,36 @@
});
}
@@ -44,7 +46,7 @@
+ // We only care about non-optional tag entries, this is the only type that can reference a resource and needs validation
+ // Optional tags should not be validated
+ if (entry instanceof ITag.TagEntry) {
+ return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder());
+ return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), resourceType);
+ }
+ return false;
+ }
@@ -63,7 +65,9 @@
}
protected ITag.Builder func_240525_b_(ITag.INamedTag<T> p_240525_1_) {
@@ -87,7 +112,7 @@
return this.field_200434_b.computeIfAbsent(p_240525_1_.func_230234_a_(), (p_240526_0_) -> {
+ existingFileHelper.trackGenerated(p_240526_0_, resourceType);
return new ITag.Builder();
});
}
@@ -72,7 +76,7 @@
private final ITag.Builder field_240528_a_;
private final Registry<T> field_240529_b_;
private final String field_240530_c_;
@@ -115,5 +140,18 @@
@@ -115,5 +143,18 @@
});
return this;
}
@@ -0,0 +1,10 @@
--- a/net/minecraft/enchantment/EfficiencyEnchantment.java
+++ b/net/minecraft/enchantment/EfficiencyEnchantment.java
@@ -22,6 +22,6 @@
}
public boolean func_92089_a(ItemStack p_92089_1_) {
- return p_92089_1_.func_77973_b() == Items.field_151097_aZ ? true : super.func_92089_a(p_92089_1_);
+ return p_92089_1_.func_77973_b() instanceof net.minecraft.item.ShearsItem ? true : super.func_92089_a(p_92089_1_);
}
}
@@ -481,7 +481,7 @@
}
public boolean func_70094_T() {
@@ -3082,6 +3138,60 @@
@@ -3082,6 +3138,58 @@
this.func_213361_c(p_213334_1_ == Hand.MAIN_HAND ? EquipmentSlotType.MAINHAND : EquipmentSlotType.OFFHAND);
}
@@ -531,12 +531,10 @@
+ }
+
+ @Override
+ public void remove(boolean keepData) {
+ super.remove(keepData);
+ if (!keepData) {
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
+
@OnlyIn(Dist.CLIENT)
@@ -0,0 +1,22 @@
--- a/net/minecraft/entity/ai/goal/TriggerSkeletonTrapGoal.java
+++ b/net/minecraft/entity/ai/goal/TriggerSkeletonTrapGoal.java
@@ -28,6 +28,10 @@
public void func_75246_d() {
ServerWorld serverworld = (ServerWorld)this.field_188516_a.field_70170_p;
+ // Forge: Trigger the trap in a tick task to avoid crashes when mods add goals to skeleton horses
+ // (MC-206338/Forge PR #7509)
+ serverworld.func_73046_m().func_212871_a_(new net.minecraft.util.concurrent.TickDelayedTask(serverworld.func_73046_m().func_71259_af(), () -> {
+ if (!this.field_188516_a.func_70089_S()) return;
DifficultyInstance difficultyinstance = serverworld.func_175649_E(this.field_188516_a.func_233580_cy_());
this.field_188516_a.func_190691_p(false);
this.field_188516_a.func_110234_j(true);
@@ -47,7 +51,7 @@
abstracthorseentity.func_70024_g(this.field_188516_a.func_70681_au().nextGaussian() * 0.5D, 0.0D, this.field_188516_a.func_70681_au().nextGaussian() * 0.5D);
serverworld.func_242417_l(abstracthorseentity);
}
-
+ }));
}
private AbstractHorseEntity func_188515_a(DifficultyInstance p_188515_1_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/entity/item/minecart/ContainerMinecartEntity.java
+++ b/net/minecraft/entity/item/minecart/ContainerMinecartEntity.java
@@ -118,17 +118,19 @@
@@ -118,17 +118,18 @@
}
@Nullable
@@ -20,11 +20,10 @@
- super.func_70106_y();
+ super.remove(keepData);
+ if (!keepData) itemHandler.invalidate();
}
protected void func_213281_b(CompoundNBT p_213281_1_) {
@@ -157,6 +159,8 @@
@@ -157,6 +158,8 @@
}
public ActionResultType func_184230_a(PlayerEntity p_184230_1_, Hand p_184230_2_) {
@@ -33,7 +32,7 @@
p_184230_1_.func_213829_a(this);
if (!p_184230_1_.field_70170_p.field_72995_K) {
PiglinTasks.func_234478_a_(p_184230_1_, true);
@@ -185,6 +189,8 @@
@@ -185,6 +188,8 @@
this.field_184290_c = null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld)this.field_70170_p)).func_216015_a(LootParameters.field_237457_g_, this.func_213303_ch()).func_216016_a(this.field_184291_d);
@@ -42,7 +41,7 @@
if (p_184288_1_ != null) {
lootcontext$builder.func_186469_a(p_184288_1_.func_184817_da()).func_216015_a(LootParameters.field_216281_a, p_184288_1_);
}
@@ -215,4 +221,17 @@
@@ -215,4 +220,23 @@
}
protected abstract Container func_213968_a(int p_213968_1_, PlayerInventory p_213968_2_);
@@ -56,6 +55,12 @@
+ return super.getCapability(capability, facing);
+ }
+
+ @Override
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ itemHandler.invalidate();
+ }
+
+ public void dropContentsWhenDead(boolean value) {
+ this.field_94112_b = value;
+ }
@@ -19,3 +19,20 @@
}
@OnlyIn(Dist.CLIENT)
@@ -687,7 +688,7 @@
}
public void func_241841_a(ServerWorld p_241841_1_, LightningBoltEntity p_241841_2_) {
- if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL) {
+ if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200759_ay, (timer) -> {})) {
field_184243_a.info("Villager {} was struck by lightning {}.", this, p_241841_2_);
WitchEntity witchentity = EntityType.field_200759_ay.func_200721_a(p_241841_1_);
witchentity.func_70012_b(this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), this.field_70177_z, this.field_70125_A);
@@ -699,6 +700,7 @@
}
witchentity.func_110163_bv();
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, witchentity);
p_241841_1_.func_242417_l(witchentity);
this.func_242369_fq();
this.func_70106_y();
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/monster/HoglinEntity.java
+++ b/net/minecraft/entity/monster/HoglinEntity.java
@@ -117,7 +117,7 @@
HoglinTasks.func_234377_a_(this);
if (this.func_234364_eK_()) {
++this.field_234358_by_;
- if (this.field_234358_by_ > 300) {
+ if (this.field_234358_by_ > 300 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233590_aW_, (timer) -> this.field_234358_by_ = timer)) {
this.func_241412_a_(SoundEvents.field_232715_fE_);
this.func_234360_a_((ServerWorld)this.field_70170_p);
}
@@ -212,6 +212,7 @@
ZoglinEntity zoglinentity = this.func_233656_b_(EntityType.field_233590_aW_, true);
if (zoglinentity != null) {
zoglinentity.func_195064_c(new EffectInstance(Effects.field_76431_k, 200, 0));
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zoglinentity);
}
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/entity/monster/PhantomEntity.java
+++ b/net/minecraft/entity/monster/PhantomEntity.java
@@ -214,7 +214,7 @@
this.field_203142_b = 60;
List<PlayerEntity> list = PhantomEntity.this.field_70170_p.func_217373_a(this.field_220842_b, PhantomEntity.this, PhantomEntity.this.func_174813_aQ().func_72314_b(16.0D, 64.0D, 16.0D));
if (!list.isEmpty()) {
- list.sort(Comparator.comparing(Entity::func_226278_cu_).reversed());
+ list.sort(Comparator.<Entity, Double>comparing(Entity::func_226278_cu_).reversed());
for(PlayerEntity playerentity : list) {
if (PhantomEntity.this.func_213344_a(playerentity, EntityPredicate.field_221016_a)) {
@@ -1,6 +1,24 @@
--- a/net/minecraft/entity/monster/ZombieEntity.java
+++ b/net/minecraft/entity/monster/ZombieEntity.java
@@ -268,12 +268,16 @@
@@ -186,7 +186,8 @@
if (!this.field_70170_p.field_72995_K && this.func_70089_S() && !this.func_175446_cd()) {
if (this.func_204706_dD()) {
--this.field_204708_bE;
- if (this.field_204708_bE < 0) {
+
+ if (this.field_204708_bE < 0 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200725_aD, (timer) -> this.field_204708_bE = timer)) {
this.func_207302_dI();
}
} else if (this.func_204703_dA()) {
@@ -248,6 +249,7 @@
if (zombieentity != null) {
zombieentity.func_207304_a(zombieentity.field_70170_p.func_175649_E(zombieentity.func_233580_cy_()).func_180170_c());
zombieentity.func_146070_a(zombieentity.func_204900_dz() && this.func_146072_bX());
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombieentity);
}
}
@@ -268,12 +270,16 @@
livingentity = (LivingEntity)p_70097_1_.func_76346_g();
}
@@ -19,7 +37,7 @@
for(int l = 0; l < 50; ++l) {
int i1 = i + MathHelper.func_76136_a(this.field_70146_Z, 7, 40) * MathHelper.func_76136_a(this.field_70146_Z, -1, 1);
int j1 = j + MathHelper.func_76136_a(this.field_70146_Z, 7, 40) * MathHelper.func_76136_a(this.field_70146_Z, -1, 1);
@@ -284,6 +288,7 @@
@@ -284,6 +290,7 @@
if (WorldEntitySpawner.func_209382_a(entityspawnplacementregistry$placementtype, this.field_70170_p, blockpos, entitytype) && EntitySpawnPlacementRegistry.func_223515_a(entitytype, serverworld, SpawnReason.REINFORCEMENT, blockpos, this.field_70170_p.field_73012_v)) {
zombieentity.func_70107_b((double)i1, (double)j1, (double)k1);
if (!this.field_70170_p.func_217358_a((double)i1, (double)j1, (double)k1, 7.0D) && this.field_70170_p.func_226668_i_(zombieentity) && this.field_70170_p.func_226669_j_(zombieentity) && !this.field_70170_p.func_72953_d(zombieentity.func_174813_aQ())) {
@@ -27,7 +45,24 @@
zombieentity.func_70624_b(livingentity);
zombieentity.func_213386_a(serverworld, this.field_70170_p.func_175649_E(zombieentity.func_233580_cy_()), SpawnReason.REINFORCEMENT, (ILivingEntityData)null, (CompoundNBT)null);
serverworld.func_242417_l(zombieentity);
@@ -448,7 +453,7 @@
@@ -369,7 +376,7 @@
public void func_241847_a(ServerWorld p_241847_1_, LivingEntity p_241847_2_) {
super.func_241847_a(p_241847_1_, p_241847_2_);
- if ((p_241847_1_.func_175659_aa() == Difficulty.NORMAL || p_241847_1_.func_175659_aa() == Difficulty.HARD) && p_241847_2_ instanceof VillagerEntity) {
+ if ((p_241847_1_.func_175659_aa() == Difficulty.NORMAL || p_241847_1_.func_175659_aa() == Difficulty.HARD) && p_241847_2_ instanceof VillagerEntity && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(p_241847_2_, EntityType.field_200727_aF, (timer) -> {})) {
if (p_241847_1_.func_175659_aa() != Difficulty.HARD && this.field_70146_Z.nextBoolean()) {
return;
}
@@ -381,6 +388,7 @@
zombievillagerentity.func_223727_a(villagerentity.func_223722_es().func_234058_a_(NBTDynamicOps.field_210820_a).getValue());
zombievillagerentity.func_213790_g(villagerentity.func_213706_dY().func_222199_a());
zombievillagerentity.func_213789_a(villagerentity.func_213708_dV());
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(p_241847_2_, zombievillagerentity);
if (!this.func_174814_R()) {
p_241847_1_.func_217378_a((PlayerEntity)null, 1026, this.func_233580_cy_(), 0);
}
@@ -448,7 +456,7 @@
}
public static boolean func_241399_a_(Random p_241399_0_) {
@@ -36,7 +71,7 @@
}
protected void func_207304_a(float p_207304_1_) {
@@ -468,7 +473,7 @@
@@ -468,7 +476,7 @@
}
protected void func_230291_eT_() {
@@ -0,0 +1,20 @@
--- a/net/minecraft/entity/monster/ZombieVillagerEntity.java
+++ b/net/minecraft/entity/monster/ZombieVillagerEntity.java
@@ -116,7 +116,7 @@
if (!this.field_70170_p.field_72995_K && this.func_70089_S() && this.func_82230_o()) {
int i = this.func_190735_dq();
this.field_82234_d -= i;
- if (this.field_82234_d <= 0) {
+ if (this.field_82234_d <= 0 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200756_av, (timer) -> this.field_82234_d = timer)) {
this.func_213791_a((ServerWorld)this.field_70170_p);
}
}
@@ -218,7 +218,7 @@
if (!this.func_174814_R()) {
p_213791_1_.func_217378_a((PlayerEntity)null, 1027, this.func_233580_cy_(), 0);
}
-
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, villagerentity);
}
private int func_190735_dq() {
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/monster/piglin/AbstractPiglinEntity.java
+++ b/net/minecraft/entity/monster/piglin/AbstractPiglinEntity.java
@@ -83,7 +83,7 @@
this.field_242334_c = 0;
}
- if (this.field_242334_c > 300) {
+ if (this.field_242334_c > 300 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233592_ba_, (timer) -> this.field_242334_c = timer)) {
this.func_241848_eP();
this.func_234416_a_((ServerWorld)this.field_70170_p);
}
@@ -98,6 +98,7 @@
ZombifiedPiglinEntity zombifiedpiglinentity = this.func_233656_b_(EntityType.field_233592_ba_, true);
if (zombifiedpiglinentity != null) {
zombifiedpiglinentity.func_195064_c(new EffectInstance(Effects.field_76431_k, 200, 0));
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombifiedpiglinentity);
}
}
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/passive/PigEntity.java
+++ b/net/minecraft/entity/passive/PigEntity.java
@@ -203,7 +203,7 @@
}
public void func_241841_a(ServerWorld p_241841_1_, LightningBoltEntity p_241841_2_) {
- if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL) {
+ if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233592_ba_, (timer) -> {})) {
ZombifiedPiglinEntity zombifiedpiglinentity = EntityType.field_233592_ba_.func_200721_a(p_241841_1_);
zombifiedpiglinentity.func_184201_a(EquipmentSlotType.MAINHAND, new ItemStack(Items.field_151010_B));
zombifiedpiglinentity.func_70012_b(this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), this.field_70177_z, this.field_70125_A);
@@ -215,6 +215,7 @@
}
zombifiedpiglinentity.func_110163_bv();
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombifiedpiglinentity);
p_241841_1_.func_217376_c(zombifiedpiglinentity);
this.func_70106_y();
} else {
@@ -43,9 +43,9 @@
+ }
+
+ @Override
+ public void remove(boolean keepData) {
+ super.remove(keepData);
+ if (!keepData && itemHandler != null) {
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ if (itemHandler != null) {
+ itemHandler.invalidate();
+ itemHandler = null;
+ }
@@ -26,7 +26,7 @@
+
if (!itemstack2.func_190926_b()) {
- boolean flag = itemstack2.func_77973_b() == Items.field_151134_bR && !EnchantedBookItem.func_92110_g(itemstack2).isEmpty();
+ if (!net.minecraftforge.common.ForgeHooks.onAnvilChange(this, itemstack, itemstack2, field_234642_c_, field_82857_m, j)) return;
+ if (!net.minecraftforge.common.ForgeHooks.onAnvilChange(this, itemstack, itemstack2, field_234642_c_, field_82857_m, j, this.field_234645_f_)) return;
+ flag = itemstack2.func_77973_b() == Items.field_151134_bR && !EnchantedBookItem.func_92110_g(itemstack2).isEmpty();
if (itemstack1.func_77984_f() && itemstack1.func_77973_b().func_82789_a(itemstack, itemstack2)) {
int l2 = Math.min(itemstack1.func_77952_i(), itemstack1.func_77958_k() / 4);
@@ -214,7 +214,7 @@
return list;
}
@@ -817,7 +841,7 @@
@@ -817,9 +841,10 @@
}
}
} else {
@@ -222,8 +222,11 @@
+ multimap = this.func_77973_b().getAttributeModifiers(p_111283_1_, this);
}
+ multimap = net.minecraftforge.common.ForgeHooks.getAttributeModifiers(this, p_111283_1_, multimap);
return multimap;
@@ -954,6 +978,35 @@
}
@@ -954,6 +979,35 @@
return this.func_77973_b().func_219971_r();
}
@@ -1,12 +0,0 @@
--- a/net/minecraft/network/play/server/SCommandListPacket.java
+++ b/net/minecraft/network/play/server/SCommandListPacket.java
@@ -119,6 +119,9 @@
String s = p_197695_0_.func_150789_c(32767);
ArgumentType<?> argumenttype = ArgumentTypes.func_197486_a(p_197695_0_);
if (argumenttype == null) {
+ if ((i & 16) != 0) { // FORGE: Flush unused suggestion data
+ p_197695_0_.func_192575_l();
+ }
return null;
} else {
RequiredArgumentBuilder<ISuggestionProvider, ?> requiredargumentbuilder = RequiredArgumentBuilder.argument(s, argumenttype);
@@ -0,0 +1,14 @@
--- a/net/minecraft/pathfinding/PathNavigator.java
+++ b/net/minecraft/pathfinding/PathNavigator.java
@@ -208,9 +208,9 @@
Vector3d vector3d = this.func_75502_i();
this.field_188561_o = this.field_75515_a.func_213311_cf() > 0.75F ? this.field_75515_a.func_213311_cf() / 2.0F : 0.75F - this.field_75515_a.func_213311_cf() / 2.0F;
Vector3i vector3i = this.field_75514_c.func_242948_g();
- double d0 = Math.abs(this.field_75515_a.func_226277_ct_() - ((double)vector3i.func_177958_n() + 0.5D));
+ double d0 = Math.abs(this.field_75515_a.func_226277_ct_() - ((double)vector3i.func_177958_n() + (this.field_75515_a.func_213311_cf() + 1) / 2D)); //Forge: Fix MC-94054
double d1 = Math.abs(this.field_75515_a.func_226278_cu_() - (double)vector3i.func_177956_o());
- double d2 = Math.abs(this.field_75515_a.func_226281_cx_() - ((double)vector3i.func_177952_p() + 0.5D));
+ double d2 = Math.abs(this.field_75515_a.func_226281_cx_() - ((double)vector3i.func_177952_p() + (this.field_75515_a.func_213311_cf() + 1) / 2D)); //Forge: Fix MC-94054
boolean flag = d0 < (double)this.field_188561_o && d2 < (double)this.field_188561_o && d1 < 1.0D;
if (flag || this.field_75515_a.func_233660_b_(this.field_75514_c.func_237225_h_().field_186287_m) && this.func_234112_b_(vector3d)) {
this.field_75514_c.func_75875_a();
@@ -55,7 +55,16 @@
SaveFormat saveformat = SaveFormat.func_237269_a_(file1.toPath());
SaveFormat.LevelSave saveformat$levelsave = saveformat.func_237274_c_(s);
MinecraftServer.func_240777_a_(saveformat$levelsave);
@@ -169,6 +176,7 @@
@@ -142,6 +149,8 @@
dimensiongeneratorsettings = optionset.has(optionspec3) ? serverproperties.field_241082_U_.func_236230_k_() : serverproperties.field_241082_U_;
}
+ // Forge: Deserialize the DimensionGeneratorSettings to ensure modded dims are loaded on first server load (see SimpleRegistryCodec#decode). Vanilla behaviour only loads from the server.properties and deserializes only after the 2nd server load.
+ dimensiongeneratorsettings = DimensionGeneratorSettings.field_236201_a_.encodeStart(net.minecraft.util.registry.WorldGenSettingsExport.func_240896_a_(NBTDynamicOps.field_210820_a, dynamicregistries$impl), dimensiongeneratorsettings).flatMap(nbt -> DimensionGeneratorSettings.field_236201_a_.parse(worldsettingsimport, nbt)).getOrThrow(false, errorMsg->{});
iserverconfiguration = new ServerWorldInfo(worldsettings, dimensiongeneratorsettings, Lifecycle.stable());
}
@@ -169,6 +178,7 @@
Thread thread = new Thread("Server Shutdown Thread") {
public void run() {
dedicatedserver.func_71263_m(true);
@@ -125,7 +125,7 @@
public ActionResultType func_219441_a(ServerPlayerEntity p_219441_1_, World p_219441_2_, ItemStack p_219441_3_, Hand p_219441_4_, BlockRayTraceResult p_219441_5_) {
BlockPos blockpos = p_219441_5_.func_216350_a();
BlockState blockstate = p_219441_2_.func_180495_p(blockpos);
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks.onRightClickBlock(p_219441_1_, p_219441_4_, blockpos, p_219441_5_.func_216354_b());
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks.onRightClickBlock(p_219441_1_, p_219441_4_, blockpos, p_219441_5_);
+ if (event.isCanceled()) return event.getCancellationResult();
if (this.field_73091_c == GameType.SPECTATOR) {
INamedContainerProvider inamedcontainerprovider = blockstate.func_215699_b(p_219441_2_, blockpos);
@@ -144,15 +144,17 @@
+ boolean flag1 = (p_219441_1_.func_226563_dT_() && flag) && !(p_219441_1_.func_184614_ca().doesSneakBypassUse(p_219441_2_, blockpos, p_219441_1_) && p_219441_1_.func_184592_cb().doesSneakBypassUse(p_219441_2_, blockpos, p_219441_1_));
ItemStack itemstack = p_219441_3_.func_77946_l();
- if (!flag1) {
+ if (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1) {
+ if (event.getUseBlock() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1)) {
ActionResultType actionresulttype = blockstate.func_227031_a_(p_219441_2_, p_219441_1_, p_219441_4_, p_219441_5_);
if (actionresulttype.func_226246_a_()) {
CriteriaTriggers.field_232607_M_.func_226695_a_(p_219441_1_, blockpos, itemstack);
@@ -312,7 +343,7 @@
@@ -311,8 +342,8 @@
}
}
if (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b())) {
- if (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b())) {
- ItemUseContext itemusecontext = new ItemUseContext(p_219441_1_, p_219441_4_, p_219441_5_);
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b()))) {
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
ActionResultType actionresulttype1;
if (this.func_73083_d()) {
@@ -106,7 +106,16 @@
if (flag2) {
serverplayerentity.field_71135_a.func_147359_a(new SPlaySoundEffectPacket(SoundEvents.field_232818_ms_, SoundCategory.BLOCKS, (double)blockpos.func_177958_n(), (double)blockpos.func_177956_o(), (double)blockpos.func_177952_p(), 1.0F, 1.0F));
}
@@ -786,7 +795,7 @@
@@ -769,6 +778,8 @@
this.field_192055_p.put(uuid, playeradvancements);
}
+ // Forge: don't overwrite active player with a fake one.
+ if (!(p_192054_1_ instanceof net.minecraftforge.common.util.FakePlayer))
playeradvancements.func_192739_a(p_192054_1_);
return playeradvancements;
}
@@ -786,7 +797,7 @@
}
public List<ServerPlayerEntity> func_181057_v() {
@@ -115,7 +124,7 @@
}
@Nullable
@@ -804,6 +813,7 @@
@@ -804,6 +815,7 @@
}
this.func_148540_a(new STagsListPacket(this.field_72400_f.func_244266_aF()));
@@ -123,7 +132,7 @@
SUpdateRecipesPacket supdaterecipespacket = new SUpdateRecipesPacket(this.field_72400_f.func_199529_aN().func_199510_b());
for(ServerPlayerEntity serverplayerentity : this.field_72404_b) {
@@ -816,4 +826,12 @@
@@ -816,4 +828,12 @@
public boolean func_206257_x() {
return this.field_72407_n;
}
@@ -118,8 +118,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
@@ -76,8 +76,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
@@ -51,8 +51,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ if (chestHandler != null)
+ chestHandler.invalidate();
+ }
@@ -1,6 +1,6 @@
--- a/net/minecraft/tileentity/LockableTileEntity.java
+++ b/net/minecraft/tileentity/LockableTileEntity.java
@@ -81,4 +81,22 @@
@@ -81,4 +81,21 @@
}
protected abstract Container func_213906_a(int p_213906_1_, PlayerInventory p_213906_2_);
@@ -10,7 +10,6 @@
+ return new net.minecraftforge.items.wrapper.InvWrapper(this);
+ }
+
+ @javax.annotation.Nullable
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, @javax.annotation.Nullable net.minecraft.util.Direction side) {
+ if (!this.field_145846_f && cap == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY )
+ return itemHandler.cast();
@@ -18,8 +17,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ itemHandler.invalidate();
+ }
}
@@ -49,7 +49,7 @@
this.field_145850_b.func_175666_e(this.field_174879_c, this.field_195045_e.func_177230_c());
}
}
@@ -133,6 +140,8 @@
@@ -133,8 +140,15 @@
public void func_145843_s() {
this.field_145846_f = true;
@@ -57,8 +57,15 @@
+ requestModelDataUpdate();
}
+ @Override
+ public void onChunkUnloaded() {
+ this.invalidateCaps();
+ }
+
public void func_145829_t() {
@@ -175,6 +184,13 @@
this.field_145846_f = false;
}
@@ -175,6 +189,13 @@
return this.field_200663_e;
}
@@ -0,0 +1,12 @@
--- a/net/minecraft/util/registry/SimpleRegistry.java
+++ b/net/minecraft/util/registry/SimpleRegistry.java
@@ -212,7 +212,8 @@
}
public static <T> Codec<SimpleRegistry<T>> func_241745_c_(RegistryKey<? extends Registry<T>> p_241745_0_, Lifecycle p_241745_1_, Codec<T> p_241745_2_) {
- return Codec.unboundedMap(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
+ // FORGE: Fix MC-197860
+ return new net.minecraftforge.common.LenientUnboundedMapCodec<>(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
SimpleRegistry<T> simpleregistry = new SimpleRegistry<>(p_241745_0_, p_241745_1_);
p_239656_2_.forEach((p_239653_2_, p_239653_3_) -> {
simpleregistry.func_218381_a(p_239653_2_, p_239653_3_, p_241745_1_);
@@ -9,3 +9,33 @@
private static final Supplier<Set<PointOfInterestType>> field_234168_y_ = Suppliers.memoize(() -> {
return Registry.field_218370_L.func_201756_e().map(VillagerProfession::func_221149_b).collect(Collectors.toSet());
});
@@ -36,7 +36,7 @@
}).filter((p_234173_0_) -> {
return p_234173_0_.func_177229_b(BedBlock.field_176472_a) == BedPart.HEAD;
}).collect(ImmutableSet.toImmutableSet());
- private static final Map<BlockState, PointOfInterestType> field_221073_u = Maps.newHashMap();
+ private static final Map<BlockState, PointOfInterestType> field_221073_u = net.minecraftforge.registries.GameData.getBlockStatePointOfInterestTypeMap();
public static final PointOfInterestType field_221054_b = func_226360_a_("unemployed", ImmutableSet.of(), 1, field_221071_s, 1);
public static final PointOfInterestType field_221055_c = func_226359_a_("armorer", func_221042_a(Blocks.field_222424_lM), 1, 1);
public static final PointOfInterestType field_221056_d = func_226359_a_("butcher", func_221042_a(Blocks.field_222423_lL), 1, 1);
@@ -112,16 +112,14 @@
}
private static PointOfInterestType func_221052_a(PointOfInterestType p_221052_0_) {
- p_221052_0_.field_221075_w.forEach((p_234169_1_) -> {
- PointOfInterestType pointofinteresttype = field_221073_u.put(p_234169_1_, p_221052_0_);
- if (pointofinteresttype != null) {
- throw (IllegalStateException)Util.func_229757_c_(new IllegalStateException(String.format("%s is defined in too many tags", p_234169_1_)));
- }
- });
return p_221052_0_;
}
public static Optional<PointOfInterestType> func_221047_b(BlockState p_221047_0_) {
return Optional.ofNullable(field_221073_u.get(p_221047_0_));
}
+
+ public ImmutableSet<BlockState> getBlockStates() {
+ return ImmutableSet.copyOf(this.field_221075_w);
+ }
}
@@ -17,6 +17,15 @@
chunkprimer.func_201637_h(blockpos);
}
}
@@ -167,7 +168,7 @@
Heightmap.func_222690_a(ichunk, enumset);
CompoundNBT compoundnbt4 = compoundnbt.func_74775_l("Structures");
ichunk.func_201612_a(func_235967_a_(p_222656_1_, compoundnbt4, p_222656_0_.func_72905_C()));
- ichunk.func_201606_b(func_227075_a_(p_222656_3_, compoundnbt4));
+ net.minecraftforge.common.ForgeHooks.fixNullStructureReferences(ichunk, func_227075_a_(p_222656_3_, compoundnbt4));
if (compoundnbt.func_74767_n("shouldSave")) {
ichunk.func_177427_f(true);
}
@@ -183,6 +184,7 @@
}
@@ -0,0 +1,20 @@
--- a/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
+++ b/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
@@ -192,7 +192,7 @@
String s3 = (String)p_242753_1_.get("level-type");
String s4 = Optional.ofNullable(s3).map((p_236217_0_) -> {
return p_236217_0_.toLowerCase(Locale.ROOT);
- }).orElse("default");
+ }).orElseGet(net.minecraftforge.common.ForgeHooks::getDefaultWorldType);
p_242753_1_.put("level-type", s4);
long i = (new Random()).nextLong();
if (!s1.isEmpty()) {
@@ -210,6 +210,8 @@
Registry<Biome> registry = p_242753_0_.func_243612_b(Registry.field_239720_u_);
Registry<DimensionSettings> registry1 = p_242753_0_.func_243612_b(Registry.field_243549_ar);
SimpleRegistry<Dimension> simpleregistry = DimensionType.func_242718_a(registry2, registry, registry1, i);
+ net.minecraftforge.common.world.ForgeWorldType type = net.minecraftforge.registries.ForgeRegistries.WORLD_TYPES.getValue(new net.minecraft.util.ResourceLocation(s4));
+ if (type != null) return type.createSettings(p_242753_0_, i, flag, false, s);
switch(s4) {
case "flat":
JsonObject jsonobject = !s.isEmpty() ? JSONUtils.func_212745_a(s) : new JsonObject();
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/server/ServerChunkProvider.java
+++ b/net/minecraft/world/server/ServerChunkProvider.java
@@ -353,7 +353,7 @@
if (optional1.isPresent()) {
Chunk chunk = optional1.get();
ChunkPos chunkpos = p_241099_7_.func_219277_h();
- if (!this.field_217237_a.func_219243_d(chunkpos)) {
+ if (!this.field_217237_a.func_219243_d(chunkpos) || field_217237_a.func_219246_e().shouldForceTicks(chunkpos.func_201841_a())) {
chunk.func_177415_c(chunk.func_177416_w() + j);
if (flag1 && (this.field_217246_l || this.field_217247_m) && this.field_73251_h.func_175723_af().func_177730_a(chunk.func_76632_l())) {
WorldEntitySpawner.func_234979_a_(this.field_73251_h, chunk, worldentityspawner$entitydensitymanager, this.field_217247_m, this.field_217246_l, flag2);
@@ -0,0 +1,49 @@
--- a/net/minecraft/world/server/Ticket.java
+++ b/net/minecraft/world/server/Ticket.java
@@ -9,9 +9,14 @@
private long field_219483_d;
protected Ticket(TicketType<T> p_i226095_1_, int p_i226095_2_, T p_i226095_3_) {
+ this(p_i226095_1_, p_i226095_2_, p_i226095_3_, false);
+ }
+
+ public Ticket(TicketType<T> p_i226095_1_, int p_i226095_2_, T p_i226095_3_, boolean forceTicks) {
this.field_219480_a = p_i226095_1_;
this.field_219481_b = p_i226095_2_;
this.field_219482_c = p_i226095_3_;
+ this.forceTicks = forceTicks;
}
public int compareTo(Ticket<?> p_compareTo_1_) {
@@ -31,16 +36,16 @@
return false;
} else {
Ticket<?> ticket = (Ticket)p_equals_1_;
- return this.field_219481_b == ticket.field_219481_b && Objects.equals(this.field_219480_a, ticket.field_219480_a) && Objects.equals(this.field_219482_c, ticket.field_219482_c);
+ return this.field_219481_b == ticket.field_219481_b && Objects.equals(this.field_219480_a, ticket.field_219480_a) && Objects.equals(this.field_219482_c, ticket.field_219482_c) && this.forceTicks == ticket.forceTicks;
}
}
public int hashCode() {
- return Objects.hash(this.field_219480_a, this.field_219481_b, this.field_219482_c);
+ return Objects.hash(this.field_219480_a, this.field_219481_b, this.field_219482_c, forceTicks);
}
public String toString() {
- return "Ticket[" + this.field_219480_a + " " + this.field_219481_b + " (" + this.field_219482_c + ")] at " + this.field_219483_d;
+ return "Ticket[" + this.field_219480_a + " " + this.field_219481_b + " (" + this.field_219482_c + ")] at " + this.field_219483_d + " force ticks " + forceTicks;
}
public TicketType<T> func_219479_a() {
@@ -59,4 +64,11 @@
long i = this.field_219480_a.func_223184_b();
return i != 0L && p_223182_1_ - this.field_219483_d > i;
}
+
+ /* ======================================== FORGE START =====================================*/
+ private final boolean forceTicks;
+
+ public boolean isForceTicks() {
+ return forceTicks;
+ }
}
@@ -0,0 +1,48 @@
--- a/net/minecraft/world/server/TicketManager.java
+++ b/net/minecraft/world/server/TicketManager.java
@@ -49,6 +49,8 @@
private final Executor field_219388_p;
private long field_219389_q;
+ private final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets = new Long2ObjectOpenHashMap<>();
+
protected TicketManager(Executor p_i50707_1_, Executor p_i50707_2_) {
ITaskExecutor<Runnable> itaskexecutor = ITaskExecutor.func_213140_a("player ticket throttler", p_i50707_2_::execute);
ChunkTaskPriorityQueueSorter chunktaskpriorityqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(itaskexecutor), p_i50707_1_, 4);
@@ -143,6 +145,10 @@
this.field_219378_f.func_215491_b(p_219347_1_, p_219347_3_.func_219477_b(), true);
}
+ if (p_219347_3_.isForceTicks()) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.computeIfAbsent(p_219347_1_, e -> SortedArraySet.func_226172_a_(4));
+ tickets.func_226175_a_(ticket);
+ }
}
private void func_219349_b(long p_219349_1_, Ticket<?> p_219349_3_) {
@@ -155,6 +161,13 @@
}
this.field_219378_f.func_215491_b(p_219349_1_, func_229844_a_(sortedarrayset), false);
+
+ if (p_219349_3_.isForceTicks()) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.get(p_219349_1_);
+ if (tickets != null) {
+ tickets.remove(p_219349_3_);
+ }
+ }
}
public <T> void func_219356_a(TicketType<T> p_219356_1_, ChunkPos p_219356_2_, int p_219356_3_, T p_219356_4_) {
@@ -242,6 +255,11 @@
return this.field_219384_l.func_225396_a();
}
+ public boolean shouldForceTicks(long chunkPos) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.get(chunkPos);
+ return tickets != null && !tickets.isEmpty();
+ }
+
class ChunkTicketTracker extends ChunkDistanceGraph {
public ChunkTicketTracker() {
super(ChunkManager.field_219249_a + 2, 16, 256);
@@ -29,8 +29,6 @@ import java.util.List;
*/
public class EarlyLoadingException extends RuntimeException {
public static class ExceptionData {
private final IModInfo modInfo;
private final String i18message;
private final Object[] args;
@@ -34,6 +34,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.forgespi.Environment;
@@ -53,6 +54,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -183,11 +185,12 @@ public class FMLLoader
naming = commonLaunchHandler.getNaming();
dist = commonLaunchHandler.getDist();
production = commonLaunchHandler.isProduction();
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData());
mcVersion = (String) arguments.get("mcVersion");
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData(), mcVersion);
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Early Loading!"));
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
mcVersion = (String) arguments.get("mcVersion");
mcpVersion = (String) arguments.get("mcpVersion");
forgeVersion = (String) arguments.get("forgeVersion");
forgeGroup = (String) arguments.get("forgeGroup");
@@ -214,7 +217,7 @@ public class FMLLoader
loadingModList = backgroundScanHandler.getLoadingModList();
commonLaunchHandler.addLibraries(backgroundScanHandler.getModFiles().getOrDefault(IModFile.Type.LIBRARY, Collections.emptyList()));
progressWindowTick.run();
return backgroundScanHandler.getModFiles();
return loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.groupingBy(ModFile::getType));
}
public static ICoreModProvider getCoreModProvider() {
@@ -170,7 +170,7 @@ public class LanguageLoadingProvider
LOGGER.error("Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
throw new EarlyLoadingException("Missing language "+modLoader, null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, "null")));
}
if (!modLoaderVersion.containsVersion(mlw.getVersion())) {
if (!VersionSupportMatrix.testVersionSupportMatrix(modLoaderVersion, modLoader, "languageloader", (llid, range) -> range.containsVersion(mlw.getVersion()))) {
LOGGER.error("Missing language {} version {} wanted by {}, found {}", modLoader, modLoaderVersion, languageFileName, mlw.getVersion());
throw new EarlyLoadingException("Missing language "+ modLoader + " matching range "+modLoaderVersion + " found "+mlw.getVersion(), null, Collections.singletonList(new EarlyLoadingException.ExceptionData("fml.language.missingversion", modLoader, modLoaderVersion, languageFileName, mlw.getVersion())));
}
@@ -36,17 +36,11 @@ import org.apache.logging.log4j.util.StringBuilderFormattable;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
@@ -56,6 +50,7 @@ public class ModSorter
private List<ModFile> modFiles;
private List<ModInfo> sortedList;
private Map<String, ModInfo> modIdNameLookup;
private List<ModFile> forgeAndMC;
private ModSorter(final List<ModFile> modFiles)
{
@@ -65,21 +60,41 @@ public class ModSorter
public static LoadingModList sort(List<ModFile> mods)
{
final ModSorter ms = new ModSorter(mods);
EarlyLoadingException earlyLoadingException = null;
try {
ms.findLanguages();
ms.buildUniqueList();
ms.verifyDependencyVersions();
ms.sort();
} catch (EarlyLoadingException ele) {
earlyLoadingException = ele;
ms.sortedList = Collections.emptyList();
} catch (EarlyLoadingException e) {
// We cannot build any list with duped mods. We have to abort immediately and report it
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(Collectors.toList()), e);
}
// try and locate languages and validate dependencies
List<EarlyLoadingException.ExceptionData> missingLangs = ms.findLanguages();
List<EarlyLoadingException.ExceptionData> missingDeps = ms.verifyDependencyVersions();
final List<ExceptionData> failedList = Stream.concat(missingLangs.stream(), missingDeps.stream()).collect(Collectors.toList());
// if we miss one or the other, we abort now
if (!failedList.isEmpty()) {
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(Collectors.toList()), new EarlyLoadingException("failure to validate mod list", null, failedList));
} else {
// Otherwise, lets try and sort the modlist and proceed
EarlyLoadingException earlyLoadingException = null;
try {
ms.sort();
} catch (EarlyLoadingException e) {
earlyLoadingException = e;
}
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
}
return LoadingModList.of(ms.modFiles, ms.sortedList, earlyLoadingException);
}
private void findLanguages() {
modFiles.forEach(ModFile::identifyLanguage);
private List<EarlyLoadingException.ExceptionData> findLanguages() {
List<EarlyLoadingException.ExceptionData> errorData = new ArrayList<>();
modFiles.forEach(modFile -> {
try {
modFile.identifyLanguage();
} catch (EarlyLoadingException e) {
errorData.addAll(e.getAllData());
}
});
return errorData;
}
@SuppressWarnings("UnstableApiUsage")
@@ -167,6 +182,11 @@ public class ModSorter
.stream()
.collect(Collectors.groupingBy(mf -> mf.getModInfos().get(0).getModId()));
// Capture forge and MC here, so we can keep them for later
forgeAndMC = new ArrayList<>();
forgeAndMC.add((ModFile)modFilesByFirstId.get("minecraft").get(0));
forgeAndMC.add((ModFile)modFilesByFirstId.get("forge").get(0));
// Select the newest by artifact version sorting of non-unique files thus identified
this.modFiles = modFilesByFirstId.entrySet().stream()
.map(this::selectNewestModInfo)
@@ -213,7 +233,7 @@ public class ModSorter
return new AbstractMap.SimpleImmutableEntry<>(fullList.getKey(), modInfoList.get(0));
}
private void verifyDependencyVersions()
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
{
final Map<String, ArtifactVersion> modVersions = modFiles
.stream()
@@ -237,24 +257,24 @@ public class ModSorter
LOGGER.debug(LOADING, "Found {} mandatory requirements", mandatoryModVersions.size());
final Set<IModInfo.ModVersion> missingVersions = mandatoryModVersions
.stream()
.filter(mv->this.modVersionMatches(mv, modVersions))
.filter(mv->this.modVersionNotContained(mv, modVersions))
.collect(Collectors.toSet());
LOGGER.debug(LOADING, "Found {} mandatory mod requirements missing", missingVersions.size());
if (!missingVersions.isEmpty()) {
final List<EarlyLoadingException.ExceptionData> exceptionData = missingVersions
return missingVersions
.stream()
.map(mv -> new EarlyLoadingException.ExceptionData("fml.modloading.missingdependency", mv.getOwner(),
.map(mv -> new ExceptionData("fml.modloading.missingdependency", mv.getOwner(),
mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
modVersions.getOrDefault(mv.getModId(), new DefaultArtifactVersion("null"))))
.collect(Collectors.toList());
throw new EarlyLoadingException("Missing mods", null, exceptionData);
}
return Collections.emptyList();
}
private boolean modVersionMatches(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
private boolean modVersionNotContained(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
{
return !(modVersions.containsKey(mv.getModId()) &&
(mv.getVersionRange().containsVersion(modVersions.get(mv.getModId())) || modVersions.get(mv.getModId()).toString().equals("NONE")));
return !(VersionSupportMatrix.testVersionSupportMatrix(mv.getVersionRange(), mv.getModId(), "mod", (modId, range) -> modVersions.containsKey(modId) &&
(range.containsVersion(modVersions.get(modId)) || modVersions.get(modId).toString().equals("NONE"))));
}
}
@@ -42,12 +42,12 @@ public class StringUtils
}
public static URL toURL(final String string) {
try
{
return new URL(string);
}
catch (MalformedURLException e)
{
if (string == null || string.trim().isEmpty() || string.contains("myurl.me") || string.contains("example.invalid"))
return null;
try {
return new URL(string); }
catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@@ -0,0 +1,55 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.loading;
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiPredicate;
public class VersionSupportMatrix {
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
static {
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.mcVersion);
if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
// 1.16.4 is Compatible with 1.16.3
add("languageloader.javafml", "34");
add("mod.minecraft", "1.16.3");
add("mod.forge", "34.1.42");
// 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
add("languageloader.javafml", "35");
add("mod.minecraft", "1.16.4");
add("mod.forge", "35.1.37");
}
}
private static void add(String key, String value) {
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
}
public static <T> boolean testVersionSupportMatrix(VersionRange declaredRange, String lookupId, String type, BiPredicate<String, VersionRange> standardLookup) {
if (standardLookup.test(lookupId, declaredRange)) return true;
List<ArtifactVersion> custom = overrideVersions.get(type +"." +lookupId);
return custom == null ? false : custom.stream().anyMatch(declaredRange::containsVersion);
}
}
@@ -22,9 +22,7 @@ package net.minecraftforge.fml.loading.progress;
import com.google.common.io.ByteStreams;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
@@ -40,10 +38,13 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.opengl.GL11.*;
@@ -58,8 +59,10 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
private Thread renderThread = new Thread(this::renderThreadFunc);
private boolean running = true;
private GLFWFramebufferSizeCallback framebufferSizeCallback;
private int[] fbSize;
private void initWindow() {
private void initWindow(@Nullable String mcVersion) {
GLFWErrorCallback.createPrint(System.err).set();
long glfwInitBegin = System.nanoTime();
@@ -81,10 +84,21 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
if (mcVersion != null)
{
// this emulates what we would get without early progress window
// as vanilla never sets these, so GLFW uses the first window title
// set them explicitly to avoid it using "FML early loading progress" as the class
String vanillaWindowTitle = "Minecraft* " + mcVersion;
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
}
window = glfwCreateWindow(screenWidth, screenHeight, "FML early loading progress", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window"); // ignore it and make the GUI optional?
}
framebufferSizeCallback = GLFWFramebufferSizeCallback.create(this::fbResize);
try (MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1);
@@ -126,6 +140,11 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
System.err.println("Failed to load forge logo");
}
}
int[] w = new int[1];
int[] h = new int[1];
glfwGetFramebufferSize(window, w, h);
fbSize = new int[] {w[0], h[0]};
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwShowWindow(window);
glfwPollEvents();
}
@@ -220,6 +239,11 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glVertex2f(screenWidth, 0);
glEnd();
}
private void fbResize(long window, int width, int height) {
if (window == this.window && width != 0 && height != 0) {
fbSize = new int[] {width, height};
}
}
private void renderMessages() {
List<Pair<Integer, StartupMessageManager.Message>> messages = StartupMessageManager.getMessages();
@@ -233,6 +257,12 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
renderMemoryInfo();
}
@Override
public void updateFBSize(final IntConsumer width, final IntConsumer height) {
width.accept(this.fbSize[0]);
height.accept(this.fbSize[1]);
}
private static final float[] memorycolour = new float[] { 0.0f, 0.0f, 0.0f};
private void renderMemoryInfo() {
@@ -283,8 +313,8 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
}
@Override
public Runnable start() {
initWindow();
public Runnable start(@Nullable String mcVersion) {
initWindow(mcVersion);
renderThread.setDaemon(true); // Don't hang the game if it terminates before handoff (i.e. datagen)
renderThread.start();
return org.lwjgl.glfw.GLFW::glfwPollEvents;
@@ -309,6 +339,8 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glfwSwapInterval(0);
glfwSwapBuffers(window);
glfwSwapInterval(1);
final GLFWFramebufferSizeCallback previous = glfwSetFramebufferSizeCallback(window, null);
previous.free();
return window;
}
}
@@ -21,27 +21,38 @@ package net.minecraftforge.fml.loading.progress;
import net.minecraftforge.api.distmarker.Dist;
import java.util.Locale;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import javax.annotation.Nullable;
public enum EarlyProgressVisualization {
INSTANCE;
private Visualization visualization;
public Runnable accept(final Dist dist, final boolean isData) {
public Runnable accept(Dist dist, boolean isData)
{
return accept(dist, isData, null);
}
public Runnable accept(final Dist dist, final boolean isData, @Nullable String mcVersion) {
visualization = !isData && dist.isClient() && Boolean.parseBoolean(System.getProperty("fml.earlyprogresswindow", "true")) ? new ClientVisualization() : new NoVisualization();
return visualization.start();
return visualization.start(mcVersion);
}
public long handOffWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, final LongSupplier monitor) {
return visualization.handOffWindow(width, height, title, monitor);
}
public void updateFBSize(IntConsumer width, IntConsumer height) {
visualization.updateFBSize(width, height);
}
interface Visualization {
Runnable start();
Runnable start(@Nullable String mcVersion);
default long handOffWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, LongSupplier monitorSupplier) {
return new LongSupplier() {
@@ -51,11 +62,14 @@ public enum EarlyProgressVisualization {
}
}.getAsLong();
}
default void updateFBSize(IntConsumer width, IntConsumer height) {
}
}
private static class NoVisualization implements Visualization {
@Override
public Runnable start() {
public Runnable start(@Nullable String mcVersion) {
return () -> {};
}
}
@@ -24,15 +24,12 @@ import com.google.common.base.CharMatcher;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class StartupMessageManager {
private static final EnumMap<MessageType, List<Message>> messages = new EnumMap<>(MessageType.class);
static {
Arrays.stream(MessageType.values()).forEach(mt->messages.computeIfAbsent(mt, k->new CopyOnWriteArrayList<>()));
}
private static volatile EnumMap<MessageType, List<Message>> messages = new EnumMap<>(MessageType.class);
public static List<Pair<Integer,Message>> getMessages() {
final long ts = System.nanoTime();
@@ -88,22 +85,42 @@ public class StartupMessageManager {
}
}
private synchronized static void addMessage(MessageType type, String message, int maxSize)
{
EnumMap<MessageType, List<Message>> newMessages = new EnumMap<>(messages);
newMessages.compute(type, (key, existingList) -> {
List<Message> newList = new ArrayList<>();
if (existingList != null)
{
if (maxSize < 0)
{
newList.addAll(existingList);
}
else
{
newList.addAll(existingList.subList(0, Math.min(existingList.size(), maxSize)));
}
}
newList.add(new Message(message, type));
return newList;
});
messages = newMessages;
}
public static void addModMessage(final String message) {
final String safeMessage = Ascii.truncate(CharMatcher.ascii().retainFrom(message),80,"~");
final List<Message> messages = StartupMessageManager.messages.get(MessageType.MOD);
messages.subList(0, Math.max(0, messages.size() - 20)).clear();
messages.add(new Message(safeMessage, MessageType.MOD));
addMessage(MessageType.MOD, safeMessage, 20);
}
public static Optional<Consumer<String>> modLoaderConsumer() {
return Optional.of(s-> messages.get(MessageType.ML).add(new Message(s, MessageType.ML)));
return Optional.of(s-> addMessage(MessageType.ML, s, -1));
}
public static Optional<Consumer<String>> locatorConsumer() {
return Optional.of(s -> messages.get(MessageType.LOC).add(new Message(s, MessageType.LOC)));
return Optional.of(s -> addMessage(MessageType.LOC, s, -1));
}
public static Optional<Consumer<String>> mcLoaderConsumer() {
return Optional.of(s-> messages.get(MessageType.MC).add(new Message(s, MessageType.MC)));
return Optional.of(s-> addMessage(MessageType.MC, s, -1));
}
}
+3 -1
View File
@@ -41,10 +41,12 @@ c4d268471ee793597917c966d1aaed29e438d366 assets/data_gen_test/models/block/oak_t
2abb8b11c91441badd91b7c52f5f8ba3226c92de assets/data_gen_test/models/block/oak_trapdoor_open.json
560d419e3d542cb0509bca078988308d387c15a9 assets/data_gen_test/models/block/oak_trapdoor_top.json
556f0d997250661e0401fba13a4afd1bb0627dcc assets/data_gen_test/models/block/stone.json
556f0d997250661e0401fba13a4afd1bb0627dcc assets/data_gen_test/models/block/test_block.json
db2cd929128c8a6e8e0b02437f90ad8d24238206 assets/data_gen_test/models/block/torch.json
81ce9ac0a7f4ed7a94d5496b918987a6f5a24988 assets/data_gen_test/models/block/wall_torch.json
6b40df2a47c13cd00e295244b6cf74462938359d assets/data_gen_test/models/item/fishing_rod.json
7fecdc30a209fca790df79b973c30b9e84415e0b assets/data_gen_test/models/item/fishing_rod_cast.json
098d8b38409fff6cc14a4e56355bedb1fc5931d1 assets/data_gen_test/models/item/test_block.json
b029993275f16569b0edf093362f55df6ea6f9be assets/data_gen_test/models/item/test_block_model.json
726e1884e53151492ca05bd752c67031603570f6 assets/data_gen_test/models/item/test_generated_model.json
1767c874758bd7c3235db446b6219e6e1edd25b4 assets/minecraft/blockstates/acacia_door.json
@@ -79,7 +81,7 @@ cf16f861eaf5815238c2278eb48bde0688cb73b7 assets/scaffolding_test/blockstates/sca
66442c8000af9af4ba36109b3c9d09d9ffd57277 data/data_gen_test/advancements/recipes/conditional2.json
ed4cbf1a3a2f5d8969f6346fdc9acdbe81d0c919 data/data_gen_test/recipes/conditional.json
ca9827bff0a49957e01cf3887ef5131ad8710320 data/data_gen_test/recipes/conditional2.json
40208299608468b044f64317995f9182ec219d90 data/data_gen_test/tags/blocks/test.json
8831e79c8d15b1bc00eb29d354bb22b64d9ddcdd data/data_gen_test/tags/blocks/test.json
d65c425e740dc833f29d16606a1171825876be0d data/data_gen_test/tags/blocks/thing/one.json
1f70ed4ddc878bada5e43d3c44a34157806beda8 data/data_gen_test/tags/blocks/thing/three.json
2c648bca262caaa826ddbbde796d35bb2ee5f03a data/data_gen_test/tags/blocks/thing/two.json
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "minecraft:block/stone"
}
}
@@ -0,0 +1,3 @@
{
"parent": "data_gen_test:block/test_block"
}
@@ -3,6 +3,7 @@
"values": [
"minecraft:diamond_block",
"#minecraft:stone_bricks",
"#forge:cobblestone",
{
"id": "chisel:marble/raw",
"required": false
@@ -22,6 +22,7 @@ package net.minecraftforge.client;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHelper;
@@ -30,6 +31,7 @@ import net.minecraft.client.audio.SoundEngine;
import net.minecraft.client.gui.AbstractGui;
import net.minecraft.client.gui.ClientBossInfo;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.client.gui.screen.MainMenuScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.play.NetworkPlayerInfo;
@@ -76,6 +78,8 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.GameType;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.World;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.client.event.*;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.model.ModelLoader;
@@ -100,12 +104,15 @@ import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
import org.lwjgl.opengl.GL13;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Stream;
@@ -769,4 +776,42 @@ public class ForgeHooksClient
}
return !(squareDistance > 4096.0f);
}
public static void renderPistonMovedBlocks(BlockPos pos, BlockState state, MatrixStack stack, IRenderTypeBuffer buffer, World world, boolean checkSides, int combinedOverlay, BlockRendererDispatcher blockRenderer) {
RenderType.getBlockRenderTypes().stream()
.filter(t -> RenderTypeLookup.canRenderInLayer(state, t))
.forEach(rendertype ->
{
rendertype = rendertype == RenderType.getTranslucent() ? RenderType.getTranslucentMovingBlock() : rendertype;
setRenderLayer(rendertype);
IVertexBuilder ivertexbuilder = buffer.getBuffer(rendertype);
blockRenderer.getBlockModelRenderer().renderModel(world, blockRenderer.getModelForState(state), state, pos, stack, ivertexbuilder, checkSides, new Random(), state.getPositionRandom(pos), combinedOverlay);
});
setRenderLayer(null);
}
public static void registerForgeWorldTypeScreens()
{
ForgeWorldTypeScreens.registerTypes();
}
public static BiomeGeneratorTypeScreens.IFactory getBiomeGeneratorTypeScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return ForgeWorldTypeScreens.getGeneratorScreenFactory(generator, biomegeneratortypescreens$ifactory);
}
public static boolean hasBiomeGeneratorSettingsOptionsScreen(Optional<BiomeGeneratorTypeScreens> generator)
{
return getBiomeGeneratorTypeScreenFactory(generator, null) != null;
}
public static Optional<BiomeGeneratorTypeScreens> getWorldTypeFromGenerator(DimensionGeneratorSettings dimensionGeneratorSettings)
{
return BiomeGeneratorTypeScreens.func_239079_a_(dimensionGeneratorSettings);
}
public static Optional<BiomeGeneratorTypeScreens> getDefaultWorldType()
{
return Optional.of(ForgeWorldTypeScreens.getDefaultGenerator());
}
}
@@ -0,0 +1,118 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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;
import com.google.common.collect.Maps;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Optional;
public class ForgeWorldTypeScreens
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens> GENERATORS = Maps.newHashMap();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens.IFactory> GENERATOR_SCREEN_FACTORIES = Maps.newHashMap();
public static synchronized void registerFactory(ForgeWorldType type, BiomeGeneratorTypeScreens.IFactory factory)
{
if (GENERATOR_SCREEN_FACTORIES.containsKey(type))
throw new IllegalStateException("Factory has already been registered for: " + type);
GENERATOR_SCREEN_FACTORIES.put(type, factory);
}
static BiomeGeneratorTypeScreens getDefaultGenerator()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def == null)
{
return BiomeGeneratorTypeScreens.field_239066_a_;
}
BiomeGeneratorTypeScreens gen = GENERATORS.get(def);
if (gen == null)
{
LOGGER.error("The default world type '{}' has not been added to the GUI. Was it registered too late?", def.getRegistryName());
return BiomeGeneratorTypeScreens.field_239066_a_;
}
return gen;
}
static BiomeGeneratorTypeScreens.IFactory getGeneratorScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return generator.filter(gen -> gen instanceof GeneratorType)
.map(type -> GENERATOR_SCREEN_FACTORIES.get(((GeneratorType)type).getWorldType()))
.orElse(biomegeneratortypescreens$ifactory);
}
static void registerTypes()
{
ForgeRegistries.WORLD_TYPES.forEach(wt -> {
GeneratorType gen = new GeneratorType(wt);
GENERATORS.put(wt, gen);
BiomeGeneratorTypeScreens.registerGenerator(gen);
});
}
private static class GeneratorType extends BiomeGeneratorTypeScreens
{
private final ForgeWorldType worldType;
public GeneratorType(ForgeWorldType wt)
{
super(wt.getDisplayName());
worldType = wt;
}
public ForgeWorldType getWorldType()
{
return worldType;
}
@Nonnull
@Override
public DimensionGeneratorSettings func_241220_a_(@Nonnull DynamicRegistries.Impl dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest)
{
return worldType.createSettings(dynamicRegistries, seed, generateStructures, bonusChest, "");
}
@Nonnull
@Override
protected ChunkGenerator func_241869_a(@Nonnull Registry<Biome> p_241869_1_, @Nonnull Registry<DimensionSettings> p_241869_2_, long p_241869_3_)
{
return worldType.createChunkGenerator(p_241869_1_, p_241869_2_, p_241869_3_, "");
}
}
}
@@ -0,0 +1,34 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.world.ClientWorld;
/**
* Call {@link net.minecraft.client.world.DimensionRenderInfo#setWeatherParticleRenderHandler(net.minecraftforge.client.IWeatherParticleRenderHandler)}, obtained from a {@link ClientWorld} with an implementation of this to override all weather particle rendering with your own.
* This handles ground particles that can be seen when it's raining (splash/smoke particles).
* This also includes playing rain sounds.
*/
@FunctionalInterface
public interface IWeatherParticleRenderHandler {
void render(int ticks, ClientWorld world, Minecraft mc, ActiveRenderInfo activeRenderInfoIn);
}
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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 net.minecraft.client.network.play.NetworkPlayerInfo;
@@ -112,7 +112,7 @@ public class ForgeIngameGui extends IngameGui
this.scaledHeight = this.mc.getMainWindow().getScaledHeight();
eventParent = new RenderGameOverlayEvent(mStack, partialTicks, this.mc.getMainWindow());
renderHealthMount = mc.player.getRidingEntity() instanceof LivingEntity;
renderFood = mc.player.getRidingEntity() == null;
renderFood = !renderHealthMount;
renderJumpBar = mc.player.isRidingHorse();
right_height = 39;
@@ -95,7 +95,7 @@ public abstract class BlockStateProvider implements IDataProvider {
this.blockModels = new BlockModelProvider(gen, modid, exFileHelper) {
@Override protected void registerModels() {}
};
this.itemModels = new ItemModelProvider(gen, modid, exFileHelper) {
this.itemModels = new ItemModelProvider(gen, modid, this.blockModels.existingFileHelper) {
@Override protected void registerModels() {}
};
}
@@ -255,7 +255,7 @@ public abstract class BlockStateProvider implements IDataProvider {
}
public void horizontalFaceBlock(Block block, Function<BlockState, ModelFile> modelFunc) {
horizontalBlock(block, modelFunc, DEFAULT_ANGLE_OFFSET);
horizontalFaceBlock(block, modelFunc, DEFAULT_ANGLE_OFFSET);
}
public void horizontalFaceBlock(Block block, Function<BlockState, ModelFile> modelFunc, int angleOffset) {
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators;
import com.google.common.base.Preconditions;
@@ -19,7 +19,11 @@
package net.minecraftforge.client.model.generators;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -33,20 +37,19 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraft.client.renderer.model.BlockFaceUV;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.model.BlockPart;
import net.minecraft.client.renderer.model.BlockPartFace;
import net.minecraft.client.renderer.model.BlockPartRotation;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.model.ItemTransformVec3f;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.texture.MissingTextureSprite;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
/**
* General purpose model builder, contains all the commonalities between item
@@ -146,7 +149,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
public T texture(String key, ResourceLocation texture) {
Preconditions.checkNotNull(key, "Key must not be null");
Preconditions.checkNotNull(texture, "Texture must not be null");
Preconditions.checkArgument(existingFileHelper.exists(texture, ResourcePackType.CLIENT_RESOURCES, ".png", "textures"),
Preconditions.checkArgument(existingFileHelper.exists(texture, ModelProvider.TEXTURE),
"Texture %s does not exist in any known resource pack", texture);
this.textures.put(key, texture.toString());
return self();
@@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import com.google.common.base.Preconditions;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
@@ -78,9 +77,9 @@ public abstract class ModelFile {
@Override
protected boolean exists() {
if (getUncheckedLocation().getPath().contains("."))
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, "", "models");
return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL_WITH_EXTENSION);
else
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, ".json", "models");
return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL);
}
}
}
@@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
@@ -35,61 +34,20 @@ import com.google.gson.GsonBuilder;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.IResource;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.common.data.ExistingFileHelper.ResourceType;
public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataProvider {
private class ExistingFileHelperIncludingGenerated extends ExistingFileHelper {
private final ExistingFileHelper delegate;
public ExistingFileHelperIncludingGenerated(ExistingFileHelper delegate) {
super(Collections.emptyList(), true);
this.delegate = delegate;
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix)
{
if (pathPrefix.equals("models") && pathSuffix.equals(".json"))
{
if (generatedModels.containsKey(loc))
{
return true;
}
}
return delegate.exists(loc, type, pathSuffix, pathPrefix);
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type) {
if (loc.getPath().startsWith("models/") && loc.getPath().endsWith(".json"))
{
ResourceLocation modelLoc = new ResourceLocation(
loc.getNamespace(),
loc.getPath().substring("models/".length(), loc.getPath().length() - ".json".length())
);
if (generatedModels.containsKey(modelLoc))
{
return true;
}
}
return delegate.exists(loc, type);
}
@Override
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException
{
return delegate.getResource(loc, type);
}
}
public static final String BLOCK_FOLDER = "block";
public static final String ITEM_FOLDER = "item";
protected static final ResourceType TEXTURE = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".png", "textures");
protected static final ResourceType MODEL = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".json", "models");
protected static final ResourceType MODEL_WITH_EXTENSION = new ResourceType(ResourcePackType.CLIENT_RESOURCES, "", "models");
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
protected final DataGenerator generator;
protected final String modid;
@@ -112,7 +70,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
Preconditions.checkNotNull(factory);
this.factory = factory;
Preconditions.checkNotNull(existingFileHelper);
this.existingFileHelper = new ExistingFileHelperIncludingGenerated(existingFileHelper);
this.existingFileHelper = existingFileHelper;
}
public ModelProvider(DataGenerator generator, String modid, String folder, BiFunction<ResourceLocation, ExistingFileHelper, T> builderFromModId, ExistingFileHelper existingFileHelper) {
@@ -122,6 +80,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
public T getBuilder(String path) {
Preconditions.checkNotNull(path, "Path must not be null");
ResourceLocation outputLoc = extendWithFolder(path.contains(":") ? new ResourceLocation(path) : new ResourceLocation(modid, path));
this.existingFileHelper.trackGenerated(outputLoc, MODEL);
return generatedModels.computeIfAbsent(outputLoc, factory);
}
@@ -26,8 +26,8 @@ import java.util.List;
import java.util.Map.Entry;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -74,7 +74,7 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
public class PartBuilder {
public BlockStateProvider.ConfiguredModelList models;
public boolean useOr;
public final Multimap<Property<?>, Comparable<?>> conditions = HashMultimap.create();
public final Multimap<Property<?>, Comparable<?>> conditions = MultimapBuilder.linkedHashKeys().arrayListValues().build();
PartBuilder(BlockStateProvider.ConfiguredModelList models) {
this.models = models;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.model.generators.loaders;
import com.google.common.base.Preconditions;
@@ -108,10 +108,33 @@ public class ForgeConfig
.comment("Fix advancement loading to use a proper topological sort. This may have visibility side-effects and can thus be turned off if needed for data-pack compatibility.")
.translation("forge.configgui.fixAdvancementLoading")
.define("fixAdvancementLoading", true);
builder.pop();
}
}
/**
* General configuration that doesn't need to be synchronized but needs to be available before server startup
*/
public static class Common {
public final ForgeConfigSpec.ConfigValue<? extends String> defaultWorldType;
Common(ForgeConfigSpec.Builder builder)
{
builder.comment("General configuration settings")
.push("general");
defaultWorldType = builder
.comment("Defines a default world type to use. The vanilla default world type is represented by 'default'.",
"The modded world types are registry names which should include the registry namespace, such as 'examplemod:example_world_type'.")
.translation("forge.configgui.defaultWorldType")
.define("defaultWorldType", "default");
builder.pop();
}
}
/**
* Client specific configuration - only loaded clientside from forge-client.toml
*/
@@ -196,6 +219,15 @@ public class ForgeConfig
}
static final ForgeConfigSpec commonSpec;
public static final Common COMMON;
static {
final Pair<Common, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Common::new);
commonSpec = specPair.getRight();
COMMON = specPair.getLeft();
}
static final ForgeConfigSpec serverSpec;
public static final Server SERVER;
static {
@@ -33,6 +33,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
@@ -43,10 +44,15 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.advancements.Advancement;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.fluid.*;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTableManager;
@@ -91,6 +97,8 @@ import net.minecraft.potion.PotionUtils;
import net.minecraft.stats.Stats;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.*;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.spawner.AbstractSpawner;
import net.minecraft.tileentity.FurnaceTileEntity;
import net.minecraft.tileentity.TileEntity;
@@ -116,10 +124,12 @@ import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifierManager;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.common.world.MobSpawnInfoBuilder;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ItemAttributeModifierEvent;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.EntityTravelToDimensionEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
@@ -177,7 +187,7 @@ public class ForgeHooks
{
//state = state.getActualState(world, pos);
if (!state.getRequiresTool())
return true;
return ForgeEventFactory.doPlayerHarvestCheck(player, state, true);
ItemStack stack = player.getHeldItemMainhand();
ToolType tool = state.getHarvestTool();
@@ -664,7 +674,8 @@ public class ForgeHooks
world.markAndNotifyBlock(snap.getPos(), world.getChunkAt(snap.getPos()), oldBlock, newBlock, updateFlag, 512);
}
player.addStat(Stats.ITEM_USED.get(item));
if (player != null)
player.addStat(Stats.ITEM_USED.get(item));
}
}
world.capturedBlockSnapshots.clear();
@@ -672,9 +683,15 @@ public class ForgeHooks
return ret;
}
@Deprecated // TODO: Remove 1.17 - Use player-contextual version below.
public static boolean onAnvilChange(RepairContainer container, @Nonnull ItemStack left, @Nonnull ItemStack right, IInventory outputSlot, String name, int baseCost)
{
AnvilUpdateEvent e = new AnvilUpdateEvent(left, right, name, baseCost);
return onAnvilChange(container, left, right, outputSlot, name, baseCost, null);
}
public static boolean onAnvilChange(RepairContainer container, @Nonnull ItemStack left, @Nonnull ItemStack right, IInventory outputSlot, String name, int baseCost, PlayerEntity player)
{
AnvilUpdateEvent e = new AnvilUpdateEvent(left, right, name, baseCost, player);
if (MinecraftForge.EVENT_BUS.post(e)) return false;
if (e.getOutput().isEmpty()) return true;
@@ -772,6 +789,7 @@ public class ForgeHooks
return evt;
}
@Deprecated //Use RayTraceResult version. TODO: Remove 1.17
public static PlayerInteractEvent.RightClickBlock onRightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, Direction face)
{
PlayerInteractEvent.RightClickBlock evt = new PlayerInteractEvent.RightClickBlock(player, hand, pos, face);
@@ -779,6 +797,13 @@ public class ForgeHooks
return evt;
}
public static PlayerInteractEvent.RightClickBlock onRightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, BlockRayTraceResult hitVec)
{
PlayerInteractEvent.RightClickBlock evt = new PlayerInteractEvent.RightClickBlock(player, hand, pos, hitVec);
MinecraftForge.EVENT_BUS.post(evt);
return evt;
}
public static void onEmptyClick(PlayerEntity player, Hand hand)
{
MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.RightClickEmpty(player, hand));
@@ -869,6 +894,14 @@ public class ForgeHooks
throw new RuntimeException("Mod fluids must override createAttributes.");
}
public static String getDefaultWorldType()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def != null)
return def.getRegistryName().toString();
return "default";
}
@FunctionalInterface
public interface BiomeCallbackFunction
{
@@ -998,6 +1031,16 @@ public class ForgeHooks
MinecraftForge.EVENT_BUS.post(new AdvancementEvent(player, advancement));
}
/**
* Hook to fire {@link ItemAttributeModifierEvent}. Modders should use {@link ItemStack#getAttributeModifiers(EquipmentSlotType)} instead.
*/
public static Multimap<Attribute,AttributeModifier> getAttributeModifiers(ItemStack stack, EquipmentSlotType equipmentSlot, Multimap<Attribute,AttributeModifier> attributes)
{
ItemAttributeModifierEvent event = new ItemAttributeModifierEvent(stack, equipmentSlot, attributes);
MinecraftForge.EVENT_BUS.post(event);
return event.getModifiers();
}
/**
* Used as the default implementation of {@link Item#getCreatorModId}. Call that method instead.
*/
@@ -1226,4 +1269,18 @@ public class ForgeHooks
modpacks.add("vanilla");
return modpacks;
}
/**
* Fixes MC-194811
* When a structure mod is removed, this map may contain null keys. This will make the world unable to save if this persists.
* If we remove a structure from the save data in this way, we then mark the chunk for saving
*/
public static void fixNullStructureReferences(IChunk chunk, Map<Structure<?>, LongSet> structureReferences)
{
if (structureReferences.remove(null) != null)
{
chunk.setModified(true);
}
chunk.setStructureReferences(structureReferences);
}
}
@@ -19,21 +19,28 @@
package net.minecraftforge.common;
import net.minecraft.command.arguments.ArgumentSerializer;
import net.minecraft.command.arguments.ArgumentTypes;
import net.minecraft.command.arguments.IArgumentSerializer;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.storage.IServerConfiguration;
import net.minecraft.world.storage.SaveFormat;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
import net.minecraftforge.fml.event.lifecycle.*;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.server.command.EnumArgument;
import net.minecraftforge.server.command.ModIdArgument;
import net.minecraftforge.versions.forge.ForgeVersion;
import net.minecraftforge.versions.mcp.MCPVersion;
@@ -66,7 +73,6 @@ import net.minecraftforge.common.data.ForgeRecipeProvider;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fml.common.Mod;
@@ -113,12 +119,14 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::preInit);
modEventBus.addListener(this::gatherData);
modEventBus.addListener(this::loadComplete);
modEventBus.register(this);
ATTRIBUTES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addGenericListener(SoundEvent.class, this::missingSoundMapping);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ForgeConfig.commonSpec);
modEventBus.register(ForgeConfig.class);
// Forge does not display problems when the remote is not matching.
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
@@ -139,13 +147,20 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
VersionChecker.startVersionCheck();
/*
* We can't actually add any of these, because vanilla clients will choke on unknown argument types
* So our custom arguments will not validate client-side, but they do still work
ArgumentTypes.register("forge:enum", EnumArgument.class, new EnumArgument.Serializer());
registerArgumentTypes();
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void registerArgumentTypes()
{
ArgumentTypes.register("forge:enum", EnumArgument.class, (IArgumentSerializer) new EnumArgument.Serializer());
ArgumentTypes.register("forge:modid", ModIdArgument.class, new ArgumentSerializer<>(ModIdArgument::modIdArgument));
ArgumentTypes.register("forge:structure_type", StructureArgument.class, new ArgumentSerializer<>(StructureArgument::structure));
*/
}
public void loadComplete(FMLLoadCompleteEvent event)
{
if (FMLEnvironment.dist == Dist.CLIENT)
ForgeHooksClient.registerForgeWorldTypeScreens();
}
public void serverStopping(FMLServerStoppingEvent evt)
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package net.minecraftforge.common;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import com.mojang.datafixers.util.Unit;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.codecs.BaseMapCodec;
import java.util.Map;
import java.util.Objects;
/**
* Key and value decoded independently, unknown set of keys
*/
public class LenientUnboundedMapCodec<K, V> implements BaseMapCodec<K, V>, Codec<Map<K, V>>
{
private final Codec<K> keyCodec;
private final Codec<V> elementCodec;
public LenientUnboundedMapCodec(final Codec<K> keyCodec, final Codec<V> elementCodec) {
this.keyCodec = keyCodec;
this.elementCodec = elementCodec;
}
@Override
public Codec<K> keyCodec() {
return keyCodec;
}
@Override
public Codec<V> elementCodec() {
return elementCodec;
}
@Override // FORGE: Modified from decode() in BaseMapCodec
public <T> DataResult<Map<K, V>> decode(DynamicOps<T> ops, MapLike<T> input)
{
final ImmutableMap.Builder<K, V> read = ImmutableMap.builder();
final ImmutableList.Builder<Pair<T, T>> failed = ImmutableList.builder();
final DataResult<Unit> result = input.entries().reduce(
DataResult.success(Unit.INSTANCE, Lifecycle.stable()),
(r, pair) -> {
final DataResult<K> k = keyCodec().parse(ops, pair.getFirst());
final DataResult<V> v = elementCodec().parse(ops, pair.getSecond());
final DataResult<Pair<K, V>> entry = k.apply2stable(Pair::of, v);
entry.error().ifPresent(e -> failed.add(pair));
entry.result().ifPresent(e -> read.put(e.getFirst(), e.getSecond())); // FORGE: This line moved outside the below apply2stable condition
return r.apply2stable((u, p) -> u, entry);
},
(r1, r2) -> r1.apply2stable((u1, u2) -> u1, r2)
);
final Map<K, V> elements = read.build();
final T errors = ops.createMap(failed.build().stream());
return result.map(unit -> elements).setPartial(elements).mapError(e -> e + " missed input: " + errors);
}
@Override
public <T> DataResult<Pair<Map<K, V>, T>> decode(final DynamicOps<T> ops, final T input) {
return ops.getMap(input).setLifecycle(Lifecycle.stable()).flatMap(map -> decode(ops, map)).map(r -> Pair.of(r, input));
}
@Override
public <T> DataResult<T> encode(final Map<K, V> input, final DynamicOps<T> ops, final T prefix) {
return encode(input, ops, ops.mapBuilder()).build(prefix);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final LenientUnboundedMapCodec<?, ?> that = (LenientUnboundedMapCodec<?, ?>) o;
return Objects.equals(keyCodec, that.keyCodec) && Objects.equals(elementCodec, that.elementCodec);
}
@Override
public int hashCode() {
return Objects.hash(keyCodec, elementCodec);
}
@Override
public String toString() {
return "LenientUnboundedMapCodec[" + keyCodec + " -> " + elementCodec + ']';
}
}
@@ -136,6 +136,12 @@ public class CompoundIngredient extends Ingredient
}
}
@Override
public boolean hasNoMatchingItems()
{
return getMatchingStacks().length == 0;
}
public static class Serializer implements IIngredientSerializer<CompoundIngredient>
{
public static final Serializer INSTANCE = new Serializer();
@@ -23,9 +23,14 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.FilePack;
import net.minecraft.resources.FolderPack;
import net.minecraft.resources.IResource;
@@ -35,20 +40,72 @@ import net.minecraft.resources.ResourcePackType;
import net.minecraft.resources.SimpleReloadableResourceManager;
import net.minecraft.resources.VanillaPack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.packs.ModFileResourcePack;
/**
* Enables data providers to check if other data files currently exist. The
* instance provided in the {@link GatherDataEvent} utilizes the standard
* resources (via {@link VanillaPack}), as well as any extra resource packs
* passed in via the {@code --existing} argument.
* resources (via {@link VanillaPack}), forge's resources, as well as any
* extra resource packs passed in via the {@code --existing} argument,
* or mod resources via the {@code --existing-mod} argument.
*/
public class ExistingFileHelper {
public interface IResourceType {
ResourcePackType getPackType();
String getSuffix();
String getPrefix();
}
public static class ResourceType implements IResourceType {
final ResourcePackType packType;
final String suffix, prefix;
public ResourceType(ResourcePackType type, String suffix, String prefix) {
this.packType = type;
this.suffix = suffix;
this.prefix = prefix;
}
@Override
public ResourcePackType getPackType() { return packType; }
@Override
public String getSuffix() { return suffix; }
@Override
public String getPrefix() { return prefix; }
}
private final SimpleReloadableResourceManager clientResources, serverData;
private final boolean enable;
private final Multimap<ResourcePackType, ResourceLocation> generated = HashMultimap.create();
@Deprecated//TODO: Remove in 1.17
public ExistingFileHelper(Collection<Path> existingPacks, boolean enable) {
this(existingPacks, Collections.emptySet(), enable);
}
/**
* Create a new helper. This should probably <em>NOT</em> be used by mods, as
* the instance provided by forge is designed to be a central instance that
* tracks existence of generated data.
* <p>
* Only create a new helper if you intentionally want to ignore the existence of
* other generated files.
*
* @param existingPacks
* @param existingMods
* @param enable
*/
public ExistingFileHelper(Collection<Path> existingPacks, Set<String> existingMods, boolean enable) {
this.clientResources = new SimpleReloadableResourceManager(ResourcePackType.CLIENT_RESOURCES);
this.serverData = new SimpleReloadableResourceManager(ResourcePackType.SERVER_DATA);
this.clientResources.addResourcePack(new VanillaPack("minecraft", "realms"));
@@ -58,12 +115,20 @@ public class ExistingFileHelper {
IResourcePack pack = file.isDirectory() ? new FolderPack(file) : new FilePack(file);
this.clientResources.addResourcePack(pack);
this.serverData.addResourcePack(pack);
};
}
for (String existingMod : existingMods) {
ModFileInfo modFileInfo = ModList.get().getModFileById(existingMod);
if (modFileInfo != null) {
IResourcePack pack = new ModFileResourcePack(modFileInfo.getFile());
this.clientResources.addResourcePack(pack);
this.serverData.addResourcePack(pack);
}
}
this.enable = enable;
}
private IResourceManager getManager(ResourcePackType type) {
return type == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData;
private IResourceManager getManager(ResourcePackType packType) {
return packType == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData;
}
private ResourceLocation getLocation(ResourceLocation base, String suffix, String prefix) {
@@ -73,17 +138,34 @@ public class ExistingFileHelper {
/**
* Check if a given resource exists in the known resource packs.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type the type of resources to check
* @param loc the complete location of the resource, e.g.
* {@code "minecraft:textures/block/stone.png"}
* @param packType the type of resources to check
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type) {
public boolean exists(ResourceLocation loc, ResourcePackType packType) {
if (!enable) {
return true;
}
return getManager(type).hasResource(loc);
return generated.get(packType).contains(loc) || getManager(packType).hasResource(loc);
}
/**
* Check if a given resource exists in the known resource packs. This is a
* convenience method to avoid repeating type/prefix/suffix and instead use the
* common definitions in {@link ResourceType}, or a custom {@link IResourceType}
* definition.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, IResourceType type) {
return exists(getLocation(loc, type.getSuffix(), type.getPrefix()), type.getPackType());
}
/**
@@ -91,25 +173,71 @@ public class ExistingFileHelper {
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type the type of resources to check
* @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"}
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) {
return exists(getLocation(loc, pathSuffix, pathPrefix), type);
public boolean exists(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
return exists(getLocation(loc, pathSuffix, pathPrefix), packType);
}
/**
* Track the existence of a generated file. This is a convenience method to
* avoid repeating type/prefix/suffix and instead use the common definitions in
* {@link ResourceType}, or a custom {@link IResourceType} definition.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
*/
public void trackGenerated(ResourceLocation loc, IResourceType type) {
this.generated.put(type.getPackType(), getLocation(loc, type.getSuffix(), type.getPrefix()));
}
/**
* Track the existence of a generated file.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"}
*/
public void trackGenerated(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
this.generated.put(packType, getLocation(loc, pathSuffix, pathPrefix));
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) throws IOException {
return getResource(getLocation(loc, pathSuffix, pathPrefix), type);
public IResource getResource(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) throws IOException {
return getResource(getLocation(loc, pathSuffix, pathPrefix), packType);
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException {
return getManager(type).getResource(loc);
public IResource getResource(ResourceLocation loc, ResourcePackType packType) throws IOException {
return getManager(packType).getResource(loc);
}
/**
@@ -140,7 +140,7 @@ public interface IForgeEntity extends ICapabilitySerializable<CompoundNBT>
*/
default boolean canBeRiddenInWater(Entity rider)
{
return this instanceof LivingEntity;
return getEntity().canBeRiddenInWater();
}
/**
@@ -30,10 +30,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import net.minecraft.loot.LootSerializers;
import net.minecraft.loot.conditions.ILootCondition;
import net.minecraft.loot.conditions.LootConditionManager;
import net.minecraft.loot.functions.ILootFunction;
import net.minecraft.loot.functions.LootFunctionManager;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -41,7 +39,6 @@ import org.apache.logging.log4j.Logger;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -56,7 +53,7 @@ import net.minecraftforge.registries.ForgeRegistries;
public class LootModifierManager extends JsonReloadListener {
public static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON_INSTANCE = (new GsonBuilder()).registerTypeHierarchyAdapter(ILootFunction.class, LootFunctionManager.func_237450_a_()).registerTypeHierarchyAdapter(ILootCondition.class, LootConditionManager.func_237474_a_()).create();
private static final Gson GSON_INSTANCE = LootSerializers.func_237387_b_().create();
private Map<ResourceLocation, IGlobalLootModifier> registeredLootModifiers = ImmutableMap.of();
private static final String folder = "loot_modifiers";
@@ -0,0 +1,102 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.common.util;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.util.SoundEvent;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
/**
* A subclass of {@link SoundType} that uses {@link Supplier<SoundEvent>}s.
* <p>
* This class allows mod developers to safely create custom {@code SoundType}s for use in their e.g. {@link Block}.
* <p>
* The problem with using {@code SoundType} directly is it requires {@link SoundEvent} instances directly, because
* {@code SoundType}s are required to be present during {@link Block} creation and registration. However,
* {@code SoundEvent} must also be registered.
* <p>
* A possible solution of initializing {@code SoundEvent}s first would require static initialization of the
* {@code SoundEvent} instances and later registration, which goes against the contract of the registry system and
* prevents the use of {@link DeferredRegister} and {@link RegistryObject}s.
* <p>
* This class offers an alternative and preferable solution, by allowing mods to create {@link SoundType}s using
* {@link Supplier}s of {@link SoundEvent}s instead, which do not require static initialization of {@code SoundEvent}s
* and allow the direct use of {@code RegistryObject}s.
*
* @see SoundType
*/
public class ForgeSoundType extends SoundType
{
private final Supplier<SoundEvent> breakSound;
private final Supplier<SoundEvent> stepSound;
private final Supplier<SoundEvent> placeSound;
private final Supplier<SoundEvent> hitSound;
private final Supplier<SoundEvent> fallSound;
public ForgeSoundType(float volumeIn, float pitchIn, Supplier<SoundEvent> breakSoundIn, Supplier<SoundEvent> stepSoundIn, Supplier<SoundEvent> placeSoundIn, Supplier<SoundEvent> hitSoundIn, Supplier<SoundEvent> fallSoundIn)
{
super(volumeIn, pitchIn, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null);
this.breakSound = breakSoundIn;
this.stepSound = stepSoundIn;
this.placeSound = placeSoundIn;
this.hitSound = hitSoundIn;
this.fallSound = fallSoundIn;
}
@Nonnull
@Override
public SoundEvent getBreakSound()
{
return breakSound.get();
}
@Nonnull
@Override
public SoundEvent getStepSound()
{
return stepSound.get();
}
@Nonnull
@Override
public SoundEvent getPlaceSound()
{
return placeSound.get();
}
@Nonnull
@Override
public SoundEvent getHitSound()
{
return hitSound.get();
}
@Nonnull
@Override
public SoundEvent getFallSound()
{
return fallSound.get();
}
}
@@ -318,13 +318,17 @@ public class LazyOptional<T>
* call this, if they are covered with a microblock panel, thus cutting off pipe
* connectivity to this side.
* <p>
* Also should be called for all when a TE is invalidated, or a world/chunk
* unloads, or a entity dies, etc... This allows modders to keep a cache of
* capability objects instead of re-checking them every tick.
* Also should be called for all when a TE is invalidated (for example, when
* the TE is removed or unloaded), or a world/chunk unloads, or a entity dies,
* etc... This allows modders to keep a cache of capability objects instead of
* re-checking them every tick.
*/
public void invalidate()
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
if (this.isValid)
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
}
}
}
@@ -0,0 +1,121 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.common.world;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StringUtils;
import net.minecraft.util.Util;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.DimensionType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistryEntry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ForgeWorldType extends ForgeRegistryEntry<ForgeWorldType>
{
private static final Logger LOGGER = LogManager.getLogger();
public static ForgeWorldType getDefaultWorldType()
{
String defaultWorldType = ForgeConfig.COMMON.defaultWorldType.get();
if (StringUtils.isNullOrEmpty(defaultWorldType) || "default".equals(defaultWorldType))
return null; // use vanilla
ForgeWorldType def = ForgeRegistries.WORLD_TYPES.getValue(new ResourceLocation(defaultWorldType));
if (def == null)
{
LOGGER.error("The defaultWorldType '{}' specified in the forge config has not been registered. The vanilla default generator will be used.", defaultWorldType);
}
return def;
}
private final IChunkGeneratorFactory factory;
public ForgeWorldType(IChunkGeneratorFactory factory)
{
this.factory = factory;
}
public ForgeWorldType(IBasicChunkGeneratorFactory factory)
{
this.factory = factory;
}
public String getTranslationKey()
{
return Util.makeTranslationKey("generator", getRegistryName());
}
public ITextComponent getDisplayName()
{
return new TranslationTextComponent(getTranslationKey());
}
/**
* Called from both the dedicated server and the world creation screen in the client.
* to construct the DimensionGEneratorSettings:
* @return The constructed chunk generator.
*/
public ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return this.factory.createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings);
}
public DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean generateLoot, String generatorSettings)
{
return this.factory.createSettings(dynamicRegistries, seed, generateStructures, generateLoot, generatorSettings);
}
public interface IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings);
default DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest, String generatorSettings) {
Registry<Biome> biomeRegistry = dynamicRegistries.getRegistry(Registry.BIOME_KEY);
Registry<DimensionType> dimensionTypeRegistry = dynamicRegistries.getRegistry(Registry.DIMENSION_TYPE_KEY);
Registry<DimensionSettings> dimensionSettingsRegistry = dynamicRegistries.getRegistry(Registry.NOISE_SETTINGS_KEY);
return new DimensionGeneratorSettings(seed, generateStructures, bonusChest,
DimensionGeneratorSettings.func_242749_a(dimensionTypeRegistry,
DimensionType.getDefaultSimpleRegistry(dimensionTypeRegistry, biomeRegistry, dimensionSettingsRegistry, seed),
createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings)));
}
}
public interface IBasicChunkGeneratorFactory extends IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed);
default ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed);
}
}
}
@@ -19,52 +19,150 @@
package net.minecraftforge.event;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.RepairContainer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
*
* AnvilUpdateEvent is fired when a player places items in both the left and right slots of a anvil.
* If the event is canceled, vanilla behavior will not run, and the output will be set to null.
* If the event is not canceled, but the output is not null, it will set the output and not run vanilla behavior.
* if the output is null, and the event is not canceled, vanilla behavior will execute.
* AnvilUpdateEvent is fired when the inputs (either input stack, or the name) to an anvil are changed. <br>
* It is called from {@link RepairContainer#updateRepairOutput}. <br>
* If the event is canceled, vanilla behavior will not run, and the output will be set to {@link ItemStack#EMPTY}. <br>
* If the event is not canceled, but the output is not empty, it will set the output and not run vanilla behavior. <br>
* if the output is empty, and the event is not canceled, vanilla behavior will execute. <br>
*/
@Cancelable
public class AnvilUpdateEvent extends Event
{
@Nonnull
private final ItemStack left; // The left side of the input
@Nonnull
private final ItemStack right; // The right side of the input
private final String name; // The name to set the item, if the user specified one.
@Nonnull
private ItemStack output; // Set this to set the output stack
private int cost; // The base cost, set this to change it if output != null
private int materialCost; // The number of items from the right slot to be consumed during the repair. Leave as 0 to consume the entire stack.
public AnvilUpdateEvent(@Nonnull ItemStack left, @Nonnull ItemStack right, String name, int cost)
private final ItemStack left;
private final ItemStack right;
private final String name;
private ItemStack output;
private int cost;
private int materialCost;
@Nullable // TODO: Remove 1.17 - Nullable only in the instance that a mod uses the deprecated ctor.
private final PlayerEntity player;
@Deprecated //TODO: Remove 1.17 - Use Player-contextual constructor below.
public AnvilUpdateEvent(ItemStack left, ItemStack right, String name, int cost)
{
this(left, right, name, cost, null);
}
public AnvilUpdateEvent(ItemStack left, ItemStack right, String name, int cost, PlayerEntity player)
{
this.left = left;
this.right = right;
this.output = ItemStack.EMPTY;
this.name = name;
this.player = player;
this.setCost(cost);
this.setMaterialCost(0);
}
@Nonnull
public ItemStack getLeft() { return left; }
@Nonnull
public ItemStack getRight() { return right; }
public String getName() { return name; }
@Nonnull
public ItemStack getOutput() { return output; }
public void setOutput(@Nonnull ItemStack output) { this.output = output; }
public int getCost() { return cost; }
public void setCost(int cost) { this.cost = cost; }
public int getMaterialCost() { return materialCost; }
public void setMaterialCost(int materialCost) { this.materialCost = materialCost; }
/**
* @return The item in the left input (leftmost) anvil slot.
*/
public ItemStack getLeft()
{
return left;
}
/**
* @return The item in the right input (center) anvil slot.
*/
public ItemStack getRight()
{
return right;
}
/**
* This is the name as sent by the client. It may be null if none has been sent. <br>
* If empty, it indicates the user wishes to clear the custom name from the item.
* @return The name that the output item will be set to, if applicable.
*/
@Nullable
public String getName()
{
return name;
}
/**
* This is the output as determined by the event, not by the vanilla behavior between these two items. <br>
* If you are the first receiver of this event, it is guaranteed to be empty. <br>
* It will only be non-empty if changed by an event handler. <br>
* If this event is cancelled, this output stack is discarded.
* @return The item to set in the output (rightmost) anvil slot.
*/
public ItemStack getOutput()
{
return output;
}
/**
* Sets the output slot to a specific itemstack.
* @param output The stack to change the output to.
*/
public void setOutput(ItemStack output)
{
this.output = output;
}
/**
* This is the level cost of this anvil operation. <br>
* When unchanged, it is guaranteed to be left.getRepairCost() + right.getRepairCost().
* @return The level cost of this anvil operation.
*/
public int getCost()
{
return cost;
}
/**
* Changes the level cost of this operation. <br>
* The level cost does prevent the output from being available. <br>
* That is, a player without enough experience may not take the output.
* @param cost The new level cost.
*/
public void setCost(int cost)
{
this.cost = cost;
}
/**
* The material cost is how many units of the right input stack are consumed.
* @return The material cost of this anvil operation.
*/
public int getMaterialCost()
{
return materialCost;
}
/**
* Sets how many right inputs are consumed. <br>
* A material cost of zero consumes the entire stack. <br>
* A material cost higher than the count of the right stack
* consumes the entire stack. <br>
* The material cost does not prevent the output from being available.
* @param materialCost The new material cost.
*/
public void setMaterialCost(int materialCost)
{
this.materialCost = materialCost;
}
/**
* Nullable in the case someone is using the deprecated constructor.
* @return The player using this anvil container.
*/
@Nullable // TODO: Remove 1.17
public PlayerEntity getPlayer()
{
return this.player;
}
}
@@ -21,6 +21,7 @@ package net.minecraftforge.event;
import java.io.File;
import java.util.*;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -36,6 +37,7 @@ import net.minecraft.command.Commands;
import net.minecraft.entity.Entity;
import net.minecraft.entity.Pose;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.LivingEntity;
@@ -103,6 +105,7 @@ import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
import net.minecraftforge.event.entity.ProjectileImpactEvent;
import net.minecraftforge.event.entity.item.ItemExpireEvent;
import net.minecraftforge.event.entity.living.AnimalTameEvent;
import net.minecraftforge.event.entity.living.LivingConversionEvent;
import net.minecraftforge.event.entity.living.LivingDestroyBlockEvent;
import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent;
import net.minecraftforge.event.entity.living.LivingExperienceDropEvent;
@@ -748,4 +751,14 @@ public class ForgeEventFactory
MinecraftForge.EVENT_BUS.post(evt);
return evt;
}
public static boolean canLivingConvert(LivingEntity entity, EntityType<? extends LivingEntity> outcome, Consumer<Integer> timer)
{
return !MinecraftForge.EVENT_BUS.post(new LivingConversionEvent.Pre(entity, outcome, timer));
}
public static void onLivingConvert(LivingEntity entity, LivingEntity outcome)
{
MinecraftForge.EVENT_BUS.post(new LivingConversionEvent.Post(entity, outcome));
}
}
@@ -0,0 +1,143 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.event;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import net.minecraftforge.eventbus.api.Event;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import com.google.common.collect.Multimap;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* This event is fired when the attributes for an ItemStack are being calculated.
* Attributes are calculated on the server when equipping and unequipping an item to add and remove attributes respectively, both must be consistent.
* Attributes are calculated on the client when rendering an item's tooltip to show relevant attributes.
* <br>
* Note that this event is fired regardless of if the stack has NBT overriding attributes or not. If your attribute should be
* ignored when attributes are overridden, you can check for the presence of the {@code AttributeModifiers} tag.
* <br>
* This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.
*/
public class ItemAttributeModifierEvent extends Event
{
private final ItemStack stack;
private final EquipmentSlotType slotType;
private final Multimap<Attribute, AttributeModifier> originalModifiers;
private Multimap<Attribute, AttributeModifier> unmodifiableModifiers;
@Nullable
private Multimap<Attribute, AttributeModifier> modifiableModifiers;
public ItemAttributeModifierEvent(ItemStack stack, EquipmentSlotType slotType, Multimap<Attribute, AttributeModifier> modifiers)
{
this.stack = stack;
this.slotType = slotType;
this.unmodifiableModifiers = this.originalModifiers = modifiers;
}
/**
* Returns an unmodifiable view of the attribute multimap. Use other methods from this event to modify the attributes map.
* Note that adding attributes based on existing attributes may lead to inconsistent results between the tooltip (client)
* and the actual attributes (server) if the listener order is different. Using {@link #getOriginalModifiers()} instead will give more consistent results.
*/
public Multimap<Attribute, AttributeModifier> getModifiers()
{
return this.unmodifiableModifiers;
}
/**
* Returns the attribute map before any changes from other event listeners was made.
*/
public Multimap<Attribute, AttributeModifier> getOriginalModifiers()
{
return this.originalModifiers;
}
/**
* Gets a modifiable map instance, creating it if the current map is currently unmodifiable
*/
private Multimap<Attribute, AttributeModifier> getModifiableMap()
{
if (this.modifiableModifiers == null)
{
this.modifiableModifiers = HashMultimap.create(this.originalModifiers);
this.unmodifiableModifiers = Multimaps.unmodifiableMultimap(this.modifiableModifiers);
}
return this.modifiableModifiers;
}
/**
* Adds a new attribute modifier to the given stack.
* Modifier must have a consistent UUID for consistency between equipping and unequipping items.
* Modifier name should clearly identify the mod that added the modifier.
* @param attribute Attribute
* @param modifier Modifier instance.
* @return True if the attribute was added, false if it was already present
*/
public boolean addModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().put(attribute, modifier);
}
/**
* Removes a single modifier for the given attribute
* @param attribute Attribute
* @param modifier Modifier instance
* @return True if an attribute was removed, false if no change
*/
public boolean removeModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().remove(attribute, modifier);
}
/**
* Removes all modifiers for the given attribute
* @param attribute Attribute
* @return Collection of removed modifiers
*/
public Collection<AttributeModifier> removeAttribute(Attribute attribute)
{
return getModifiableMap().removeAll(attribute);
}
/**
* Removes all modifiers for all attributes
*/
public void clearModifiers()
{
getModifiableMap().clear();
}
/** Gets the slot containing this stack */
public EquipmentSlotType getSlotType()
{
return this.slotType;
}
/** Gets the item stack instance */
public ItemStack getItemStack()
{
return this.stack;
}
}
@@ -122,9 +122,20 @@ public class RegistryEvent<T extends IForgeRegistryEntry<T>> extends GenericEven
return this.registry;
}
/*
* This used to be fired on the Mod specific bus, and we could tell which mod was asking for mappings.
* It no longer is, so this method is useless and just returns getAllMappings.
* TODO: Ask cpw how if he wants to re-enable the ModBus rethrow.
*/
@Deprecated
public ImmutableList<Mapping<T>> getMappings()
{
return ImmutableList.copyOf(this.mappings.stream().filter(e -> e.key.getNamespace().equals(this.activeMod.getModId())).collect(Collectors.toList()));
return this.activeMod == null ? getAllMappings() : getMappings(this.activeMod.getModId());
}
public ImmutableList<Mapping<T>> getMappings(String modid)
{
return ImmutableList.copyOf(this.mappings.stream().filter(e -> e.key.getNamespace().equals(modid)).collect(Collectors.toList()));
}
public ImmutableList<Mapping<T>> getAllMappings()
@@ -0,0 +1,108 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.event.entity.living;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraftforge.eventbus.api.Cancelable;
import java.util.function.Consumer;
public class LivingConversionEvent extends LivingEvent
{
public LivingConversionEvent(LivingEntity entity)
{
super(entity);
}
/**
* LivingConversionEvent.Pre is triggered when an entity is trying
* to replace itself with another entity
*
* This event may trigger every tick even if it was cancelled last tick
* for entities like Zombies and Hoglins. To prevent it, the conversion
* timer needs to be changed or reset
*
* This event is {@link Cancelable}
* If cancelled, the replacement will not occur
*/
@Cancelable
public static class Pre extends LivingConversionEvent
{
private final EntityType<? extends LivingEntity> outcome;
private final Consumer<Integer> timer;
public Pre(LivingEntity entity, EntityType<? extends LivingEntity> outcome, Consumer<Integer> timer)
{
super(entity);
this.outcome = outcome;
this.timer = timer;
}
/**
* Gets the entity type of the new entity this living entity is
* converting to
* @return the entity type of the new entity
*/
public EntityType<? extends LivingEntity> getOutcome()
{
return outcome;
}
/**
* Sets the conversion timer, by changing this it prevents the
* event being triggered every tick
* Do note the timer of some of the entities are increments, but
* some of them are decrements
* Not every conversion is applicable for this
* @param ticks timer ticks
*/
public void setConversionTimer(int ticks)
{
timer.accept(ticks);
}
}
/**
* LivingConversionEvent.Post is triggered when an entity is replacing
* itself with another entity.
* The old living entity is likely to be removed right after this event.
*/
public static class Post extends LivingConversionEvent
{
private final LivingEntity outcome;
public Post(LivingEntity entity, LivingEntity outcome)
{
super(entity);
this.outcome = outcome;
}
/**
* Gets the finalized new entity (with all data like potion
* effect and equipments set)
* @return the finalized new entity
*/
public LivingEntity getOutcome()
{
return outcome;
}
}
}
@@ -20,13 +20,16 @@
package net.minecraftforge.event.entity.player;
import com.google.common.base.Preconditions;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
@@ -129,27 +132,35 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* This event is fired on both sides whenever the player right clicks while targeting a block.
* This event controls which of {@link net.minecraft.block.Block#onBlockActivated} and/or {@link net.minecraft.item.Item#onItemUse}
* will be called after {@link net.minecraft.item.Item#onItemUseFirst} is called.
* Canceling the event will cause none of the above three to be called
*
* Let result be a return value of the above three methods, or {@link #cancellationResult} if the event is cancelled.
* If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then try {@link RightClickItem}.
*
* There are various results to this event, see the getters below.
* Note that handling things differently on the client vs server may cause desynchronizations!
* This event is fired on both sides whenever the player right clicks while targeting a block. <br>
* This event controls which of {@link Item#onItemUseFirst}, {@link Block#onBlockActivated}, and {@link Item#onItemUse}
* will be called. <br>
* Canceling the event will cause none of the above three to be called. <br>
* <br>
* Let result be the first non-pass return value of the above three methods, or pass, if they all pass. <br>
* Or {@link #cancellationResult} if the event is cancelled. <br>
* If result equals {@link ActionResultType#PASS}, we proceed to {@link RightClickItem}. <br>
* <br>
* There are various results to this event, see the getters below. <br>
* Note that handling things differently on the client vs server may cause desynchronizations!
*/
@Cancelable
public static class RightClickBlock extends PlayerInteractEvent
{
private Result useBlock = DEFAULT;
private Result useItem = DEFAULT;
private BlockRayTraceResult hitVec;
@Deprecated //Use RayTraceResult version. TODO: Remove 1.17
public RightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, Direction face) {
super(player, hand, pos, face);
}
public RightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, BlockRayTraceResult hitVec) {
super(player, hand, pos, hitVec.getFace());
this.hitVec = hitVec;
}
/**
* @return If {@link net.minecraft.block.Block#onBlockActivated} should be called
*/
@@ -167,9 +178,18 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* DENY: Block will never be used.
* DEFAULT: Default behaviour (sneak will not use block, unless all items return true in {@link net.minecraft.item.Item#doesSneakBypassUse}).
* ALLOW: Block will always be used, regardless of sneaking and doesSneakBypassUse.
* @return The ray trace result targeting the block.
*/
public BlockRayTraceResult getHitVec()
{
return hitVec;
}
/**
* DENY: {@link Block#onBlockActivated} will never be called. <br>
* DEFAULT: {@link Block#onBlockActivated} will be called if {@link Item#onItemUseFirst} passes. <br>
* Note that default activation can be blocked if the user is sneaking and holding an item that does not return true to {@link Item#doesSneakBypassUse}. <br>
* ALLOW: {@link Block#onBlockActivated} will always be called, unless {@link Item#onItemUseFirst} does not pass. <br>
*/
public void setUseBlock(Result triggerBlock)
{
@@ -177,9 +197,9 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* DENY: The item will never be used.
* DEFAULT: The item will be used if the block fails.
* ALLOW: The item will always be used.
* DENY: Neither {@link Item#onItemUse} or {@link Item#onItemUseFirst} will be called. <br>
* DEFAULT: {@link Item#onItemUseFirst} will always be called, and {@link Item#onItemUse} will be called if the block passes. <br>
* ALLOW: {@link Item#onItemUseFirst} will always be called, and {@link Item#onItemUse} will be called if the block passes, regardless of cooldowns or emptiness. <br>
*/
public void setUseItem(Result triggerItem)
{
@@ -19,12 +19,15 @@
package net.minecraftforge.fluids;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.registries.ForgeRegistries;
@@ -36,6 +39,8 @@ import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Optional;
/**
* ItemStack substitute for Fluids.
*
@@ -50,6 +55,18 @@ public class FluidStack
public static final FluidStack EMPTY = new FluidStack(Fluids.EMPTY, 0);
public static final Codec<FluidStack> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
Registry.FLUID.fieldOf("FluidName").forGetter(FluidStack::getFluid),
Codec.INT.fieldOf("Amount").forGetter(FluidStack::getAmount),
CompoundNBT.CODEC.optionalFieldOf("Tag").forGetter(stack -> Optional.ofNullable(stack.getTag()))
).apply(instance, (fluid, amount, tag) -> {
FluidStack stack = new FluidStack(fluid, amount);
tag.ifPresent(stack::setTag);
return stack;
})
);
private boolean isEmpty;
private int amount;
private CompoundNBT tag;
@@ -19,6 +19,7 @@
package net.minecraftforge.fml;
import java.util.Collections;
import net.minecraft.util.registry.Bootstrap;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
@@ -39,14 +40,23 @@ public class DatagenModLoader {
return runningDataGen;
}
public static void begin(final Set<String> mods, final Path path, final java.util.Collection<Path> inputs, Collection<Path> existingPacks, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
@Deprecated //TODO: Remove in 1.17
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
begin(mods, path, inputs, existingPacks, Collections.emptySet(), serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
}
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks, Set<String> existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
if (mods.contains("minecraft") && mods.size() == 1) return;
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
runningDataGen = true;
Bootstrap.register();
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
existingFileHelper = new ExistingFileHelper(existingPacks, structureValidator);
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{});
if (!mods.contains("forge")) {
//If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data
existingMods.add("forge");
}
existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, structureValidator);
ModLoader.get().runEventGenerator(mc->new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
dataGeneratorConfig.runAll();
}
@@ -40,6 +40,33 @@ public class ExtensionPoint<T>
*
* The supplier provides my "local" version for sending across the network or writing to disk
* The predicate tests the version from a remote instance or save for acceptability (Boolean is true for network, false for local save)
* and returns true if the version is compatible.
*
* <p>Return {@link net.minecraftforge.fml.network.FMLNetworkConstants#IGNORESERVERONLY} in the supplier, if you wish to be ignored
* as a server side only mod.</p>
* <p>Return true in the predicate for all values of the input string (when network boolean is true) if you are client side,
* and don't care about matching any potential server version.</p>
*
* <p>
* Examples: A server only mod
*
* <code><pre>
* registerExtensionPoint(DISPLAYTEST, ()->Pair.of(
* ()->FMLNetworkConstants.IGNORESERVERONLY, // ignore me, I'm a server only mod
* (s,b)->true // i accept anything from the server or the save, if I'm asked
* )
* </pre></code>
* </p>
* <p>
* Examples: A client only mod
* <code><pre>
* registerExtensionPoint(DISPLAYTEST, ()->Pair.of(
* ()->"anything. i don't care", // if i'm actually on the server, this string is sent but i'm a client only mod, so it won't be
* (remoteversionstring,networkbool)->networkbool // i accept anything from the server, by returning true if it's asking about the server
* )
* </pre></code>
* </p>
*
*/
public static final ExtensionPoint<Pair<Supplier<String>, BiPredicate<String, Boolean>>> DISPLAYTEST = new ExtensionPoint<>();
Loaded 100 of 128 files, more files were not shown because too many files have changed in this diff. Show more