如果你学习过我们之前在1.12.2的建筑生成教程,那么对本次的教程的理解可能会相对轻松。

往期回顾

Minecraft 1.12.2模组开发(十四) 建筑生成 (structure generation)
Minecraft 1.12.2模组开发(二十二) 多种建筑生成

我们本次将在1.16.5版本中实现建筑的自动生成。

1.首先我们需要生成一个建筑的.nbt文件

创建一个新世界

通过命令让我们获得一个建筑方块:

/give @s minecraft:structure_block

之后我们建造一个建筑

通过对建筑操作的坐标变换,将我们这个建筑完全包裹在区域内:

点击’Save’,建筑成功保存下来

保存的建筑会生成一个.nbt文件,我们需要将这个文件找到,路径为

开发包\run\saves\1_8version_test(你的存档名称)\generated\minecraft\structures

2.在data包中新建structures文件夹,将生成的.nbt文件放入其中。

3.在worldgen文件夹中新建template_pool(建筑模板库)文件夹 -> 新建一个与我们建筑名称对应的文件夹(以tank1为例) -> 在tank1中新建一个start_pool.json文件

在start_pool.json中编写:

{"name": "re8joymod:tank1/start_pool", //格式:模组名:建筑名称/start_pool的文件路径"fallback": "minecraft:empty","elements": [{"weight": 1,"element": {"location": "re8joymod:tank1",  //格式:模组名:建筑名称"processors": "minecraft:empty","projection": "rigid","element_type": "minecraft:single_pool_element"}}]
}

4.在common文件夹下新建 world文件夹 -> world文件夹中新建structure文件夹 -> structure文件夹中新建 structures文件夹 -> structures中新建一个建筑物类(以Tank1Structure.java为例)

在Tank1Structure.java中编写:

package com.joy187.re8joymod.common.world.structure.structures;import com.google.common.collect.ImmutableList;
import com.mojang.serialization.Codec;
import net.minecraft.entity.EntityType;
import net.minecraft.util.SharedSeedRandom;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.util.math.vector.Vector3i;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.MobSpawnInfo;
import net.minecraft.world.biome.provider.BiomeProvider;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.feature.jigsaw.JigsawManager;
import net.minecraft.world.gen.feature.structure.*;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.world.gen.feature.template.TemplateManager;
import net.minecraft.block.BlockState;
import net.minecraft.util.ResourceLocation;
import com.joy187.re8joymod.Utils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;import java.util.List;public class Tank1Structure extends Structure<NoFeatureConfig> {public Tank1Structure(Codec<NoFeatureConfig> codec) {super(codec);}@Overridepublic IStartFactory<NoFeatureConfig> getStartFactory() {return Tank1Structure.Start::new;}@Overridepublic GenerationStage.Decoration step() {return GenerationStage.Decoration.SURFACE_STRUCTURES;}private static final List<MobSpawnInfo.Spawners> STRUCTURE_MONSTERS = ImmutableList.of(new MobSpawnInfo.Spawners(EntityType.ILLUSIONER, 10, 1, 4),new MobSpawnInfo.Spawners(EntityType.VINDICATOR, 10, 1, 4));private static final List<MobSpawnInfo.Spawners> STRUCTURE_CREATURES = ImmutableList.of(new MobSpawnInfo.Spawners(EntityType.SHEEP, 10, 1, 5),new MobSpawnInfo.Spawners(EntityType.RABBIT, 10, 1, 4));@Overridepublic List<MobSpawnInfo.Spawners> getDefaultSpawnList() {return STRUCTURE_MONSTERS;}@Overridepublic List<MobSpawnInfo.Spawners> getDefaultCreatureSpawnList() {return STRUCTURE_CREATURES;}@Overrideprotected boolean isFeatureChunk(ChunkGenerator chunkGenerator, BiomeProvider biomeSource,long seed, SharedSeedRandom chunkRandom, int chunkX, int chunkZ,Biome biome, ChunkPos chunkPos, NoFeatureConfig featureConfig) {BlockPos centerOfChunk = new BlockPos((chunkX << 4) + 7, 0, (chunkZ << 4) + 7);int landHeight = chunkGenerator.getBaseHeight(centerOfChunk.getX(), centerOfChunk.getZ(), Heightmap.Type.WORLD_SURFACE_WG);IBlockReader columnOfBlocks = chunkGenerator.getBaseColumn(centerOfChunk.getX(), centerOfChunk.getZ());BlockState topBlock = columnOfBlocks.getBlockState(centerOfChunk.above(landHeight));return topBlock.getFluidState().isEmpty();}@Overridepublic boolean getDefaultRestrictsSpawnsToInside() {return true;}public static class Start extends StructureStart<NoFeatureConfig>  {public Start(Structure<NoFeatureConfig> structureIn, int chunkX, int chunkZ, MutableBoundingBox mutableBoundingBox, int referenceIn, long seedIn) {super(structureIn, chunkX, chunkZ, mutableBoundingBox, referenceIn, seedIn);}@Overridepublic void generatePieces(DynamicRegistries dynamicRegistryManager, ChunkGenerator chunkGenerator, TemplateManager templateManagerIn, int chunkX, int chunkZ, Biome biomeIn, NoFeatureConfig config) {// Turns the chunk coordinates into actual coordinates we can useint x = chunkX * 16 + 7;int z = chunkZ * 16 + 7;/** We pass this into addPieces to tell it where to generate the structure.* If addPieces's last parameter is true, blockpos's Y value is ignored and the* structure will spawn at terrain height instead. Set that parameter to false to* force the structure to spawn at blockpos's Y value instead. You got options here!*/BlockPos centerPos = new BlockPos(x, 0, z);/** If you are doing Nether structures, you'll probably want to spawn your structure on top of ledges.* Best way to do that is to use getBaseColumn to grab a column of blocks at the structure's x/z position.* Then loop through it and look for land with air above it and set blockpos's Y value to it.* Make sure to set the final boolean in JigsawManager.addPieces to false so* that the structure spawns at blockpos's y value instead of placing the structure on the Bedrock roof!*///IBlockReader blockReader = chunkGenerator.getBaseColumn(blockpos.getX(), blockpos.getZ());// All a structure has to do is call this method to turn it into a jigsaw based structure!JigsawManager.addPieces(dynamicRegistryManager,new VillageConfig(() -> dynamicRegistryManager.registryOrThrow(Registry.TEMPLATE_POOL_REGISTRY)// The path to the starting Template Pool JSON file to read.//// Note, this is "structure_tutorial:run_down_house/start_pool" which means// the game will automatically look into the following path for the template pool:// "resources/data/structure_tutorial/worldgen/template_pool/run_down_house/start_pool.json"// This is why your pool files must be in "data/<modid>/worldgen/template_pool/<the path to the pool here>"// because the game automatically will check in worldgen/template_pool for the pools..get(new ResourceLocation(Utils.MOD_ID, "tank1/start_pool")),// How many pieces outward from center can a recursive jigsaw structure spawn.// Our structure is only 1 piece outward and isn't recursive so any value of 1 or more doesn't change anything.// However, I recommend you keep this a decent value like 10 so people can use datapacks to add additional pieces to your structure easily.// But don't make it too large for recursive structures like villages or you'll crash server due to hundreds of pieces attempting to generate!10),AbstractVillagePiece::new,chunkGenerator,templateManagerIn,centerPos, // Position of the structure. Y value is ignored if last parameter is set to true.this.pieces, // The list that will be populated with the jigsaw pieces after this method.this.random,false, // Special boundary adjustments for villages. It's... hard to explain. Keep this false and make your pieces not be partially intersecting.// Either not intersecting or fully contained will make children pieces spawn just fine. It's easier that way.true);  // Place at heightmap (top land). Set this to false for structure to be place at the passed in blockpos's Y value instead.// Definitely keep this false when placing structures in the nether as otherwise, heightmap placing will put the structure on the Bedrock roof.// **THE FOLLOWING TWO LINES ARE OPTIONAL**//// Right here, you can do interesting stuff with the pieces in this.pieces such as offset the// center piece by 50 blocks up for no reason, remove repeats of a piece or add a new piece so// only 1 of that piece exists, etc. But you do not have access to the piece's blocks as this list// holds just the piece's size and positions. Blocks will be placed later in JigsawManager.//// In this case, we do `piece.offset` to raise pieces up by 1 block so that the house is not right on// the surface of water or sunken into land a bit.//// Then we extend the bounding box down by 1 by doing `piece.getBoundingBox().minY` which will cause the// land formed around the structure to be lowered and not cover the doorstep. You can raise the bounding// box to force the structure to be buried as well. This bounding box stuff with land is only for structures// that you added to Structure.NOISE_AFFECTING_FEATURES field handles adding land around the base of structures.//// By lifting the house up by 1 and lowering the bounding box, the land at bottom of house will now be// flush with the surrounding terrain without blocking off the doorstep.this.pieces.forEach(piece -> piece.move(0, 1, 0));this.pieces.forEach(piece -> piece.getBoundingBox().y0 -= 1);// Since by default, the start piece of a structure spawns with it's corner at centerPos// and will randomly rotate around that corner, we will center the piece on centerPos instead.// This is so that our structure's start piece is now centered on the water check done in isFeatureChunk.// Whatever the offset done to center the start piece, that offset is applied to all other pieces// so the entire structure is shifted properly to the new spot.Vector3i structureCenter = this.pieces.get(0).getBoundingBox().getCenter();int xOffset = centerPos.getX() - structureCenter.getX();int zOffset = centerPos.getZ() - structureCenter.getZ();for(StructurePiece structurePiece : this.pieces){structurePiece.move(xOffset, 0, zOffset);}this.calculateBoundingBox();//用作Debug,查看建筑生成的位置LogManager.getLogger().log(Level.DEBUG, "Rundown House at " +this.pieces.get(0).getBoundingBox().x0 + " " +this.pieces.get(0).getBoundingBox().y0 + " " +this.pieces.get(0).getBoundingBox().z0);}}}

5.在刚刚新建的 structure文件夹中新建 ModStructure.java

在ModStructure.java中编写:

package com.joy187.re8joymod.common.world.structure;import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.joy187.re8joymod.Utils;
import com.joy187.re8joymod.common.world.structure.structures.Tank1Structure;
import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.gen.settings.DimensionStructuresSettings;
import net.minecraft.world.gen.settings.StructureSeparationSettings;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;import java.util.HashMap;
import java.util.Map;public class ModStructures {//  STStructures.javapublic static final DeferredRegister<Structure<?>> STRUCTURES =DeferredRegister.create(ForgeRegistries.STRUCTURE_FEATURES, Utils.MOD_ID);//    public static final RegistryObject<Structure<NoFeatureConfig>> TANK1 = STRUCTURES.register("tank1", Tank1Structure::new);public static final RegistryObject<Structure<NoFeatureConfig>> TANK1 =STRUCTURES.register("tank1", () -> (new Tank1Structure(NoFeatureConfig.CODEC)));/* average distance apart in chunks between spawn attempts *//* minimum distance apart in chunks between spawn attempts. MUST BE LESS THAN ABOVE VALUE*//* this modifies the seed of the structure so no two structures always spawn over each-other.Make this large and unique. */public static void setupStructures() {setupMapSpacingAndLand(TANK1.get(),new StructureSeparationSettings(100,50, 1234567897), true);}public static <F extends Structure<?>> void setupMapSpacingAndLand(F structure,StructureSeparationSettings structureSeparationSettings,boolean transformSurroundingLand){/** We need to add our structures into the map in Structure class* alongside vanilla structures or else it will cause errors.** If the registration is setup properly for the structure,* getRegistryName() should never return null.*/Structure.STRUCTURES_REGISTRY.put(structure.getRegistryName().toString(), structure);/** Whether surrounding land will be modified automatically to conform to the bottom of the structure.* Basically, it adds land at the base of the structure like it does for Villages and Outposts.* Doesn't work well on structure that have pieces stacked vertically or change in heights.** Note: The air space this method will create will be filled with water if the structure is below sealevel.* This means this is best for structure above sealevel so keep that in mind.** NOISE_AFFECTING_FEATURES requires AccessTransformer  (See resources/META-INF/accesstransformer.cfg)*/if(transformSurroundingLand){Structure.NOISE_AFFECTING_FEATURES = ImmutableList.<Structure<?>>builder().addAll(Structure.NOISE_AFFECTING_FEATURES).add(structure).build();}/** This is the map that holds the default spacing of all structures.* Always add your structure to here so that other mods can utilize it if needed.** However, while it does propagate the spacing to some correct dimensions from this map,* it seems it doesn't always work for code made dimensions as they read from this list beforehand.** Instead, we will use the WorldEvent.Load event in StructureTutorialMain to add the structure* spacing from this list into that dimension or to do dimension blacklisting properly.* We also use our entry in DimensionStructuresSettings.DEFAULTS in WorldEvent.Load as well.** DEFAULTS requires AccessTransformer  (See resources/META-INF/accesstransformer.cfg)*/DimensionStructuresSettings.DEFAULTS =ImmutableMap.<Structure<?>, StructureSeparationSettings>builder().putAll(DimensionStructuresSettings.DEFAULTS).put(structure, structureSeparationSettings).build();/** There are very few mods that relies on seeing your structure in the noise settings registry before the world is made.** You may see some mods add their spacings to DimensionSettings.BUILTIN_OVERWORLD instead of the NOISE_GENERATOR_SETTINGS loop below but* that field only applies for the default overworld and won't add to other worldtypes or dimensions (like amplified or Nether).* So yeah, don't do DimensionSettings.BUILTIN_OVERWORLD. Use the NOISE_GENERATOR_SETTINGS loop below instead if you must.*/WorldGenRegistries.NOISE_GENERATOR_SETTINGS.entrySet().forEach(settings -> {Map<Structure<?>, StructureSeparationSettings> structureMap = settings.getValue().structureSettings().structureConfig();/** Pre-caution in case a mod makes the structure map immutable like datapacks do.* I take no chances myself. You never know what another mods does...** structureConfig requires AccessTransformer  (See resources/META-INF/accesstransformer.cfg)*/if(structureMap instanceof ImmutableMap){Map<Structure<?>, StructureSeparationSettings> tempMap = new HashMap<>(structureMap);tempMap.put(structure, structureSeparationSettings);settings.getValue().structureSettings().structureConfig = tempMap;}else{structureMap.put(structure, structureSeparationSettings);}});}public static void register(IEventBus eventBus) {STRUCTURES.register(eventBus);}
}

如果你出现了诸如这样的问题:


这说明你还没有配置accesstransformer.cfg文件(路径:**resources/META-INF/**accesstransformer.cfg)
在该路径下新建一个accesstransformer.cfg文件,将如下的代码copy进去:

public-f net.minecraft.world.gen.feature.structure.Structure field_236384_t_ #LAND_TRANSFORMING_STRUCTURES
public-f net.minecraft.world.gen.settings.DimensionStructuresSettings field_236191_b_ #DEFAULT_STRUCTURE_CONFIGS
public-f net.minecraft.world.gen.FlatGenerationSettings field_202247_j #STRUCTURES
public-f net.minecraft.world.gen.settings.DimensionStructuresSettings field_236193_d_ #structures

之后对我们的build.gradle进行修改:

在’mappings channel’下方另起一行添加如下语句:
 accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')

Gradle修改之后需要进行一次重新加载(过程略慢,请耐心等待)

之后报错的字段应该就自然消除了。

6.接下来我们需要在world/gen文件夹中新建一个所有的建筑的配置文件:ModConfiguredStructures.java

在ModConfiguredStructures中编写

package com.joy187.re8joymod.common.world.gen;import com.joy187.re8joymod.Utils;
import com.joy187.re8joymod.common.world.structure.ModStructures;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.world.gen.FlatGenerationSettings;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;public class ModConfiguredStructures {/*** Static instance of our structure so we can reference it and add it to biomes easily.*///你可以添加多个public static StructureFeature<?, ?> CONFIGURED_TANK1_HOUSE = ModStructures.TANK1.get().configured(IFeatureConfig.NONE);/*** Registers the configured structure which is what gets added to the biomes.* Noticed we are not using a forge registry because there is none for configured structures.** We can register configured structures at any time before a world is clicked on and made.* But the best time to register configured features by code is honestly to do it in FMLCommonSetupEvent.*/public static void registerConfiguredStructures() {Registry<StructureFeature<?, ?>> registry = WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE;//可以继续添加多个Registry.register(registry, new ResourceLocation(Utils.MOD_ID, "configured_tank1_house"), CONFIGURED_TANK1_HOUSE);/** Requires AccessTransformer ( see resources/META-INF/accesstransformer.cfg )*///将上方的你的所有的建筑都加进来(put函数)FlatGenerationSettings.STRUCTURE_FEATURES.put(ModStructures.TANK1.get(), CONFIGURED_TANK1_HOUSE);}
}

7.在world/gen文件夹中新建一个ModStructureGeneration.java 用于编写建筑在世界生成的相关规则:

在ModStructureGeneration.java中编写:

package com.joy187.re8joymod.common.world.gen;import com.joy187.re8joymod.common.init.BiomeInit;
import com.joy187.re8joymod.common.world.structure.ModStructures;
import net.minecraft.util.RegistryKey;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.event.world.BiomeLoadingEvent;import java.util.List;
import java.util.Set;
import java.util.function.Supplier;public class ModStructureGeneration {public static void generateStructures(final BiomeLoadingEvent event) {RegistryKey<Biome> key = RegistryKey.create(Registry.BIOME_REGISTRY, event.getName());Set<BiomeDictionary.Type> types = BiomeDictionary.getTypes(key);//这里是MC中的地形,你可以让你的建筑生成在想要的地形中//例如生成在平原:types.contains(BiomeDictionary.Type.PLAINS)if(types.contains(BiomeInit.RE8_BIOME)) {//你可以添加多个自己想要生成的建筑event.getGeneration().getStructures().add(() -> ModConfiguredStructures.CONFIGURED_TANK1_HOUSE);}//else if... 可以添加多个想要生成的地形中的建筑}
}

8.在ModWorldEvents.java中(没有则在world文件夹中新建)添加一个函数addDimensionalSpacing():

package com.joy187.re8joymod.common.world;import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.joy187.re8joymod.Utils;
import com.joy187.re8joymod.common.world.gen.ModFlowerGeneration;
import com.joy187.re8joymod.common.world.gen.ModStructureGeneration;
import com.joy187.re8joymod.common.world.structure.ModStructures;
import com.joy187.re8joymod.common.world.structure.structures.Tank1Structure;
import com.mojang.serialization.Codec;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.world.World;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.FlatChunkGenerator;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.gen.settings.DimensionStructuresSettings;
import net.minecraft.world.gen.settings.StructureSeparationSettings;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.event.world.BiomeLoadingEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import org.apache.logging.log4j.LogManager;import javax.swing.plaf.synth.SynthTreeUI;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;@Mod.EventBusSubscriber(modid = Utils.MOD_ID)
public class ModWorldEvents {//StructureTutorialMain.java@SubscribeEventpublic static void biomeLoadingEvent(final BiomeLoadingEvent event) {//加入建筑的生成事件的声明ModStructureGeneration.generateStructures(event);//        ModOreGeneration.generateOres(event);
//        ModFlowerGeneration.generateFlowers(event);
//        ModTreeGeneration.generateTrees(event);}//加入空间生成的相关设置@SubscribeEventpublic static void addDimensionalSpacing(final WorldEvent.Load event) {if(event.getWorld() instanceof ServerWorld) {ServerWorld serverWorld = (ServerWorld) event.getWorld();//建筑生成异常就会抛出相应错误try {Method GETCODEC_METHOD =ObfuscationReflectionHelper.findMethod(ChunkGenerator.class, "func_230347_a_");ResourceLocation cgRL = Registry.CHUNK_GENERATOR.getKey((Codec<? extends ChunkGenerator>)GETCODEC_METHOD.invoke(serverWorld.getChunkSource().generator));if (cgRL != null && cgRL.getNamespace().equals("terraforged")) {return;}} catch (Exception e) {LogManager.getLogger().error("Was unable to check if " + serverWorld.getLevel()+ " is using Terraforged's ChunkGenerator.");}// 放止建筑在超平坦世界生成if (serverWorld.getChunkSource().generator instanceof FlatChunkGenerator &&serverWorld.getLevel().equals(World.OVERWORLD)) {return;}// 将我们的建筑添加到建筑生成地图中Map<Structure<?>, StructureSeparationSettings> tempMap =new HashMap<>(serverWorld.getChunkSource().generator.getSettings().structureConfig());tempMap.putIfAbsent(ModStructures.TANK1.get(),DimensionStructuresSettings.DEFAULTS.get(ModStructures.TANK1.get()));serverWorld.getChunkSource().generator.getSettings().structureConfig = tempMap;}}}

9.在Main.java进行修改(添加建筑的相关注册与初始化语句):

在setup()中添加:

        event.enqueueWork(() -> {ModStructures.setupStructures();ModConfiguredStructures.registerConfiguredStructures();});

在Main()中添加:

        ModStructures.register(bus);SurfaceBuilderInit.SURFACE_BUILDERS.register(bus);

10.代码的部分结束了,之后进入游戏进行测试:

新建一个世界 -> 进入后输入查找我们的建筑的指令:

/locate re8joymod:tank1

之后我们会得到建筑的具体坐标

输入tp指令进行坐标传送:

tp @s 具体坐标

我们成功发现了我们自然生成的建筑!

Minecraft 1.16.5模组开发(三十一) 自定义建筑生成(structure) (新)相关推荐

  1. Minecraft 1.16.5模组开发(三十) 自定义成就系统(advancements)

    我们本次将尝试在模组中加入属于自己的成就系统 1.打开Minecraft成就生成制作网站进行成就的制作 我的世界成就系统制作网站 在data包下新建advancement文件夹 -> 在文件夹中 ...

  2. Minecraft 1.16.5模组开发(三十八) 3D盔甲(新)

    Minecraft升级到1.16.5后,3D盔甲的制作方法也跟之前版本稍有不同(主要在第二步.第四步),建议先复习一下往期教程: Minecraft 1.12.2模组开发(三十七) 3D盔甲 1.在b ...

  3. Minecraft 1.16.5模组开发(三十二) 自定义投掷物品实体

    如果你了解过之前我们的实体开发教程,那么本次的教程会相对比较好理解. Minecraft 1.12.2模组开发(七) 实体(魔改Zombie) 我们本次将参考雪球在MC中制作一个属于我们自己的可投掷实 ...

  4. Minecraft 1.16.5模组开发(五十一) 方块实体 (Tile Entity)

    Minecraft1.12.2 方块实体教程 Minecraft1.18.2 方块实体教程 MC中有许多很有趣的方块实体如告示牌.酿造台.附魔台-我们今天在1.16的版本下实现一个类似于熔炉的方块实体 ...

  5. Minecraft 1.16.5模组开发(三十四) 自定义载具

    想在MC中开车吗?今天我们在MC中制作一辆车. 由于车辆是一个生物实体,所以要首先了解MC中的实体:我的世界实体教程 1.首先我们要制作一个车辆实体的模型(blockbench) 下载地址: 将模型导 ...

  6. Minecraft 1.16.5模组开发(四十八) 传送门

    Minecraft 1.18.2模组 传送门教程 我们今天在模组中实现一个传送门,让我们可以传送到自己的维度中.(文末附数据包下载链接) 1.在src\main\resources\data中新建一个 ...

  7. Minecraft 1.12.2模组开发(四十三) 自定义盾牌(Shield)

    今天我们在模组中实现一个自定义盾牌 1.新建一个接口类IHasModel: IHasModel.java public interface IHasModel {public void registe ...

  8. Minecraft——Forge1.16.5模组开发(36.2.20)——(1)开发环境搭建

    声明:本文旨在提升作者的代码逻辑记忆能力,加深思考mojang的代码底层逻辑,更新mojang由于版本迭代替换掉的方法名称和实体名称,部分转载自Forge官方开发文档,指路->1.16.5开发, ...

  9. Minecraft 1.16.5模组开发(四十七) 动画生物实体

    1.18.2动画生物实体教程 今天我们尝试在1.16.5中添加一个能够做各种动作的生物实体,由于使用的是geckolib进行开发,所以代码方面和1.18.2没有太大差别. 1.首先,为了实现这些效果, ...

最新文章

  1. 手机拍视频最怕抖,只能靠AI拯救了
  2. python使用方法-Python的使用方法
  3. CSS Overflow属性详解(转)
  4. 【数据挖掘】特征相关性挖掘神器-线性非线性关系一键挖掘!
  5. Logistic回归与梯度下降法
  6. duilib设置滚动条自动滚动到底
  7. C语言for循环的嵌套例题,c语言 for循环的嵌套(含答案)
  8. ip地址管理系统_门禁监控管理系统项目总结
  9. django ipython shell_希望能早点了解的Django性能优化技巧
  10. hpux 下查看内存的的大小的几种方法:
  11. 解决:configure: error: Missing Xext.h, maybe to install libxext-dev packages?
  12. iOS 代码命名规范 及Android 代码命名规范(2)Android
  13. python将灰度图转为彩色值_python实现彩色图转换成灰度图
  14. Postman 中文包使用
  15. 集线器、网桥、交换机的区别(详解干货!!!)
  16. RTL8367学习笔记1——基础知识
  17. Hyperledger/Quorum等区块链技术综述
  18. 全球6G产业及政策进展研究
  19. golang panic和recover
  20. 【网络】RPC通信之Apache Thrift

热门文章

  1. kafka的消费顺序_Kafka如何保证消息的顺序性
  2. 网址大全(hao123和2345)
  3. 太原师范学院计算机考研资料汇总
  4. Mysql单表查询30个经典案例
  5. 磨金石教育摄影技能干货分享|世界顶级的手机摄影作品欣赏
  6. 基于Autoware制作高精地图(一)
  7. 大星星学物联网概览篇-硬件
  8. CM安装成功,CM的web界面登录不上解决方案
  9. java读取excel表格数据
  10. 旅游流的概念_国内旅游流综述