This mod provides functional for RTS multiblock structures. It also can be used as a structure copy/paste
To save structure you need structure tool - use /give or operator tab;
Right click - position 1;
Left click - position 2;
Shift + right click - anchor position
CTRL + mouse click - expand area (can be changed in keybinds)
Shift + left click - placement anchor
/rtstrucutres save <name> - saves structure
/rtstrucutres load <name> <anchor> - pre-loads structure + displays paste box
/rtstrucutres execute <build_type> - pastes pre-loaded structure in world
/rtstrucutres execload <name> <anchor> <build_type> - pastes structure in world
/rtstrucutres toggle_boxes <true/false> - alway display tool selection area
repositories {
maven {
url = "https://api.modrinth.com/maven"
}
}
dependencies {
implementation "maven.modrinth:rtstrucures-framework:0.1.4"
}
Here is the example of /execload command
ServerLevel level = ctx.getSource().getLevel();
String filename = "house";
Path worldDir = level.getServer().getWorldPath(LevelResource.ROOT);
StructureTemplate template = StructureCache.get(worldDir, filename);
BlockPos anchorPos = StructureToolState.placeAnchor; // Place position
PlacementAnchor anchorMode = PlacementAnchor.CUSTOM; // Recommended to use custom anchor
StructureInstance instance = new StructureInstance(level, template, anchorPos, anchorMode);
StructureManager.add(instance);
instance.build(BuildType.FAST, 2.0f); // Execute in the world; Layer-by layer building
StructureInstance class provides more methods for structure management;
StructureTemplate template = StructureCapture.capture(level, pos1, pos2, customAnchor);
Path path = worldDir.resolve("generated/rtstructures/house.rtstructure");
StructureSerializer.save(template, path);
Path path = worldDir.resolve("generated/rtstructures/house.rtstructure");
StructureTemplate template = StructureDeserializer.load(path);
StructureManager.add(instance);
instance.build(BuildType.FAST,10);
BuildType = construction logicspeed = blocks per tickboolean damaged = instance.isDamaged();
float percent = instance.getCompletionPercent();
float percent = instance.getDamagePercent();
ValidationResult result = instance.validate();
Instant layered building
Best for:
Layered building without replacing existing blocks
Best for:
Builds only connected blocks
Best for:
Growth-style construction from anchor
Best for:
Just like SEPARATED but corner blocks are used as anchor too
Demolished structure from top to bottom
Mod provides DefferedRegistered structure
public final class StructuresInit {
private StructuresInit() {}
public static final DeferredRegister<StructureType> STRUCTURES =
DeferredRegister.create(RTSRegistries.STRUCTURES, RTStructureFramework.MOD_ID);
public static final Supplier<StructureType> SIMPLE_HOUSE = STRUCTURES.register("simple_house", SimpleHouseStructure::new);
public static final Supplier<StructureType> AIRFIELD = STRUCTURES.register("airfield", AirfieldStructure::new);
public static final Supplier<StructureType> CRYSTAL = STRUCTURES.register("crystal", CrystalStructure::new);
public static final Supplier<StructureType> PROTECTED_STRUCTURE = STRUCTURES.register("protected_structure", ProtectedStructure::new);
public static void register(IEventBus bus) {
STRUCTURES.register(bus);
}
}
Structure class
public class SimpleHouseStructure extends StructureType {
public SimpleHouseStructure() {
super("simple_house", StructureProperties.create()
// Structure file
.modPath("basic/simple_house", RTStructureFramework.MOD_ID) // In your resources/data/mod_id/...
// Default placement
.defaultAnchor(PlacementAnchor.CENTER)
// Default build behavior
.defaultBuildType(BuildType.FAST)
.defaultBuildSpeed(2f)
// Validation
.damagedThreshold(0.15f)
.destroyedThreshold(0.5f)
);
}
}
Library provides some methods for management
public void onCompleted(StructureInstance instance) {}
public void onDamaged(StructureInstance instance) {}
public void onDestroyed(StructureInstance instance) {}
public void onDemolished(StructureInstance instance) {}
Example usage:
public class AirfieldStructure extends StructureType {
private int productionTick;
public AirfieldStructure() {
super("airfield", StructureProperties.create()
.modPath("basic/airfield", RTStructureFramework.MOD_ID)
.defaultAnchor(PlacementAnchor.CENTER)
.defaultBuildType(BuildType.FAST)
.defaultBuildSpeed(3f)
.damagedThreshold(0.2f)
.destroyedThreshold(0.6f)
);
}
@Override
public void onCompleted(StructureInstance instance) {
System.out.println("[RTS] Airfield completed");
}
@Override
public void onTick(StructureInstance instance) {
if (!instance.isCompleted()) return;
productionTick++;
if (productionTick >= 100) {
productionTick = 0;
System.out.println("[RTS] Kirov reporting...");
// Do your stuff. E.g spawn unit
}
}
@Override
public void onDestroyed(StructureInstance instance) {
System.out.println("[RTS] Airfield destroyed!");
}
}
StructureInstance instance = StructuresInit.AIRFIELD.get().create(level, anchorPos);
StructureManager.add(instance);
instance.build();
StructureManager.add(instance); Actually creates your structure class;
instance.build(); just constructs your structure;
If you need to remove your structure use instance.destroy(); (warning! could call stackoverflow)
Example of usage:
public class CrystalStructure extends StructureType {
public CrystalStructure() {
super("crystal", StructureProperties.create()
.modPath("crystal", RTStructureFramework.MOD_ID)
.defaultBuildType(BuildType.FAST)
.defaultBuildSpeed(1f)
.defaultAnchor(PlacementAnchor.CUSTOM)
.damagedThreshold(0.05f)
.destroyedThreshold(0.8f)
);
}
@Override
public void onTick(StructureInstance instance) {
if (instance.isDamaged()) {
if (!instance.isBuilding()) {
instance.build(BuildType.FAST, 0.5f);
}
}
}
@Override
public void onDestroyed(StructureInstance instance) {
if (instance.getDamagePercent() >= 0.95f) {
instance.destroy();
}
}
@Override
public void onCompleted(StructureInstance instance) {
System.out.println(instance.debugInfo());
}
}
This description will be scratched to a normal mod description. For documentation view github wiki