This commit is contained in:
modmuss50 2023-08-09 18:04:04 +01:00
parent 0b2eb405dc
commit 0ba8e9ce03
50 changed files with 88 additions and 1386 deletions

View file

@ -1,10 +0,0 @@
version = getSubprojectVersion(project)
moduleDependencies(project, [
'fabric-api-base',
'fabric-loot-api-v2'
])
dependencies {
testmodRuntimeOnly(project(path: ':fabric-resource-loader-v0', configuration: 'namedElements'))
}

View file

@ -1,43 +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.api.loot.v1;
import java.util.List;
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;
/**
* 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;
}
List<LootPoolEntry> getEntries();
List<LootCondition> getConditions();
List<LootFunction> getFunctions();
LootNumberProvider getRolls();
}

View file

@ -1,115 +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.api.loot.v1;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.provider.number.LootNumberProvider;
import net.minecraft.loot.entry.LootPoolEntry;
import net.minecraft.loot.function.LootFunction;
/**
* @deprecated Replaced with {@link net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder}.
*/
@Deprecated
public class FabricLootPoolBuilder extends LootPool.Builder {
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);
return this;
}
@Override
public FabricLootPoolBuilder with(LootPoolEntry.Builder<?> entry) {
super.with(entry);
return this;
}
@Override
public FabricLootPoolBuilder conditionally(LootCondition.Builder condition) {
super.conditionally(condition);
return this;
}
@Override
public FabricLootPoolBuilder apply(LootFunction.Builder function) {
super.apply(function);
return this;
}
public FabricLootPoolBuilder withEntry(LootPoolEntry entry) {
asV2().with(entry);
return this;
}
public FabricLootPoolBuilder withCondition(LootCondition condition) {
asV2().conditionally(condition);
return this;
}
public FabricLootPoolBuilder withFunction(LootFunction function) {
asV2().apply(function);
return this;
}
/**
* Copies the entries, conditions and functions of the {@code pool} to this
* builder.
*
* <p>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.
*
* <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 extended = (FabricLootPool) pool;
asV2().with(extended.getEntries());
asV2().conditionally(extended.getConditions());
asV2().apply(extended.getFunctions());
if (copyRolls) {
rolls(extended.getRolls());
}
return this;
}
public static FabricLootPoolBuilder builder() {
return new FabricLootPoolBuilder();
}
public static FabricLootPoolBuilder of(LootPool pool) {
return new FabricLootPoolBuilder(pool);
}
}

View file

@ -1,43 +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.api.loot.v1;
import java.util.List;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.context.LootContextType;
import net.minecraft.loot.function.LootFunction;
/**
* 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;
}
List<LootPool> getPools();
List<LootFunction> getFunctions();
default LootContextType getType() {
return asVanilla().getType(); // Vanilla has this now
}
}

View file

@ -1,112 +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.api.loot.v1;
import java.util.Collection;
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.v2.FabricLootTableBuilder;
/**
* @deprecated Replaced with {@link FabricLootTableBuilder}.
*/
@Deprecated
public class FabricLootSupplierBuilder extends LootTable.Builder {
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);
return this;
}
@Override
public FabricLootSupplierBuilder type(LootContextType type) {
super.type(type);
return this;
}
@Override
public FabricLootSupplierBuilder apply(LootFunction.Builder function) {
super.apply(function);
return this;
}
public FabricLootSupplierBuilder withPool(LootPool pool) {
asV2().pool(pool);
return this;
}
public FabricLootSupplierBuilder withFunction(LootFunction function) {
asV2().apply(function);
return this;
}
public FabricLootSupplierBuilder withPools(Collection<LootPool> pools) {
asV2().pools(pools);
return this;
}
public FabricLootSupplierBuilder withFunctions(Collection<LootFunction> functions) {
asV2().apply(functions);
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(LootTable 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(LootTable supplier, boolean copyType) {
FabricLootSupplier extendedSupplier = (FabricLootSupplier) supplier;
asV2().pools(extendedSupplier.getPools());
asV2().apply(extendedSupplier.getFunctions());
if (copyType) {
type(extendedSupplier.getType());
}
return this;
}
public static FabricLootSupplierBuilder builder() {
return new FabricLootSupplierBuilder();
}
public static FabricLootSupplierBuilder of(LootTable supplier) {
return new FabricLootSupplierBuilder(supplier);
}
}

View file

@ -1,43 +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.api.loot.v1;
import net.minecraft.loot.entry.LootPoolEntry;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonSerializer;
import net.fabricmc.fabric.impl.loot.table.LootEntryTypeRegistryImpl;
/**
* Fabric's extensions to {@link net.minecraft.loot.entry.LootPoolEntryTypes} for registering
* custom loot entry types.
*
* @see #register
* @deprecated Use {@link net.minecraft.registry.Registries#LOOT_POOL_ENTRY_TYPE} from vanilla instead.
*/
@Deprecated
public interface LootEntryTypeRegistry {
LootEntryTypeRegistry INSTANCE = new LootEntryTypeRegistryImpl();
/**
* Registers a loot entry type serializer by its ID.
*
* @param id the loot entry's ID
* @param serializer the loot entry serializer
*/
void register(Identifier id, JsonSerializer<? extends LootPoolEntry> serializer);
}

View file

@ -1,42 +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.api.loot.v1;
import java.io.Reader;
import com.google.gson.Gson;
import net.minecraft.loot.LootGsons;
import net.minecraft.util.JsonHelper;
/**
* @deprecated Use {@link LootGsons#getTableGsonBuilder()} from vanilla instead.
*/
@Deprecated
public final class LootJsonParser {
private static final Gson GSON = LootGsons.getTableGsonBuilder().create();
private LootJsonParser() { }
public static <T> T read(Reader json, Class<T> c) {
return JsonHelper.deserialize(GSON, json, c);
}
public static <T> T read(String json, Class<T> c) {
return JsonHelper.deserialize(GSON, json, c);
}
}

View file

@ -1,53 +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.api.loot.v1.event;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.loot.LootManager;
import net.minecraft.loot.LootTable;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
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);
}
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

@ -1,116 +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.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);
}
}
}

View file

@ -1,33 +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.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.minecraft.registry.Registries;
import net.minecraft.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) {
Registry.register(Registries.LOOT_POOL_ENTRY_TYPE, id, new LootPoolEntryType(serializer));
}
}

View file

@ -1,67 +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.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();
}
}
}
});
}
}

View file

@ -1,71 +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.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 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;
import net.fabricmc.fabric.api.loot.v1.FabricLootPool;
@Mixin(LootPool.class)
public abstract class LootPoolMixin implements FabricLootPool {
@Shadow
@Final
LootPoolEntry[] entries;
@Shadow
@Final
LootCondition[] conditions;
@Shadow
@Final
LootFunction[] functions;
@Shadow
@Final
LootNumberProvider rolls;
@Override
public List<LootPoolEntry> getEntries() {
return ImmutableList.copyOf(entries);
}
@Override
public List<LootCondition> getConditions() {
return ImmutableList.copyOf(conditions);
}
@Override
public List<LootFunction> getFunctions() {
return ImmutableList.copyOf(functions);
}
@Override
public LootNumberProvider getRolls() {
return rolls;
}
}

View file

@ -1,51 +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.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 net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.function.LootFunction;
import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier;
@Mixin(LootTable.class)
public abstract class LootTableMixin implements FabricLootSupplier {
@Shadow
@Final
LootPool[] pools;
@Shadow
@Final
LootFunction[] functions;
@Override
public List<LootPool> getPools() {
return ImmutableList.copyOf(pools);
}
@Override
public List<LootFunction> getFunctions() {
return ImmutableList.copyOf(functions);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,12 +0,0 @@
{
"required": true,
"package": "net.fabricmc.fabric.mixin.loot.table",
"compatibilityLevel": "JAVA_16",
"mixins": [
"LootPoolMixin",
"LootTableMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View file

@ -1,33 +0,0 @@
{
"schemaVersion": 1,
"id": "fabric-loot-tables-v1",
"name": "Fabric Loot Tables (v1)",
"version": "${version}",
"environment": "*",
"license": "Apache-2.0",
"icon": "assets/fabric-loot-tables-v1/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-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": "deprecated"
}
}

View file

@ -1,96 +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.test.loot;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.minecraft.block.Blocks;
import net.minecraft.item.Items;
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 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\"}";
@Override
public void onInitialize() {
// Test loot entry
LootEntryTypeRegistry.INSTANCE.register(new Identifier("fabric", "extended_tag"), new TestSerializer());
// Test loot table load event
LootTableLoadingCallback.EVENT.register((resourceManager, manager, id, supplier, setter) -> {
// 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()
.withEntry(ItemEntry.builder(Items.FEATHER).build())
.withEntry(entryFromString)
.rolls(ConstantLootNumberProvider.create(1))
.withCondition(SurvivesExplosionLootCondition.builder().build())
.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);
}
});
}
private static class TestSerializer extends LootPoolEntry.Serializer<TagEntry> {
private static final TagEntry.Serializer SERIALIZER = new TagEntry.Serializer();
@Override
public void addEntryFields(JsonObject json, TagEntry entry, JsonSerializationContext context) {
SERIALIZER.addEntryFields(json, entry, context);
json.addProperty("fabric", true);
}
@Override
public TagEntry fromJson(JsonObject var1, JsonDeserializationContext var2, LootCondition[] var3) {
LOGGER.info("Is this a Fabric loot entry? " + JsonHelper.getBoolean(var1, "fabric", true));
return SERIALIZER.fromJson(var1, var2, var3);
}
}
}

View file

@ -1,44 +0,0 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"conditions": [
{
"condition": "minecraft:match_tool",
"predicate": {
"enchantments": [
{
"enchantment": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
],
"name": "minecraft:stone"
},
{
"type": "fabric:extended_tag",
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"name": "minecraft:wool",
"expand": false
}
]
}
]
}
]
}

View file

@ -1,16 +0,0 @@
{
"schemaVersion": 1,
"id": "fabric-loot-tables-v1-testmod",
"name": "Fabric Loot Tables API (v1) Test Mod",
"version": "1.0.0",
"environment": "*",
"license": "Apache-2.0",
"depends": {
"fabric-loot-tables-v1": "*"
},
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.loot.LootV1Test"
]
}
}

View file

@ -1,33 +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.api.registry;
import net.minecraft.loot.entry.LootPoolEntry;
import net.fabricmc.fabric.impl.content.registry.LootEntryTypeRegistryImpl;
/**
* @deprecated Use {@link net.fabricmc.fabric.api.loot.v1.LootEntryTypeRegistry}
*/
@Deprecated
public interface LootEntryTypeRegistry {
@Deprecated
LootEntryTypeRegistry INSTANCE = new LootEntryTypeRegistryImpl();
@Deprecated
void register(LootPoolEntry.Serializer<?> serializer);
}

View file

@ -1,61 +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.impl.content.registry;
import java.lang.reflect.Method;
import net.minecraft.loot.entry.LootPoolEntryTypes;
import net.minecraft.loot.entry.LootPoolEntry;
import net.fabricmc.fabric.api.registry.LootEntryTypeRegistry;
@Deprecated
public final class LootEntryTypeRegistryImpl implements LootEntryTypeRegistry {
private static final Method REGISTER_METHOD;
static {
Method target = null;
for (Method m : LootPoolEntryTypes.class.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0] == LootPoolEntry.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);
}
}
public LootEntryTypeRegistryImpl() { }
@Override
public void register(LootPoolEntry.Serializer<?> serializer) {
try {
REGISTER_METHOD.invoke(null, serializer);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}

View file

@ -199,7 +199,7 @@ public abstract class FabricLanguageProvider implements DataProvider {
* @param value The value of the entry.
*/
default void add(StatType<?> statType, String value) {
add(statType.getTranslationKey(), value);
add("stat_type." + Registries.STAT_TYPE.getId(statType).toString().replace(':', '.'), value);
}
/**

View file

@ -46,6 +46,6 @@ public abstract class SimpleFabricLootTableProvider implements FabricLootTablePr
@Override
public String getName() {
return Objects.requireNonNull(LootContextTypes.getId(lootContextType), "Could not get id for loot context type") + " Loot Table";
return Objects.requireNonNull(LootContextTypes.MAP.inverse().get(lootContextType), "Could not get id for loot context type") + " Loot Table";
}
}

View file

@ -25,14 +25,15 @@ import java.util.concurrent.CompletableFuture;
import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import net.minecraft.data.DataOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.data.DataWriter;
import net.minecraft.loot.LootDataType;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.context.LootContextType;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
@ -65,7 +66,7 @@ public final class FabricLootTableProviderImpl {
final List<CompletableFuture<?>> futures = new ArrayList<>();
for (Map.Entry<Identifier, LootTable> entry : builders.entrySet()) {
JsonObject tableJson = (JsonObject) LootDataType.LOOT_TABLES.getGson().toJsonTree(entry.getValue());
JsonObject tableJson = (JsonObject) Util.getResult(LootTable.field_45796.encodeStart(JsonOps.INSTANCE, entry.getValue()), IllegalStateException::new);
ConditionJsonProvider.write(tableJson, conditionMap.remove(entry.getKey()));
futures.add(DataProvider.writeToPath(writer, tableJson, getOutputPath(fabricDataOutput, entry.getKey())));

View file

@ -33,6 +33,8 @@ accessible method net/minecraft/registry/BuiltinRegistries validate (Lnet/minecr
accessible field net/minecraft/registry/RegistryBuilder registries Ljava/util/List;
accessible class net/minecraft/registry/RegistryBuilder$RegistryInfo
accessible field net/minecraft/loot/context/LootContextTypes MAP Lcom/google/common/collect/BiMap;
transitive-accessible method net/minecraft/data/family/BlockFamilies register (Lnet/minecraft/block/Block;)Lnet/minecraft/data/family/BlockFamily$Builder;
transitive-accessible field net/minecraft/data/client/BlockStateModelGenerator blockStateCollector Ljava/util/function/Consumer;
@ -129,6 +131,7 @@ transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider req
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider conditionsFromItem (Lnet/minecraft/predicate/NumberRange$IntRange;Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/advancement/criterion/InventoryChangedCriterion$Conditions;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider conditionsFromItem (Lnet/minecraft/item/ItemConvertible;)Lnet/minecraft/advancement/criterion/InventoryChangedCriterion$Conditions;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider conditionsFromTag (Lnet/minecraft/registry/tag/TagKey;)Lnet/minecraft/advancement/criterion/InventoryChangedCriterion$Conditions;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider method_53499 ([Lnet/minecraft/predicate/item/ItemPredicate$Builder;)Lnet/minecraft/advancement/criterion/InventoryChangedCriterion$Conditions;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider conditionsFromItemPredicates ([Lnet/minecraft/predicate/item/ItemPredicate;)Lnet/minecraft/advancement/criterion/InventoryChangedCriterion$Conditions;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider hasItem (Lnet/minecraft/item/ItemConvertible;)Ljava/lang/String;
transitive-accessible method net/minecraft/data/server/recipe/RecipeProvider getItemPath (Lnet/minecraft/item/ItemConvertible;)Ljava/lang/String;

View file

@ -28,6 +28,8 @@ accessible method net/minecraft/registry/BuiltinRegistries validate (Lnet/minecr
accessible field net/minecraft/registry/RegistryBuilder registries Ljava/util/List;
accessible class net/minecraft/registry/RegistryBuilder$RegistryInfo
accessible field net/minecraft/loot/context/LootContextTypes MAP Lcom/google/common/collect/BiMap;
transitive-accessible method net/minecraft/data/family/BlockFamilies register (Lnet/minecraft/block/Block;)Lnet/minecraft/data/family/BlockFamily$Builder;
transitive-accessible field net/minecraft/data/client/BlockStateModelGenerator blockStateCollector Ljava/util/function/Consumer;

View file

@ -34,7 +34,7 @@ public class FakePlayerNetworkHandler extends ServerPlayNetworkHandler {
}
@Override
public void send(Packet<?> packet, @Nullable PacketCallbacks callbacks, boolean flush) { }
public void send(Packet<?> packet, @Nullable PacketCallbacks callbacks) { }
private static final class FakeClientConnection extends ClientConnection {
private FakeClientConnection() {

View file

@ -17,7 +17,6 @@
package net.fabricmc.fabric.api.loot.v2;
import java.util.Collection;
import java.util.List;
import org.jetbrains.annotations.ApiStatus;
@ -107,8 +106,8 @@ public interface FabricLootPoolBuilder {
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()));
.with(accessor.fabric_getEntries())
.conditionally(accessor.fabric_getConditions())
.apply(accessor.fabric_getFunctions());
}
}

View file

@ -17,7 +17,6 @@
package net.fabricmc.fabric.api.loot.v2;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import org.jetbrains.annotations.ApiStatus;
@ -104,9 +103,9 @@ public interface FabricLootTableBuilder {
LootTableAccessor accessor = (LootTableAccessor) table;
builder.type(table.getType());
builder.pools(List.of(accessor.fabric_getPools()));
builder.apply(List.of(accessor.fabric_getFunctions()));
builder.randomSequenceId(accessor.fabric_getRandomSequenceId());
builder.pools(accessor.fabric_getPools());
builder.apply(accessor.fabric_getFunctions());
accessor.fabric_getRandomSequenceId().ifPresent(builder::randomSequenceId);
return builder;
}

View file

@ -16,6 +16,8 @@
package net.fabricmc.fabric.mixin.loot;
import java.util.List;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@ -38,11 +40,11 @@ public interface LootPoolAccessor {
LootNumberProvider fabric_getBonusRolls();
@Accessor("entries")
LootPoolEntry[] fabric_getEntries();
List<LootPoolEntry> fabric_getEntries();
@Accessor("conditions")
LootCondition[] fabric_getConditions();
List<LootCondition> fabric_getConditions();
@Accessor("functions")
LootFunction[] fabric_getFunctions();
List<LootFunction> fabric_getFunctions();
}

View file

@ -17,8 +17,8 @@
package net.fabricmc.fabric.mixin.loot;
import java.util.Collection;
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;
@ -39,15 +39,15 @@ import net.fabricmc.fabric.api.loot.v2.FabricLootPoolBuilder;
abstract class LootPoolBuilderMixin implements FabricLootPoolBuilder {
@Shadow
@Final
private List<LootPoolEntry> entries;
private ImmutableList.Builder<LootPoolEntry> entries;
@Shadow
@Final
private List<LootCondition> conditions;
private ImmutableList.Builder<LootCondition> conditions;
@Shadow
@Final
private List<LootFunction> functions;
private ImmutableList.Builder<LootFunction> functions;
@Unique
private LootPool.Builder self() {

View file

@ -16,6 +16,9 @@
package net.fabricmc.fabric.mixin.loot;
import java.util.List;
import java.util.Optional;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@ -31,11 +34,11 @@ import net.minecraft.util.Identifier;
@Mixin(LootTable.class)
public interface LootTableAccessor {
@Accessor("pools")
LootPool[] fabric_getPools();
List<LootPool> fabric_getPools();
@Accessor("functions")
LootFunction[] fabric_getFunctions();
List<LootFunction> fabric_getFunctions();
@Accessor("randomSequenceId")
Identifier fabric_getRandomSequenceId();
Optional<Identifier> fabric_getRandomSequenceId();
}

View file

@ -16,13 +16,15 @@
package net.fabricmc.fabric.mixin.loot;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
import com.google.common.collect.ImmutableList;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@ -41,11 +43,12 @@ import net.fabricmc.fabric.api.loot.v2.FabricLootTableBuilder;
abstract class LootTableBuilderMixin implements FabricLootTableBuilder {
@Shadow
@Final
private List<LootPool> pools;
@Mutable
private ImmutableList.Builder<LootPool> pools;
@Shadow
@Final
private List<LootFunction> functions;
private ImmutableList.Builder<LootFunction> functions;
@Unique
private LootTable.Builder self() {
@ -79,7 +82,8 @@ abstract class LootTableBuilderMixin implements FabricLootTableBuilder {
@Override
public LootTable.Builder modifyPools(Consumer<? super LootPool.Builder> modifier) {
ListIterator<LootPool> iterator = pools.listIterator();
var list = new ArrayList<>(pools.build());
ListIterator<LootPool> iterator = list.listIterator();
while (iterator.hasNext()) {
LootPool.Builder poolBuilder = FabricLootPoolBuilder.copyOf(iterator.next());
@ -87,6 +91,9 @@ abstract class LootTableBuilderMixin implements FabricLootTableBuilder {
iterator.set(poolBuilder.build());
}
this.pools = ImmutableList.builder();
this.pools.addAll(list);
return self();
}
}

View file

@ -25,7 +25,7 @@ import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.EntityTrackingListener;
import net.minecraft.server.network.PlayerAssociatedNetworkHandler;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
@ -118,7 +118,7 @@ public final class PlayerLookup {
// return an immutable collection to guard against accidental removals.
if (tracker != null) {
return Collections.unmodifiableCollection(tracker.getPlayersTracking()
.stream().map(EntityTrackingListener::getPlayer).collect(Collectors.toSet()));
.stream().map(PlayerAssociatedNetworkHandler::getPlayer).collect(Collectors.toSet()));
}
return Collections.emptySet();

View file

@ -17,9 +17,9 @@
package net.fabricmc.fabric.impl.networking.payload;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.c2s.login.LoginQueryResponse;
import net.minecraft.network.packet.c2s.login.LoginQueryResponsePayload;
public record PacketByteBufLoginQueryResponse(PacketByteBuf data) implements LoginQueryResponse {
public record PacketByteBufLoginQueryResponse(PacketByteBuf data) implements LoginQueryResponsePayload {
@Override
public void write(PacketByteBuf buf) {
PayloadHelper.write(buf, data());

View file

@ -188,8 +188,7 @@ public final class ServerConfigurationNetworkAddon extends AbstractChanneledNetw
@Override
public void sendPacket(Packet<?> packet, PacketCallbacks callback) {
// Ensure we flush the packet.
handler.send(packet, callback, true);
handler.send(packet, callback);
}
private enum RegisterState {

View file

@ -22,7 +22,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.c2s.login.LoginQueryResponse;
import net.minecraft.network.packet.c2s.login.LoginQueryResponsePayload;
import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket;
import net.fabricmc.fabric.impl.networking.payload.PacketByteBufLoginQueryResponse;
@ -30,8 +30,8 @@ import net.fabricmc.fabric.impl.networking.payload.PayloadHelper;
@Mixin(LoginQueryResponseC2SPacket.class)
public class LoginQueryResponseC2SPacketMixin {
@Inject(method = "readResponse", at = @At("HEAD"), cancellable = true)
private static void readResponse(int queryId, PacketByteBuf buf, CallbackInfoReturnable<LoginQueryResponse> cir) {
@Inject(method = "readPayload", at = @At("HEAD"), cancellable = true)
private static void readResponse(int queryId, PacketByteBuf buf, CallbackInfoReturnable<LoginQueryResponsePayload> cir) {
boolean hasPayload = buf.readBoolean();
if (!hasPayload) {

View file

@ -21,10 +21,10 @@ import java.util.Set;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.server.world.EntityTrackingListener;
import net.minecraft.server.network.PlayerAssociatedNetworkHandler;
@Mixin(targets = "net/minecraft/server/world/ThreadedAnvilChunkStorage$EntityTracker")
public interface EntityTrackerAccessor {
@Accessor("listeners")
Set<EntityTrackingListener> getPlayersTracking();
Set<PlayerAssociatedNetworkHandler> getPlayersTracking();
}

View file

@ -17,11 +17,6 @@
package net.fabricmc.fabric.api.event.registry;
public enum RegistryAttribute {
/**
* Registry will be saved to disk when modded.
*/
PERSISTED,
/**
* Registry will be synced to the client when modded.
*/

View file

@ -45,8 +45,7 @@ public class FabricRegistryInit implements ModInitializer {
// StatusEffectInstance serialises with raw id.
RegistryAttributeHolder.get(Registries.STATUS_EFFECT)
.addAttribute(RegistryAttribute.SYNCED)
.addAttribute(RegistryAttribute.PERSISTED);
.addAttribute(RegistryAttribute.SYNCED);
// Synced in ChunkDeltaUpdateS2CPacket among other places, a pallet is used when saving.
RegistryAttributeHolder.get(Registries.BLOCK)

View file

@ -87,7 +87,7 @@ public final class RegistrySyncManager {
return;
}
final Map<Identifier, Object2IntMap<Identifier>> map = RegistrySyncManager.createAndPopulateRegistryMap(true, null);
final Map<Identifier, Object2IntMap<Identifier>> map = RegistrySyncManager.createAndPopulateRegistryMap(null);
if (map == null) {
// Don't send when there is nothing to map
@ -151,12 +151,11 @@ public final class RegistrySyncManager {
/**
* Creates a {@link NbtCompound} used to save or sync the registry ids.
*
* @param isClientSync true when syncing to the client, false when saving
* @param activeMap contains the registry ids that were previously read and applied, can be null.
* @return a {@link NbtCompound} to save or sync, null when empty
*/
@Nullable
public static Map<Identifier, Object2IntMap<Identifier>> createAndPopulateRegistryMap(boolean isClientSync, @Nullable Map<Identifier, Object2IntMap<Identifier>> activeMap) {
public static Map<Identifier, Object2IntMap<Identifier>> createAndPopulateRegistryMap(@Nullable Map<Identifier, Object2IntMap<Identifier>> activeMap) {
Map<Identifier, Object2IntMap<Identifier>> map = new LinkedHashMap<>();
for (Identifier registryId : Registries.REGISTRIES.getIds()) {
@ -210,31 +209,23 @@ public final class RegistrySyncManager {
RegistryAttributeHolder attributeHolder = RegistryAttributeHolder.get(registry.getKey());
if (!attributeHolder.hasAttribute(isClientSync ? RegistryAttribute.SYNCED : RegistryAttribute.PERSISTED)) {
LOGGER.debug("Not {} registry: {}", isClientSync ? "syncing" : "saving", registryId);
if (!attributeHolder.hasAttribute(RegistryAttribute.SYNCED)) {
LOGGER.debug("Not syncing registry: {}", registryId);
continue;
}
/*
* Dont do anything with vanilla registries on client sync.
* When saving skip none modded registries that doesnt have previous registry data
*
* This will not sync IDs if a world has been previously modded, either from removed mods
* or a previous version of fabric registry sync, but will save these ids to disk in case the mod or mods
* are added back.
* or a previous version of fabric registry sync.
*/
if ((previousIdMap == null || isClientSync) && !attributeHolder.hasAttribute(RegistryAttribute.MODDED)) {
if (previousIdMap == null || !attributeHolder.hasAttribute(RegistryAttribute.MODDED)) {
LOGGER.debug("Skipping un-modded registry: " + registryId);
continue;
} else if (previousIdMap != null) {
LOGGER.debug("Preserving previously modded registry: " + registryId);
}
if (isClientSync) {
LOGGER.debug("Syncing registry: " + registryId);
} else {
LOGGER.debug("Saving registry: " + registryId);
}
LOGGER.debug("Syncing registry: " + registryId);
if (registry instanceof RemappableRegistry) {
Object2IntMap<Identifier> idMap = new Object2IntLinkedOpenHashMap<>();
@ -265,33 +256,10 @@ public final class RegistrySyncManager {
idMap.put(id, rawId);
}
/*
* Look for existing registry key/values that are not in the current registries.
* This can happen when registry entries are removed, preventing that ID from being re-used by something else.
*/
if (!isClientSync && previousIdMap != null) {
for (Identifier key : previousIdMap.keySet()) {
if (!idMap.containsKey(key)) {
LOGGER.debug("Saving orphaned registry entry: " + key);
idMap.put(key, previousIdMap.getInt(key));
}
}
}
map.put(registryId, idMap);
}
}
// Ensure any orphaned registry's are kept on disk
if (!isClientSync && activeMap != null) {
for (Identifier registryKey : activeMap.keySet()) {
if (!map.containsKey(registryKey)) {
LOGGER.debug("Saving orphaned registry: " + registryKey);
map.put(registryKey, activeMap.get(registryKey));
}
}
}
if (map.isEmpty()) {
return null;
}

View file

@ -1,173 +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.registry.sync;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtIo;
import net.minecraft.util.Identifier;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.world.SaveProperties;
import net.minecraft.world.level.storage.LevelStorage;
import net.fabricmc.fabric.impl.registry.sync.RegistryMapSerializer;
import net.fabricmc.fabric.impl.registry.sync.RegistrySyncManager;
import net.fabricmc.fabric.impl.registry.sync.RemapException;
import net.fabricmc.fabric.impl.registry.sync.RemappableRegistry;
@Mixin(LevelStorage.Session.class)
public class LevelStorageSessionMixin {
@Unique
private static final int FABRIC_ID_REGISTRY_BACKUPS = 3;
@Unique
private static final Logger FABRIC_LOGGER = LoggerFactory.getLogger("FabricRegistrySync");
@Unique
private Map<Identifier, Object2IntMap<Identifier>> fabric_lastSavedRegistryMap = null;
@Unique
private Map<Identifier, Object2IntMap<Identifier>> fabric_activeRegistryMap = null;
@Shadow
@Final
private LevelStorage.LevelSave directory;
@Unique
private boolean fabric_readIdMapFile(File file) throws IOException, RemapException {
FABRIC_LOGGER.debug("Reading registry data from " + file.toString());
if (file.exists()) {
FileInputStream fileInputStream = new FileInputStream(file);
NbtCompound tag = NbtIo.readCompressed(fileInputStream);
fileInputStream.close();
if (tag != null) {
fabric_activeRegistryMap = RegistryMapSerializer.fromNbt(tag);
RegistrySyncManager.apply(fabric_activeRegistryMap, RemappableRegistry.RemapMode.AUTHORITATIVE);
return true;
}
}
return false;
}
@Unique
private File fabric_getWorldIdMapFile(int i) {
return new File(new File(directory.path().toFile(), "data"), "fabricRegistry" + ".dat" + (i == 0 ? "" : ("." + i)));
}
@Unique
private void fabric_saveRegistryData() {
FABRIC_LOGGER.debug("Starting registry save");
Map<Identifier, Object2IntMap<Identifier>> newMap = RegistrySyncManager.createAndPopulateRegistryMap(false, fabric_activeRegistryMap);
if (newMap == null) {
FABRIC_LOGGER.debug("Not saving empty registry data");
return;
}
if (!newMap.equals(fabric_lastSavedRegistryMap)) {
for (int i = FABRIC_ID_REGISTRY_BACKUPS - 1; i >= 0; i--) {
File file = fabric_getWorldIdMapFile(i);
if (file.exists()) {
if (i == FABRIC_ID_REGISTRY_BACKUPS - 1) {
file.delete();
} else {
File target = fabric_getWorldIdMapFile(i + 1);
file.renameTo(target);
}
}
}
try {
File file = fabric_getWorldIdMapFile(0);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
if (!parentFile.mkdirs()) {
FABRIC_LOGGER.warn("[fabric-registry-sync] Could not create directory " + parentFile + "!");
}
}
FABRIC_LOGGER.debug("Saving registry data to " + file);
FileOutputStream fileOutputStream = new FileOutputStream(file);
NbtIo.writeCompressed(RegistryMapSerializer.toNbt(newMap), fileOutputStream);
fileOutputStream.close();
} catch (IOException e) {
FABRIC_LOGGER.warn("[fabric-registry-sync] Failed to save registry file!", e);
}
fabric_lastSavedRegistryMap = newMap;
}
}
@Inject(method = "backupLevelDataFile(Lnet/minecraft/registry/DynamicRegistryManager;Lnet/minecraft/world/SaveProperties;Lnet/minecraft/nbt/NbtCompound;)V", at = @At("HEAD"))
public void saveWorld(DynamicRegistryManager registryTracker, SaveProperties saveProperties, NbtCompound compoundTag, CallbackInfo info) {
if (!Files.exists(directory.path())) {
return;
}
fabric_saveRegistryData();
}
// TODO: stop double save on client?
@Inject(method = "readLevelProperties", at = @At("HEAD"))
public void readWorldProperties(CallbackInfoReturnable<SaveProperties> callbackInfo) {
// Load
for (int i = 0; i < FABRIC_ID_REGISTRY_BACKUPS; i++) {
FABRIC_LOGGER.trace("[fabric-registry-sync] Loading Fabric registry [file " + (i + 1) + "/" + (FABRIC_ID_REGISTRY_BACKUPS + 1) + "]");
try {
if (fabric_readIdMapFile(fabric_getWorldIdMapFile(i))) {
FABRIC_LOGGER.info("[fabric-registry-sync] Loaded registry data [file " + (i + 1) + "/" + (FABRIC_ID_REGISTRY_BACKUPS + 1) + "]");
return;
}
} catch (FileNotFoundException e) {
// pass
} catch (IOException e) {
if (i >= FABRIC_ID_REGISTRY_BACKUPS - 1) {
throw new RuntimeException(e);
} else {
FABRIC_LOGGER.warn("Reading registry file failed!", e);
}
} catch (RemapException e) {
throw new RuntimeException("Remapping world failed!", e);
}
}
// If not returned (not present), try saving the registry data
fabric_saveRegistryData();
}
}

View file

@ -154,7 +154,7 @@ public abstract class SimpleRegistryMixin<T> implements MutableRegistry<T>, Rema
onChange(registryKey);
}
@Inject(method = "set", at = @At("RETURN"))
@Inject(method = "method_46744", at = @At("RETURN"))
private <V extends T> void set(int rawId, RegistryKey<Registry<T>> registryKey, V entry, Lifecycle lifecycle, CallbackInfoReturnable<RegistryEntry<T>> info) {
// We need to restore the 1.19 behavior of binding the value to references immediately.
// Unfrozen registries cannot be interacted with otherwise, because the references would throw when
@ -179,7 +179,7 @@ public abstract class SimpleRegistryMixin<T> implements MutableRegistry<T>, Rema
}
}
@Inject(method = "set", at = @At("HEAD"))
@Inject(method = "method_46744", at = @At("HEAD"))
public void setPre(int id, RegistryKey<T> registryId, T object, Lifecycle lifecycle, CallbackInfoReturnable<RegistryEntry<T>> info) {
int indexedEntriesId = entryToRawId.getInt(object);
@ -207,7 +207,7 @@ public abstract class SimpleRegistryMixin<T> implements MutableRegistry<T>, Rema
}
}
@Inject(method = "set", at = @At("RETURN"))
@Inject(method = "method_46744", at = @At("RETURN"))
public void setPost(int id, RegistryKey<T> registryId, T object, Lifecycle lifecycle, CallbackInfoReturnable<RegistryEntry<T>> info) {
if (fabric_isObjectNew) {
fabric_addObjectEvent.invoker().onEntryAdded(id, registryId.getValue(), object);

View file

@ -7,7 +7,6 @@
"ChunkSerializerMixin",
"DebugChunkGeneratorAccessor",
"IdListMixin",
"LevelStorageSessionMixin",
"MinecraftServerMixin",
"RegistriesAccessor",
"RegistriesMixin",

View file

@ -84,7 +84,6 @@ public class RegistrySyncTest implements ModInitializer {
Validate.isTrue(RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.MODDED));
Validate.isTrue(RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.SYNCED));
Validate.isTrue(!RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.PERSISTED));
final AtomicBoolean setupCalled = new AtomicBoolean(false);

View file

@ -42,8 +42,8 @@ abstract class GameRendererMixin {
@Unique
private Screen renderingScreen;
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void onBeforeRenderScreen(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, MatrixStack matrixStack, DrawContext drawContext) {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V"), locals = LocalCapture.CAPTURE_FAILHARD)
private void onBeforeRenderScreen(float tickDelta, long startTime, boolean tick, CallbackInfo ci, boolean b1, int mouseX, int mouseY, MatrixStack matrixStack, DrawContext drawContext) {
// Store the screen in a variable in case someone tries to change the screen during this before render event.
// If someone changes the screen, the after render event will likely have class cast exceptions or an NPE.
this.renderingScreen = this.client.currentScreen;
@ -51,8 +51,8 @@ abstract class GameRendererMixin {
}
// This injection should end up in the try block so exceptions are caught
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void onAfterRenderScreen(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, MatrixStack matrixStack, DrawContext drawContext) {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD)
private void onAfterRenderScreen(float tickDelta, long startTime, boolean tick, CallbackInfo ci, boolean b1, int mouseX, int mouseY, MatrixStack matrixStack, DrawContext drawContext) {
ScreenEvents.afterRender(this.renderingScreen).invoker().afterRender(this.renderingScreen, drawContext, mouseX, mouseY, tickDelta);
// Finally set the currently rendering screen to null
this.renderingScreen = null;

View file

@ -20,13 +20,11 @@ transitive-accessible class net/minecraft/client/gui/screen/ingame/HandledScreen
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 entries Ljava/util/List;
transitive-accessible field net/minecraft/loot/LootPool conditions Ljava/util/List;
transitive-accessible field net/minecraft/loot/LootPool functions Ljava/util/List;
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;
# Villager trade factories
transitive-accessible class net/minecraft/village/TradeOffers$TypedWrapperFactory

View file

@ -15,13 +15,11 @@ transitive-accessible class net/minecraft/client/gui/screen/ingame/HandledScreen
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 entries Ljava/util/List;
transitive-accessible field net/minecraft/loot/LootPool conditions Ljava/util/List;
transitive-accessible field net/minecraft/loot/LootPool functions Ljava/util/List;
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;
# Villager trade factories
transitive-accessible class net/minecraft/village/TradeOffers$TypedWrapperFactory

View file

@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx2560M
org.gradle.parallel=true
fabric.loom.multiProjectOptimisation=true
version=0.86.1
minecraft_version=23w31a
yarn_version=+build.11
version=0.86.2
minecraft_version=23w32a
yarn_version=+build.2
loader_version=0.14.22
installer_version=0.11.1
@ -20,13 +20,13 @@ fabric-blockrenderlayer-v1-version=1.1.41
fabric-command-api-v1-version=1.2.34
fabric-command-api-v2-version=2.2.13
fabric-commands-v0-version=0.2.51
fabric-containers-v0-version=0.1.63
fabric-content-registries-v0-version=4.0.10
fabric-containers-v0-version=0.1.64
fabric-content-registries-v0-version=5.0.0
fabric-crash-report-info-v1-version=0.2.19
fabric-data-generation-api-v1-version=12.2.2
fabric-data-generation-api-v1-version=12.2.3
fabric-dimensions-v1-version=2.1.53
fabric-entity-events-v1-version=1.5.23
fabric-events-interaction-v0-version=0.6.2
fabric-events-interaction-v0-version=0.6.3
fabric-events-lifecycle-v0-version=0.2.63
fabric-game-rule-api-v1-version=1.0.39
fabric-gametest-api-v1-version=1.2.13
@ -35,17 +35,16 @@ fabric-item-group-api-v1-version=4.0.11
fabric-key-binding-api-v1-version=1.0.37
fabric-keybindings-v0-version=0.2.35
fabric-lifecycle-events-v1-version=2.2.22
fabric-loot-api-v2-version=1.1.40
fabric-loot-tables-v1-version=1.1.44
fabric-loot-api-v2-version=2.0.0
fabric-message-api-v1-version=5.1.8
fabric-mining-level-api-v1-version=2.1.50
fabric-model-loading-api-v1-version=1.0.3
fabric-models-v0-version=0.4.2
fabric-networking-api-v1-version=2.0.0
fabric-networking-api-v1-version=3.0.0
fabric-object-builder-api-v1-version=11.1.2
fabric-particles-v1-version=1.1.2
fabric-recipe-api-v1-version=1.0.20
fabric-registry-sync-v0-version=2.4.0
fabric-recipe-api-v1-version=1.0.21
fabric-registry-sync-v0-version=3.0.0
fabric-renderer-api-v1-version=3.1.2
fabric-renderer-indigo-version=1.4.2
fabric-renderer-registries-v1-version=3.2.46
@ -55,10 +54,10 @@ fabric-rendering-v0-version=1.1.49
fabric-rendering-v1-version=3.0.8
fabric-resource-conditions-api-v1-version=2.3.6
fabric-resource-loader-v0-version=0.11.10
fabric-screen-api-v1-version=2.0.8
fabric-screen-handler-api-v1-version=1.3.29
fabric-screen-api-v1-version=2.0.9
fabric-screen-handler-api-v1-version=1.3.30
fabric-sound-api-v1-version=1.0.13
fabric-transfer-api-v1-version=3.3.1
fabric-transitive-access-wideners-v1-version=5.0.0
fabric-transitive-access-wideners-v1-version=5.0.1
fabric-convention-tags-v1-version=1.5.5
fabric-client-tags-api-v1-version=1.1.2

View file

@ -64,4 +64,3 @@ include 'deprecated:fabric-keybindings-v0'
include 'deprecated:fabric-models-v0'
include 'deprecated:fabric-renderer-registries-v1'
include 'deprecated:fabric-rendering-v0'
include 'deprecated:fabric-loot-tables-v1'