mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-24 08:38:17 -05:00
Loot table API v2, iteration 2 (#1241)
* Improve loot table API Alternative to #629. - Deprecates all classes and methods that use outdated Yarn names. - Adds FabricLootTable and FabricLootTableBuilder to replace the LootSupplier naming variants. - Deprecates LootEntryTypeRegistry and LootJsonParser as their functionality is exposed in vanilla now. - Adds methods to FabricLootPoolBuilder for working with collections as builder parameters. - FabricLootPool and FabricLootTable/Supplier now return immutable lists instead of modifiable fixed-size ones. Still WIP: LootTableLoadingCallback uses the deprecated FabricLootSupplier. Update fabric-loot-tables-v1/src/main/java/net/fabricmc/fabric/api/loot/v1/FabricLootTableBuilder.java Co-authored-by: i509VCB <i509vcb@gmail.com> Fix compilation Create loot table API v2 Move incorrect classes and revert unnecessary change Add test for replacing loot tables Document FabricLootPools builder() -> create() Add accessor for LootPool.bonusRolls Add loot pool builder method for bonus rolls Use Blocks.DIRT.getLootTableId() instead of raw string in v1 loot test mod Make links in deprecation docs cleaner Make FabricLootPoolBuilder.copyFrom(pool, true) also copy bonus rolls ...and mention it in the javadoc Remove copyFrom from v2 builders It seems like a maintainability mess if Mojang ever decides to extend loot tables, and the chosen boolean flags are arbitrary. It also doesn't really have use cases apart from the internal use in the copyOf methods, and even then users can replicate its functionality with the other API methods. Rename 'supplier' to 'table' in LootManagerMixin Add 'stable' lifecycle to loot-table-api-v2, deprecate v1 Add internal comment for implementors about updates Cancel all remaining callbacks when a loot table is replaced Remove unused shadowed logger from LootManagerMixin Migrate subproject versioning to new system Start the AW migration Update test mod * Use interface injection * Fix some issues * Remove outdated bonusRolls test from LootTest It's a vanilla feature now. * Create transitive access widener module * Replace LootTableLoadingCallback with two events * Use friendlier exception message * Add resource source tracking * Add loot table sources * Add resource pack source for DefaultResourcePack$1 (anon resource) * Add license header * Make FabricResource an internal API in resource loader * Remove my TAW module * Add loot table-related TAWs * Run CI * Fix LootUtil.determineSource giving null values * Clarify LootUtil comment * Rename loot-table-api => loot-api + minor comment changes * Add README * Fix mixin file name * Use ImmutableMap.Builder instead of HashMap.computeIfAbsent in loot event impl * Prefix accessor methods with fabric_ to prevent conflicts with loot v1 * Document mixins * Document mixins more extensively * Improve NRMMixin comments * Change weird wording in FabricResourceImpl * Minor updates - Support new built-in mod respack source - Fix ResourceMixin comment - Add more docs to LootTableEvents.MODIFY - Add package-info * Add license header
This commit is contained in:
parent
2c7b4abb73
commit
e747827905
51 changed files with 1590 additions and 175 deletions
29
fabric-loot-api-v2/README.md
Normal file
29
fabric-loot-api-v2/README.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Fabric Loot API (v2)
|
||||
|
||||
This module includes APIs for modifying and creating loot tables.
|
||||
|
||||
## [Loot table events](src/main/java/net/fabricmc/fabric/api/loot/v2/LootTableEvents.java)
|
||||
|
||||
This class provides two events for modifying loot tables.
|
||||
|
||||
`LootTableEvents.REPLACE` runs first and lets you replace loot tables completely.
|
||||
|
||||
`LootTableEvents.MODIFY` runs after and lets you modify loot tables, including the ones created in `REPLACE`,
|
||||
by adding new loot pools or loot functions to them.
|
||||
|
||||
### Loot table sources
|
||||
|
||||
Both events have access to a [loot table source](src/main/java/net/fabricmc/fabric/api/loot/v2/LootTableSource.java)
|
||||
that you can use to check where a loot table is loaded from.
|
||||
|
||||
For example, you can use this to check if a loot table is from a user data pack and
|
||||
not modify the user-provided data in your event.
|
||||
|
||||
## Enhanced loot table and loot pool builders
|
||||
|
||||
`LootTable.Builder` and `LootPool.Builder` implement
|
||||
injected interfaces ([`FabricLootTableBuilder`](src/main/java/net/fabricmc/fabric/api/loot/v2/FabricLootTableBuilder.java)
|
||||
and [`FabricLootPoolBuilder`](src/main/java/net/fabricmc/fabric/api/loot/v2/FabricLootPoolBuilder.java))
|
||||
which have additional methods for dealing with already-built objects and collections of objects.
|
||||
|
||||
Those interfaces also have `copyOf` methods for creating copies of existing loot tables/pools as builders.
|
7
fabric-loot-api-v2/build.gradle
Normal file
7
fabric-loot-api-v2/build.gradle
Normal file
|
@ -0,0 +1,7 @@
|
|||
archivesBaseName = "fabric-loot-api-v2"
|
||||
version = getSubprojectVersion(project)
|
||||
|
||||
moduleDependencies(project, [
|
||||
'fabric-api-base',
|
||||
'fabric-resource-loader-v0'
|
||||
])
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.v2;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.mixin.loot.LootPoolAccessor;
|
||||
|
||||
/**
|
||||
* Convenience extensions to {@link LootPool.Builder}
|
||||
* for adding pre-built objects or collections.
|
||||
*
|
||||
* <p>This interface is automatically injected to {@link LootPool.Builder}.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface FabricLootPoolBuilder {
|
||||
/**
|
||||
* Adds an entry to this builder.
|
||||
*
|
||||
* @param entry the added loot entry
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder with(LootPoolEntry entry) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entries to this builder.
|
||||
*
|
||||
* @param entries the added loot entries
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder with(Collection<? extends LootPoolEntry> entries) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition to this builder.
|
||||
*
|
||||
* @param condition the added condition
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder conditionally(LootCondition condition) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds conditions to this builder.
|
||||
*
|
||||
* @param conditions the added conditions
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder conditionally(Collection<? extends LootCondition> conditions) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a function to this builder.
|
||||
*
|
||||
* @param function the applied loot function
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder apply(LootFunction function) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies loot functions to this builder.
|
||||
*
|
||||
* @param functions the applied loot functions
|
||||
* @return this builder
|
||||
*/
|
||||
default LootPool.Builder apply(Collection<? extends LootFunction> functions) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder copy of a loot pool.
|
||||
*
|
||||
* @param pool the loot pool
|
||||
* @return the copied builder
|
||||
*/
|
||||
static LootPool.Builder copyOf(LootPool pool) {
|
||||
LootPoolAccessor accessor = (LootPoolAccessor) pool;
|
||||
return LootPool.builder()
|
||||
.rolls(accessor.fabric_getRolls())
|
||||
.bonusRolls(accessor.fabric_getBonusRolls())
|
||||
.with(List.of(accessor.fabric_getEntries()))
|
||||
.conditionally(List.of(accessor.fabric_getConditions()))
|
||||
.apply(List.of(accessor.fabric_getFunctions()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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.v2;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.mixin.loot.LootTableAccessor;
|
||||
|
||||
/**
|
||||
* Convenience extensions to {@link LootTable.Builder}
|
||||
* for adding pre-built objects or collections.
|
||||
*
|
||||
* <p>This interface is automatically injected to {@link LootTable.Builder}.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface FabricLootTableBuilder {
|
||||
/**
|
||||
* Adds a loot pool to this builder.
|
||||
*
|
||||
* @param pool the added pool
|
||||
* @return this builder
|
||||
*/
|
||||
default LootTable.Builder pool(LootPool pool) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a loot function to this builder.
|
||||
*
|
||||
* @param function the applied function
|
||||
* @return this builder
|
||||
*/
|
||||
default LootTable.Builder apply(LootFunction function) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds loot pools to this builder.
|
||||
*
|
||||
* @param pools the added pools
|
||||
* @return this builder
|
||||
*/
|
||||
default LootTable.Builder pools(Collection<? extends LootPool> pools) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies loot functions to this builder.
|
||||
*
|
||||
* @param functions the applied functions
|
||||
* @return this builder
|
||||
*/
|
||||
default LootTable.Builder apply(Collection<? extends LootFunction> functions) {
|
||||
throw new UnsupportedOperationException("Implemented via mixin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder copy of a loot table.
|
||||
*
|
||||
* @param table the loot table
|
||||
* @return the copied builder
|
||||
*/
|
||||
static LootTable.Builder copyOf(LootTable table) {
|
||||
LootTable.Builder builder = LootTable.builder();
|
||||
LootTableAccessor accessor = (LootTableAccessor) table;
|
||||
|
||||
builder.type(table.getType());
|
||||
builder.pools(List.of(accessor.fabric_getPools()));
|
||||
builder.apply(List.of(accessor.fabric_getFunctions()));
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.v2;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.loot.LootManager;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Events for manipulating loot tables.
|
||||
*/
|
||||
public final class LootTableEvents {
|
||||
/**
|
||||
* This event can be used to replace loot tables.
|
||||
* If a loot table is replaced, the iteration will stop for that loot table.
|
||||
*/
|
||||
public static final Event<Replace> REPLACE = EventFactory.createArrayBacked(Replace.class, listeners -> (resourceManager, lootManager, id, original, source) -> {
|
||||
for (Replace listener : listeners) {
|
||||
@Nullable LootTable replaced = listener.replaceLootTable(resourceManager, lootManager, id, original, source);
|
||||
|
||||
if (replaced != null) {
|
||||
return replaced;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
/**
|
||||
* This event can be used to modify loot tables.
|
||||
* The main use case is to add items to vanilla or mod loot tables (e.g. modded seeds to grass).
|
||||
*
|
||||
* <p>You can also modify loot tables that are created by {@link #REPLACE}.
|
||||
* They have the loot table source {@link LootTableSource#REPLACED}.
|
||||
*
|
||||
* <h2>Example: adding diamonds to the cobblestone loot table</h2>
|
||||
* <pre>
|
||||
* {@code
|
||||
* LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> {
|
||||
* // If the loot table is for the cobblestone block and it is not overridden by a user:
|
||||
* if (Blocks.COBBLESTONE.getLootTableId().equals(id) && source.isBuiltin()) {
|
||||
* // Create a new loot pool that will hold the diamonds.
|
||||
* LootPool.Builder pool = LootPool.builder()
|
||||
* // Add diamonds...
|
||||
* .with(ItemEntry.builder(Items.DIAMOND))
|
||||
* // ...only if the block would survive a potential explosion.
|
||||
* .conditionally(SurvivesExplosionLootCondition.builder());
|
||||
*
|
||||
* // Add the loot pool to the loot table
|
||||
* tableBuilder.pool(pool);
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public static final Event<Modify> MODIFY = EventFactory.createArrayBacked(Modify.class, listeners -> (resourceManager, lootManager, id, tableBuilder, source) -> {
|
||||
for (Modify listener : listeners) {
|
||||
listener.modifyLootTable(resourceManager, lootManager, id, tableBuilder, source);
|
||||
}
|
||||
});
|
||||
|
||||
public interface Replace {
|
||||
/**
|
||||
* Replaces loot tables.
|
||||
*
|
||||
* @param resourceManager the server resource manager
|
||||
* @param lootManager the loot manager
|
||||
* @param id the loot table ID
|
||||
* @param original the original loot table
|
||||
* @param source the source of the original loot table
|
||||
* @return the new loot table, or null if it wasn't replaced
|
||||
*/
|
||||
@Nullable
|
||||
LootTable replaceLootTable(ResourceManager resourceManager, LootManager lootManager, Identifier id, LootTable original, LootTableSource source);
|
||||
}
|
||||
|
||||
public interface Modify {
|
||||
/**
|
||||
* Called when a loot table is loading to modify loot tables.
|
||||
*
|
||||
* @param resourceManager the server resource manager
|
||||
* @param lootManager the loot manager
|
||||
* @param id the loot table ID
|
||||
* @param tableBuilder a builder of the loot table being loaded
|
||||
* @param source the source of the loot table
|
||||
*/
|
||||
void modifyLootTable(ResourceManager resourceManager, LootManager lootManager, Identifier id, LootTable.Builder tableBuilder, LootTableSource source);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.v2;
|
||||
|
||||
/**
|
||||
* Describes where a loot table has been loaded from.
|
||||
*/
|
||||
public enum LootTableSource {
|
||||
/**
|
||||
* A loot table loaded from the default data pack.
|
||||
*/
|
||||
VANILLA(true),
|
||||
|
||||
/**
|
||||
* A loot table loaded from mods' bundled resources.
|
||||
*
|
||||
* <p>This includes the additional builtin data packs registered by mods
|
||||
* with Fabric Resource Loader.
|
||||
*/
|
||||
MOD(true),
|
||||
|
||||
/**
|
||||
* A loot table loaded from an external data pack.
|
||||
*/
|
||||
DATA_PACK(false),
|
||||
|
||||
/**
|
||||
* A loot table created in {@link LootTableEvents#REPLACE}.
|
||||
*/
|
||||
REPLACED(false);
|
||||
|
||||
private final boolean builtin;
|
||||
|
||||
LootTableSource(boolean builtin) {
|
||||
this.builtin = builtin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this loot table source is builtin
|
||||
* and bundled in the vanilla or mod resources.
|
||||
*
|
||||
* <p>{@link #VANILLA} and {@link #MOD} are builtin.
|
||||
*
|
||||
* @return {@code true} if builtin, {@code false} otherwise
|
||||
*/
|
||||
public boolean isBuiltin() {
|
||||
return builtin;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Fabric Loot API for manipulating and creating loot tables.
|
||||
*
|
||||
* <h2>Events</h2>
|
||||
* {@link net.fabricmc.fabric.api.loot.v2.LootTableEvents} has events to modify existing loot tables,
|
||||
* or outright replace them with a new loot table.
|
||||
*
|
||||
* <p>You can also check where loot tables are coming from in those events with
|
||||
* {@link net.fabricmc.fabric.api.loot.v2.LootTableSource}. This is useful when you only want to modify
|
||||
* loot tables from mods or vanilla, but not user-created data packs.
|
||||
*
|
||||
* <h2>Extended loot table and pool builders</h2>
|
||||
* This API has injected interfaces to add useful methods to
|
||||
* {@linkplain net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder loot table} and
|
||||
* {@linkplain net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder loot pool} builders.
|
||||
* They let you add pre-built objects instead of builders, and collections of objects to the builder
|
||||
* with one method call.
|
||||
*/
|
||||
package net.fabricmc.fabric.api.loot.v2;
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableSource;
|
||||
import net.fabricmc.fabric.impl.resource.loader.BuiltinModResourcePackSource;
|
||||
import net.fabricmc.fabric.impl.resource.loader.FabricResource;
|
||||
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator;
|
||||
|
||||
public final class LootUtil {
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("fabric-loot-api-v2");
|
||||
|
||||
public static LootTableSource determineSource(Identifier lootTableId, ResourceManager resourceManager) {
|
||||
Identifier resourceId = new Identifier(lootTableId.getNamespace(), "loot_tables/%s.json".formatted(lootTableId.getPath()));
|
||||
|
||||
try (Resource resource = resourceManager.getResource(resourceId)) {
|
||||
ResourcePackSource packSource = ((FabricResource) resource).getFabricPackSource();
|
||||
|
||||
if (packSource == ResourcePackSource.PACK_SOURCE_BUILTIN) {
|
||||
return LootTableSource.VANILLA;
|
||||
} else if (packSource == ModResourcePackCreator.RESOURCE_PACK_SOURCE || packSource instanceof BuiltinModResourcePackSource) {
|
||||
return LootTableSource.MOD;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Could not open resource for loot table {} to check its source", lootTableId, e);
|
||||
}
|
||||
|
||||
// If not builtin or mod, assume external data pack.
|
||||
// It might also be a virtual loot table injected via mixin instead of being loaded
|
||||
// from a resource, but we can't determine that here.
|
||||
return LootTableSource.DATA_PACK;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.mixin.loot;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonObject;
|
||||
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 net.minecraft.loot.LootManager;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.LootTables;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder;
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableSource;
|
||||
import net.fabricmc.fabric.impl.loot.LootUtil;
|
||||
|
||||
/**
|
||||
* Implements the events from {@link LootTableEvents}.
|
||||
*/
|
||||
@Mixin(LootManager.class)
|
||||
abstract class LootManagerMixin {
|
||||
@Shadow
|
||||
private Map<Identifier, LootTable> tables;
|
||||
|
||||
@Inject(method = "apply", at = @At("RETURN"))
|
||||
private void apply(Map<Identifier, JsonObject> jsonMap, ResourceManager resourceManager, Profiler profiler, CallbackInfo info) {
|
||||
// The builder for the new LootManager.tables map with modified loot tables.
|
||||
// We're using an immutable map to match vanilla.
|
||||
ImmutableMap.Builder<Identifier, LootTable> newTables = ImmutableMap.builder();
|
||||
|
||||
tables.forEach((id, table) -> {
|
||||
if (id.equals(LootTables.EMPTY)) {
|
||||
// This is a special table and cannot be modified.
|
||||
// Vanilla also warns about that.
|
||||
return;
|
||||
}
|
||||
|
||||
// noinspection ConstantConditions
|
||||
LootManager lootManager = (LootManager) (Object) this;
|
||||
LootTableSource source = LootUtil.determineSource(id, resourceManager);
|
||||
|
||||
// Invoke the REPLACE event for the current loot table.
|
||||
LootTable replacement = LootTableEvents.REPLACE.invoker().replaceLootTable(resourceManager, lootManager, id, table, source);
|
||||
|
||||
if (replacement != null) {
|
||||
// Set the loot table to MODIFY to be the replacement loot table.
|
||||
// The MODIFY event will also see it as a replaced loot table via the source.
|
||||
table = replacement;
|
||||
source = LootTableSource.REPLACED;
|
||||
}
|
||||
|
||||
// Turn the current table into a modifiable builder and invoke the MODIFY event.
|
||||
LootTable.Builder builder = FabricLootTableBuilder.copyOf(table);
|
||||
LootTableEvents.MODIFY.invoker().modifyLootTable(resourceManager, lootManager, id, builder, source);
|
||||
|
||||
// Turn the builder back into a loot table and store it in the new table.
|
||||
newTables.put(id, builder.build());
|
||||
});
|
||||
|
||||
// Finally, store the new loot table map in the field.
|
||||
tables = newTables.build();
|
||||
}
|
||||
}
|
|
@ -14,9 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.loot.table;
|
||||
|
||||
import java.util.List;
|
||||
package net.fabricmc.fabric.mixin.loot;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
@ -25,13 +23,26 @@ import net.minecraft.loot.LootPool;
|
|||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
import net.minecraft.loot.provider.number.LootNumberProvider;
|
||||
|
||||
@Mixin(LootPool.Builder.class)
|
||||
public interface LootPoolBuilderHooks {
|
||||
@Accessor
|
||||
List<LootPoolEntry> getEntries();
|
||||
@Accessor
|
||||
List<LootCondition> getConditions();
|
||||
@Accessor
|
||||
List<LootFunction> getFunctions();
|
||||
/**
|
||||
* Accesses loot pool fields for {@link net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder#copyOf(LootPool)}.
|
||||
* These are normally available in the transitive access widener module.
|
||||
*/
|
||||
@Mixin(LootPool.class)
|
||||
public interface LootPoolAccessor {
|
||||
@Accessor("rolls")
|
||||
LootNumberProvider fabric_getRolls();
|
||||
|
||||
@Accessor("bonusRolls")
|
||||
LootNumberProvider fabric_getBonusRolls();
|
||||
|
||||
@Accessor("entries")
|
||||
LootPoolEntry[] fabric_getEntries();
|
||||
|
||||
@Accessor("conditions")
|
||||
LootCondition[] fabric_getConditions();
|
||||
|
||||
@Accessor("functions")
|
||||
LootFunction[] fabric_getFunctions();
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.mixin.loot;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder;
|
||||
|
||||
/**
|
||||
* The implementation of the injected interface {@link FabricLootPoolBuilder}.
|
||||
* Simply implements the new methods by adding the relevant objects inside the lists.
|
||||
*/
|
||||
@Mixin(LootPool.Builder.class)
|
||||
abstract class LootPoolBuilderMixin implements FabricLootPoolBuilder {
|
||||
@Shadow
|
||||
@Final
|
||||
private List<LootPoolEntry> entries;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private List<LootCondition> conditions;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private List<LootFunction> functions;
|
||||
|
||||
@Unique
|
||||
private LootPool.Builder self() {
|
||||
// noinspection ConstantConditions
|
||||
return (LootPool.Builder) (Object) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder with(LootPoolEntry entry) {
|
||||
this.entries.add(entry);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder with(Collection<? extends LootPoolEntry> entries) {
|
||||
this.entries.addAll(entries);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder conditionally(LootCondition condition) {
|
||||
this.conditions.add(condition);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder conditionally(Collection<? extends LootCondition> conditions) {
|
||||
this.conditions.addAll(conditions);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder apply(LootFunction function) {
|
||||
this.functions.add(function);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootPool.Builder apply(Collection<? extends LootFunction> functions) {
|
||||
this.functions.addAll(functions);
|
||||
return self();
|
||||
}
|
||||
}
|
|
@ -14,9 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.loot.table;
|
||||
|
||||
import java.util.List;
|
||||
package net.fabricmc.fabric.mixin.loot;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
@ -25,10 +23,15 @@ import net.minecraft.loot.LootPool;
|
|||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
@Mixin(LootTable.Builder.class)
|
||||
public interface LootSupplierBuilderHooks {
|
||||
@Accessor
|
||||
List<LootPool> getPools();
|
||||
@Accessor
|
||||
List<LootFunction> getFunctions();
|
||||
/**
|
||||
* Accesses loot table fields for {@link net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder#copyOf(LootTable)}.
|
||||
* These are normally available in the transitive access widener module.
|
||||
*/
|
||||
@Mixin(LootTable.class)
|
||||
public interface LootTableAccessor {
|
||||
@Accessor("pools")
|
||||
LootPool[] fabric_getPools();
|
||||
|
||||
@Accessor("functions")
|
||||
LootFunction[] fabric_getFunctions();
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.mixin.loot;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder;
|
||||
|
||||
/**
|
||||
* The implementation of the injected interface {@link FabricLootTableBuilder}.
|
||||
* Simply implements the new methods by adding the relevant objects inside the lists.
|
||||
*/
|
||||
@Mixin(LootTable.Builder.class)
|
||||
abstract class LootTableBuilderMixin implements FabricLootTableBuilder {
|
||||
@Shadow
|
||||
@Final
|
||||
private List<LootPool> pools;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private List<LootFunction> functions;
|
||||
|
||||
@Unique
|
||||
private LootTable.Builder self() {
|
||||
// noinspection ConstantConditions
|
||||
return (LootTable.Builder) (Object) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootTable.Builder pool(LootPool pool) {
|
||||
this.pools.add(pool);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootTable.Builder apply(LootFunction function) {
|
||||
this.functions.add(function);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootTable.Builder pools(Collection<? extends LootPool> pools) {
|
||||
this.pools.addAll(pools);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LootTable.Builder apply(Collection<? extends LootFunction> functions) {
|
||||
this.functions.addAll(functions);
|
||||
return self();
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.fabricmc.fabric.mixin.loot",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"LootManagerMixin",
|
||||
"LootPoolAccessor",
|
||||
"LootPoolBuilderMixin",
|
||||
"LootTableAccessor",
|
||||
"LootTableBuilderMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
34
fabric-loot-api-v2/src/main/resources/fabric.mod.json
Normal file
34
fabric-loot-api-v2/src/main/resources/fabric.mod.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-loot-api-v2",
|
||||
"name": "Fabric Loot API (v2)",
|
||||
"version": "${version}",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"icon": "assets/fabric-loot-api-v2/icon.png",
|
||||
"contact": {
|
||||
"homepage": "https://fabricmc.net",
|
||||
"irc": "irc://irc.esper.net:6667/fabric",
|
||||
"issues": "https://github.com/FabricMC/fabric/issues",
|
||||
"sources": "https://github.com/FabricMC/fabric"
|
||||
},
|
||||
"authors": [
|
||||
"FabricMC"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*",
|
||||
"fabric-resource-loader-v0": "*"
|
||||
},
|
||||
"description": "Hooks for manipulating loot tables.",
|
||||
"mixins": [
|
||||
"fabric-loot-api-v2.mixins.json"
|
||||
],
|
||||
"custom": {
|
||||
"fabric-api:module-lifecycle": "stable",
|
||||
"loom:injected_interfaces": {
|
||||
"net/minecraft/class_52\u0024class_53": ["net/fabricmc/fabric/api/loot/v2/FabricLootTableBuilder"],
|
||||
"net/minecraft/class_55\u0024class_56": ["net/fabricmc/fabric/api/loot/v2/FabricLootPoolBuilder"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.test.loot;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.condition.SurvivesExplosionLootCondition;
|
||||
import net.minecraft.loot.entry.ItemEntry;
|
||||
import net.minecraft.loot.function.SetNameLootFunction;
|
||||
import net.minecraft.text.LiteralText;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableSource;
|
||||
|
||||
public class LootTest implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// Test loot table load event
|
||||
// The LootTable.Builder LootPool.Builder methods here should use
|
||||
// prebuilt entries and pools to test the injected methods.
|
||||
LootTableEvents.REPLACE.register((resourceManager, lootManager, id, original, source) -> {
|
||||
if (Blocks.BLACK_WOOL.getLootTableId().equals(id)) {
|
||||
if (source != LootTableSource.VANILLA) {
|
||||
throw new AssertionError("black wool loot table should have LootTableSource.VANILLA");
|
||||
}
|
||||
|
||||
// Replace black wool drops with an iron ingot
|
||||
LootPool pool = LootPool.builder()
|
||||
.with(ItemEntry.builder(Items.IRON_INGOT).build())
|
||||
.build();
|
||||
|
||||
return LootTable.builder().pool(pool).build();
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
// Test that the event is stopped when the loot table is replaced
|
||||
LootTableEvents.REPLACE.register((resourceManager, lootManager, id, original, source) -> {
|
||||
if (Blocks.BLACK_WOOL.getLootTableId().equals(id)) {
|
||||
throw new AssertionError("Event should have been stopped from replaced loot table");
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> {
|
||||
if (Blocks.BLACK_WOOL.getLootTableId().equals(id) && source != LootTableSource.REPLACED) {
|
||||
throw new AssertionError("black wool loot table should have LootTableSource.REPLACED");
|
||||
}
|
||||
|
||||
if (Blocks.WHITE_WOOL.getLootTableId().equals(id)) {
|
||||
if (source != LootTableSource.VANILLA) {
|
||||
throw new AssertionError("white wool loot table should have LootTableSource.VANILLA");
|
||||
}
|
||||
|
||||
// Add gold ingot with custom name to white wool drops
|
||||
LootPool pool = LootPool.builder()
|
||||
.with(ItemEntry.builder(Items.GOLD_INGOT).build())
|
||||
.conditionally(SurvivesExplosionLootCondition.builder().build())
|
||||
.apply(SetNameLootFunction.builder(new LiteralText("Gold from White Wool")).build())
|
||||
.build();
|
||||
|
||||
tableBuilder.pool(pool);
|
||||
}
|
||||
|
||||
// We modify red wool to drop diamonds in the test mod resources.
|
||||
if (Blocks.RED_WOOL.getLootTableId().equals(id) && source != LootTableSource.MOD) {
|
||||
throw new AssertionError("red wool loot table should have LootTableSource.MOD");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:diamond"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
16
fabric-loot-api-v2/src/testmod/resources/fabric.mod.json
Normal file
16
fabric-loot-api-v2/src/testmod/resources/fabric.mod.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-loot-api-v2-testmod",
|
||||
"name": "Fabric Loot Table API (v2) Test Mod",
|
||||
"version": "1.0.0",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"depends": {
|
||||
"fabric-loot-api-v2": "*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.loot.LootTest"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -2,5 +2,10 @@ archivesBaseName = "fabric-loot-tables-v1"
|
|||
version = getSubprojectVersion(project)
|
||||
|
||||
moduleDependencies(project, [
|
||||
'fabric-api-base'
|
||||
'fabric-api-base',
|
||||
'fabric-loot-api-v2'
|
||||
])
|
||||
|
||||
dependencies {
|
||||
testmodRuntimeOnly(project(path: ':fabric-resource-loader-v0', configuration: 'namedElements'))
|
||||
}
|
||||
|
|
|
@ -19,15 +19,18 @@ package net.fabricmc.fabric.api.loot.v1;
|
|||
import java.util.List;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.provider.number.LootNumberProvider;
|
||||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
import net.minecraft.loot.provider.number.LootNumberProvider;
|
||||
|
||||
/**
|
||||
* An interface implemented by all {@code net.minecraft.loot.LootPool} instances when
|
||||
* Fabric API is present. Contains accessors for various fields.
|
||||
*
|
||||
* @deprecated Replaced with transitive access wideners in Fabric Transitive Access Wideners (v1).
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FabricLootPool {
|
||||
default LootPool asVanilla() {
|
||||
return (LootPool) this;
|
||||
|
|
|
@ -22,17 +22,21 @@ import net.minecraft.loot.provider.number.LootNumberProvider;
|
|||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.mixin.loot.table.LootPoolBuilderHooks;
|
||||
|
||||
/**
|
||||
* @deprecated Replaced with {@link net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class FabricLootPoolBuilder extends LootPool.Builder {
|
||||
private final LootPoolBuilderHooks extended = (LootPoolBuilderHooks) this;
|
||||
|
||||
private FabricLootPoolBuilder() { }
|
||||
|
||||
private FabricLootPoolBuilder(LootPool pool) {
|
||||
copyFrom(pool, true);
|
||||
}
|
||||
|
||||
private net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder asV2() {
|
||||
return (net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootPoolBuilder rolls(LootNumberProvider range) {
|
||||
super.rolls(range);
|
||||
|
@ -58,17 +62,17 @@ public class FabricLootPoolBuilder extends LootPool.Builder {
|
|||
}
|
||||
|
||||
public FabricLootPoolBuilder withEntry(LootPoolEntry entry) {
|
||||
extended.getEntries().add(entry);
|
||||
asV2().with(entry);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricLootPoolBuilder withCondition(LootCondition condition) {
|
||||
extended.getConditions().add(condition);
|
||||
asV2().conditionally(condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricLootPoolBuilder withFunction(LootFunction function) {
|
||||
extended.getFunctions().add(function);
|
||||
asV2().apply(function);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -89,13 +93,13 @@ public class FabricLootPoolBuilder extends LootPool.Builder {
|
|||
* <p>If {@code copyRolls} is true, the {@link FabricLootPool#getRolls 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());
|
||||
FabricLootPool extended = (FabricLootPool) pool;
|
||||
asV2().with(extended.getEntries());
|
||||
asV2().conditionally(extended.getConditions());
|
||||
asV2().apply(extended.getFunctions());
|
||||
|
||||
if (copyRolls) {
|
||||
rolls(extendedPool.getRolls());
|
||||
rolls(extended.getRolls());
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
|
@ -24,9 +24,12 @@ import net.minecraft.loot.context.LootContextType;
|
|||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
/**
|
||||
* An interface implemented by all {@code net.minecraft.loot.LootSupplier} instances when
|
||||
* An interface implemented by all {@link LootTable} instances when
|
||||
* Fabric API is present. Contains accessors for various fields.
|
||||
*
|
||||
* @deprecated Replaced with transitive access wideners in Fabric Transitive Access Wideners (v1).
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FabricLootSupplier {
|
||||
default LootTable asVanilla() {
|
||||
return (LootTable) this;
|
||||
|
@ -34,5 +37,7 @@ public interface FabricLootSupplier {
|
|||
|
||||
List<LootPool> getPools();
|
||||
List<LootFunction> getFunctions();
|
||||
LootContextType getType();
|
||||
default LootContextType getType() {
|
||||
return asVanilla().getType(); // Vanilla has this now
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,17 +23,23 @@ import net.minecraft.loot.LootTable;
|
|||
import net.minecraft.loot.context.LootContextType;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.mixin.loot.table.LootSupplierBuilderHooks;
|
||||
import net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder;
|
||||
|
||||
/**
|
||||
* @deprecated Replaced with {@link FabricLootTableBuilder}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class FabricLootSupplierBuilder extends LootTable.Builder {
|
||||
private final LootSupplierBuilderHooks extended = (LootSupplierBuilderHooks) this;
|
||||
|
||||
protected FabricLootSupplierBuilder() { }
|
||||
|
||||
private FabricLootSupplierBuilder(LootTable supplier) {
|
||||
copyFrom(supplier, true);
|
||||
}
|
||||
|
||||
private FabricLootTableBuilder asV2() {
|
||||
return (FabricLootTableBuilder) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder pool(LootPool.Builder pool) {
|
||||
super.pool(pool);
|
||||
|
@ -53,22 +59,22 @@ public class FabricLootSupplierBuilder extends LootTable.Builder {
|
|||
}
|
||||
|
||||
public FabricLootSupplierBuilder withPool(LootPool pool) {
|
||||
extended.getPools().add(pool);
|
||||
asV2().pool(pool);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricLootSupplierBuilder withFunction(LootFunction function) {
|
||||
extended.getFunctions().add(function);
|
||||
asV2().apply(function);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricLootSupplierBuilder withPools(Collection<LootPool> pools) {
|
||||
pools.forEach(this::withPool);
|
||||
asV2().pools(pools);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FabricLootSupplierBuilder withFunctions(Collection<LootFunction> functions) {
|
||||
functions.forEach(this::withFunction);
|
||||
asV2().apply(functions);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -86,8 +92,8 @@ public class FabricLootSupplierBuilder extends LootTable.Builder {
|
|||
*/
|
||||
public FabricLootSupplierBuilder copyFrom(LootTable supplier, boolean copyType) {
|
||||
FabricLootSupplier extendedSupplier = (FabricLootSupplier) supplier;
|
||||
extended.getPools().addAll(extendedSupplier.getPools());
|
||||
extended.getFunctions().addAll(extendedSupplier.getFunctions());
|
||||
asV2().pools(extendedSupplier.getPools());
|
||||
asV2().apply(extendedSupplier.getFunctions());
|
||||
|
||||
if (copyType) {
|
||||
type(extendedSupplier.getType());
|
||||
|
|
|
@ -23,11 +23,13 @@ import net.minecraft.util.JsonSerializer;
|
|||
import net.fabricmc.fabric.impl.loot.table.LootEntryTypeRegistryImpl;
|
||||
|
||||
/**
|
||||
* Fabric's extensions to {@code net.minecraft.loot.entry.LootEntries} for registering
|
||||
* Fabric's extensions to {@link net.minecraft.loot.entry.LootPoolEntryTypes} for registering
|
||||
* custom loot entry types.
|
||||
*
|
||||
* @see #register
|
||||
* @deprecated Use {@link net.minecraft.util.registry.Registry#LOOT_POOL_ENTRY_TYPE} from vanilla instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface LootEntryTypeRegistry {
|
||||
LootEntryTypeRegistry INSTANCE = new LootEntryTypeRegistryImpl();
|
||||
|
||||
|
|
|
@ -17,37 +17,26 @@
|
|||
package net.fabricmc.fabric.api.loot.v1;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import net.minecraft.loot.LootGsons;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.Lazy;
|
||||
import net.minecraft.loot.LootManager;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link LootGsons#getTableGsonBuilder()} from vanilla instead.
|
||||
*/
|
||||
@Deprecated
|
||||
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 static final Gson GSON = LootGsons.getTableGsonBuilder().create();
|
||||
|
||||
private LootJsonParser() { }
|
||||
|
||||
public static <T> T read(Reader json, Class<T> c) {
|
||||
return JsonHelper.deserialize(GSON.get(), json, c);
|
||||
return JsonHelper.deserialize(GSON, json, c);
|
||||
}
|
||||
|
||||
public static <T> T read(String json, Class<T> c) {
|
||||
return JsonHelper.deserialize(GSON.get(), json, c);
|
||||
return JsonHelper.deserialize(GSON, json, c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,13 @@ import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder;
|
|||
/**
|
||||
* An event handler that is called when loot tables are loaded.
|
||||
* Use {@link #EVENT} to register instances.
|
||||
*
|
||||
* @deprecated Replaced with {@link net.fabricmc.fabric.api.loot.v2.LootTableEvents}.
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface LootTableLoadingCallback {
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
interface LootTableSetter {
|
||||
void set(LootTable supplier);
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.context.LootContextType;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier;
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder;
|
||||
import net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder;
|
||||
|
||||
/**
|
||||
* A {@link FabricLootSupplierBuilder} that caches all methods so they can be applied to a v2 {@link FabricLootTableBuilder}.
|
||||
* Used for hooking {@code LootTableLoadingCallback} to the two different {@link net.fabricmc.fabric.api.loot.v2.LootTableEvents}.
|
||||
*/
|
||||
public class BufferingLootTableBuilder extends FabricLootSupplierBuilder {
|
||||
private final List<Consumer<LootTable.Builder>> modifications = new ArrayList<>();
|
||||
|
||||
private FabricLootSupplierBuilder addAction(Consumer<LootTable.Builder> action) {
|
||||
modifications.add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
private FabricLootSupplierBuilder addV2Action(Consumer<FabricLootTableBuilder> action) {
|
||||
return addAction(builder -> action.accept((FabricLootTableBuilder) builder));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder pool(LootPool.Builder pool) {
|
||||
super.pool(pool);
|
||||
return addAction(builder -> builder.pool(pool));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder type(LootContextType type) {
|
||||
super.type(type);
|
||||
return addAction(builder -> builder.type(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder apply(LootFunction.Builder function) {
|
||||
super.apply(function);
|
||||
return addAction(builder -> builder.apply(function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder withPool(LootPool pool) {
|
||||
super.withPool(pool);
|
||||
return addV2Action(builder -> builder.pool(pool));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder withFunction(LootFunction function) {
|
||||
super.withFunction(function);
|
||||
return addV2Action(builder -> builder.apply(function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder withPools(Collection<LootPool> pools) {
|
||||
super.withPools(pools);
|
||||
return addV2Action(builder -> builder.pools(pools));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder withFunctions(Collection<LootFunction> functions) {
|
||||
super.withFunctions(functions);
|
||||
return addV2Action(builder -> builder.apply(functions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricLootSupplierBuilder copyFrom(LootTable supplier, boolean copyType) {
|
||||
super.copyFrom(supplier, copyType);
|
||||
return addV2Action(builder -> {
|
||||
FabricLootSupplier extended = (FabricLootSupplier) supplier;
|
||||
builder.pools(extended.getPools());
|
||||
builder.apply(extended.getFunctions());
|
||||
|
||||
if (copyType) {
|
||||
((LootTable.Builder) builder).type(supplier.getType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void init(LootTable original) {
|
||||
super.type(original.getType());
|
||||
super.withPools(((FabricLootSupplier) original).getPools());
|
||||
super.withFunctions(((FabricLootSupplier) original).getFunctions());
|
||||
}
|
||||
|
||||
public void applyTo(LootTable.Builder builder) {
|
||||
for (Consumer<LootTable.Builder> modification : modifications) {
|
||||
modification.accept(builder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,16 +17,16 @@
|
|||
package net.fabricmc.fabric.impl.loot.table;
|
||||
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.entry.LootPoolEntryType;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonSerializer;
|
||||
|
||||
import net.fabricmc.fabric.mixin.loot.table.LootPoolEntryTypesAccessor;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
public final class LootEntryTypeRegistryImpl implements net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry {
|
||||
public LootEntryTypeRegistryImpl() { }
|
||||
|
||||
@Override
|
||||
public void register(Identifier id, JsonSerializer<? extends LootPoolEntry> serializer) {
|
||||
LootPoolEntryTypesAccessor.register(id.toString(), serializer);
|
||||
Registry.register(Registry.LOOT_POOL_ENTRY_TYPE, id, new LootPoolEntryType(serializer));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.table;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
||||
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
|
||||
|
||||
public final class LootTablesV1Init implements ModInitializer {
|
||||
private static final ThreadLocal<Map<Identifier, BufferingLootTableBuilder>> BUFFERS = ThreadLocal.withInitial(HashMap::new);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
LootTableEvents.REPLACE.register((resourceManager, lootManager, id, original, source) -> {
|
||||
BufferingLootTableBuilder builder = new BufferingLootTableBuilder();
|
||||
builder.init(original);
|
||||
BUFFERS.get().put(id, builder);
|
||||
|
||||
LootTable[] result = new LootTable[1];
|
||||
LootTableLoadingCallback.EVENT.invoker().onLootTableLoading(
|
||||
resourceManager,
|
||||
lootManager,
|
||||
id,
|
||||
builder,
|
||||
table -> result[0] = table
|
||||
);
|
||||
|
||||
return result[0];
|
||||
});
|
||||
|
||||
LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> {
|
||||
Map<Identifier, BufferingLootTableBuilder> buffers = BUFFERS.get();
|
||||
|
||||
if (buffers.containsKey(id)) {
|
||||
try {
|
||||
buffers.get(id).applyTo(tableBuilder);
|
||||
} finally {
|
||||
buffers.remove(id);
|
||||
|
||||
if (buffers.isEmpty()) {
|
||||
BUFFERS.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* 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.mixin.loot.table;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonObject;
|
||||
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 net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
import net.minecraft.loot.LootManager;
|
||||
import net.minecraft.loot.LootTable;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder;
|
||||
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
||||
|
||||
@Mixin(LootManager.class)
|
||||
public class MixinLootManager {
|
||||
@Shadow private Map<Identifier, LootTable> tables;
|
||||
|
||||
@Inject(method = "apply", at = @At("RETURN"))
|
||||
private void apply(Map<Identifier, JsonObject> objectMap, ResourceManager manager, Profiler profiler, CallbackInfo info) {
|
||||
Map<Identifier, LootTable> newSuppliers = new HashMap<>();
|
||||
|
||||
tables.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.build());
|
||||
});
|
||||
|
||||
tables = ImmutableMap.copyOf(newSuppliers);
|
||||
}
|
||||
}
|
|
@ -16,19 +16,18 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.loot.table;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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 net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.provider.number.LootNumberProvider;
|
||||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
import net.minecraft.loot.provider.number.LootNumberProvider;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootPool;
|
||||
|
||||
|
@ -36,32 +35,37 @@ import net.fabricmc.fabric.api.loot.v1.FabricLootPool;
|
|||
public abstract class MixinLootPool implements FabricLootPool {
|
||||
@Shadow
|
||||
@Final
|
||||
private LootPoolEntry[] entries;
|
||||
LootPoolEntry[] entries;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private LootCondition[] conditions;
|
||||
LootCondition[] conditions;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private LootFunction[] functions;
|
||||
LootFunction[] functions;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
LootNumberProvider rolls;
|
||||
|
||||
@Override
|
||||
public List<LootPoolEntry> getEntries() {
|
||||
return Arrays.asList(entries);
|
||||
return ImmutableList.copyOf(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LootCondition> getConditions() {
|
||||
return Arrays.asList(conditions);
|
||||
return ImmutableList.copyOf(conditions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LootFunction> getFunctions() {
|
||||
return Arrays.asList(functions);
|
||||
return ImmutableList.copyOf(functions);
|
||||
}
|
||||
|
||||
@Accessor
|
||||
@Override
|
||||
public abstract LootNumberProvider getRolls();
|
||||
public LootNumberProvider getRolls() {
|
||||
return rolls;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,15 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.loot.table;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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 net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.context.LootContextType;
|
||||
import net.minecraft.loot.function.LootFunction;
|
||||
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier;
|
||||
|
@ -35,22 +33,19 @@ import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier;
|
|||
public abstract class MixinLootSupplier implements FabricLootSupplier {
|
||||
@Shadow
|
||||
@Final
|
||||
private LootPool[] pools;
|
||||
LootPool[] pools;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private LootFunction[] functions;
|
||||
LootFunction[] functions;
|
||||
|
||||
@Override
|
||||
public List<LootPool> getPools() {
|
||||
return Arrays.asList(pools);
|
||||
return ImmutableList.copyOf(pools);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LootFunction> getFunctions() {
|
||||
return Arrays.asList(functions);
|
||||
return ImmutableList.copyOf(functions);
|
||||
}
|
||||
|
||||
@Accessor
|
||||
@Override
|
||||
public abstract LootContextType getType();
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
"package": "net.fabricmc.fabric.mixin.loot.table",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"mixins": [
|
||||
"LootPoolBuilderHooks",
|
||||
"LootPoolEntryTypesAccessor",
|
||||
"LootSupplierBuilderHooks",
|
||||
"MixinLootManager",
|
||||
"MixinLootPool",
|
||||
"MixinLootSupplier"
|
||||
],
|
||||
|
|
|
@ -17,13 +17,17 @@
|
|||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric-api-base": "*"
|
||||
"fabric-api-base": "*",
|
||||
"fabric-loot-api-v2": "*"
|
||||
},
|
||||
"entrypoints": {
|
||||
"main": ["net.fabricmc.fabric.impl.loot.table.LootTablesV1Init"]
|
||||
},
|
||||
"description": "Hooks for manipulating loot tables.",
|
||||
"mixins": [
|
||||
"fabric-loot-tables-v1.mixins.json"
|
||||
],
|
||||
"custom": {
|
||||
"fabric-api:module-lifecycle": "stable"
|
||||
"fabric-api:module-lifecycle": "deprecated"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,28 +20,31 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
|
||||
import net.minecraft.loot.LootGsons;
|
||||
import net.minecraft.loot.LootPool;
|
||||
import net.minecraft.loot.LootTable;
|
||||
import net.minecraft.loot.condition.LootCondition;
|
||||
import net.minecraft.loot.condition.SurvivesExplosionLootCondition;
|
||||
import net.minecraft.loot.entry.ItemEntry;
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.entry.TagEntry;
|
||||
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder;
|
||||
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplierBuilder;
|
||||
import net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry;
|
||||
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
||||
|
||||
public class LootTest implements ModInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LootTest.class);
|
||||
public class LootV1Test implements ModInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LootV1Test.class);
|
||||
|
||||
private static final Gson LOOT_GSON = LootGsons.getTableGsonBuilder().create();
|
||||
private static final String LOOT_ENTRY_JSON = "{\"type\":\"minecraft:item\",\"name\":\"minecraft:apple\"}";
|
||||
|
@ -53,7 +56,9 @@ public class LootTest implements ModInitializer {
|
|||
|
||||
// Test loot table load event
|
||||
LootTableLoadingCallback.EVENT.register((resourceManager, manager, id, supplier, setter) -> {
|
||||
if ("minecraft:blocks/dirt".equals(id.toString())) {
|
||||
// Add feathers and apples to dirt (only one drops at the time since they're in the same pool),
|
||||
// and replace grass block drops with wheat
|
||||
if (Blocks.DIRT.getLootTableId().equals(id)) {
|
||||
LootPoolEntry entryFromString = LOOT_GSON.fromJson(LOOT_ENTRY_JSON, LootPoolEntry.class);
|
||||
|
||||
LootPool pool = FabricLootPoolBuilder.builder()
|
||||
|
@ -64,6 +69,11 @@ public class LootTest implements ModInitializer {
|
|||
.build();
|
||||
|
||||
supplier.withPool(pool);
|
||||
} else if (Blocks.GRASS_BLOCK.getLootTableId().equals(id)) {
|
||||
LootTable table = FabricLootSupplierBuilder.builder()
|
||||
.pool(FabricLootPoolBuilder.builder().with(ItemEntry.builder(Items.WHEAT)))
|
||||
.build();
|
||||
setter.set(table);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.loot.LootTest"
|
||||
"net.fabricmc.fabric.test.loot.LootV1Test"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.resource.loader;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
/**
|
||||
* Extensions to {@link net.minecraft.resource.Resource}.
|
||||
* Automatically implemented there via a mixin.
|
||||
* Currently, this is only for use in other Fabric API modules.
|
||||
*/
|
||||
public interface FabricResource {
|
||||
/**
|
||||
* Gets the resource pack source of this resource.
|
||||
* The source is used to separate vanilla/mod resources from user resources in Fabric API.
|
||||
*
|
||||
* <p>Custom {@link net.minecraft.resource.Resource} implementations should override this method.
|
||||
*
|
||||
* @return the resource pack source
|
||||
*/
|
||||
default ResourcePackSource getFabricPackSource() {
|
||||
LoggerFactory.getLogger(FabricResource.class).error("Unknown Resource implementation {}, returning PACK_SOURCE_NONE as the source", getClass().getName());
|
||||
return ResourcePackSource.PACK_SOURCE_NONE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.resource.loader;
|
||||
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
/**
|
||||
* An extended version of {@link FabricResource} that supports
|
||||
* setting the pack resource. Only for use from within this module.
|
||||
* Note that <strong>not all</strong> resources are instances of this interface.
|
||||
*/
|
||||
public interface FabricResourceImpl extends Resource, FabricResource {
|
||||
void setFabricPackSource(ResourcePackSource packSource);
|
||||
}
|
|
@ -130,7 +130,9 @@ public abstract class GroupResourcePack implements ResourcePack {
|
|||
for (ModResourcePack pack : packs) {
|
||||
if (pack.contains(manager.getType(), id)) {
|
||||
InputStream metadataInputStream = pack.contains(manager.getType(), metadataId) ? manager.fabric$accessor_open(metadataId, pack) : null;
|
||||
resources.add(new ResourceImpl(pack.getName(), id, manager.fabric$accessor_open(id, pack), metadataInputStream));
|
||||
ResourceImpl resource = new ResourceImpl(pack.getName(), id, manager.fabric$accessor_open(id, pack), metadataInputStream);
|
||||
((FabricResourceImpl) resource).setFabricPackSource(ModResourcePackCreator.RESOURCE_PACK_SOURCE);
|
||||
resources.add(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.resource.loader;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.resource.ResourcePack;
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
/**
|
||||
* Tracks the sources of resource packs in a global weak hash map.
|
||||
* {@link ResourcePack} doesn't hold a reference to its {@link ResourcePackSource}
|
||||
* so we store the source in the map when the resource packs are created.
|
||||
* See {@link net.fabricmc.fabric.mixin.resource.loader.ResourcePackProfileMixin ResourcePackProfileMixin}.
|
||||
*
|
||||
* <p>The sources are later read for use in {@link FabricResource} and {@link FabricResourceImpl}.
|
||||
* See {@link net.fabricmc.fabric.mixin.resource.loader.NamespaceResourceManagerMixin NamespaceResourceManagerMixin}.
|
||||
*/
|
||||
public final class ResourcePackSourceTracker {
|
||||
// Use a weak hash map so that if resource packs would be deleted, this won't keep them alive.
|
||||
private static final WeakHashMap<ResourcePack, ResourcePackSource> SOURCES = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Gets the source of a pack.
|
||||
*
|
||||
* @param pack the resource pack
|
||||
* @return the source, or {@link ResourcePackSource#PACK_SOURCE_NONE} if not tracked
|
||||
*/
|
||||
public static ResourcePackSource getSource(ResourcePack pack) {
|
||||
return SOURCES.getOrDefault(pack, ResourcePackSource.PACK_SOURCE_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source of a pack.
|
||||
*
|
||||
* @param pack the resource pack
|
||||
* @param source the source
|
||||
*/
|
||||
public static void setSource(ResourcePack pack, ResourcePackSource source) {
|
||||
SOURCES.put(pack, source);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.mixin.resource.loader;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
import net.fabricmc.fabric.impl.resource.loader.FabricResource;
|
||||
|
||||
/**
|
||||
* Implements {@link FabricResource} for the anonymous resource implementation
|
||||
* in {@link net.minecraft.resource.DefaultResourcePack#getResource}.
|
||||
*/
|
||||
@Mixin(targets = "net/minecraft/resource/DefaultResourcePack$1")
|
||||
abstract class DefaultResourcePackResourceMixin implements FabricResource {
|
||||
@Override
|
||||
public ResourcePackSource getFabricPackSource() {
|
||||
// The default resource pack only contains built-in vanilla resources.
|
||||
return ResourcePackSource.PACK_SOURCE_BUILTIN;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
package net.fabricmc.fabric.mixin.resource.loader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -32,7 +33,9 @@ import net.minecraft.resource.ResourcePack;
|
|||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.impl.resource.loader.FabricResourceImpl;
|
||||
import net.fabricmc.fabric.impl.resource.loader.GroupResourcePack;
|
||||
import net.fabricmc.fabric.impl.resource.loader.ResourcePackSourceTracker;
|
||||
|
||||
@Mixin(NamespaceResourceManager.class)
|
||||
public class NamespaceResourceManagerMixin {
|
||||
|
@ -66,4 +69,32 @@ public class NamespaceResourceManagerMixin {
|
|||
|
||||
return pack.contains(type, id);
|
||||
}
|
||||
|
||||
/* The two injectors below set the resource pack sources (see FabricResourceImpl)
|
||||
* for resources created in NamespaceResourceManager.getAllResources and NamespaceResourceManager.getResource.
|
||||
*
|
||||
* Since (in 1.18.2) ResourceImpl doesn't hold a reference to its resource pack,
|
||||
* we have to get the source from the resource pack when the resource is created.
|
||||
* These are the main creation sites for resources in 1.18.2
|
||||
* along with DefaultResourcePack.getResource and Fabric API's GroupResourcePack,
|
||||
* which also either track the source similarly or provide other types of Resource instances
|
||||
* that have a different FabricResource implementation.
|
||||
*/
|
||||
|
||||
@Inject(method = "getAllResources", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", remap = false, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void trackSourceOnGetAllResources(Identifier id, CallbackInfoReturnable<List<Resource>> cir, List<Resource> resources, Identifier metadataPath, Iterator<ResourcePack> packs, ResourcePack resourcePack) {
|
||||
// After the created resource has been added, read it from the list and set its source
|
||||
// to match the tracked source of its resource pack.
|
||||
if (resources.get(resources.size() - 1) instanceof FabricResourceImpl resource) {
|
||||
resource.setFabricPackSource(ResourcePackSourceTracker.getSource(resourcePack));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getResource", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void trackSourceOnGetResource(Identifier id, CallbackInfoReturnable<Resource> cir, ResourcePack metaResourcePack, Identifier metadataPath, int i, ResourcePack resourcePack) {
|
||||
// Set the resource's source to match the tracked source of its resource pack.
|
||||
if (cir.getReturnValue() instanceof FabricResourceImpl resource) {
|
||||
resource.setFabricPackSource(ResourcePackSourceTracker.getSource(resourcePack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.mixin.resource.loader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import net.minecraft.resource.ResourceImpl;
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
import net.fabricmc.fabric.impl.resource.loader.FabricResourceImpl;
|
||||
|
||||
/**
|
||||
* Implements {@link FabricResourceImpl} (resource source getter/setter)
|
||||
* for vanilla's basic {@link ResourceImpl} used for most game resources.
|
||||
*
|
||||
* @see NamespaceResourceManagerMixin the usage site for this mixin
|
||||
*/
|
||||
@Mixin(ResourceImpl.class)
|
||||
abstract class ResourceImplMixin implements FabricResourceImpl {
|
||||
@Unique
|
||||
private @Nullable ResourcePackSource fabric_packSource;
|
||||
|
||||
@Override
|
||||
public ResourcePackSource getFabricPackSource() {
|
||||
return Objects.requireNonNullElse(fabric_packSource, ResourcePackSource.PACK_SOURCE_NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFabricPackSource(ResourcePackSource packSource) {
|
||||
this.fabric_packSource = packSource;
|
||||
}
|
||||
}
|
|
@ -14,20 +14,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.loot.table;
|
||||
package net.fabricmc.fabric.mixin.resource.loader;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import net.minecraft.loot.entry.LootPoolEntry;
|
||||
import net.minecraft.loot.entry.LootPoolEntryType;
|
||||
import net.minecraft.loot.entry.LootPoolEntryTypes;
|
||||
import net.minecraft.util.JsonSerializer;
|
||||
import net.minecraft.resource.Resource;
|
||||
|
||||
@Mixin(LootPoolEntryTypes.class)
|
||||
public interface LootPoolEntryTypesAccessor {
|
||||
@Invoker("register")
|
||||
static LootPoolEntryType register(String id, JsonSerializer<? extends LootPoolEntry> serializer) {
|
||||
throw new UnsupportedOperationException("Mixin dummy");
|
||||
}
|
||||
import net.fabricmc.fabric.impl.resource.loader.FabricResource;
|
||||
|
||||
// Add FabricResource to Resource's superinterfaces.
|
||||
@Mixin(Resource.class)
|
||||
interface ResourceMixin extends FabricResource {
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.mixin.resource.loader;
|
||||
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.resource.ResourcePack;
|
||||
import net.minecraft.resource.ResourcePackProfile;
|
||||
import net.minecraft.resource.ResourcePackSource;
|
||||
|
||||
import net.fabricmc.fabric.impl.resource.loader.ResourcePackSourceTracker;
|
||||
|
||||
/**
|
||||
* Implements resource pack source tracking (for {@link net.fabricmc.fabric.impl.resource.loader.FabricResource}).
|
||||
* {@link ResourcePack} doesn't hold a reference to its {@link ResourcePackSource}
|
||||
* so we store the source in a global tracker when the resource packs are created.
|
||||
*
|
||||
* @see ResourcePackSourceTracker
|
||||
*/
|
||||
@Mixin(ResourcePackProfile.class)
|
||||
abstract class ResourcePackProfileMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private ResourcePackSource source;
|
||||
|
||||
@Inject(method = "createResourcePack", at = @At("RETURN"))
|
||||
private void onCreateResourcePack(CallbackInfoReturnable<ResourcePack> info) {
|
||||
ResourcePackSourceTracker.setSource(info.getReturnValue(), source);
|
||||
}
|
||||
}
|
|
@ -5,14 +5,18 @@
|
|||
"mixins": [
|
||||
"FileResourcePackProviderAccessor",
|
||||
"DefaultResourcePackMixin",
|
||||
"DefaultResourcePackResourceMixin",
|
||||
"KeyedResourceReloadListenerMixin",
|
||||
"LifecycledResourceManagerImplMixin",
|
||||
"MinecraftServerMixin",
|
||||
"NamespaceResourceManagerAccessor",
|
||||
"NamespaceResourceManagerMixin",
|
||||
"ReloadableResourceManagerImplMixin",
|
||||
"ResourceImplMixin",
|
||||
"ResourceMixin",
|
||||
"ResourcePackManagerMixin",
|
||||
"ResourcePackManagerAccessor",
|
||||
"ResourcePackProfileMixin",
|
||||
"SimpleResourceReloadMixin"
|
||||
],
|
||||
"client": [
|
||||
|
|
|
@ -15,6 +15,15 @@ transitive-accessible method net/minecraft/screen/ScreenHandlerType <init> (Lnet
|
|||
transitive-accessible class net/minecraft/client/gui/screen/ingame/HandledScreens$Provider
|
||||
transitive-accessible method net/minecraft/client/gui/screen/ingame/HandledScreens register (Lnet/minecraft/screen/ScreenHandlerType;Lnet/minecraft/client/gui/screen/ingame/HandledScreens$Provider;)V
|
||||
|
||||
# Data contained in loot tables and pools
|
||||
transitive-accessible field net/minecraft/loot/LootPool entries [Lnet/minecraft/loot/entry/LootPoolEntry;
|
||||
transitive-accessible field net/minecraft/loot/LootPool conditions [Lnet/minecraft/loot/condition/LootCondition;
|
||||
transitive-accessible field net/minecraft/loot/LootPool functions [Lnet/minecraft/loot/function/LootFunction;
|
||||
transitive-accessible field net/minecraft/loot/LootPool rolls Lnet/minecraft/loot/provider/number/LootNumberProvider;
|
||||
transitive-accessible field net/minecraft/loot/LootPool bonusRolls Lnet/minecraft/loot/provider/number/LootNumberProvider;
|
||||
transitive-accessible field net/minecraft/loot/LootTable pools [Lnet/minecraft/loot/LootPool;
|
||||
transitive-accessible field net/minecraft/loot/LootTable functions [Lnet/minecraft/loot/function/LootFunction;
|
||||
|
||||
### Generated access wideners below
|
||||
# Constructors of non-abstract block classes
|
||||
transitive-accessible method net/minecraft/block/AirBlock <init> (Lnet/minecraft/block/AbstractBlock$Settings;)V
|
||||
|
|
|
@ -15,4 +15,13 @@ transitive-accessible method net/minecraft/screen/ScreenHandlerType <init> (Lnet
|
|||
transitive-accessible class net/minecraft/client/gui/screen/ingame/HandledScreens$Provider
|
||||
transitive-accessible method net/minecraft/client/gui/screen/ingame/HandledScreens register (Lnet/minecraft/screen/ScreenHandlerType;Lnet/minecraft/client/gui/screen/ingame/HandledScreens$Provider;)V
|
||||
|
||||
# Data contained in loot tables and pools
|
||||
transitive-accessible field net/minecraft/loot/LootPool entries [Lnet/minecraft/loot/entry/LootPoolEntry;
|
||||
transitive-accessible field net/minecraft/loot/LootPool conditions [Lnet/minecraft/loot/condition/LootCondition;
|
||||
transitive-accessible field net/minecraft/loot/LootPool functions [Lnet/minecraft/loot/function/LootFunction;
|
||||
transitive-accessible field net/minecraft/loot/LootPool rolls Lnet/minecraft/loot/provider/number/LootNumberProvider;
|
||||
transitive-accessible field net/minecraft/loot/LootPool bonusRolls Lnet/minecraft/loot/provider/number/LootNumberProvider;
|
||||
transitive-accessible field net/minecraft/loot/LootTable pools [Lnet/minecraft/loot/LootPool;
|
||||
transitive-accessible field net/minecraft/loot/LootTable functions [Lnet/minecraft/loot/function/LootFunction;
|
||||
|
||||
### Generated access wideners below
|
||||
|
|
|
@ -29,6 +29,7 @@ fabric-item-groups-v0-version=0.3.12
|
|||
fabric-key-binding-api-v1-version=1.0.12
|
||||
fabric-keybindings-v0-version=0.2.10
|
||||
fabric-lifecycle-events-v1-version=2.0.4
|
||||
fabric-loot-api-v2-version=1.0.0
|
||||
fabric-loot-tables-v1-version=1.0.11
|
||||
fabric-mining-level-api-v1-version=2.1.1
|
||||
fabric-models-v0-version=0.3.6
|
||||
|
|
|
@ -33,6 +33,7 @@ include 'fabric-item-groups-v0'
|
|||
include 'fabric-keybindings-v0'
|
||||
include 'fabric-key-binding-api-v1'
|
||||
include 'fabric-lifecycle-events-v1'
|
||||
include 'fabric-loot-api-v2'
|
||||
include 'fabric-loot-tables-v1'
|
||||
include 'fabric-mining-level-api-v1'
|
||||
include 'fabric-models-v0'
|
||||
|
|
Loading…
Reference in a new issue