- Версия(и) Minecraft
- 1.12.2
Не нашёл в ру сегменте полноценной информации об этой теме и решил написать полноценный гайд.
Генерация структур
Для начала настроим главный класс мода:
Далее создадим рядом класс Reference который будет хранить наш MODID, MODNAME, VERSION, а также ссылки на ClientProxy и CommonProxy:
И само собой создаём директорию templesmod.proxy, в которой создаём ClientProxy и CommonProxy:
Далее в temples.util.handlers создадим класс для регистрации RegisterHandler, который будет в преинициализации регистрировать наш генератор структур:
Также для генератора в templesmod.util.interfaces заранее создадим интерфейс IStructure, который будет задавать параметры расположения структуры:
И вот дошли до самого генератора. Создаём директорию templesmod.generation и в ней создаём класс WorldGenCustomStructures, в котором будет прописываться запуск генератора для измерений, а также высчитываться позиция для генерации структуры:
Далее создаём в директории templesmod.generation.generators сам генератор WorldGenStructure:
Далее начинается более интересная часть - создаём директорию в ресурсах assets.templesmod.structures и пока оставляем её. Далее заходим в минекрафт и в плоском мире (кому как удобно) начинаем строить нашу структуру.
После того как построили наш шедевр необходимо выдать себе блок для разметки структуры командой
и расположить его в углу постройки следующим образом:
После чего настроить размеры конструкции в настройках блока (после ПКМ нажать "данные", название такое же как и в коде)
И финальным штрихом нажать "запись", после чего перейти в saves/[название мира]/structures и скопировать [название постройки].nbt в ранее нами созданную директорию assets.templesmod.structures
После чего заходим в игру и видим наши структуры:
Чтобы убрать пустое пространство при генерации необходимо перед сохранением постройки заполнить это пустое пространство нужными блоками (область постройки включает в себя в том числе блок воздуха и вырезает под него место)
Генерация лута в сундуках
Для генерации лута из списка loot_table необходимо добавить несколько строк в класс WorldGenStructure:
Данный цикл просчитывает структуру и ищет блок типа TileEntityChest и если он найден, то загружает в него ваш loot_table.
Также необходимо создать саму таблицу в директории assets.templesmod.loot_tables.chests с названием вашей структуры (к примеру yoda_home.json) и сгенерировать необходимую таблицу с помощью инструмента от Amaury Carrade. ВАЖНО после того как вставите сгенерированную разметку необходимо перед "rolls" указать "name" к примеру "name": "yoda_homeMain".
Благодарю за внимание и прошу строго не судить за мой первый гайд
Генерация структур
Для начала настроим главный класс мода:
Main:
@Mod(modid = Reference.MODID, version = Reference.VERSION)
public class Main
{
@Instance
public static TemplesMod instance;
@SidedProxy(clientSide = Reference.CLIENT, serverSide = Reference.SERVER)
public static CommonProxy proxy;
@EventHandler
public void preInit(FMLPreInitializationEvent event)
{
proxy.preInit(event);
}
@EventHandler
public void init(FMLInitializationEvent event)
{
proxy.init(event);
}
@EventHandler
public void postInit(FMLPostInitializationEvent event)
{
proxy.postInit(event);
}
}
Reference:
public class Reference
{
public static final String MODID = "templesmod";
public static final String MODNAME = "Temples Mod";
public static final String VERSION = "1.0";
public static final String CLIENT = "daola.templesmod.proxy.ClientProxy";
public static final String SERVER = "daola.templesmod.proxy.CommonProxy";
}
ClientProxy:
public class ClientProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent event)
{
super.preInit(event);
}
@Override
public void init(FMLInitializationEvent event)
{
super.init(event);
}
@Override
public void postInit(FMLPostInitializationEvent event)
{
super.postInit(event);
}
}
CommonProxy:
public class CommonProxy
{
public void preInit(FMLPreInitializationEvent event)
{
RegistryHandler.preInitRegistries();
}
public void init(FMLInitializationEvent event)
{
}
public void postInit(FMLPostInitializationEvent event)
{
}
}
RegisterHandler:
@EventBusSubscriber
public class RegistryHandler
{
public static void preInitRegistries()
{
GameRegistry.registerWorldGenerator(new WorldGenCustomStructures(), 0);
}
}
IStructure:
public interface IStructure
{
public static final WorldServer worldServer = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(0);
public static final PlacementSettings settings = (new PlacementSettings()).setChunk(null)
.setIgnoreEntities(false)
.setIgnoreStructureBlock(false)
.setMirror(Mirror.NONE)
.setRotation(Rotation.NONE);
}
WorldGenCustomStructures:
public class WorldGenCustomStructures implements IWorldGenerator
{
public static final WorldGenStructure YODA_HOME = new WorldGenStructure("yoda_home");
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider)
{
switch(world.provider.getDimension())
{
//case 2: если есть своё измерение
// break;
case 1: //край
break;
case 0: //обычный мир
generateStructure(YODA_HOME, world, random, chunkX, chunkZ, 10, Blocks.SAND, BiomeMesa.class); //структура объявленная выше, мир, рандом, чанкХ, чанкZ, частота спавна (меньше чаще), на каком блоке будет спавниться, биом
break;
case -1: //ад
break;
}
}
private void generateStructure(WorldGenerator generator,
World world, Random random, int chunkX, int chunkZ, int chance, Block topBlock, Class<?>...classes)
{
ArrayList<Class<?>> classesList = new ArrayList<Class<?>>(Arrays.asList(classes));
int x = (chunkX * 16) + random.nextInt(15);
int z = (chunkZ * 16) + random.nextInt(15);
int y = calculateGenerationHeight(world, x, z, topBlock);
BlockPos pos = new BlockPos(x,y,z);
Class<?> biome = world.provider.getBiomeForCoords(pos).getClass();
if(world.getWorldType() != WorldType.FLAT)
{
if(classesList.contains(biome))
{
if(random.nextInt(chance) == 0)
{
generator.generate(world, random, pos);
}
}
}
}
private static int calculateGenerationHeight(World world, int x, int z, Block topBlock) //высчитывание высоты (y)
{
int y = world.getHeight(); //получаем высоту мира (256)
boolean foundGround = false;
while(!foundGround && y-- >= 0) //если земля не найдена и значение уменьшения высоты больше или равно 0
{
Block block = world.getBlockState(new BlockPos(x,y,z)).getBlock();
foundGround = block == topBlock; //если найденный block равен topBlock, то foundGround = true
}
return y; //возвращаем высоту (если постройка уходит вниз под землю, то убавляем тут количество блоков от нужного "пола" постройки, чтобы она генерировалась ниже)
}
}
WorldGenStructure:
public class WorldGenStructure extends WorldGenerator implements IStructure
{
public static String structureName;
public WorldGenStructure (String name)
{
this.structureName = name; //передаём название структуры в переменную name
}
@Override
public boolean generate(World worldIn, Random rand, BlockPos position)
{
this.generateStructure(worldIn, position, rand);
return true;
}
public static void generateStructure(World world, BlockPos pos, Random rand)
{
MinecraftServer mcServer = world.getMinecraftServer();
TemplateManager manager = worldServer.getStructureTemplateManager();
ResourceLocation location = new ResourceLocation(Reference.MODID, structureName);
Template template = manager.get(mcServer, location);
if(template != null)
{
IBlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 3);
template.addBlocksToWorldChunk(world, pos, settings);
}
}
}
После того как построили наш шедевр необходимо выдать себе блок для разметки структуры командой
/give @a minecraft:structure_block
и расположить его в углу постройки следующим образом:
После чего заходим в игру и видим наши структуры:
Генерация лута в сундуках
Для генерации лута из списка loot_table необходимо добавить несколько строк в класс WorldGenStructure:
WorldGenStructure:
if(template != null)
{
IBlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 3);
template.addBlocksToWorldChunk(world, pos, settings);
for(int x = 0; x <= template.getSize().getX(); x++) {
for(int y = 0; y <= template.getSize().getY(); y++) {
for(int z = 0; z <= template.getSize().getZ(); z++){
BlockPos tmp = new BlockPos(pos.getX() + x, pos.getY() + y, pos.getZ() + z);
if(world.getTileEntity(tmp) != null){
if(world.getTileEntity(tmp) instanceof TileEntityChest){
TileEntityChest chest = (TileEntityChest) world.getTileEntity(tmp);
((TileEntityChest)chest).setLootTable(new ResourceLocation(Reference.MODID + ":chests/" + structureName), rand.nextLong());
}
}
}
}
}
Также необходимо создать саму таблицу в директории assets.templesmod.loot_tables.chests с названием вашей структуры (к примеру yoda_home.json) и сгенерировать необходимую таблицу с помощью инструмента от Amaury Carrade. ВАЖНО после того как вставите сгенерированную разметку необходимо перед "rolls" указать "name" к примеру "name": "yoda_homeMain".
yoda_home:
{
"pools": [
{
"name": "yoda_homeMain",
"rolls": {
"min": 4,
"max": 7
},
"bonus_rolls": {
"min": 2,
"max": 5
},
"entries": [
{
"type": "item",
"weight": 1,
"name": "minecraft:stone"
},
{
"type": "item",
"weight": 1,
"name": "minecraft:book",
"functions": [
{
"function": "enchant_randomly"
}
]
},
{
"type": "item",
"weight": 1,
"name": "minecraft:rotten_flesh",
"functions": [
{
"function": "set_count",
"count": {
"min": 3,
"max": 7
}
}
]
},
{
"type": "item",
"weight": 1,
"name": "minecraft:bone",
"functions": [
{
"function": "set_count",
"count": {
"min": 4,
"max": 10
}
}
]
}
]
},
{
"name": "yoda_homeLuck",
"rolls": {
"min": 5,
"max": 8
},
"bonus_rolls": {
"min": 1,
"max": 3
},
"entries": [
{
"type": "item",
"weight": 1,
"name": "minecraft:diamond",
"functions": [
{
"function": "set_count",
"count": 1
}
]
},
{
"type": "item",
"weight": 1,
"name": "minecraft:emerald",
"functions": [
{
"function": "set_count",
"count": {
"min": 1,
"max": 3
}
}
]
}
]
}
]
}
Благодарю за внимание и прошу строго не судить за мой первый гайд