基于Cell Noise的Minecraft模组地下实验室生成技术问询
Got it, let's break this down step by step—using Cell Noise (aka Voronoi Noise) for room-based underground labs is such a cool choice, way more organic than rigid grid layouts while still keeping the structured feel you need for a lab. Here's how to turn that idea into working code tailored to your Minecraft mod:
Cell Noise works by generating a set of random "cells" (each representing a room) in your world space. Every grid coordinate maps to the closest cell, and we use that relationship to determine walls (whether adjacent grids belong to the same room) and room types.
First, create a collection of cells where each cell defines a room's position, size, and type. This is where you'll control room variety (different sizes/types):
// Minecraft mod code is usually Java, so here's a pseudo-implementation class VoronoiRoomCell { double worldX, worldY; // Center of the room (in world units, not grid cells) double radius; // Controls room size (larger = bigger room) int roomType; // 0 = core lab, 1 = regular lab, 2 = storage, etc. } List<VoronoiRoomCell> generateLabCells(int worldWidth, int worldHeight, int cellCount) { List<VoronoiRoomCell> cells = new ArrayList<>(); for (int i = 0; i < cellCount; i++) { VoronoiRoomCell cell = new VoronoiRoomCell(); // Randomize position across your world bounds cell.worldX = Math.random() * worldWidth; cell.worldY = Math.random() * worldHeight; // Randomize room size (adjust ranges to fit your needs) cell.radius = 3 + Math.random() * 6; // Rooms between 3-9 grid cells wide // Assign room type based on size (or randomize with weighted odds) cell.roomType = cell.radius > 7 ? 0 : cell.radius > 4 ? 1 : 2; cells.add(cell); } return cells; }
For each grid cell (x, y), find the closest Voronoi room cell. To make larger rooms dominate more grid space, use a weighted distance calculation (divide raw distance by the cell's radius):
VoronoiRoomCell getClosestRoom(int gridX, int gridY, List<VoronoiRoomCell> cells) { // Convert grid coords to world units (assuming 1 grid = 1 world block) double worldX = gridX * 1.0; double worldY = gridY * 1.0; VoronoiRoomCell closestCell = null; double minWeightedDistance = Double.MAX_VALUE; for (VoronoiRoomCell cell : cells) { // Weighted distance: larger rooms "pull" grid cells closer double rawDistance = Math.hypot(worldX - cell.worldX, worldY - cell.worldY); double weightedDistance = rawDistance / cell.radius; if (weightedDistance < minWeightedDistance) { minWeightedDistance = weightedDistance; closestCell = cell; } } return closestCell; }
The boolean values represent whether a wall exists between the current grid cell and its neighbor. If the neighbor belongs to a different room cell, we add a wall:
// Your desired return structure class LabGridCell { boolean top; boolean right; boolean down; boolean left; int roomType; } LabGridCell generateLabGridCell(int gridX, int gridY, List<VoronoiRoomCell> cells) { VoronoiRoomCell currentRoom = getClosestRoom(gridX, gridY, cells); // Check neighbors to determine walls VoronoiRoomCell topNeighbor = getClosestRoom(gridX, gridY + 1, cells); VoronoiRoomCell rightNeighbor = getClosestRoom(gridX + 1, gridY, cells); VoronoiRoomCell downNeighbor = getClosestRoom(gridX, gridY - 1, cells); VoronoiRoomCell leftNeighbor = getClosestRoom(gridX - 1, gridY, cells); LabGridCell result = new LabGridCell(); // True = wall exists (different room), False = no wall (same room) result.top = currentRoom != topNeighbor; result.right = currentRoom != rightNeighbor; result.down = currentRoom != downNeighbor; result.left = currentRoom != leftNeighbor; result.roomType = currentRoom.roomType; return result; }
- Add Doors Between Rooms: Instead of full walls between every different room, randomly set 1-2 adjacent grid cells' wall booleans to
false(create a door) when two rooms are close enough (e.g., when their centers are within sum of radii * 0.9). - Avoid Isolated Rooms: Run Lloyd Relaxation on your Voronoi cells after generation to spread rooms more evenly and eliminate tiny, isolated spaces.
- 3D Expansion: Extend the 2D logic to Z-axis by adding a
worldZfield toVoronoiRoomCell, then checkfront/backneighbors for walls. - Precompute Cells: For performance (critical in Minecraft), precompute all grid cells' room assignments on world generation instead of calculating on the fly.
内容的提问来源于stack exchange,提问作者Samū

