191 lines
11 KiB
Python
191 lines
11 KiB
Python
import json
|
|
import os
|
|
|
|
PROJECT_ROOT = "/Users/davidkotnik/repos/novafarma"
|
|
LDTK_FILE = os.path.join(PROJECT_ROOT, "AutoLayers_2_stamps.ldtk")
|
|
|
|
def main():
|
|
# Re-create a clean, valid file structure based on what worked before, BUT including the new updates correctly.
|
|
|
|
# 1. Base Structure
|
|
data = {
|
|
"__header__": { "fileType": "LDtk Project JSON", "app": "LDtk", "doc": "https://ldtk.io/json", "schema": "https://ldtk.io/files/JSON_SCHEMA.json", "appAuthor": "David via Antigravity", "appVersion": "1.5.3", "url": "https://ldtk.io" },
|
|
"iid": "6440c680-d380-11f0-b813-5db2a94f8a9c",
|
|
"jsonVersion": "1.5.3",
|
|
"appBuildId": 473703,
|
|
"nextUid": 10000,
|
|
"identifierStyle": "Capitalize",
|
|
"toc": [],
|
|
"worldLayout": "Free",
|
|
"worldGridWidth": 256, "worldGridHeight": 256,
|
|
"defaultLevelWidth": 512, "defaultLevelHeight": 512,
|
|
"defaultPivotX": 0, "defaultPivotY": 0,
|
|
"defaultGridSize": 16, "defaultEntityWidth": 16, "defaultEntityHeight": 16,
|
|
"bgColor": "#40465B", "defaultLevelBgColor": "#696A79",
|
|
"minifyJson": False,
|
|
"externalLevels": False, # THIS WAS THE ERROR SOURCE potentially if missing? It was present in previous valid versions.
|
|
"exportTiled": False, "simplifiedExport": False, "imageExportMode": "None", "exportLevelBg": True,
|
|
"pngFilePattern": None, "backupOnSave": False, "backupLimit": 10, "backupRelPath": None, "levelNamePattern": "Level_%idx",
|
|
"tutorialDesc": None, "customCommands": [], "flags": [],
|
|
"defs": { "layers": [], "entities": [], "tilesets": [], "enums": [], "externalEnums": [], "levelFields": [] },
|
|
"levels": [],
|
|
"worlds": [],
|
|
"dummyWorldIid": "6440c681-d380-11f0-b813-a103d476f7a1"
|
|
}
|
|
|
|
# 2. TILESETS
|
|
# Atlas
|
|
atlas_def = {
|
|
"__cWid": 16, "__cHei": 16, "identifier": "Terrain_Atlas", "uid": 150,
|
|
"relPath": "godot/phases/FAZA_1_FARMA/tilesets/TerrainAtlas.png",
|
|
"embedAtlas": None, "pxWid": 512, "pxHei": 512, "tileGridSize": 32, "spacing": 0, "padding": 0, "tags": [], "tagsSourceEnumUid": None, "enumTags": [], "customData": [], "savedSelections": [], "cachedPixelData": None
|
|
}
|
|
# Kai
|
|
ts_kai = {
|
|
"__cWid": 1, "__cHei": 1, "identifier": "TS_Kai", "uid": 160,
|
|
"relPath": "godot/characters/KAI/kai_walk_east_1767695851347.png", "embedAtlas": None, "pxWid": 256, "pxHei": 256, "tileGridSize": 256, "spacing": 0, "padding": 0, "tags": [], "tagsSourceEnumUid": None, "enumTags": [], "customData": [], "savedSelections": [], "cachedPixelData": None
|
|
}
|
|
# Weed
|
|
ts_weed = {
|
|
"__cWid": 1, "__cHei": 1, "identifier": "TS_Weed", "uid": 161,
|
|
"relPath": "godot/phases/DEMO/crops/cannabis/growth_stages/cannabis_stage1_sprout.png", "embedAtlas": None, "pxWid": 32, "pxHei": 32, "tileGridSize": 256, "spacing": 0, "padding": 0, "tags": [], "tagsSourceEnumUid": None, "enumTags": [], "customData": [], "savedSelections": [], "cachedPixelData": None
|
|
}
|
|
|
|
data['defs']['tilesets'] = [atlas_def, ts_kai, ts_weed]
|
|
|
|
# 3. ENTITIES
|
|
kai_def = {
|
|
"identifier": "Kai_Hoe", "uid": 400, "width": 256, "height": 256, "color": "#FF00FF", "renderMode": "Tile", "tileRenderMode": "FitInside",
|
|
"tileRect": { "tilesetUid": 160, "x": 0, "y": 0, "w": 256, "h": 256 }, # Use Tileset UID
|
|
"tilesetId": 160, "tileId": 0,
|
|
"resizableX": False, "resizableY": False, "keepAspectRatio": True, "fillOpacity": 0.5, "lineOpacity": 1, "hollow": False, "pivotX": 0.5, "pivotY": 1, "fieldDefs": [], "maxCount": 0, "limitScope": "PerLevel", "limitBehavior": "MoveLastOne"
|
|
}
|
|
cannabis_def = {
|
|
"identifier": "Crop_Cannabis", "uid": 401, "width": 32, "height": 32, "color": "#00FF00", "renderMode": "Tile", "tileRenderMode": "FitInside",
|
|
"tileRect": { "tilesetUid": 161, "x": 0, "y": 0, "w": 32, "h": 32 },
|
|
"tilesetId": 161, "tileId": 0,
|
|
"resizableX": False, "resizableY": False, "keepAspectRatio": True, "fillOpacity": 0.5, "lineOpacity": 1, "hollow": False, "pivotX": 0.5, "pivotY": 1, "fieldDefs": [], "maxCount": 0, "limitScope": "PerLevel", "limitBehavior": "MoveLastOne"
|
|
}
|
|
data['defs']['entities'] = [kai_def, cannabis_def]
|
|
|
|
# 4. LAYERS
|
|
# IntGrid
|
|
int_grid_def = {
|
|
"__type": "IntGrid", "identifier": "Terrain_Control", "type": "IntGrid", "uid": 200, "gridSize": 32, "displayOpacity": 0.5, "pxOffsetX": 0, "pxOffsetY": 0,
|
|
"intGridValues": [
|
|
{ "value": 1, "identifier": "Grass", "color": "#36BC29" },
|
|
{ "value": 2, "identifier": "Dirt", "color": "#8B5F2A" },
|
|
{ "value": 3, "identifier": "Water", "color": "#388BE7" },
|
|
{ "value": 4, "identifier": "Farm", "color": "#54301A" }
|
|
],
|
|
"autoRuleGroups": [], "autoSourceLayerDefUid": None, "tilesetDefUid": None, "tilePivotX": 0, "tilePivotY": 0
|
|
}
|
|
|
|
# Visuals (AutoLayer)
|
|
# Re-create rules for Atlas
|
|
def get_region_ids(start_id, rows=8, cols=8, stride=16):
|
|
ids = []
|
|
for r in range(rows):
|
|
for c in range(cols):
|
|
ids.append(start_id + (r * stride) + c)
|
|
return ids
|
|
|
|
rule_uid = 5000
|
|
def make_group(name, int_val, tile_ids):
|
|
nonlocal rule_uid
|
|
g_uid = rule_uid; rule_uid += 1
|
|
r_uid = rule_uid; rule_uid += 1
|
|
return {
|
|
"uid": g_uid, "name": name, "active": True, "isOptional": False,
|
|
"rules": [{
|
|
"uid": r_uid, "active": True, "size": 1, "tileIds": tile_ids, "alpha": 1, "chance": 1, "breakOnMatch": True, "pattern": [int_val],
|
|
"flipX": True, "flipY": True, "xModulo": 1, "yModulo": 1, "checker": "None", "tileMode": "Random", "pivotX": 0, "pivotY": 0, "outTileIds": [], "perlinActive": False, "perlinSeed": 0, "perlinScale": 0.2, "perlinOctaves": 2
|
|
}]
|
|
}
|
|
|
|
layer_visuals = {
|
|
"__type": "AutoLayer", "identifier": "Terrain_Visuals", "type": "AutoLayer", "uid": 300, "gridSize": 32, "displayOpacity": 1, "pxOffsetX": 0, "pxOffsetY": 0,
|
|
"autoSourceLayerDefUid": 200, "tilesetDefUid": 150, "tilePivotX": 0, "tilePivotY": 0,
|
|
"autoRuleGroups": [
|
|
make_group("Grass", 1, get_region_ids(0)),
|
|
make_group("Dirt", 2, get_region_ids(8)),
|
|
make_group("Water", 3, get_region_ids(128)),
|
|
make_group("Farm", 4, get_region_ids(136))
|
|
]
|
|
}
|
|
|
|
# Entity Layer
|
|
layer_entities = {
|
|
"__type": "Entities", "identifier": "Entities", "type": "Entities", "uid": 201, "gridSize": 32, "displayOpacity": 1, "pxOffsetX": 0, "pxOffsetY": 0,
|
|
"requiredTags": [], "excludedTags": [], "intGridValues": [], "autoRuleGroups": [], "autoSourceLayerDefUid": None, "tilesetDefUid": None, "tilePivotX": 0, "tilePivotY": 0
|
|
}
|
|
|
|
data['defs']['layers'] = [int_grid_def, layer_entities, layer_visuals] # Order: Control, Entities, Visuals (Top to Bottom rendering? No, Top of list is top layer)
|
|
# Actually, we want:
|
|
# 1. Control (Semi-transparent OVERLAY)
|
|
# 2. Entities (Above visuals)
|
|
# 3. Visuals (Background)
|
|
|
|
# 5. LEVEL 0
|
|
# Paint 3x3 farm + Entities
|
|
|
|
# IntGrid CSV
|
|
csv = [0] * 1024 # 32x32 tiles for 1024x1024 map? Wait default was 512x512.
|
|
# Check header
|
|
# If 512x512, grid 32 -> 16x16 tiles = 256.
|
|
# My previous script assumed 1024 but header said 512.
|
|
# Let's clean this up.
|
|
# HEADER says 512x512. So CSV should be 256 length.
|
|
csv = [0] * 256
|
|
|
|
start_x, start_y = 6, 6
|
|
for y in range(3):
|
|
for x in range(3):
|
|
# Safe check
|
|
if start_x+x < 16 and start_y+y < 16:
|
|
idx = (start_y + y) * 16 + (start_x + x)
|
|
csv[idx] = 4
|
|
|
|
# Entity Instances
|
|
ent_instances = []
|
|
# Crops
|
|
for y in range(3):
|
|
for x in range(3):
|
|
px_x = (start_x + x) * 32 + 16
|
|
px_y = (start_y + y) * 32 + 32
|
|
ent_instances.append({
|
|
"__identifier": "Crop_Cannabis", "__grid": [start_x + x, start_y + y], "__pivot": [0.5, 1], "__tags": [], "__tile": { "tilesetUid": 161, "x": 0, "y": 0, "w": 32, "h": 32 }, "__smartColor": "#00FF00", "iid": f"crop_{x}_{y}", "width": 32, "height": 32, "defUid": 401, "px": [px_x, px_y], "fieldInstances": []
|
|
})
|
|
# Kai
|
|
kai_pos_x, kai_pos_y = 10, 7
|
|
ent_instances.append({
|
|
"__identifier": "Kai_Hoe", "__grid": [kai_pos_x, kai_pos_y], "__pivot": [0.5, 1], "__tags": [], "__tile": { "tilesetUid": 160, "x": 0, "y": 0, "w": 256, "h": 256 }, "__smartColor": "#FF00FF", "iid": "kai_npc", "width": 256, "height": 256, "defUid": 400, "px": [kai_pos_x * 32 + 16, kai_pos_y * 32 + 32], "fieldInstances": []
|
|
})
|
|
|
|
level_0 = {
|
|
"identifier": "Level_0", "iid": "level_0_iid", "uid": 0, "worldX": 0, "worldY": 0, "worldDepth": 0,
|
|
"pxWid": 512, "pxHei": 512, "__bgColor": "#696A79", "bgColor": None, "useAutoIdentifier": True, "bgRelPath": None, "bgPos": None, "bgPivotX": 0.5, "bgPivotY": 0.5, "__smartColor": "#ADADB5", "__bgPos": None, "externalRelPath": None, "fieldInstances": [],
|
|
"layerInstances": [
|
|
{ # Control
|
|
"__identifier": "Terrain_Control", "__type": "IntGrid", "__cWid": 16, "__cHei": 16, "__gridSize": 32, "__opacity": 0.5, "__pxTotalOffsetX": 0, "__pxTotalOffsetY": 0, "__tilesetDefUid": None, "__tilesetRelPath": None, "iid": "inst_200", "levelId": 0, "layerDefUid": 200, "pxOffsetX": 0, "pxOffsetY": 0, "visible": True, "optionalRules": [], "intGridCsv": csv, "autoLayerTiles": [], "seed": 0, "overrideTilesetUid": None, "gridTiles": [], "entityInstances": []
|
|
},
|
|
{ # Entities
|
|
"__identifier": "Entities", "__type": "Entities", "__cWid": 16, "__cHei": 16, "__gridSize": 32, "__opacity": 1, "__pxTotalOffsetX": 0, "__pxTotalOffsetY": 0, "__tilesetDefUid": None, "__tilesetRelPath": None, "iid": "inst_201", "levelId": 0, "layerDefUid": 201, "pxOffsetX": 0, "pxOffsetY": 0, "visible": True, "optionalRules": [], "intGridCsv": [], "autoLayerTiles": [], "seed": 0, "overrideTilesetUid": None, "gridTiles": [], "entityInstances": ent_instances
|
|
},
|
|
{ # Visuals
|
|
"__identifier": "Terrain_Visuals", "__type": "AutoLayer", "__cWid": 16, "__cHei": 16, "__gridSize": 32, "__opacity": 1, "__pxTotalOffsetX": 0, "__pxTotalOffsetY": 0, "__tilesetDefUid": 150, "__tilesetRelPath": "godot/phases/FAZA_1_FARMA/tilesets/TerrainAtlas.png", "iid": "inst_300", "levelId": 0, "layerDefUid": 300, "pxOffsetX": 0, "pxOffsetY": 0, "visible": True, "optionalRules": [], "intGridCsv": [], "autoLayerTiles": [], "seed": 0, "overrideTilesetUid": None, "gridTiles": [], "entityInstances": []
|
|
}
|
|
],
|
|
"__neighbours": []
|
|
}
|
|
|
|
data['levels'] = [level_0]
|
|
|
|
with open(LDTK_FILE, 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
print("LDtk recovered and fully valid!")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|