diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/LootEntryTypeRegistry.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/LootEntryTypeRegistry.java index 251e2bab6..197579113 100644 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/LootEntryTypeRegistry.java +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/api/registry/LootEntryTypeRegistry.java @@ -20,18 +20,13 @@ import net.fabricmc.fabric.impl.registry.LootEntryTypeRegistryImpl; import net.minecraft.world.loot.entry.LootEntry; /** - * Fabric's extensions to {@code net.minecraft.world.loot.entry.LootEntries} for registering - * custom loot entry types. - * - * @see #register + * @deprecated Use {@link net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry} */ +@Deprecated public interface LootEntryTypeRegistry { + @Deprecated final LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE; - /** - * Registers a loot entry type by its serializer. - * - * @param serializer the loot entry serializer - */ + @Deprecated void register(LootEntry.Serializer<?> serializer); } diff --git a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/registry/LootEntryTypeRegistryImpl.java b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/registry/LootEntryTypeRegistryImpl.java index c07cad5c2..9182cf50e 100644 --- a/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/registry/LootEntryTypeRegistryImpl.java +++ b/fabric-content-registries-v0/src/main/java/net/fabricmc/fabric/impl/registry/LootEntryTypeRegistryImpl.java @@ -21,10 +21,9 @@ import net.minecraft.world.loot.entry.LootEntries; import net.minecraft.world.loot.entry.LootEntry; import java.lang.reflect.Method; -import java.util.function.Consumer; +@Deprecated public final class LootEntryTypeRegistryImpl implements LootEntryTypeRegistry { - private static Consumer<LootEntry.Serializer<?>> registerFunction; public static final LootEntryTypeRegistryImpl INSTANCE = new LootEntryTypeRegistryImpl(); private static final Method REGISTER_METHOD; diff --git a/fabric-loot-tables-v1/build.gradle b/fabric-loot-tables-v1/build.gradle new file mode 100644 index 000000000..1b3ee6646 --- /dev/null +++ b/fabric-loot-tables-v1/build.gradle @@ -0,0 +1,6 @@ +archivesBaseName = "fabric-loot-tables-v1" +version = "0.1.0" + +dependencies { + compile project(path: ':fabric-api-base', configuration: 'dev') +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPool.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPool.java new file mode 100644 index 000000000..5ce08cf96 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPool.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootTableRange; +import net.minecraft.world.loot.condition.LootCondition; +import net.minecraft.world.loot.entry.LootEntry; +import net.minecraft.world.loot.function.LootFunction; + +import java.util.List; + +/** + * An interface implemented by all {@code net.minecraft.world.loot.LootPool} instances when + * Fabric API is present. Contains accessors for various fields. + */ +public interface FabricLootPool { + default LootPool asVanilla() { + return (LootPool) this; + } + List<LootEntry> getEntries(); + List<LootCondition> getConditions(); + List<LootFunction> getFunctions(); + LootTableRange getRollsRange(); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPoolBuilder.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPoolBuilder.java new file mode 100644 index 000000000..b694563b6 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootPoolBuilder.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import net.fabricmc.fabric.mixin.loot.LootPoolBuilderHooks; +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootTableRange; +import net.minecraft.world.loot.condition.LootCondition; +import net.minecraft.world.loot.entry.LootEntry; +import net.minecraft.world.loot.function.LootFunction; + +public class FabricLootPoolBuilder extends LootPool.Builder { + private final LootPoolBuilderHooks extended = (LootPoolBuilderHooks) this; + + private FabricLootPoolBuilder() {} + + private FabricLootPoolBuilder(LootPool pool) { + copyFrom(pool, true); + } + + @Override + public FabricLootPoolBuilder withRolls(LootTableRange range) { + super.withRolls(range); + return this; + } + + @Override + public FabricLootPoolBuilder withEntry(LootEntry.Builder<?> entry) { + super.withEntry(entry); + return this; + } + + @Override + public FabricLootPoolBuilder withCondition(LootCondition.Builder condition) { + super.method_356(condition); + return this; + } + + @Override + public FabricLootPoolBuilder withFunction(LootFunction.Builder function) { + super.method_353(function); + return this; + } + + public FabricLootPoolBuilder withEntry(LootEntry entry) { + extended.getEntries().add(entry); + return this; + } + + public FabricLootPoolBuilder withCondition(LootCondition condition) { + extended.getConditions().add(condition); + return this; + } + + public FabricLootPoolBuilder withFunction(LootFunction function) { + extended.getFunctions().add(function); + return this; + } + + /** + * Copies the entries, conditions and functions of the {@code pool} to this + * builder. + * + * This is equal to {@code copyFrom(pool, false)}. + */ + public FabricLootPoolBuilder copyFrom(LootPool pool) { + return copyFrom(pool, false); + } + + /** + * Copies the entries, conditions and functions of the {@code pool} to this + * builder. + * + * If {@code copyRolls} is true, the {@link FabricLootPool#getRollsRange rolls} of the pool are also copied. + */ + public FabricLootPoolBuilder copyFrom(LootPool pool, boolean copyRolls) { + FabricLootPool extendedPool = (FabricLootPool) pool; + extended.getConditions().addAll(extendedPool.getConditions()); + extended.getFunctions().addAll(extendedPool.getFunctions()); + extended.getEntries().addAll(extendedPool.getEntries()); + + if (copyRolls) { + withRolls(extendedPool.getRollsRange()); + } + + return this; + } + + public static FabricLootPoolBuilder builder() { + return new FabricLootPoolBuilder(); + } + + public static FabricLootPoolBuilder of(LootPool pool) { + return new FabricLootPoolBuilder(pool); + } +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplier.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplier.java new file mode 100644 index 000000000..cf2e56106 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplier.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootSupplier; +import net.minecraft.world.loot.context.LootContextType; +import net.minecraft.world.loot.function.LootFunction; + +import java.util.List; + +/** + * An interface implemented by all {@code net.minecraft.world.loot.LootSupplier} instances when + * Fabric API is present. Contains accessors for various fields. + */ +public interface FabricLootSupplier { + default LootSupplier asVanilla() { + return (LootSupplier) this; + } + List<LootPool> getPools(); + List<LootFunction> getFunctions(); + LootContextType getType(); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplierBuilder.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplierBuilder.java new file mode 100644 index 000000000..0174436b6 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootSupplierBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import net.fabricmc.fabric.mixin.loot.LootSupplierBuilderHooks; +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootSupplier; +import net.minecraft.world.loot.context.LootContextType; +import net.minecraft.world.loot.function.LootFunction; + +import java.util.Collection; + +public class FabricLootSupplierBuilder extends LootSupplier.Builder { + private final LootSupplierBuilderHooks extended = (LootSupplierBuilderHooks) this; + + protected FabricLootSupplierBuilder() {} + + private FabricLootSupplierBuilder(LootSupplier supplier) { + copyFrom(supplier, true); + } + + @Override + public FabricLootSupplierBuilder withPool(LootPool.Builder pool) { + super.withPool(pool); + return this; + } + + @Override + public FabricLootSupplierBuilder withType(LootContextType type) { + super.withType(type); + return this; + } + + @Override + public FabricLootSupplierBuilder withFunction(LootFunction.Builder function) { + super.method_335(function); + return this; + } + + public FabricLootSupplierBuilder withPool(LootPool pool) { + extended.getPools().add(pool); + return this; + } + + public FabricLootSupplierBuilder withFunction(LootFunction function) { + extended.getFunctions().add(function); + return this; + } + + public FabricLootSupplierBuilder withPools(Collection<LootPool> pools) { + pools.forEach(this::withPool); + return this; + } + + public FabricLootSupplierBuilder withFunctions(Collection<LootFunction> functions) { + functions.forEach(this::withFunction); + return this; + } + + /** + * Copies the pools and functions of the {@code supplier} to this builder. + * This is equal to {@code copyFrom(supplier, false)}. + */ + public FabricLootSupplierBuilder copyFrom(LootSupplier supplier) { + return copyFrom(supplier, false); + } + + /** + * Copies the pools and functions of the {@code supplier} to this builder. + * If {@code copyType} is true, the {@link FabricLootSupplier#getType type} of the supplier is also copied. + */ + public FabricLootSupplierBuilder copyFrom(LootSupplier supplier, boolean copyType) { + FabricLootSupplier extendedSupplier = (FabricLootSupplier) supplier; + extended.getPools().addAll(extendedSupplier.getPools()); + extended.getFunctions().addAll(extendedSupplier.getFunctions()); + + if (copyType) { + withType(extendedSupplier.getType()); + } + + return this; + } + + public static FabricLootSupplierBuilder builder() { + return new FabricLootSupplierBuilder(); + } + + public static FabricLootSupplierBuilder of(LootSupplier supplier) { + return new FabricLootSupplierBuilder(supplier); + } +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootEntryTypeRegistry.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootEntryTypeRegistry.java new file mode 100644 index 000000000..fa7fbea1c --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootEntryTypeRegistry.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import net.fabricmc.fabric.impl.loot.LootEntryTypeRegistryImpl; +import net.minecraft.world.loot.entry.LootEntry; + +/** + * Fabric's extensions to {@code net.minecraft.world.loot.entry.LootEntries} for registering + * custom loot entry types. + * + * @see #register + */ +public interface LootEntryTypeRegistry { + final LootEntryTypeRegistry INSTANCE = LootEntryTypeRegistryImpl.INSTANCE; + + /** + * Registers a loot entry type by its serializer. + * + * @param serializer the loot entry serializer + */ + void register(LootEntry.Serializer<?> serializer); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootJsonParser.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootJsonParser.java new file mode 100644 index 000000000..58df54867 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/LootJsonParser.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1; + +import com.google.gson.Gson; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.util.JsonHelper; +import net.minecraft.util.Lazy; +import net.minecraft.world.loot.*; +import net.minecraft.world.loot.condition.LootCondition; +import net.minecraft.world.loot.entry.LootEntry; +import net.minecraft.world.loot.function.LootFunction; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.stream.Stream; + +public final class LootJsonParser { + /* Reading this from LootManager to access all serializers from vanilla. */ + private static final Lazy<Gson> GSON = new Lazy<>(() -> { + try { + Field gsonField = Stream.of(LootManager.class.getDeclaredFields()) + .filter(field -> field.getType() == Gson.class) + .findFirst() + .orElseThrow(() -> new RuntimeException("Gson not found in LootManager!")); + gsonField.setAccessible(true); + return (Gson) gsonField.get(null); + } catch (Exception e) { + throw new RuntimeException("Exception while getting Gson instance from LootManager", e); + } + }); + + private LootJsonParser() { + + } + + public static <T> T read(Reader json, Class<T> c) { + return JsonHelper.deserialize(GSON.get(), json, c); + } + + public static <T> T read(String json, Class<T> c) { + return JsonHelper.deserialize(GSON.get(), json, c); + } +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/event/LootTableLoadingCallback.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/event/LootTableLoadingCallback.java new file mode 100644 index 000000000..f59018088 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/event/LootTableLoadingCallback.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.loot.v1.event; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.world.loot.LootManager; +import net.minecraft.world.loot.LootSupplier; + +/** + * An event handler that is called when loot tables are loaded. + * Use {@link #EVENT} to register instances. + */ +@FunctionalInterface +public interface LootTableLoadingCallback { + @FunctionalInterface + interface LootTableSetter { + void set(LootSupplier supplier); + } + + final Event<LootTableLoadingCallback> EVENT = EventFactory.createArrayBacked( + LootTableLoadingCallback.class, + (listeners) -> (resourceManager, manager, id, supplier, setter) -> { + for (LootTableLoadingCallback callback : listeners) { + callback.onLootTableLoading(resourceManager, manager, id, supplier, setter); + } + } + ); + + void onLootTableLoading(ResourceManager resourceManager, LootManager manager, Identifier id, FabricLootSupplierBuilder supplier, LootTableSetter setter); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/impl/loot/LootEntryTypeRegistryImpl.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/impl/loot/LootEntryTypeRegistryImpl.java new file mode 100644 index 000000000..194c9a8a4 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/impl/loot/LootEntryTypeRegistryImpl.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.loot; + +import net.minecraft.world.loot.entry.LootEntries; +import net.minecraft.world.loot.entry.LootEntry; + +import java.lang.reflect.Method; + +public final class LootEntryTypeRegistryImpl implements net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry { + public static final LootEntryTypeRegistryImpl INSTANCE = new LootEntryTypeRegistryImpl(); + private static final Method REGISTER_METHOD; + + static { + Method target = null; + for (Method m : LootEntries.class.getDeclaredMethods()) { + if (m.getParameterCount() == 1 && m.getParameterTypes()[0] == LootEntry.Serializer.class) { + if (target != null) { + throw new RuntimeException("More than one register-like method found in LootEntries!"); + } else { + target = m; + } + } + } + + if (target == null) { + throw new RuntimeException("Could not find register-like method in LootEntries!"); + } else { + REGISTER_METHOD = target; + REGISTER_METHOD.setAccessible(true); + } + } + + private LootEntryTypeRegistryImpl() { + } + + @Override + public void register(LootEntry.Serializer<?> serializer) { + try { + REGISTER_METHOD.invoke(null, serializer); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootPoolBuilderHooks.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootPoolBuilderHooks.java new file mode 100644 index 000000000..f1bddb8ad --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootPoolBuilderHooks.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.loot; + +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.condition.LootCondition; +import net.minecraft.world.loot.entry.LootEntry; +import net.minecraft.world.loot.function.LootFunction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(LootPool.Builder.class) +public interface LootPoolBuilderHooks { + @Accessor + List<LootEntry> getEntries(); + @Accessor + List<LootCondition> getConditions(); + @Accessor + List<LootFunction> getFunctions(); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootSupplierBuilderHooks.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootSupplierBuilderHooks.java new file mode 100644 index 000000000..05f7f5836 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/LootSupplierBuilderHooks.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.loot; + +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootSupplier; +import net.minecraft.world.loot.function.LootFunction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(LootSupplier.Builder.class) +public interface LootSupplierBuilderHooks { + @Accessor + List<LootPool> getPools(); + @Accessor + List<LootFunction> getFunctions(); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootManager.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootManager.java new file mode 100644 index 000000000..4187ecc35 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootManager.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.loot; + +import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback; +import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; +import net.minecraft.world.loot.LootManager; +import net.minecraft.world.loot.LootSupplier; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.HashMap; +import java.util.Map; + +@Mixin(LootManager.class) +public class MixinLootManager { + @Shadow @Final private Map<Identifier, LootSupplier> suppliers; + + @Inject(method = "apply", at = @At("RETURN")) + private void apply(ResourceManager manager, CallbackInfo info) { + Map<Identifier, LootSupplier> newSuppliers = new HashMap<>(); + + suppliers.forEach((id, supplier) -> { + FabricLootSupplierBuilder builder = FabricLootSupplierBuilder.of(supplier); + + //noinspection ConstantConditions + LootTableLoadingCallback.EVENT.invoker().onLootTableLoading( + manager, (LootManager) (Object) this, id, builder, (s) -> newSuppliers.put(id, s) + ); + + newSuppliers.computeIfAbsent(id, (i) -> builder.create()); + }); + + for (Identifier id : newSuppliers.keySet()) { + suppliers.put(id, newSuppliers.get(id)); + } + } +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootPool.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootPool.java new file mode 100644 index 000000000..c9ff1cd01 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootPool.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.loot; + +import net.fabricmc.fabric.api.loot.v1.FabricLootPool; +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootTableRange; +import net.minecraft.world.loot.condition.LootCondition; +import net.minecraft.world.loot.entry.LootEntry; +import net.minecraft.world.loot.function.LootFunction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Arrays; +import java.util.List; + +@Mixin(LootPool.class) +public abstract class MixinLootPool implements FabricLootPool { + @Shadow @Final private LootEntry[] entries; + + @Shadow @Final private LootCondition[] conditions; + + @Shadow @Final private LootFunction[] functions; + + @Override + public List<LootEntry> getEntries() { + return Arrays.asList(entries); + } + + @Override + public List<LootCondition> getConditions() { + return Arrays.asList(conditions); + } + + @Override + public List<LootFunction> getFunctions() { + return Arrays.asList(functions); + } + + @Accessor + @Override + public abstract LootTableRange getRollsRange(); +} diff --git a/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootSupplier.java b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootSupplier.java new file mode 100644 index 000000000..a5c63152d --- /dev/null +++ b/fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/mixin/loot/MixinLootSupplier.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.loot; + +import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier; +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.LootSupplier; +import net.minecraft.world.loot.context.LootContextType; +import net.minecraft.world.loot.function.LootFunction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Arrays; +import java.util.List; + +@Mixin(LootSupplier.class) +public abstract class MixinLootSupplier implements FabricLootSupplier { + @Shadow @Final private LootPool[] pools; + @Shadow @Final private LootFunction[] functions; + + @Override + public List<LootPool> getPools() { + return Arrays.asList(pools); + } + + @Override + public List<LootFunction> getFunctions() { + return Arrays.asList(functions); + } + + @Accessor + @Override + public abstract LootContextType getType(); +} diff --git a/fabric-loot-tables-v1/src/main/resources/fabric-loot-tables-v1.mixins.json b/fabric-loot-tables-v1/src/main/resources/fabric-loot-tables-v1.mixins.json new file mode 100644 index 000000000..0d120730d --- /dev/null +++ b/fabric-loot-tables-v1/src/main/resources/fabric-loot-tables-v1.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "net.fabricmc.fabric.mixin.loot", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "LootPoolBuilderHooks", + "LootSupplierBuilderHooks", + "MixinLootManager", + "MixinLootPool", + "MixinLootSupplier" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/fabric-loot-tables-v1/src/main/resources/fabric.mod.json b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..6aa0d2d58 --- /dev/null +++ b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json @@ -0,0 +1,13 @@ +{ + "schemaVersion": 1, + "id": "fabric-loot-tables-v1", + "version": "${version}", + "license": "Apache-2.0", + "depends": { + "fabricloader": ">=0.4.0", + "fabric-api-base": "*" + }, + "mixins": [ + "fabric-loot-tables-v1.mixins.json" + ] +} diff --git a/fabric-testmods/java/net/fabricmc/fabric/loot/LootTableMod.java b/fabric-testmods/java/net/fabricmc/fabric/loot/LootTableMod.java new file mode 100644 index 000000000..9646c059d --- /dev/null +++ b/fabric-testmods/java/net/fabricmc/fabric/loot/LootTableMod.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.loot; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.loot.LootTableLoadingCallback; +import net.fabricmc.fabric.api.loot.FabricLootPoolBuilder; +import net.fabricmc.fabric.api.loot.LootUtilities; +import net.minecraft.item.Items; +import net.minecraft.world.loot.ConstantLootTableRange; +import net.minecraft.world.loot.LootPool; +import net.minecraft.world.loot.condition.SurvivesExplosionLootCondition; +import net.minecraft.world.loot.entry.ItemEntry; +import net.minecraft.world.loot.entry.LootEntry; + +public class LootTableMod implements ModInitializer { + private static final String LOOT_ENTRY_JSON = "{\"type\":\"minecraft:item\",\"name\":\"minecraft:apple\"}"; + + @Override + public void onInitialize() { + LootTableLoadingCallback.EVENT.register((manager, id, supplier) -> { + if ("minecraft:blocks/dirt".equals(id.toString())) { + LootEntry entryFromString = LootUtilities.readEntryFromJson(LOOT_ENTRY_JSON); + + LootPool pool = FabricLootPoolBuilder.builder() + .withEntry(ItemEntry.builder(Items.FEATHER)) + .withEntry(entryFromString) + .withRolls(ConstantLootTableRange.create(1)) + .withCondition(SurvivesExplosionLootCondition.method_871()) + .build(); + + supplier.withPool(pool); + } + }); + } +} diff --git a/settings.gradle b/settings.gradle index 7e79bd499..32bda252f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,6 +22,7 @@ include 'fabric-events-interaction-v0' include 'fabric-events-lifecycle-v0' include 'fabric-item-groups-v0' include 'fabric-keybindings-v0' +include 'fabric-loot-tables-v1' include 'fabric-mining-levels-v0' include 'fabric-models-v0' include 'fabric-networking-v0'