Add support for custom tag types (#7289)
This commit is contained in:
parent
43391c009c
commit
45f8dc5245
27 changed files with 1059 additions and 24 deletions
|
@ -352,6 +352,7 @@ project(':forge') {
|
|||
'--mod', 'piston_event_test',
|
||||
'--mod', 'global_loot_test',
|
||||
'--mod', 'scaffolding_test',
|
||||
'--mod', 'custom_tag_types_test',
|
||||
'--output', rootProject.file('src/generated_test/resources/'),
|
||||
'--existing', sourceSets.main.resources.srcDirs[0]
|
||||
}
|
||||
|
|
|
@ -77,7 +77,21 @@
|
|||
if (effect != null) {
|
||||
EffectInstance effectinstance = new EffectInstance(effect, p_147260_1_.func_180755_e(), p_147260_1_.func_149428_f(), p_147260_1_.func_186984_g(), p_147260_1_.func_179707_f(), p_147260_1_.func_205527_h());
|
||||
effectinstance.func_100012_b(p_147260_1_.func_149429_c());
|
||||
@@ -1883,10 +1896,12 @@
|
||||
@@ -1388,11 +1401,12 @@
|
||||
public void func_199723_a(STagsListPacket p_199723_1_) {
|
||||
PacketThreadUtil.func_218797_a(p_199723_1_, this, this.field_147299_f);
|
||||
ITagCollectionSupplier itagcollectionsupplier = p_199723_1_.func_199858_a();
|
||||
- Multimap<ResourceLocation, ResourceLocation> multimap = TagRegistryManager.func_242198_b(itagcollectionsupplier);
|
||||
+ Multimap<ResourceLocation, ResourceLocation> multimap = TagRegistryManager.validateVanillaTags(itagcollectionsupplier);
|
||||
if (!multimap.isEmpty()) {
|
||||
field_147301_d.warn("Incomplete server tags, disconnecting. Missing: {}", (Object)multimap);
|
||||
this.field_147302_e.func_150718_a(new TranslationTextComponent("multiplayer.disconnect.missing_tags"));
|
||||
} else {
|
||||
+ net.minecraftforge.common.ForgeTagHandler.resetCachedTagCollections();
|
||||
this.field_199725_m = itagcollectionsupplier;
|
||||
if (!this.field_147302_e.func_150731_c()) {
|
||||
itagcollectionsupplier.func_242212_e();
|
||||
@@ -1883,10 +1897,12 @@
|
||||
int l5 = packetbuffer.readInt();
|
||||
this.field_147299_f.field_184132_p.field_229018_q_.func_229022_a_(blockpos8, l3, s10, l5);
|
||||
} else {
|
||||
|
|
|
@ -16,7 +16,15 @@
|
|||
GameRules gamerules = serverworld1.func_82736_K();
|
||||
boolean flag = gamerules.func_223586_b(GameRules.field_226683_z_);
|
||||
boolean flag1 = gamerules.func_223586_b(GameRules.field_223612_o);
|
||||
@@ -170,7 +172,7 @@
|
||||
@@ -156,6 +158,7 @@
|
||||
serverplaynethandler.func_147359_a(new SHeldItemChangePacket(p_72355_2_.field_71071_by.field_70461_c));
|
||||
serverplaynethandler.func_147359_a(new SUpdateRecipesPacket(this.field_72400_f.func_199529_aN().func_199510_b()));
|
||||
serverplaynethandler.func_147359_a(new STagsListPacket(this.field_72400_f.func_244266_aF()));
|
||||
+ net.minecraftforge.fml.network.NetworkHooks.syncCustomTagTypes(p_72355_2_, this.field_72400_f.func_244266_aF());
|
||||
this.func_187243_f(p_72355_2_);
|
||||
p_72355_2_.func_147099_x().func_150877_d();
|
||||
p_72355_2_.func_192037_E().func_192826_c(p_72355_2_);
|
||||
@@ -170,7 +173,7 @@
|
||||
|
||||
this.func_232641_a_(iformattabletextcomponent.func_240699_a_(TextFormatting.YELLOW), ChatType.SYSTEM, Util.field_240973_b_);
|
||||
serverplaynethandler.func_147364_a(p_72355_2_.func_226277_ct_(), p_72355_2_.func_226278_cu_(), p_72355_2_.func_226281_cx_(), p_72355_2_.field_70177_z, p_72355_2_.field_70125_A);
|
||||
|
@ -25,7 +33,7 @@
|
|||
this.field_177454_f.put(p_72355_2_.func_110124_au(), p_72355_2_);
|
||||
this.func_148540_a(new SPlayerListItemPacket(SPlayerListItemPacket.Action.ADD_PLAYER, p_72355_2_));
|
||||
|
||||
@@ -225,6 +227,7 @@
|
||||
@@ -225,6 +228,7 @@
|
||||
}
|
||||
|
||||
p_72355_2_.func_71116_b();
|
||||
|
@ -33,7 +41,7 @@
|
|||
}
|
||||
|
||||
protected void func_96456_a(ServerScoreboard p_96456_1_, ServerPlayerEntity p_96456_2_) {
|
||||
@@ -285,6 +288,7 @@
|
||||
@@ -285,6 +289,7 @@
|
||||
compoundnbt1 = compoundnbt;
|
||||
p_72380_1_.func_70020_e(compoundnbt);
|
||||
field_148546_d.debug("loading single player");
|
||||
|
@ -41,7 +49,7 @@
|
|||
} else {
|
||||
compoundnbt1 = this.field_72412_k.func_237336_b_(p_72380_1_);
|
||||
}
|
||||
@@ -293,6 +297,7 @@
|
||||
@@ -293,6 +298,7 @@
|
||||
}
|
||||
|
||||
protected void func_72391_b(ServerPlayerEntity p_72391_1_) {
|
||||
|
@ -49,7 +57,7 @@
|
|||
this.field_72412_k.func_237335_a_(p_72391_1_);
|
||||
ServerStatisticsManager serverstatisticsmanager = this.field_148547_k.get(p_72391_1_.func_110124_au());
|
||||
if (serverstatisticsmanager != null) {
|
||||
@@ -307,6 +312,7 @@
|
||||
@@ -307,6 +313,7 @@
|
||||
}
|
||||
|
||||
public void func_72367_e(ServerPlayerEntity p_72367_1_) {
|
||||
|
@ -57,7 +65,7 @@
|
|||
ServerWorld serverworld = p_72367_1_.func_71121_q();
|
||||
p_72367_1_.func_195066_a(Stats.field_75947_j);
|
||||
this.func_72391_b(p_72367_1_);
|
||||
@@ -330,7 +336,7 @@
|
||||
@@ -330,7 +337,7 @@
|
||||
p_72367_1_.func_213319_R();
|
||||
serverworld.func_217434_e(p_72367_1_);
|
||||
p_72367_1_.func_192039_O().func_192745_a();
|
||||
|
@ -66,7 +74,7 @@
|
|||
this.field_72400_f.func_201300_aS().func_201382_b(p_72367_1_);
|
||||
UUID uuid = p_72367_1_.func_110124_au();
|
||||
ServerPlayerEntity serverplayerentity = this.field_177454_f.get(uuid);
|
||||
@@ -400,8 +406,8 @@
|
||||
@@ -400,8 +407,8 @@
|
||||
}
|
||||
|
||||
public ServerPlayerEntity func_232644_a_(ServerPlayerEntity p_232644_1_, boolean p_232644_2_) {
|
||||
|
@ -77,7 +85,7 @@
|
|||
BlockPos blockpos = p_232644_1_.func_241140_K_();
|
||||
float f = p_232644_1_.func_242109_L();
|
||||
boolean flag = p_232644_1_.func_241142_M_();
|
||||
@@ -424,6 +430,7 @@
|
||||
@@ -424,6 +431,7 @@
|
||||
ServerPlayerEntity serverplayerentity = new ServerPlayerEntity(this.field_72400_f, serverworld1, p_232644_1_.func_146103_bH(), playerinteractionmanager);
|
||||
serverplayerentity.field_71135_a = p_232644_1_.field_71135_a;
|
||||
serverplayerentity.func_193104_a(p_232644_1_, p_232644_2_);
|
||||
|
@ -85,7 +93,7 @@
|
|||
serverplayerentity.func_145769_d(p_232644_1_.func_145782_y());
|
||||
serverplayerentity.func_184819_a(p_232644_1_.func_184591_cq());
|
||||
|
||||
@@ -465,10 +472,11 @@
|
||||
@@ -465,10 +473,11 @@
|
||||
this.func_72354_b(serverplayerentity, serverworld1);
|
||||
this.func_187243_f(serverplayerentity);
|
||||
serverworld1.func_217433_d(serverplayerentity);
|
||||
|
@ -98,7 +106,7 @@
|
|||
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 +794,7 @@
|
||||
@@ -786,7 +795,7 @@
|
||||
}
|
||||
|
||||
public List<ServerPlayerEntity> func_181057_v() {
|
||||
|
@ -107,7 +115,15 @@
|
|||
}
|
||||
|
||||
@Nullable
|
||||
@@ -816,4 +824,12 @@
|
||||
@@ -804,6 +813,7 @@
|
||||
}
|
||||
|
||||
this.func_148540_a(new STagsListPacket(this.field_72400_f.func_244266_aF()));
|
||||
+ net.minecraftforge.fml.network.NetworkHooks.syncCustomTagTypes(this.field_72400_f.func_244266_aF());
|
||||
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 @@
|
||||
public boolean func_206257_x() {
|
||||
return this.field_72407_n;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
--- a/net/minecraft/tags/ITagCollectionSupplier.java
|
||||
+++ b/net/minecraft/tags/ITagCollectionSupplier.java
|
||||
@@ -8,7 +8,7 @@
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
-public interface ITagCollectionSupplier {
|
||||
+public interface ITagCollectionSupplier extends net.minecraftforge.common.extensions.IForgeTagCollectionSupplier {
|
||||
ITagCollectionSupplier field_242208_a = func_242209_a(ITagCollection.func_242205_c(), ITagCollection.func_242205_c(), ITagCollection.func_242205_c(), ITagCollection.func_242205_c());
|
||||
|
||||
ITagCollection<Block> func_241835_a();
|
||||
@@ -22,6 +22,7 @@
|
||||
default void func_242212_e() {
|
||||
TagRegistryManager.func_242193_a(this);
|
||||
Blocks.func_235419_a_();
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.TagsUpdatedEvent(this));
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.TagsUpdatedEvent.VanillaTagTypes(this));
|
||||
}
|
||||
|
||||
default void func_242210_a(PacketBuffer p_242210_1_) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
--- a/net/minecraft/tags/NetworkTagManager.java
|
||||
+++ b/net/minecraft/tags/NetworkTagManager.java
|
||||
@@ -20,6 +20,7 @@
|
||||
protected TagCollectionReader<Item> field_199720_b = new TagCollectionReader<>(Registry.field_212630_s::func_241873_b, "tags/items", "item");
|
||||
protected TagCollectionReader<Fluid> field_205705_c = new TagCollectionReader<>(Registry.field_212619_h::func_241873_b, "tags/fluids", "fluid");
|
||||
protected TagCollectionReader<EntityType<?>> field_215299_d = new TagCollectionReader<>(Registry.field_212629_r::func_241873_b, "tags/entity_types", "entity_type");
|
||||
+ protected Map<ResourceLocation, TagCollectionReader<?>> customTagTypeReaders = net.minecraftforge.common.ForgeTagHandler.createCustomTagTypeReaders();
|
||||
private ITagCollectionSupplier field_242230_e = ITagCollectionSupplier.field_242208_a;
|
||||
|
||||
public ITagCollectionSupplier func_242231_a() {
|
||||
@@ -31,11 +32,13 @@
|
||||
CompletableFuture<Map<ResourceLocation, ITag.Builder>> completablefuture1 = this.field_199720_b.func_242224_a(p_215226_2_, p_215226_5_);
|
||||
CompletableFuture<Map<ResourceLocation, ITag.Builder>> completablefuture2 = this.field_205705_c.func_242224_a(p_215226_2_, p_215226_5_);
|
||||
CompletableFuture<Map<ResourceLocation, ITag.Builder>> completablefuture3 = this.field_215299_d.func_242224_a(p_215226_2_, p_215226_5_);
|
||||
- return CompletableFuture.allOf(completablefuture, completablefuture1, completablefuture2, completablefuture3).thenCompose(p_215226_1_::func_216872_a).thenAcceptAsync((p_232979_5_) -> {
|
||||
+ CompletableFuture<java.util.List<net.minecraftforge.common.ForgeTagHandler.TagCollectionReaderInfo>> customTagTypeResults = net.minecraftforge.common.ForgeTagHandler.getCustomTagTypeReloadResults(p_215226_2_, p_215226_5_, customTagTypeReaders);
|
||||
+ return CompletableFuture.allOf(completablefuture, completablefuture1, completablefuture2, completablefuture3, customTagTypeResults).thenCompose(p_215226_1_::func_216872_a).thenAcceptAsync((p_232979_5_) -> {
|
||||
ITagCollection<Block> itagcollection = this.field_199719_a.func_242226_a(completablefuture.join());
|
||||
ITagCollection<Item> itagcollection1 = this.field_199720_b.func_242226_a(completablefuture1.join());
|
||||
ITagCollection<Fluid> itagcollection2 = this.field_205705_c.func_242226_a(completablefuture2.join());
|
||||
ITagCollection<EntityType<?>> itagcollection3 = this.field_215299_d.func_242226_a(completablefuture3.join());
|
||||
+ net.minecraftforge.common.ForgeTagHandler.updateCustomTagTypes(customTagTypeResults.join());
|
||||
ITagCollectionSupplier itagcollectionsupplier = ITagCollectionSupplier.func_242209_a(itagcollection, itagcollection1, itagcollection2, itagcollection3);
|
||||
Multimap<ResourceLocation, ResourceLocation> multimap = TagRegistryManager.func_242198_b(itagcollectionsupplier);
|
||||
if (!multimap.isEmpty()) {
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
public class TagCollectionManager {
|
||||
- private static volatile ITagCollectionSupplier field_232918_a_ = ITagCollectionSupplier.func_242209_a(ITagCollection.func_242202_a(BlockTags.func_242174_b().stream().collect(Collectors.toMap(ITag.INamedTag::func_230234_a_, (p_242183_0_) -> {
|
||||
+ private static volatile ITagCollectionSupplier field_232918_a_ = ITagCollectionSupplier.func_242209_a(ITagCollection.func_242202_a(BlockTags.func_242174_b().stream().distinct().collect(Collectors.toMap(ITag.INamedTag::func_230234_a_, (p_242183_0_) -> {
|
||||
+ private static volatile ITagCollectionSupplier field_232918_a_ = net.minecraftforge.common.ForgeTagHandler.populateTagCollectionManager(ITagCollection.func_242202_a(BlockTags.func_242174_b().stream().distinct().collect(Collectors.toMap(ITag.INamedTag::func_230234_a_, (p_242183_0_) -> {
|
||||
return p_242183_0_;
|
||||
- }))), ITagCollection.func_242202_a(ItemTags.func_242177_b().stream().collect(Collectors.toMap(ITag.INamedTag::func_230234_a_, (p_242182_0_) -> {
|
||||
+ }))), ITagCollection.func_242202_a(ItemTags.func_242177_b().stream().distinct().collect(Collectors.toMap(ITag.INamedTag::func_230234_a_, (p_242182_0_) -> {
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
--- a/net/minecraft/tags/TagRegistry.java
|
||||
+++ b/net/minecraft/tags/TagRegistry.java
|
||||
@@ -22,7 +22,15 @@
|
||||
@@ -16,13 +16,51 @@
|
||||
private ITagCollection<T> field_232930_b_ = ITagCollection.func_242205_c();
|
||||
private final List<TagRegistry.NamedTag<T>> field_232931_c_ = Lists.newArrayList();
|
||||
private final Function<ITagCollectionSupplier, ITagCollection<T>> field_242184_c;
|
||||
+ private static java.util.Map<ResourceLocation, List<TagRegistry.NamedTag<?>>> toAdd = com.google.common.collect.Maps.newHashMap();
|
||||
|
||||
public TagRegistry(Function<ITagCollectionSupplier, ITagCollection<T>> p_i241894_1_) {
|
||||
this.field_242184_c = p_i241894_1_;
|
||||
}
|
||||
|
||||
public ITag.INamedTag<T> func_232937_a_(String p_232937_1_) {
|
||||
|
@ -12,12 +19,41 @@
|
|||
+ return add(new TagRegistry.OptionalNamedTag<>(key, defaults));
|
||||
+ }
|
||||
+
|
||||
+ /** Call via ForgeTagHandler#makeWrapperTag to avoid any exceptions due to calling this after it is safe to call {@link #func_232937_a_(String)} */
|
||||
+ public static <T> ITag.INamedTag<T> createDelayedTag(ResourceLocation tagRegistry, ResourceLocation name) {
|
||||
+ return delayedAdd(tagRegistry, new TagRegistry.NamedTag<>(name));
|
||||
+ }
|
||||
+
|
||||
+ /** Call via ForgeTagHandler#createOptionalTag to avoid any exceptions due to calling this after it is safe to call {@link #createOptional(ResourceLocation, java.util.function.Supplier)} */
|
||||
+ public static <T> net.minecraftforge.common.Tags.IOptionalNamedTag<T> createDelayedOptional(ResourceLocation tagRegistry, ResourceLocation key, @Nullable java.util.function.Supplier<Set<T>> defaults) {
|
||||
+ return delayedAdd(tagRegistry, new TagRegistry.OptionalNamedTag<>(key, defaults));
|
||||
+ }
|
||||
+
|
||||
+ private static synchronized <T, R extends TagRegistry.NamedTag<T>> R delayedAdd(ResourceLocation tagRegistry, R tag) {
|
||||
+ if (toAdd == null) throw new RuntimeException("Creating delayed tags or optional tags, is only supported before custom tag types have been added.");
|
||||
+ toAdd.computeIfAbsent(tagRegistry, registry -> Lists.newArrayList()).add(tag);
|
||||
+ return tag;
|
||||
+ }
|
||||
+
|
||||
+ public static void performDelayedAdd() {
|
||||
+ if (toAdd != null) {
|
||||
+ for (java.util.Map.Entry<ResourceLocation, List<TagRegistry.NamedTag<?>>> entry : toAdd.entrySet()) {
|
||||
+ TagRegistry<?> tagRegistry = TagRegistryManager.get(entry.getKey());
|
||||
+ if (tagRegistry == null) throw new RuntimeException("A mod attempted to add a delayed tag for a registry that doesn't have custom tag support.");
|
||||
+ for (TagRegistry.NamedTag<?> tag : entry.getValue()) {
|
||||
+ tagRegistry.add((TagRegistry.NamedTag) tag);
|
||||
+ }
|
||||
+ }
|
||||
+ toAdd = null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private <R extends TagRegistry.NamedTag<T>> R add(R namedtag) {
|
||||
+ namedtag.func_232943_a_(field_232930_b_::func_199910_a);
|
||||
this.field_232931_c_.add(namedtag);
|
||||
return namedtag;
|
||||
}
|
||||
@@ -56,7 +64,7 @@
|
||||
@@ -56,7 +94,7 @@
|
||||
|
||||
public Set<ResourceLocation> func_242189_b(ITagCollectionSupplier p_242189_1_) {
|
||||
ITagCollection<T> itagcollection = this.field_242184_c.apply(p_242189_1_);
|
||||
|
@ -26,7 +62,7 @@
|
|||
ImmutableSet<ResourceLocation> immutableset = ImmutableSet.copyOf(itagcollection.func_199908_a());
|
||||
return Sets.difference(set, immutableset);
|
||||
}
|
||||
@@ -93,5 +101,45 @@
|
||||
@@ -93,5 +131,45 @@
|
||||
public List<T> func_230236_b_() {
|
||||
return this.func_232944_c_().func_230236_b_();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
--- a/net/minecraft/tags/TagRegistryManager.java
|
||||
+++ b/net/minecraft/tags/TagRegistryManager.java
|
||||
@@ -51,4 +51,23 @@
|
||||
throw new IllegalStateException("Missing helper registrations");
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @javax.annotation.Nullable
|
||||
+ public static TagRegistry<?> get(ResourceLocation rl) {
|
||||
+ return field_242190_a.get(rl);
|
||||
+ }
|
||||
+
|
||||
+ public static Multimap<ResourceLocation, ResourceLocation> validateVanillaTags(ITagCollectionSupplier tagCollectionSupplier) {
|
||||
+ Multimap<ResourceLocation, ResourceLocation> missingTags = HashMultimap.create();
|
||||
+ for (java.util.Map.Entry<ResourceLocation, TagRegistry<?>> entry : field_242190_a.entrySet()) {
|
||||
+ if (!net.minecraftforge.common.ForgeTagHandler.getCustomTagTypeNames().contains(entry.getKey())) {
|
||||
+ missingTags.putAll(entry.getKey(), entry.getValue().func_242189_b(tagCollectionSupplier));
|
||||
+ }
|
||||
+ }
|
||||
+ return missingTags;
|
||||
+ }
|
||||
+
|
||||
+ public static void fetchCustomTagTypes(ITagCollectionSupplier tagCollectionSupplier) {
|
||||
+ net.minecraftforge.common.ForgeTagHandler.getCustomTagTypeNames().forEach(tagRegistry -> field_242190_a.get(tagRegistry).func_242188_a(tagCollectionSupplier));
|
||||
+ }
|
||||
}
|
|
@ -67,6 +67,8 @@ a012d6d92bab1c91913bd0f2dc0492a0fce916f2 assets/minecraft/blockstates/wall_torch
|
|||
d2c8e860521c5e738ed0798337f5728d610825ff assets/piston_event_test/models/block/shiftonmove.json
|
||||
f51f026a75e27a0a53a76771d553c0e3385a2966 assets/piston_event_test/models/item/shiftonmove.json
|
||||
cf16f861eaf5815238c2278eb48bde0688cb73b7 assets/scaffolding_test/blockstates/scaffolding_method_test.json
|
||||
42d3ce7d941eb8b80c3d541b937d0f93c9cf7c3c data/custom_tag_types_test/tags/biomes/oceans.json
|
||||
862196702dcd5538c5ceb4ac6202e57eb5c8a97f data/custom_tag_types_test/tags/custom_tag_types_test/custom_types/tests.json
|
||||
4fbaf6f4a3ea05cc071076e27f44ac81f9cc50e3 data/data_gen_test/advancements/conditional.json
|
||||
ed4cbf1a3a2f5d8969f6346fdc9acdbe81d0c919 data/data_gen_test/recipes/conditional.json
|
||||
40208299608468b044f64317995f9182ec219d90 data/data_gen_test/tags/blocks/test.json
|
||||
|
@ -74,3 +76,6 @@ d65c425e740dc833f29d16606a1171825876be0d data/data_gen_test/tags/blocks/thing/on
|
|||
1f70ed4ddc878bada5e43d3c44a34157806beda8 data/data_gen_test/tags/blocks/thing/three.json
|
||||
2c648bca262caaa826ddbbde796d35bb2ee5f03a data/data_gen_test/tags/blocks/thing/two.json
|
||||
b0565ce75fc7880be7517e86a218d1ed9d9e346f data/data_gen_test/tags/blocks/things.json
|
||||
7572ecfdcedc05dfcabf8a4c69c75e007023256f data/forge/loot_modifiers/global_loot_modifiers.json
|
||||
f65e40b06ce7ad18e053ec88058b951f98ae5f40 data/global_loot_test/loot_modifiers/smelting.json
|
||||
f991cfd612acf5ce98a43f4771ee04727219ae53 data/global_loot_test/loot_modifiers/wheat_harvest.json
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"minecraft:ocean",
|
||||
"minecraft:frozen_ocean",
|
||||
"minecraft:deep_ocean",
|
||||
"minecraft:warm_ocean",
|
||||
"minecraft:lukewarm_ocean",
|
||||
"minecraft:cold_ocean",
|
||||
"minecraft:deep_warm_ocean",
|
||||
"minecraft:deep_lukewarm_ocean",
|
||||
"minecraft:deep_cold_ocean",
|
||||
"minecraft:deep_frozen_ocean"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"custom_tag_types_test:custom"
|
||||
]
|
||||
}
|
|
@ -110,7 +110,7 @@ public class ForgeInternalHandler
|
|||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public synchronized void tagsUpdated(TagsUpdatedEvent event)
|
||||
public synchronized void tagsUpdated(TagsUpdatedEvent.VanillaTagTypes event)
|
||||
{
|
||||
ForgeHooks.updateBurns();
|
||||
}
|
||||
|
|
343
src/main/java/net/minecraftforge/common/ForgeTagHandler.java
Normal file
343
src/main/java/net/minecraftforge/common/ForgeTagHandler.java
Normal file
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.tags.ITag;
|
||||
import net.minecraft.tags.ITag.INamedTag;
|
||||
import net.minecraft.tags.ITagCollection;
|
||||
import net.minecraft.tags.ITagCollectionSupplier;
|
||||
import net.minecraft.tags.TagCollectionReader;
|
||||
import net.minecraft.tags.TagRegistry;
|
||||
import net.minecraft.tags.TagRegistryManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.Tags.IOptionalNamedTag;
|
||||
import net.minecraftforge.fml.network.FMLPlayMessages.SyncCustomTagTypes;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ForgeTagHandler
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static Map<ResourceLocation, ITagCollection<?>> customTagTypes = Collections.emptyMap();
|
||||
private static Set<ResourceLocation> customTagTypeNames = Collections.emptySet();
|
||||
private static boolean tagTypesSet = false;
|
||||
|
||||
@Nullable
|
||||
private static <T extends IForgeRegistryEntry<T>> TagRegistry<T> getTagRegistry(IForgeRegistry<T> registry)
|
||||
{
|
||||
return (TagRegistry<T>) TagRegistryManager.get(registry.getRegistryName());
|
||||
}
|
||||
|
||||
private static void validateRegistrySupportsTags(IForgeRegistry<?> registry)
|
||||
{
|
||||
//Note: We also check against getTagRegistry in case someone decides to use the helpers for tag creation for types supported by vanilla
|
||||
if (getTagRegistry(registry) == null && (!(registry instanceof ForgeRegistry) || ((ForgeRegistry<?>) registry).getTagFolder() == null))
|
||||
{
|
||||
throw new IllegalArgumentException("Registry " + registry.getRegistryName() + " does not support tag types.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a named tag for a forge registry, erroring if the registry doesn't support custom tag types. If the custom tag types
|
||||
* have not been set yet, this method falls back and creates the tag reference delaying adding it to the tag registry to allow for statically
|
||||
* initializing and referencing the tag.
|
||||
* @param registry Registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param <T> Type of the registry
|
||||
* @return A named tag
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> ITag.INamedTag<T> makeWrapperTag(IForgeRegistry<T> registry, ResourceLocation name)
|
||||
{
|
||||
validateRegistrySupportsTags(registry);
|
||||
if (tagTypesSet)
|
||||
{
|
||||
TagRegistry<T> tagRegistry = getTagRegistry(registry);
|
||||
if (tagRegistry == null) throw new IllegalArgumentException("Registry " + registry.getRegistryName() + " does not support tag types.");
|
||||
return tagRegistry.func_232937_a_(name.toString());
|
||||
}
|
||||
return TagRegistry.createDelayedTag(registry.getRegistryName(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates an optional tag for a forge registry, erroring if the registry doesn't support custom tag types. If the custom tag types
|
||||
* have not been set yet, this method falls back and creates the tag reference delaying adding it to the tag registry to allow for statically
|
||||
* initializing and referencing the tag.
|
||||
* @param registry Registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param <T> Type of the registry
|
||||
* @return An optional tag
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> IOptionalNamedTag<T> createOptionalTag(IForgeRegistry<T> registry, ResourceLocation name)
|
||||
{
|
||||
return createOptionalTag(registry, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates an optional tag for a forge registry, erroring if the registry doesn't support custom tag types. If the custom tag types
|
||||
* have not been set yet, this method falls back and creates the tag reference delaying adding it to the tag registry to allow for statically
|
||||
* initializing and referencing the tag.
|
||||
* @param registry Registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param defaults Default values for the optional tag
|
||||
* @param <T> Type of the registry
|
||||
* @return An optional tag
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> IOptionalNamedTag<T> createOptionalTag(IForgeRegistry<T> registry, ResourceLocation name, @Nullable Supplier<Set<T>> defaults)
|
||||
{
|
||||
validateRegistrySupportsTags(registry);
|
||||
if (tagTypesSet)
|
||||
{
|
||||
TagRegistry<T> tagRegistry = getTagRegistry(registry);
|
||||
if (tagRegistry == null) throw new IllegalArgumentException("Registry " + registry.getRegistryName() + " does not support tag types.");
|
||||
return tagRegistry.createOptional(name, defaults);
|
||||
}
|
||||
return TagRegistry.createDelayedOptional(registry.getRegistryName(), name, defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for creating named tags for custom forge registries. If the custom tag types have not been set yet, this method falls back and creates
|
||||
* the tag reference delaying adding it to the tag registry to allow for statically initializing and referencing the tag.
|
||||
* @param registryName Name of the registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param <T> Type of the registry
|
||||
* @return A named tag
|
||||
* @implNote This method only errors instantly if tag types have already been set, otherwise the error is delayed until after registries finish initializing
|
||||
* and we can validate if the custom registry really does support custom tags.
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> ITag.INamedTag<T> makeWrapperTag(ResourceLocation registryName, ResourceLocation name)
|
||||
{
|
||||
if (tagTypesSet)
|
||||
{
|
||||
IForgeRegistry<T> registry = RegistryManager.ACTIVE.getRegistry(registryName);
|
||||
if (registry == null) throw new IllegalArgumentException("Could not find registry named: " + registryName);
|
||||
return makeWrapperTag(registry, name);
|
||||
}
|
||||
return TagRegistry.createDelayedTag(registryName, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for creating optional tags for custom forge registries. If the custom tag types have not been set yet, this method falls back and creates
|
||||
* the tag reference delaying adding it to the tag registry to allow for statically initializing and referencing the tag.
|
||||
* @param registryName Name of the registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param <T> Type of the registry
|
||||
* @return An optional tag
|
||||
* @implNote This method only errors instantly if tag types have already been set, otherwise the error is delayed until after registries finish initializing
|
||||
* and we can validate if the custom registry really does support custom tags.
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> IOptionalNamedTag<T> createOptionalTag(ResourceLocation registryName, ResourceLocation name)
|
||||
{
|
||||
return createOptionalTag(registryName, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for creating optional tags for custom forge registries. If the custom tag types have not been set yet, this method falls back and creates
|
||||
* the tag reference delaying adding it to the tag registry to allow for statically initializing and referencing the tag.
|
||||
* @param registryName Name of the registry the tag is for
|
||||
* @param name Name of the tag
|
||||
* @param defaults Default values for the optional tag
|
||||
* @param <T> Type of the registry
|
||||
* @return An optional tag
|
||||
* @implNote This method only errors instantly if tag types have already been set, otherwise the error is delayed until after registries finish initializing
|
||||
* and we can validate if the custom registry really does support custom tags.
|
||||
*/
|
||||
public static <T extends IForgeRegistryEntry<T>> IOptionalNamedTag<T> createOptionalTag(ResourceLocation registryName, ResourceLocation name, @Nullable Supplier<Set<T>> defaults)
|
||||
{
|
||||
if (tagTypesSet)
|
||||
{
|
||||
IForgeRegistry<T> registry = RegistryManager.ACTIVE.getRegistry(registryName);
|
||||
if (registry == null) throw new IllegalArgumentException("Could not find registry named: " + registryName);
|
||||
return createOptionalTag(registry, name, defaults);
|
||||
}
|
||||
return TagRegistry.createDelayedOptional(registryName, name, defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the all the registry names of registries that support custom tag types.
|
||||
*/
|
||||
public static Set<ResourceLocation> getCustomTagTypeNames()
|
||||
{
|
||||
return customTagTypeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a map of registry name to tag collection for all custom tag types.
|
||||
*
|
||||
* @apiNote Prefer interacting with this via the current {@link ITagCollectionSupplier} and using one of the forge extension getCustomTypeCollection methods
|
||||
*/
|
||||
public static Map<ResourceLocation, ITagCollection<?>> getCustomTagTypes()
|
||||
{
|
||||
return customTagTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the set containing the resource locations representing the registry name of each forge registry that supports custom tag types.
|
||||
*
|
||||
* @apiNote Internal: Calling this manually <strong>WILL</strong> cause a crash to occur as it can only be called once, and is done so by
|
||||
* forge after all registries have been initialized.
|
||||
*/
|
||||
public static void setCustomTagTypes(Set<ResourceLocation> customTagTypes)
|
||||
{
|
||||
if (tagTypesSet) throw new RuntimeException("Custom tag types have already been set, this method should only be called by forge, and after registries are initialized");
|
||||
tagTypesSet = true;
|
||||
customTagTypeNames = ImmutableSet.copyOf(customTagTypes);
|
||||
TagRegistry.performDelayedAdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a map for custom tag type to tag reader
|
||||
*
|
||||
* @apiNote Internal: For use by NetworkTagManager
|
||||
*/
|
||||
public static Map<ResourceLocation, TagCollectionReader<?>> createCustomTagTypeReaders()
|
||||
{
|
||||
LOGGER.debug("Gathering custom tag collection reader from types.");
|
||||
ImmutableMap.Builder<ResourceLocation, TagCollectionReader<?>> builder = ImmutableMap.builder();
|
||||
for (ResourceLocation registryName : customTagTypeNames)
|
||||
{
|
||||
ForgeRegistry<?> registry = RegistryManager.ACTIVE.getRegistry(registryName);
|
||||
if (registry != null && registry.getTagFolder() != null)
|
||||
{
|
||||
builder.put(registryName, new TagCollectionReader<>(rl -> Optional.ofNullable(registry.getValue(rl)), "tags/" + registry.getTagFolder(), registryName.getPath()));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the cached collections for the various custom tag types.
|
||||
*
|
||||
* @apiNote Internal
|
||||
*/
|
||||
public static void resetCachedTagCollections()
|
||||
{
|
||||
ImmutableMap.Builder<ResourceLocation, ITagCollection<?>> builder = ImmutableMap.builder();
|
||||
for (ResourceLocation registryName : customTagTypeNames)
|
||||
{
|
||||
TagRegistry<?> tagRegistry = TagRegistryManager.get(registryName);
|
||||
if (tagRegistry != null)
|
||||
{
|
||||
builder.put(registryName, ITagCollection.func_242202_a(tagRegistry.func_241288_c_().stream().distinct().collect(Collectors.toMap(INamedTag::func_230234_a_, namedTag -> namedTag))));
|
||||
}
|
||||
}
|
||||
customTagTypes = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to ensure that all custom tag types have a defaulted collection when vanilla is initializing a defaulted TagCollectionManager
|
||||
*
|
||||
* @apiNote Internal: For use by TagCollectionManager
|
||||
*/
|
||||
public static ITagCollectionSupplier populateTagCollectionManager(ITagCollection<Block> blockTags, ITagCollection<Item> itemTags, ITagCollection<Fluid> fluidTags, ITagCollection<EntityType<?>> entityTypeTags)
|
||||
{
|
||||
//Default the tag collections
|
||||
resetCachedTagCollections();
|
||||
if (!customTagTypes.isEmpty())
|
||||
{
|
||||
LOGGER.debug("Populated the TagCollectionManager with {} extra types", customTagTypes.size());
|
||||
}
|
||||
return ITagCollectionSupplier.func_242209_a(blockTags, itemTags, fluidTags, entityTypeTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the custom tag types' tags from reloading via NetworkTagManager
|
||||
*
|
||||
* @apiNote Internal: For use by NetworkTagManager
|
||||
*/
|
||||
public static void updateCustomTagTypes(List<TagCollectionReaderInfo> tagCollectionReaders)
|
||||
{
|
||||
ImmutableMap.Builder<ResourceLocation, ITagCollection<?>> builder = ImmutableMap.builder();
|
||||
for (TagCollectionReaderInfo info : tagCollectionReaders)
|
||||
{
|
||||
builder.put(info.tagType, info.reader.func_242226_a(info.tagBuilders));
|
||||
}
|
||||
customTagTypes = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the custom tag types' tags from packet
|
||||
*
|
||||
* @apiNote Internal
|
||||
*/
|
||||
public static void updateCustomTagTypes(SyncCustomTagTypes packet)
|
||||
{
|
||||
customTagTypes = packet.getCustomTagTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the completable future containing the reload results for all custom tag types.
|
||||
*
|
||||
* @apiNote Internal: For use by NetworkTagManager
|
||||
*/
|
||||
public static CompletableFuture<List<TagCollectionReaderInfo>> getCustomTagTypeReloadResults(IResourceManager resourceManager, Executor backgroundExecutor, Map<ResourceLocation, TagCollectionReader<?>> readers)
|
||||
{
|
||||
CompletableFuture<List<TagCollectionReaderInfo>> customResults = CompletableFuture.completedFuture(new ArrayList<>());
|
||||
for (Map.Entry<ResourceLocation, TagCollectionReader<?>> entry : readers.entrySet())
|
||||
{
|
||||
customResults = customResults.thenCombine(entry.getValue().func_242224_a(resourceManager, backgroundExecutor), (results, result) -> {
|
||||
results.add(new TagCollectionReaderInfo(entry.getKey(), entry.getValue(), result));
|
||||
return results;
|
||||
});
|
||||
}
|
||||
return customResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper storage class for keeping track of various data for all custom tag types in the NetworkTagReader to make the code easier to read.
|
||||
*
|
||||
* @apiNote Internal: For use by NetworkTagManager
|
||||
*/
|
||||
public static class TagCollectionReaderInfo
|
||||
{
|
||||
|
||||
private final ResourceLocation tagType;
|
||||
private final TagCollectionReader<?> reader;
|
||||
private final Map<ResourceLocation, ITag.Builder> tagBuilders;
|
||||
|
||||
private TagCollectionReaderInfo(ResourceLocation tagType, TagCollectionReader<?> reader, Map<ResourceLocation, ITag.Builder> tagBuilders)
|
||||
{
|
||||
this.tagType = tagType;
|
||||
this.reader = reader;
|
||||
this.tagBuilders = tagBuilders;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.data;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.TagsProvider;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
|
||||
public abstract class ForgeRegistryTagsProvider<T extends IForgeRegistryEntry<T>> extends TagsProvider<T>
|
||||
{
|
||||
//Special handling for vanilla tag types in case someone decides to use the ForgeRegistryTagsProvider instead of one of the vanilla subtypes
|
||||
private static final Map<IForgeRegistry<?>, String> vanillaTypes = ImmutableMap.<IForgeRegistry<?>, String>builder()
|
||||
.put(ForgeRegistries.BLOCKS, "blocks")
|
||||
.put(ForgeRegistries.ENTITIES, "entity_types")
|
||||
.put(ForgeRegistries.FLUIDS, "fluids")
|
||||
.put(ForgeRegistries.ITEMS, "items")
|
||||
.build();
|
||||
|
||||
private static <T extends IForgeRegistryEntry<T>> Registry<T> wrapRegistry(IForgeRegistry<T> registryIn)
|
||||
{
|
||||
if (!(registryIn instanceof ForgeRegistry))
|
||||
throw new IllegalArgumentException("Forge registry " + registryIn.getRegistryName() + " is not an instance of a ForgeRegistry");
|
||||
ForgeRegistry<T> forgeRegistry = (ForgeRegistry<T>) registryIn;
|
||||
if (forgeRegistry.getTagFolder() == null && !vanillaTypes.containsKey(registryIn))
|
||||
throw new IllegalArgumentException("Forge registry " + registryIn.getRegistryName() + " does not have support for tags");
|
||||
if (forgeRegistry.getDefaultKey() == null)
|
||||
return GameData.getWrapper(forgeRegistry.getRegistryKey(), Lifecycle.experimental());
|
||||
return GameData.getWrapper(forgeRegistry.getRegistryKey(), Lifecycle.experimental(), "default");
|
||||
}
|
||||
|
||||
private final String folder;
|
||||
|
||||
public ForgeRegistryTagsProvider(DataGenerator generatorIn, IForgeRegistry<T> registryIn, String modId, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(generatorIn, wrapRegistry(registryIn), modId, existingFileHelper);
|
||||
String tagFolder = ((ForgeRegistry<T>) registryIn).getTagFolder();
|
||||
folder = tagFolder == null ? vanillaTypes.get(registryIn) : tagFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path makePath(ResourceLocation id)
|
||||
{
|
||||
return generator.getOutputFolder().resolve("data/" + id.getNamespace() + "/tags/" + folder + "/" + id.getPath() + ".json");
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ package net.minecraftforge.common.extensions;
|
|||
|
||||
import net.minecraft.data.TagsProvider;
|
||||
import net.minecraft.tags.ITag;
|
||||
import net.minecraft.util.RegistryKey;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
//TODO, Tag removal support.
|
||||
|
@ -40,6 +41,14 @@ public interface IForgeTagBuilder<T>
|
|||
return builder;
|
||||
}
|
||||
|
||||
default TagsProvider.Builder<T> add(RegistryKey<T>... keys) {
|
||||
TagsProvider.Builder<T> builder = getBuilder();
|
||||
for (RegistryKey<T> key : keys) {
|
||||
builder.getInternalBuilder().func_232961_a_(key.func_240901_a_(), getBuilder().getModID());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
default TagsProvider.Builder<T> replace() {
|
||||
return replace(true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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.extensions;
|
||||
|
||||
import java.util.Map;
|
||||
import net.minecraft.tags.ITagCollection;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.ForgeTagHandler;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
|
||||
public interface IForgeTagCollectionSupplier
|
||||
{
|
||||
/**
|
||||
* Gets the tag map of registry names to tag collections for the various custom tag types.
|
||||
*
|
||||
* @apiNote Prefer using one of the getCustomTypeCollection methods
|
||||
*/
|
||||
default Map<ResourceLocation, ITagCollection<?>> getCustomTagTypes()
|
||||
{
|
||||
return ForgeTagHandler.getCustomTagTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ITagCollection} for a forge registry with the given name, or throws an exception if the registry doesn't support custom tag types.
|
||||
* @param regName Name of the forge registry
|
||||
* @return The tag collection
|
||||
*/
|
||||
default ITagCollection<?> getCustomTypeCollection(ResourceLocation regName)
|
||||
{
|
||||
if (!ForgeTagHandler.getCustomTagTypeNames().contains(regName)) throw new IllegalArgumentException("Registry " + regName + ", does not support custom tag types");
|
||||
return getCustomTagTypes().get(regName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ITagCollection} for a forge registry, or throws an exception if the registry doesn't support custom tag types.
|
||||
* @param reg Forge registry
|
||||
* @return The tag collection
|
||||
*/
|
||||
default <T extends IForgeRegistryEntry<T>> ITagCollection<T> getCustomTypeCollection(IForgeRegistry<T> reg)
|
||||
{
|
||||
return (ITagCollection<T>) getCustomTypeCollection(reg.getRegistryName());
|
||||
}
|
||||
}
|
|
@ -45,4 +45,26 @@ public class TagsUpdatedEvent extends Event
|
|||
{
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after the Vanilla Tag types have been processed
|
||||
*/
|
||||
public static class VanillaTagTypes extends TagsUpdatedEvent
|
||||
{
|
||||
public VanillaTagTypes(ITagCollectionSupplier manager)
|
||||
{
|
||||
super(manager);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after any custom tag types have been processed
|
||||
*/
|
||||
public static class CustomTagTypes extends TagsUpdatedEvent
|
||||
{
|
||||
public CustomTagTypes(ITagCollectionSupplier manager)
|
||||
{
|
||||
super(manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,6 +198,8 @@ public class ModLoader
|
|||
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
||||
statusConsumer.ifPresent(c->c.accept("Populating registries"));
|
||||
dispatchAndHandleError(ModLoadingStage.LOAD_REGISTRIES, syncExecutor, parallelExecutor, periodicTask);
|
||||
statusConsumer.ifPresent(c->c.accept("Adding custom tag types"));
|
||||
GameData.setCustomTagTypesFromRegistries();
|
||||
statusConsumer.ifPresent(c->c.accept("Early mod loading complete"));
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,14 @@
|
|||
|
||||
package net.minecraftforge.fml.network;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.IHasContainer;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
|
@ -27,23 +34,36 @@ import net.minecraft.client.gui.screen.Screen;
|
|||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.tags.ITag;
|
||||
import net.minecraft.tags.ITagCollection;
|
||||
import net.minecraft.tags.ITagCollectionSupplier;
|
||||
import net.minecraft.tags.TagRegistryManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.FuzzedBiomeMagnifier;
|
||||
import net.minecraftforge.common.ForgeTagHandler;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.TagsUpdatedEvent;
|
||||
import net.minecraftforge.fml.LogicalSidedProvider;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.IForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FMLPlayMessages
|
||||
{
|
||||
|
@ -308,4 +328,144 @@ public class FMLPlayMessages
|
|||
return additionalData;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SyncCustomTagTypes
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final Map<ResourceLocation, ITagCollection<?>> customTagTypeCollections;
|
||||
|
||||
SyncCustomTagTypes(Map<ResourceLocation, ITagCollection<?>> customTagTypeCollections)
|
||||
{
|
||||
this.customTagTypeCollections = customTagTypeCollections;
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, ITagCollection<?>> getCustomTagTypes()
|
||||
{
|
||||
return customTagTypeCollections;
|
||||
}
|
||||
|
||||
public static void encode(SyncCustomTagTypes msg, PacketBuffer buf)
|
||||
{
|
||||
buf.writeVarInt(msg.customTagTypeCollections.size());
|
||||
msg.customTagTypeCollections.forEach((registryName, modded) -> forgeTagCollectionWrite(buf, registryName, modded.func_241833_a()));
|
||||
}
|
||||
|
||||
private static <T> void forgeTagCollectionWrite(PacketBuffer buf, ResourceLocation registryName, Map<ResourceLocation, ITag<T>> tags)
|
||||
{
|
||||
buf.writeResourceLocation(registryName);
|
||||
buf.writeVarInt(tags.size());
|
||||
tags.forEach((name, tag) -> {
|
||||
buf.writeResourceLocation(name);
|
||||
List<T> elements = tag.func_230236_b_();
|
||||
buf.writeVarInt(elements.size());
|
||||
for (T element : elements)
|
||||
{
|
||||
buf.writeResourceLocation(((IForgeRegistryEntry<?>) element).getRegistryName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static SyncCustomTagTypes decode(PacketBuffer buf)
|
||||
{
|
||||
ImmutableMap.Builder<ResourceLocation, ITagCollection<?>> builder = ImmutableMap.builder();
|
||||
int size = buf.readVarInt();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
ResourceLocation regName = buf.readResourceLocation();
|
||||
IForgeRegistry<?> registry = RegistryManager.ACTIVE.getRegistry(regName);
|
||||
if (registry != null)
|
||||
{
|
||||
builder.put(regName, readTagCollection(buf, registry));
|
||||
}
|
||||
}
|
||||
return new SyncCustomTagTypes(builder.build());
|
||||
}
|
||||
|
||||
private static <T extends IForgeRegistryEntry<T>> ITagCollection<T> readTagCollection(PacketBuffer buf, IForgeRegistry<T> registry)
|
||||
{
|
||||
Map<ResourceLocation, ITag<T>> tags = Maps.newHashMap();
|
||||
int totalTags = buf.readVarInt();
|
||||
for (int i = 0; i < totalTags; i++)
|
||||
{
|
||||
ImmutableSet.Builder<T> elementBuilder = ImmutableSet.builder();
|
||||
ResourceLocation name = buf.readResourceLocation();
|
||||
int totalElements = buf.readVarInt();
|
||||
for (int j = 0; j < totalElements; j++)
|
||||
{
|
||||
T element = registry.getValue(buf.readResourceLocation());
|
||||
if (element != null)
|
||||
{
|
||||
elementBuilder.add(element);
|
||||
}
|
||||
}
|
||||
tags.put(name, ITag.func_232946_a_(elementBuilder.build()));
|
||||
}
|
||||
return ITagCollection.func_242202_a(tags);
|
||||
}
|
||||
|
||||
public static void handle(SyncCustomTagTypes msg, Supplier<NetworkEvent.Context> ctx)
|
||||
{
|
||||
ctx.get().enqueueWork(() -> {
|
||||
if (Minecraft.getInstance().world != null)
|
||||
{
|
||||
ITagCollectionSupplier tagCollectionSupplier = Minecraft.getInstance().world.getTags();
|
||||
//Validate that all the tags exist using the tag type collections from the packet
|
||||
// We mimic vanilla in that we validate before updating the actual stored tags so that it can gracefully fallback
|
||||
// to the last working set of tags
|
||||
//Note: We gracefully ignore any tag types the server may have that we don't as they won't be in our tag registry
|
||||
// so they won't be validated
|
||||
Multimap<ResourceLocation, ResourceLocation> missingTags = TagRegistryManager.func_242198_b(new ITagCollectionSupplier()
|
||||
{
|
||||
@Override
|
||||
public ITagCollection<Block> func_241835_a()
|
||||
{
|
||||
return tagCollectionSupplier.func_241835_a();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITagCollection<Item> func_241836_b()
|
||||
{
|
||||
return tagCollectionSupplier.func_241836_b();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITagCollection<Fluid> func_241837_c()
|
||||
{
|
||||
return tagCollectionSupplier.func_241837_c();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITagCollection<EntityType<?>> func_241838_d()
|
||||
{
|
||||
return tagCollectionSupplier.func_241838_d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ResourceLocation, ITagCollection<?>> getCustomTagTypes()
|
||||
{
|
||||
//Override and use the tags from the packet to test for validation before we actually set them
|
||||
return msg.customTagTypeCollections;
|
||||
}
|
||||
});
|
||||
if (missingTags.isEmpty())
|
||||
{
|
||||
//If we have no missing tags, update the custom tag types
|
||||
ForgeTagHandler.updateCustomTagTypes(msg);
|
||||
if (!ctx.get().getNetworkManager().isLocalChannel())
|
||||
{
|
||||
//And if everything hasn't already been set due to being in single player
|
||||
// Fetch and update the custom tag types. We skip vanilla tag types as they have already been fetched
|
||||
// And fire an event that the custom tag types have been updated
|
||||
TagRegistryManager.fetchCustomTagTypes(tagCollectionSupplier);
|
||||
MinecraftForge.EVENT_BUS.post(new TagsUpdatedEvent.CustomTagTypes(tagCollectionSupplier));
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("Incomplete server tags, disconnecting. Missing: {}", missingTags);
|
||||
ctx.get().getNetworkManager().closeChannel(new TranslationTextComponent("multiplayer.disconnect.missing_tags"));
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package net.minecraftforge.fml.network;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -26,6 +27,8 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.tags.ITagCollection;
|
||||
import net.minecraft.tags.ITagCollectionSupplier;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
@ -208,4 +211,31 @@ public class NetworkHooks
|
|||
player.openContainer.addListener(player);
|
||||
MinecraftForge.EVENT_BUS.post(new PlayerContainerEvent.Open(player, c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the custom tag types attached to a {@link ITagCollectionSupplier} to all connected players.
|
||||
* @param tagCollectionSupplier The tag collection supplier containing the custom tags
|
||||
*/
|
||||
public static void syncCustomTagTypes(ITagCollectionSupplier tagCollectionSupplier)
|
||||
{
|
||||
Map<ResourceLocation, ITagCollection<?>> customTagTypes = tagCollectionSupplier.getCustomTagTypes();
|
||||
if (!customTagTypes.isEmpty())
|
||||
{
|
||||
FMLNetworkConstants.playChannel.send(PacketDistributor.ALL.noArg(), new FMLPlayMessages.SyncCustomTagTypes(customTagTypes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the custom tag types attached to a {@link ITagCollectionSupplier} to the given player.
|
||||
* @param player The player to sync the custom tags to.
|
||||
* @param tagCollectionSupplier The tag collection supplier containing the custom tags
|
||||
*/
|
||||
public static void syncCustomTagTypes(ServerPlayerEntity player, ITagCollectionSupplier tagCollectionSupplier)
|
||||
{
|
||||
Map<ResourceLocation, ITagCollection<?>> customTagTypes = tagCollectionSupplier.getCustomTagTypes();
|
||||
if (!customTagTypes.isEmpty())
|
||||
{
|
||||
FMLNetworkConstants.playChannel.sendTo(new FMLPlayMessages.SyncCustomTagTypes(customTagTypes), player.connection.getNetworkManager(), NetworkDirection.PLAY_TO_CLIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,12 @@ class NetworkInitialization {
|
|||
// .consumer(FMLPlayMessages.DimensionInfoMessage::handle)
|
||||
// .add();
|
||||
|
||||
playChannel.messageBuilder(FMLPlayMessages.SyncCustomTagTypes.class, 3).
|
||||
decoder(FMLPlayMessages.SyncCustomTagTypes::decode).
|
||||
encoder(FMLPlayMessages.SyncCustomTagTypes::encode).
|
||||
consumer(FMLPlayMessages.SyncCustomTagTypes::handle).
|
||||
add();
|
||||
|
||||
return playChannel;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
|
|||
private final int max;
|
||||
private final boolean allowOverrides;
|
||||
private final boolean isModifiable;
|
||||
@Nullable
|
||||
private final String tagFolder;
|
||||
|
||||
private V defaultValue = null;
|
||||
boolean isFrozen = false;
|
||||
|
@ -120,6 +122,7 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
|
|||
this.isDelegated = ForgeRegistryEntry.class.isAssignableFrom(superType); //TODO: Make this IDelegatedRegistryEntry?
|
||||
this.allowOverrides = builder.getAllowOverrides();
|
||||
this.isModifiable = builder.getAllowModifications();
|
||||
this.tagFolder = builder.getTagFolder();
|
||||
if (this.create != null)
|
||||
this.create.onCreate(this, stage);
|
||||
}
|
||||
|
@ -175,6 +178,12 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
|
|||
return superType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTagFolder()
|
||||
{
|
||||
return tagFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAll(@SuppressWarnings("unchecked") V... values)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@ package net.minecraftforge.registries;
|
|||
import com.google.common.collect.*;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import net.minecraft.block.AirBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -47,6 +49,7 @@ import net.minecraft.potion.Effect;
|
|||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import net.minecraft.stats.StatType;
|
||||
import net.minecraft.tags.TagRegistryManager;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.ObjectIntIdentityMap;
|
||||
import net.minecraft.util.RegistryKey;
|
||||
|
@ -68,6 +71,7 @@ import net.minecraft.world.gen.foliageplacer.FoliagePlacerType;
|
|||
import net.minecraft.world.gen.placement.Placement;
|
||||
import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
|
||||
import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
|
||||
import net.minecraftforge.common.ForgeTagHandler;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
|
||||
import net.minecraftforge.event.RegistryEvent;
|
||||
|
@ -175,7 +179,7 @@ public class GameData
|
|||
makeRegistry(TREE_DECORATOR_TYPES, c(TreeDecoratorType.class)).disableSaving().disableSync().create();
|
||||
|
||||
// Dynamic Worldgen
|
||||
makeRegistry(BIOMES, Biome.class).create();
|
||||
makeRegistry(BIOMES, Biome.class).tagFolder("biomes").create();
|
||||
|
||||
// Custom forge registries
|
||||
makeRegistry(DATA_SERIALIZERS, DataSerializerEntry.class, 256 /*vanilla space*/, MAX_VARINT).disableSaving().disableOverrides().addCallback(SerializerCallbacks.INSTANCE).create();
|
||||
|
@ -190,11 +194,11 @@ public class GameData
|
|||
}
|
||||
private static <T extends IForgeRegistryEntry<T>> RegistryBuilder<T> makeRegistry(RegistryKey<? extends Registry<T>> key, Class<T> type, int min, int max)
|
||||
{
|
||||
return new RegistryBuilder<T>().setName(key.func_240901_a_()).setType(type).setIDRange(min, max).addCallback(new NamespacedWrapper.Factory<T>());
|
||||
return new RegistryBuilder<T>().setName(key.func_240901_a_()).setType(type).setIDRange(min, max).hasWrapper();
|
||||
}
|
||||
private static <T extends IForgeRegistryEntry<T>> RegistryBuilder<T> makeRegistry(RegistryKey<? extends Registry<T>> key, Class<T> type, String _default)
|
||||
{
|
||||
return new RegistryBuilder<T>().setName(key.func_240901_a_()).setType(type).setMaxID(MAX_VARINT).addCallback(new NamespacedDefaultedWrapper.Factory<T>()).setDefaultKey(new ResourceLocation(_default));
|
||||
return new RegistryBuilder<T>().setName(key.func_240901_a_()).setType(type).setMaxID(MAX_VARINT).hasWrapper().setDefaultKey(new ResourceLocation(_default));
|
||||
}
|
||||
|
||||
public static <T extends IForgeRegistryEntry<T>> SimpleRegistry<T> getWrapper(RegistryKey<? extends Registry<T>> key, Lifecycle lifecycle)
|
||||
|
@ -360,6 +364,22 @@ public class GameData
|
|||
};
|
||||
}
|
||||
|
||||
public static void setCustomTagTypesFromRegistries()
|
||||
{
|
||||
Set<ResourceLocation> customTagTypes = new HashSet<>();
|
||||
for (Map.Entry<ResourceLocation, ForgeRegistry<? extends IForgeRegistryEntry<?>>> entry : RegistryManager.ACTIVE.registries.entrySet())
|
||||
{
|
||||
ResourceLocation registryName = entry.getKey();
|
||||
if (entry.getValue().getTagFolder() != null && TagRegistryManager.get(registryName) == null)
|
||||
{
|
||||
LOGGER.debug(REGISTRIES, "Registering custom tag type for: {}", registryName);
|
||||
customTagTypes.add(registryName);
|
||||
TagRegistryManager.func_242196_a(registryName, tagCollectionSupplier -> tagCollectionSupplier.getCustomTypeCollection(registryName));
|
||||
}
|
||||
}
|
||||
ForgeTagHandler.setCustomTagTypes(customTagTypes);
|
||||
}
|
||||
|
||||
//Lets us clear the map so we can rebuild it.
|
||||
private static class ClearableObjectIntIdentityMap<I> extends ObjectIntIdentityMap<I>
|
||||
{
|
||||
|
|
|
@ -48,6 +48,9 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
|
|||
private boolean sync = true;
|
||||
private boolean allowOverrides = true;
|
||||
private boolean allowModifications = false;
|
||||
private boolean hasWrapper = false;
|
||||
@Nullable
|
||||
private String tagFolder;
|
||||
private DummyFactory<T> dummyFactory;
|
||||
private MissingFactory<T> missingFactory;
|
||||
private Set<ResourceLocation> legacyNames = new HashSet<>();
|
||||
|
@ -203,6 +206,21 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
|
|||
return this;
|
||||
}
|
||||
|
||||
RegistryBuilder<T> hasWrapper()
|
||||
{
|
||||
this.hasWrapper = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryBuilder<T> tagFolder(String tagFolder)
|
||||
{
|
||||
if (tagFolder == null || !tagFolder.matches("[a-z_/]+")) throw new IllegalArgumentException("Non [a-z_/] character in tag folder " + tagFolder);
|
||||
this.tagFolder = tagFolder;
|
||||
//Also mark this registry as having a wrapper to a vanilla registry so that it can be used in data generators properly
|
||||
hasWrapper();
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistryBuilder<T> legacyName(String name)
|
||||
{
|
||||
return legacyName(new ResourceLocation(name));
|
||||
|
@ -216,6 +234,13 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
|
|||
|
||||
public IForgeRegistry<T> create()
|
||||
{
|
||||
if (hasWrapper)
|
||||
{
|
||||
if (getDefault() == null)
|
||||
addCallback(new NamespacedWrapper.Factory<T>());
|
||||
else
|
||||
addCallback(new NamespacedDefaultedWrapper.Factory<T>());
|
||||
}
|
||||
return RegistryManager.ACTIVE.createRegistry(registryName, this);
|
||||
}
|
||||
|
||||
|
@ -325,6 +350,12 @@ public class RegistryBuilder<T extends IForgeRegistryEntry<T>>
|
|||
return allowModifications;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getTagFolder()
|
||||
{
|
||||
return tagFolder;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DummyFactory<T> getDummyFactory()
|
||||
{
|
||||
|
|
|
@ -66,7 +66,7 @@ import java.util.List;
|
|||
@Mod(GlobalLootModifiersTest.MODID)
|
||||
public class GlobalLootModifiersTest {
|
||||
public static final String MODID = "global_loot_test";
|
||||
public static final boolean ENABLE = false;
|
||||
public static final boolean ENABLE = true;
|
||||
|
||||
public GlobalLootModifiersTest()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.debug.misc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.tags.ITag;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.Biomes;
|
||||
import net.minecraftforge.common.ForgeTagHandler;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.data.ForgeRegistryTagsProvider;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.RegistryObject;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.ForgeRegistryEntry;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryBuilder;
|
||||
|
||||
@Mod(CustomTagTypesTest.MODID)
|
||||
public class CustomTagTypesTest
|
||||
{
|
||||
public static final String MODID = "custom_tag_types_test";
|
||||
private static final ResourceLocation customRegistryName = new ResourceLocation(MODID, "custom_type_registry");
|
||||
private static final DeferredRegister<Custom> CUSTOMS = DeferredRegister.create(Custom.class, MODID);
|
||||
private static final RegistryObject<Custom> CUSTOM = CUSTOMS.register("custom", Custom::new);
|
||||
private static final Supplier<IForgeRegistry<Custom>> CUSTOM_REG = CUSTOMS.makeRegistry(customRegistryName.getPath(),
|
||||
() -> new RegistryBuilder<Custom>().tagFolder(MODID + "/custom_types"));
|
||||
private static final ITag.INamedTag<Biome> OCEANS = ForgeTagHandler.makeWrapperTag(ForgeRegistries.BIOMES, new ResourceLocation(MODID, "oceans"));
|
||||
private static final ITag.INamedTag<Custom> TESTS = ForgeTagHandler.makeWrapperTag(customRegistryName, new ResourceLocation(MODID, "tests"));
|
||||
|
||||
public CustomTagTypesTest()
|
||||
{
|
||||
IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
CUSTOMS.register(modBus);
|
||||
modBus.addListener(this::gatherData);
|
||||
}
|
||||
|
||||
private void gatherData(GatherDataEvent event)
|
||||
{
|
||||
if (event.includeServer())
|
||||
{
|
||||
DataGenerator gen = event.getGenerator();
|
||||
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
|
||||
gen.addProvider(new BiomeTags(gen, existingFileHelper));
|
||||
gen.addProvider(new CustomRegistryTags(gen, existingFileHelper));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Custom extends ForgeRegistryEntry<Custom> {
|
||||
}
|
||||
|
||||
public static class BiomeTags extends ForgeRegistryTagsProvider<Biome>
|
||||
{
|
||||
public BiomeTags(DataGenerator gen, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(gen, ForgeRegistries.BIOMES, MODID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerTags()
|
||||
{
|
||||
func_240522_a_(OCEANS).add(Biomes.OCEAN, Biomes.FROZEN_OCEAN, Biomes.DEEP_OCEAN, Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN,
|
||||
Biomes.COLD_OCEAN, Biomes.DEEP_WARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.DEEP_COLD_OCEAN, Biomes.DEEP_FROZEN_OCEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Biome Tags";
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomRegistryTags extends ForgeRegistryTagsProvider<Custom>
|
||||
{
|
||||
public CustomRegistryTags(DataGenerator gen, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(gen, CUSTOM_REG.get(), MODID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerTags()
|
||||
{
|
||||
func_240522_a_(TESTS).func_240532_a_(CUSTOM.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Custom Registry Tags";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,3 +82,5 @@ license="LGPL v2.1"
|
|||
modId="finite_water_test"
|
||||
[[mods]]
|
||||
modId="scaffolding_test"
|
||||
[[mods]]
|
||||
modId="custom_tag_types_test"
|
||||
|
|
Loading…
Reference in a new issue