import json import os PROJECT_ROOT = "/Users/davidkotnik/repos/novafarma" LDTK_FILE = os.path.join(PROJECT_ROOT, "AutoLayers_2_stamps.ldtk") def main(): with open(LDTK_FILE, 'r') as f: data = json.load(f) # 1. DEFINE ENTITIES (Kai & Cannabis) # We need to add them to 'defs' -> 'entities' # Kai (id: Kai_Hoe) # Cannabis (id: Crop_Cannabis_1) entities = [] uid_c = 400 # KAI Definition kai_def = { "identifier": "Kai_Hoe", "uid": uid_c, "width": 256, "height": 256, "color": "#FF00FF", # Pink for Kai "renderMode": "Tile", "tileRenderMode": "FitInside", "tileRect": { "tilesetUid": None, # Will define tileset below if possible, or just color for now to be safe "x": 0, "y": 0, "w": 256, "h": 256 }, "tilesetId": None, "tileId": None, "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" } # To connect image to entity, we usually use a tileset defined for entities. # But let's keep it simple: Just definitions first. uid_c += 1 # CANNABIS Definition cannabis_def = { "identifier": "Crop_Cannabis", "uid": uid_c, "width": 32, # Crops are smaller on grid? Or 256 visual? Let's say 32 grid size but visual 256. "height": 32, "color": "#00FF00", "renderMode": "Rectangle", # Simple rectangle for now "tileRenderMode": "FitInside", "tileRect": None, "tilesetId": None, "tileId": None, "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] # 2. PAINT THE 3x3 FARM (IntGrid) # 3x3 square in middle of 512x512 map (16x16 grid) # Middle is roughly x=6,7,8; y=6,7,8 # IntGrid is a 1D CSV array: value 4 (Farm) = Farm # Grid width = 16 grid_w = 16 grid_h = 16 csv = [0] * (grid_w * grid_h) # Clear all first # Paint 3x3 Farm start_x, start_y = 6, 6 for y in range(3): for x in range(3): idx = (start_y + y) * grid_w + (start_x + x) csv[idx] = 4 # 4 = Farmland value defined in IntGrid def # Update IntGrid Layer Instance # Find layer with defUid 200 (Terrain_Control) for level in data['levels']: for layer in level['layerInstances']: if layer['__identifier'] == "Terrain_Control": layer['intGridCsv'] = csv # 3. PLACE ENTITIES # Place Cannabis on the 3x3 grid # Place Kai next to it entity_instances = [] # 9 Cannabis plants for y in range(3): for x in range(3): # Centered in 32x32 cell # X pos = (6+x)*32 + 16 (half) # Y pos = (6+y)*32 + 32 (bottom pivot) px_x = (start_x + x) * 32 + 16 px_y = (start_y + y) * 32 + 32 inst = { "__identifier": "Crop_Cannabis", "__grid": [start_x + x, start_y + y], "__pivot": [0.5, 1], "__tags": [], "__tile": None, "__smartColor": "#00FF00", "iid": f"crop_{x}_{y}", "width": 32, "height": 32, "defUid": cannabis_def['uid'], "px": [px_x, px_y], "fieldInstances": [] } entity_instances.append(inst) # Kai standing to the right # x=10, y=7 kai_pos_x = 10 kai_pos_y = 7 kai_inst = { "__identifier": "Kai_Hoe", "__grid": [kai_pos_x, kai_pos_y], "__pivot": [0.5, 1], "__tags": [], "__tile": None, "__smartColor": "#FF00FF", "iid": "kai_npc", "width": 256, "height": 256, "defUid": kai_def['uid'], "px": [kai_pos_x * 32 + 16, kai_pos_y * 32 + 32], "fieldInstances": [] } entity_instances.append(kai_inst) # Find Entities Layer Instance (uid 201 was created in first step, # but wait, do we have an Entities layer instance in the LEVEL?) # In 'setup_ldtk_atlas', we defined layer defs but maybe didn't add Entity layer instance to level. # Let's check defs to find Entity Layer Def UID. entity_layer_def_uid = None for l_def in data['defs']['layers']: if l_def['type'] == "Entities" and l_def['identifier'] == "Entities": entity_layer_def_uid = l_def['uid'] break # If not found, create one in defs (should be there from first setup, usually 201) if not entity_layer_def_uid: # Create Entity Layer Def entity_layer_def_uid = 201 ent_layer_def = { "__type": "Entities", "identifier": "Entities", "type": "Entities", "uid": entity_layer_def_uid, "gridSize": 32, "displayOpacity": 1, "pxOffsetX": 0, "pxOffsetY": 0, "requiredTags": [], "excludedTags": [], "intGridValues": [], "autoRuleGroups": [], "autoSourceLayerDefUid": None, "tilesetDefUid": None, "tilePivotX": 0, "tilePivotY": 0 } data['defs']['layers'].append(ent_layer_def) # Check if Instance exists in Level found_inst = False for level in data['levels']: for layer in level['layerInstances']: if layer['__identifier'] == "Entities": layer['entityInstances'] = entity_instances found_inst = True if not found_inst: # Add new layer instance for Entities new_inst = { "__identifier": "Entities", "__type": "Entities", "__cWid": 16, "__cHei": 16, "__gridSize": 32, "__opacity": 1, "__pxTotalOffsetX": 0, "__pxTotalOffsetY": 0, "__tilesetDefUid": None, "__tilesetRelPath": None, "iid": "inst_entities", "levelId": 0, "layerDefUid": entity_layer_def_uid, "pxOffsetX": 0, "pxOffsetY": 0, "visible": True, "optionalRules": [], "intGridCsv": [], "autoLayerTiles": [], "seed": 0, "overrideTilesetUid": None, "gridTiles": [], "entityInstances": entity_instances } data['levels'][0]['layerInstances'].insert(0, new_inst) # Top layer with open(LDTK_FILE, 'w') as f: json.dump(data, f, indent=2) print("LDtk Level 0 updated: 3x3 Farm, Cannabis, Kai!") if __name__ == "__main__": main()