Loot table manipulation API (#160)

This commit is contained in:
Juuxel 2019-06-09 21:47:28 +02:00 committed by asie
parent 6dad974e70
commit 05f11b75e4
20 changed files with 827 additions and 11 deletions

View file

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

View file

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

View file

@ -0,0 +1,6 @@
archivesBaseName = "fabric-loot-tables-v1"
version = "0.1.0"
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,15 @@
{
"required": true,
"package": "net.fabricmc.fabric.mixin.loot",
"compatibilityLevel": "JAVA_8",
"mixins": [
"LootPoolBuilderHooks",
"LootSupplierBuilderHooks",
"MixinLootManager",
"MixinLootPool",
"MixinLootSupplier"
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -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"
]
}

View file

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

View file

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