Skip to content

Commit

Permalink
Add a feature generator and allow undoing of feature placement [WIP]
Browse files Browse the repository at this point in the history
Apply changes to Forge as well

Use proper translatable components
  • Loading branch information
me4502 committed Mar 10, 2023
1 parent f40ea0d commit c2da495
Show file tree
Hide file tree
Showing 13 changed files with 696 additions and 3 deletions.
Expand Up @@ -122,6 +122,13 @@
"changes": [
"METHOD_NEW_DEFAULT"
]
},
{
"type": "com.sk89q.worldedit.world.World",
"member": "Method com.sk89q.worldedit.world.World.generateFeature(com.sk89q.worldedit.world.generation.ConfiguredFeatureType,com.sk89q.worldedit.EditSession,com.sk89q.worldedit.math.BlockVector3)",
"changes": [
"METHOD_NEW_DEFAULT"
]
}
],
"LazyReference was never publicly extensible": [
Expand Down
Expand Up @@ -39,6 +39,7 @@
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.generation.ConfiguredFeatureType;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
Expand Down Expand Up @@ -235,6 +236,23 @@ public int pumpkins(Actor actor, LocalSession session, EditSession editSession,
return affected;
}

@Command(
name = "/feature",
desc = "Generate Minecraft features"
)
@CommandPermissions("worldedit.generation.feature")
@Logging(POSITION)
public int feature(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The feature")
ConfiguredFeatureType feature) throws WorldEditException {
if (editSession.getWorld().generateFeature(feature, editSession, session.getPlacementPosition(actor))) {
actor.printInfo(TranslatableComponent.of("worldedit.feature.created"));
} else {
actor.printError(TranslatableComponent.of("worldedit.feature.failed"));
}
return 0;
}

@Command(
name = "/hpyramid",
desc = "Generate a hollow pyramid"
Expand Down
Expand Up @@ -32,6 +32,7 @@
import com.sk89q.worldedit.world.fluid.FluidCategory;
import com.sk89q.worldedit.world.fluid.FluidType;
import com.sk89q.worldedit.world.gamemode.GameMode;
import com.sk89q.worldedit.world.generation.ConfiguredFeatureType;
import com.sk89q.worldedit.world.item.ItemCategory;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.weather.WeatherType;
Expand Down Expand Up @@ -62,7 +63,8 @@ public static void register(CommandManager commandManager) {
FluidType.class,
FluidCategory.class,
GameMode.class,
WeatherType.class
WeatherType.class,
ConfiguredFeatureType.class
)
.stream()
.map(c -> (Class<Keyed>) c)
Expand Down
13 changes: 13 additions & 0 deletions worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java
Expand Up @@ -41,6 +41,7 @@
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.generation.ConfiguredFeatureType;
import com.sk89q.worldedit.world.weather.WeatherType;

import java.nio.file.Path;
Expand Down Expand Up @@ -273,6 +274,18 @@ default boolean regenerate(Region region, Extent extent, RegenOptions options) {
*/
boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException;

/**
* Generate a feature at the given position.
*
* @param type The feature type
* @param editSession The {@link EditSession}
* @param position The position
* @return True if the generation was successful
*/
default boolean generateFeature(ConfiguredFeatureType type, EditSession editSession, BlockVector3 position) {
return false;
}

/**
* Load the chunk at the given position if it isn't loaded.
*
Expand Down
@@ -0,0 +1,38 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.world.generation;

import com.sk89q.worldedit.registry.Keyed;
import com.sk89q.worldedit.registry.NamespacedRegistry;

public class ConfiguredFeatureType implements Keyed {
public static final NamespacedRegistry<ConfiguredFeatureType> REGISTRY = new NamespacedRegistry<>("configured feature type");

private final String id;

public ConfiguredFeatureType(String id) {
this.id = id;
}

@Override
public String getId() {
return this.id;
}
}
2 changes: 2 additions & 0 deletions worldedit-core/src/main/resources/lang/strings.json
Expand Up @@ -245,6 +245,8 @@
"worldedit.sphere.created": "{0} blocks have been created.",
"worldedit.forestgen.created": "{0} trees created.",
"worldedit.pumpkins.created": "{0} pumpkin patches created.",
"worldedit.feature.created": "Feature created.",
"worldedit.feature.failed": "Failed to generate feature. Is it a valid spot for it?",
"worldedit.pyramid.created": "{0} blocks have been created.",
"worldedit.generate.created": "{0} blocks have been created.",
"worldedit.generatebiome.changed": "{0} biomes affected.",
Expand Down
Expand Up @@ -31,6 +31,7 @@
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
Expand All @@ -47,6 +48,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.Vec3;

Expand Down Expand Up @@ -196,6 +198,15 @@ public static BlockState adapt(net.minecraft.world.level.block.state.BlockState
return worldEdit;
}

public static BaseBlock adapt(BlockEntity blockEntity) {
int blockStateId = Block.getId(blockEntity.getBlockState());
BlockState worldEdit = BlockStateIdAccess.getBlockStateById(blockStateId);
if (worldEdit == null) {
worldEdit = FabricTransmogrifier.transmogToWorldEdit(blockEntity.getBlockState());
}
return worldEdit.toBaseBlock(LazyReference.from(() -> NBTConverter.fromNative(blockEntity.saveWithId())));
}

public static Block adapt(BlockType blockType) {
return FabricWorldEdit.getRegistry(Registries.BLOCK).get(new ResourceLocation(blockType.getId()));
}
Expand Down
Expand Up @@ -34,6 +34,7 @@
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.fabric.internal.ExtendedMinecraftServer;
import com.sk89q.worldedit.fabric.internal.FabricEditSessionDelegate;
import com.sk89q.worldedit.fabric.internal.FabricWorldNativeAccess;
import com.sk89q.worldedit.fabric.internal.NBTConverter;
import com.sk89q.worldedit.fabric.mixin.AccessorDerivedLevelData;
Expand All @@ -60,6 +61,7 @@
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.generation.ConfiguredFeatureType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.weather.WeatherType;
import com.sk89q.worldedit.world.weather.WeatherTypes;
Expand Down Expand Up @@ -463,11 +465,18 @@ public boolean generateTree(TreeType type, EditSession editSession, BlockVector3
position = position.add(0, 1, 0);
}
return generator != null && generator.place(
world, chunkManager.getGenerator(), random,
new FabricEditSessionDelegate(editSession, world), chunkManager.getGenerator(), random,
FabricAdapter.toBlockPos(position)
);
}

public boolean generateFeature(ConfiguredFeatureType type, EditSession editSession, BlockVector3 position) {
ServerLevel world = (ServerLevel) getWorld();
ConfiguredFeature<?, ?> k = world.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).get(ResourceLocation.tryParse(type.getId()));
ServerChunkCache chunkManager = world.getChunkSource();
return k != null && k.place(new FabricEditSessionDelegate(editSession, world), chunkManager.getGenerator(), random, FabricAdapter.toBlockPos(position));
}

@Override
public void checkLoadedChunk(BlockVector3 pt) {
getWorld().getChunk(FabricAdapter.toBlockPos(pt));
Expand Down
Expand Up @@ -40,6 +40,7 @@
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.generation.ConfiguredFeatureType;
import com.sk89q.worldedit.world.item.ItemCategory;
import com.sk89q.worldedit.world.item.ItemType;
import net.fabricmc.api.ModInitializer;
Expand Down Expand Up @@ -228,6 +229,12 @@ private void setupRegistries(MinecraftServer server) {
ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
}
});
// Features
for (ResourceLocation name: server.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE).keySet()) {
if (ConfiguredFeatureType.REGISTRY.get(name.toString()) == null) {
ConfiguredFeatureType.REGISTRY.register(name.toString(), new ConfiguredFeatureType(name.toString()));
}
}
}

private void onStartingServer(MinecraftServer minecraftServer) {
Expand Down

0 comments on commit c2da495

Please sign in to comment.