mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-30 03:26:07 -05:00
Structure Pool Callback (#1540)
* Structure Pool Callback * Update build.gradle * Update fabric-structure-api-v1/src/main/java/net/fabricmc/fabric/api/structure/v1/FabricStructurePool.java Co-authored-by: liach <7806504+liach@users.noreply.github.com> * Update fabric-structure-api-v1/src/main/java/net/fabricmc/fabric/api/structure/v1/FabricStructurePool.java Co-authored-by: liach <7806504+liach@users.noreply.github.com> * Fix certain concerns * Expose identifier for easier access * Final test mod thing * fix access widener * Fix a few things * Fix a few things * Fix license * haha lets see if this works * checkstyle was working after I did checkstyleMain so u bettar work * i take too much time to do checkstyle fixes * checkstyle fix testmod ugh amirite * Fix a few concerns brought up <3 * Oops, forgot to add a mutanle there * Let's test this one more time? * Remove Access Widener woop woop * rename to poolAccessor * Simplify the pool modification a bit Co-authored-by: liach <7806504+liach@users.noreply.github.com>
This commit is contained in:
parent
361124d717
commit
48a9ad892d
8 changed files with 274 additions and 0 deletions
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.structure.v1;
|
||||||
|
|
||||||
|
import net.minecraft.structure.pool.StructurePool;
|
||||||
|
import net.minecraft.structure.pool.StructurePoolElement;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a modifiable structure pool that has several helper methods for modders.
|
||||||
|
*/
|
||||||
|
public interface FabricStructurePool {
|
||||||
|
/**
|
||||||
|
* Adds a new {@link StructurePoolElement} to the {@link StructurePool}.
|
||||||
|
* See the alternative {@link #addStructurePoolElement(StructurePoolElement, int)} for details.
|
||||||
|
*
|
||||||
|
* @param element the element to add
|
||||||
|
*/
|
||||||
|
void addStructurePoolElement(StructurePoolElement element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new {@link StructurePoolElement} to the {@link StructurePool}.
|
||||||
|
* Its weight determines the amount of times an element is added to a list used for sampling during structure generation.
|
||||||
|
*
|
||||||
|
* @param element the element to add
|
||||||
|
* @param weight the weight of the element
|
||||||
|
*/
|
||||||
|
void addStructurePoolElement(StructurePoolElement element, int weight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the underlying structure pool.
|
||||||
|
*/
|
||||||
|
StructurePool getUnderlyingPool();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the identifier for the pool.
|
||||||
|
*/
|
||||||
|
default Identifier getId() {
|
||||||
|
return getUnderlyingPool().getId();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.api.structure.v1;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback for newly added structure pools.
|
||||||
|
*
|
||||||
|
* <p><strong>Word of warning</strong>: Mods may be editing on the structure pool from user configured data packs
|
||||||
|
* instead of the builtin Minecraft or mod resources.
|
||||||
|
*
|
||||||
|
* <p>Example usage:
|
||||||
|
* <pre>{@code
|
||||||
|
* StructurePoolAddCallback.EVENT.register(structurePool -> {
|
||||||
|
* if (structurePool.getId().equals(new Identifier("minecraft:village/desert/houses"))) {
|
||||||
|
* structurePool.addStructurePoolElement(StructurePoolElement.ofProcessedLegacySingle("fabric:cactus_farm", StructureProcessorLists.FARM_PLAINS).apply(StructurePool.Projection.RIGID));
|
||||||
|
* }
|
||||||
|
* });}
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface StructurePoolAddCallback {
|
||||||
|
/**
|
||||||
|
* Called when structure pools are reloaded at data pack reload time.
|
||||||
|
*/
|
||||||
|
Event<StructurePoolAddCallback> EVENT = EventFactory.createArrayBacked(StructurePoolAddCallback.class,
|
||||||
|
listeners -> initialPool -> {
|
||||||
|
for (StructurePoolAddCallback listener : listeners) {
|
||||||
|
listener.onAdd(initialPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
void onAdd(FabricStructurePool initialPool);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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.structure;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.structure.pool.StructurePool;
|
||||||
|
import net.minecraft.structure.pool.StructurePoolElement;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.structure.v1.FabricStructurePool;
|
||||||
|
import net.fabricmc.fabric.mixin.structure.StructurePoolAccessor;
|
||||||
|
|
||||||
|
public class FabricStructurePoolImpl implements FabricStructurePool {
|
||||||
|
private final StructurePool pool;
|
||||||
|
|
||||||
|
public FabricStructurePoolImpl(StructurePool pool) {
|
||||||
|
this.pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addStructurePoolElement(StructurePoolElement element) {
|
||||||
|
addStructurePoolElement(element, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addStructurePoolElement(StructurePoolElement element, int weight) {
|
||||||
|
if (weight <= 0) {
|
||||||
|
throw new IllegalArgumentException("weight must be positive");
|
||||||
|
}
|
||||||
|
|
||||||
|
//adds to elementCounts list; minecraft makes these immutable lists, so we temporarily replace them with an array list
|
||||||
|
StructurePoolAccessor poolAccessor = (StructurePoolAccessor) getUnderlyingPool();
|
||||||
|
|
||||||
|
List<Pair<StructurePoolElement, Integer>> list = new ArrayList<>(poolAccessor.getElementCounts());
|
||||||
|
list.add(Pair.of(element, weight));
|
||||||
|
poolAccessor.setElementCounts(ImmutableList.copyOf(list));
|
||||||
|
|
||||||
|
//adds to elements list
|
||||||
|
for (int i = 0; i < weight; i++) {
|
||||||
|
poolAccessor.getElements().add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructurePool getUnderlyingPool() {
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.structure;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Coerce;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
|
import net.minecraft.structure.pool.StructurePool;
|
||||||
|
import net.minecraft.util.dynamic.RegistryOps;
|
||||||
|
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.structure.v1.StructurePoolAddCallback;
|
||||||
|
import net.fabricmc.fabric.impl.structure.FabricStructurePoolImpl;
|
||||||
|
|
||||||
|
@Mixin(DynamicRegistryManager.class)
|
||||||
|
public abstract class DynamicRegistryManagerMixin {
|
||||||
|
@Inject(method = "load(Lnet/minecraft/util/dynamic/RegistryOps;Lnet/minecraft/util/registry/DynamicRegistryManager;Lnet/minecraft/util/registry/DynamicRegistryManager$Info;)V", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||||
|
private static <E> void load(RegistryOps<?> ops, DynamicRegistryManager manager, @Coerce Object info, CallbackInfo ci, RegistryKey<? extends Registry<E>> registryKey) {
|
||||||
|
if (registryKey.equals(Registry.STRUCTURE_POOL_KEY)) {
|
||||||
|
for (E registryEntry : manager.get(registryKey)) {
|
||||||
|
if (registryEntry instanceof StructurePool pool) {
|
||||||
|
StructurePoolAddCallback.EVENT.invoker().onAdd(new FabricStructurePoolImpl(pool));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.structure;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import net.minecraft.structure.pool.StructurePool;
|
||||||
|
import net.minecraft.structure.pool.StructurePoolElement;
|
||||||
|
|
||||||
|
@Mixin(StructurePool.class)
|
||||||
|
public interface StructurePoolAccessor {
|
||||||
|
@Accessor(value = "elements")
|
||||||
|
List<StructurePoolElement> getElements();
|
||||||
|
|
||||||
|
@Accessor(value = "elementCounts")
|
||||||
|
List<Pair<StructurePoolElement, Integer>> getElementCounts();
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
@Accessor(value = "elementCounts")
|
||||||
|
void setElementCounts(List<Pair<StructurePoolElement, Integer>> list);
|
||||||
|
}
|
|
@ -4,8 +4,10 @@
|
||||||
"compatibilityLevel": "JAVA_16",
|
"compatibilityLevel": "JAVA_16",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ChunkSerializerMixin",
|
"ChunkSerializerMixin",
|
||||||
|
"DynamicRegistryManagerMixin",
|
||||||
"FlatChunkGeneratorConfigAccessor",
|
"FlatChunkGeneratorConfigAccessor",
|
||||||
"StructureFeatureAccessor",
|
"StructureFeatureAccessor",
|
||||||
|
"StructurePoolAccessor",
|
||||||
"StructuresConfigAccessor"
|
"StructuresConfigAccessor"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
|
|
@ -24,6 +24,9 @@ import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.structure.pool.StructurePool;
|
||||||
|
import net.minecraft.structure.pool.StructurePoolElement;
|
||||||
|
import net.minecraft.structure.processor.StructureProcessorLists;
|
||||||
import net.minecraft.structure.StructureManager;
|
import net.minecraft.structure.StructureManager;
|
||||||
import net.minecraft.structure.StructurePieceType;
|
import net.minecraft.structure.StructurePieceType;
|
||||||
import net.minecraft.structure.StructurePieceWithDimensions;
|
import net.minecraft.structure.StructurePieceWithDimensions;
|
||||||
|
@ -47,6 +50,7 @@ import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||||
import net.minecraft.world.gen.feature.StructureFeature;
|
import net.minecraft.world.gen.feature.StructureFeature;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
|
import net.fabricmc.fabric.api.structure.v1.FabricStructureBuilder;
|
||||||
|
import net.fabricmc.fabric.api.structure.v1.StructurePoolAddCallback;
|
||||||
|
|
||||||
public class StructureTest {
|
public class StructureTest {
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
@ -64,6 +68,16 @@ public class StructureTest {
|
||||||
.adjustsSurface()
|
.adjustsSurface()
|
||||||
.register();
|
.register();
|
||||||
Registry.register(Registry.STRUCTURE_PIECE, new Identifier("fabric", "test_structure_piece"), PIECE);
|
Registry.register(Registry.STRUCTURE_PIECE, new Identifier("fabric", "test_structure_piece"), PIECE);
|
||||||
|
|
||||||
|
//Basic Test of Callback
|
||||||
|
StructurePoolAddCallback.EVENT.register(structurePool -> LOGGER.info("Structure pool {} added", structurePool.getId()));
|
||||||
|
|
||||||
|
//The ideal usage of this callback is to add structures to a Village. Here, I constructed a Cactus Farm, which will be added to the house pool for deserts. For testing purposes, we will make it very common, and use a plains-style log outline so it is clear that it doesn't belong.
|
||||||
|
StructurePoolAddCallback.EVENT.register(structurePool -> {
|
||||||
|
if (structurePool.getId().equals(new Identifier("minecraft:village/desert/houses"))) {
|
||||||
|
structurePool.addStructurePoolElement(StructurePoolElement.ofProcessedLegacySingle("fabric:cactus_farm", StructureProcessorLists.FARM_PLAINS).apply(StructurePool.Projection.RIGID));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TestStructureFeature extends StructureFeature<DefaultFeatureConfig> {
|
public static class TestStructureFeature extends StructureFeature<DefaultFeatureConfig> {
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue