Map exec
This commit is contained in:
1 parent
7940f4c487
commit
726233e55f
29 files changed
+149
-30
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
module('platform')
|
module('platform')
|
||||||
module('input')
|
module('input')
|
||||||
module('scene')
|
module('scene')
|
||||||
|
module('map')
|
||||||
|
|
||||||
-- Default Input bindings.
|
-- Default Input bindings.
|
||||||
if PLATFORM == "psp" then
|
if PLATFORM == "psp" then
|
||||||
@@ -38,3 +39,4 @@ else
|
|||||||
end
|
end
|
||||||
|
|
||||||
sceneSet('map')
|
sceneSet('map')
|
||||||
|
mapLoad('map/testmap/testmap.dmf')
|
||||||
@@ -3,4 +3,4 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_asset(MAP map.json)
|
add_subdirectory(testmap)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"mapName": "Test"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
add_asset(MAP testmap.json)
|
||||||
|
add_asset(SCRIPT testmap.lua)
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "Test"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
print('Test Map Script Run')
|
||||||
@@ -1 +1 @@
|
|||||||
print('map')
|
-- Map Scene
|
||||||
@@ -89,5 +89,5 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
|
|||||||
.header = "DSF",
|
.header = "DSF",
|
||||||
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
||||||
.custom = assetScriptHandler
|
.custom = assetScriptHandler
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
+28
-2
@@ -11,6 +11,7 @@
|
|||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
#include "rpg/entity/entity.h"
|
#include "rpg/entity/entity.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
map_t MAP;
|
map_t MAP;
|
||||||
|
|
||||||
@@ -44,6 +45,19 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
|
|||||||
// Store the map file path
|
// Store the map file path
|
||||||
stringCopy(MAP.filePath, path, MAP_FILE_PATH_MAX);
|
stringCopy(MAP.filePath, path, MAP_FILE_PATH_MAX);
|
||||||
|
|
||||||
|
// Determine directory path (it is dirname)
|
||||||
|
stringCopy(MAP.dirPath, path, MAP_FILE_PATH_MAX);
|
||||||
|
char_t *last = stringFindLastChar(MAP.dirPath, '/');
|
||||||
|
if(last == NULL) errorThrow("Invalid map file path");
|
||||||
|
|
||||||
|
// Store filename, sans extension
|
||||||
|
stringCopy(MAP.fileName, last + 1, MAP_FILE_PATH_MAX);
|
||||||
|
*last = '\0'; // Terminate to get directory path
|
||||||
|
|
||||||
|
last = stringFindLastChar(MAP.fileName, '.');
|
||||||
|
if(last == NULL) errorThrow("Map file name has no extension");
|
||||||
|
*last = '\0'; // Terminate to remove extension
|
||||||
|
|
||||||
// Reset map position
|
// Reset map position
|
||||||
MAP.chunkPosition = position;
|
MAP.chunkPosition = position;
|
||||||
|
|
||||||
@@ -64,6 +78,18 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute map script.
|
// Execute map script.
|
||||||
|
char_t scriptPath[MAP_FILE_PATH_MAX + 16];
|
||||||
|
stringFormat(
|
||||||
|
scriptPath, sizeof(scriptPath), "%s/%s.dsf",
|
||||||
|
MAP.dirPath, MAP.fileName
|
||||||
|
);
|
||||||
|
if(assetFileExists(scriptPath)) {
|
||||||
|
scriptcontext_t ctx;
|
||||||
|
errorChain(scriptContextInit(&ctx));
|
||||||
|
errorChain(scriptContextExecFile(&ctx, scriptPath));
|
||||||
|
scriptContextDispose(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +209,8 @@ errorret_t mapChunkLoad(chunk_t* chunk) {
|
|||||||
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
||||||
|
|
||||||
// Get chunk filepath.
|
// Get chunk filepath.
|
||||||
snprintf(buffer, sizeof(buffer), "%s/%d_%d_%d.dcf",
|
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dcf",
|
||||||
MAP.filePath,
|
MAP.dirPath,
|
||||||
chunk->position.x,
|
chunk->position.x,
|
||||||
chunk->position.y,
|
chunk->position.y,
|
||||||
chunk->position.z
|
chunk->position.z
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
typedef struct map_s {
|
typedef struct map_s {
|
||||||
char_t filePath[MAP_FILE_PATH_MAX];
|
char_t filePath[MAP_FILE_PATH_MAX];
|
||||||
|
char_t dirPath[MAP_FILE_PATH_MAX];
|
||||||
|
char_t fileName[MAP_FILE_PATH_MAX];
|
||||||
|
|
||||||
chunk_t chunks[MAP_CHUNK_COUNT];
|
chunk_t chunks[MAP_CHUNK_COUNT];
|
||||||
chunk_t *chunkOrder[MAP_CHUNK_COUNT];
|
chunk_t *chunkOrder[MAP_CHUNK_COUNT];
|
||||||
chunkpos_t chunkPosition;
|
chunkpos_t chunkPosition;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
#include "debug/debug.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "rpg/world/map.h"
|
||||||
|
|
||||||
|
int32_t moduleMapLoad(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL");
|
||||||
|
|
||||||
|
if(!lua_isstring(L, 1)) {
|
||||||
|
luaL_error(L, "Expected string map filename");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potentially provide up to 3 params
|
||||||
|
chunkpos_t initial = { .x = 0, .y = 0, .z = 0 };
|
||||||
|
if(lua_isnumber(L, 2)) {
|
||||||
|
initial.x = (chunkunit_t)luaL_checkinteger(L, 2);
|
||||||
|
}
|
||||||
|
if(lua_isnumber(L, 3)) {
|
||||||
|
initial.y = (chunkunit_t)luaL_checkinteger(L, 3);
|
||||||
|
}
|
||||||
|
if(lua_isnumber(L, 4)) {
|
||||||
|
initial.z = (chunkunit_t)luaL_checkinteger(L, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the map.
|
||||||
|
errorret_t ret = mapLoad(luaL_checkstring(L, 1), initial);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
luaL_error(L, "Failed to load map");
|
||||||
|
errorCatch(errorPrint(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moduleMapSystem(scriptcontext_t *context) {
|
||||||
|
assertNotNull(context, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
scriptContextRegFunc(context, "mapLoad", moduleMapLoad);
|
||||||
|
}
|
||||||
@@ -10,12 +10,14 @@
|
|||||||
#include "script/module/moduleinput.h"
|
#include "script/module/moduleinput.h"
|
||||||
#include "script/module/moduleplatform.h"
|
#include "script/module/moduleplatform.h"
|
||||||
#include "script/module/modulescene.h"
|
#include "script/module/modulescene.h"
|
||||||
|
#include "script/module/modulemap.h"
|
||||||
|
|
||||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||||
{ .name = "system", .callback = moduleSystem },
|
{ .name = "system", .callback = moduleSystem },
|
||||||
{ .name = "input", .callback = moduleInput },
|
{ .name = "input", .callback = moduleInput },
|
||||||
{ .name = "platform", .callback = modulePlatform },
|
{ .name = "platform", .callback = modulePlatform },
|
||||||
{ .name = "scene", .callback = moduleScene },
|
{ .name = "scene", .callback = moduleScene },
|
||||||
|
{ .name = "map", .callback = moduleMapSystem },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRIPT_MODULE_COUNT ( \
|
#define SCRIPT_MODULE_COUNT ( \
|
||||||
|
|||||||
@@ -57,6 +57,17 @@ char_t * stringToken(char_t *str, const char_t *delim) {
|
|||||||
return strtok(str, delim);
|
return strtok(str, delim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char_t * stringFindLastChar(const char_t *str, const char_t c) {
|
||||||
|
assertNotNull(str, "str must not be NULL");
|
||||||
|
char_t *last = NULL;
|
||||||
|
for(const char_t *p = str; *p != '\0'; p++) {
|
||||||
|
if(*p == c) {
|
||||||
|
last = (char_t *)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t stringFormat(
|
int32_t stringFormat(
|
||||||
char_t *dest,
|
char_t *dest,
|
||||||
const size_t destSize,
|
const size_t destSize,
|
||||||
|
|||||||
@@ -64,6 +64,16 @@ void stringTrim(char_t *str);
|
|||||||
*/
|
*/
|
||||||
char_t * stringToken(char_t *str, const char_t *delim);
|
char_t * stringToken(char_t *str, const char_t *delim);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the last occurrence of a character in a string.
|
||||||
|
*
|
||||||
|
* @param str The string to search.
|
||||||
|
* @param c The character to find.
|
||||||
|
* @return A pointer to the last occurrence of the character in the string, or
|
||||||
|
* NULL if not found.
|
||||||
|
*/
|
||||||
|
char_t * stringFindLastChar(const char_t *str, const char_t c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a string.
|
* Formats a string.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -111,11 +111,11 @@ def processMap(asset):
|
|||||||
|
|
||||||
map = Map(None)
|
map = Map(None)
|
||||||
map.load(asset['path'])
|
map.load(asset['path'])
|
||||||
dir = map.getMapDirectory()
|
chunksDir = map.getChunkDirectory()
|
||||||
|
|
||||||
files = os.listdir(dir)
|
files = os.listdir(chunksDir)
|
||||||
if len(files) == 0:
|
if len(files) == 0:
|
||||||
print(f"Error: No chunk files found in map directory {dir}.")
|
print(f"Error: No chunk files found in {chunksDir}.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
chunkFiles = []
|
chunkFiles = []
|
||||||
@@ -133,21 +133,22 @@ def processMap(asset):
|
|||||||
result = processChunk(chunk)
|
result = processChunk(chunk)
|
||||||
chunkFiles.extend(result['files'])
|
chunkFiles.extend(result['files'])
|
||||||
|
|
||||||
outMap = {
|
# Map file
|
||||||
'files': chunkFiles
|
outBuffer = bytearray()
|
||||||
}
|
outBuffer.extend(b'DMF')
|
||||||
return assetCache(asset['path'], outMap)
|
outBuffer.extend(len(chunkFiles).to_bytes(4, 'little'))
|
||||||
|
|
||||||
# List files
|
# DMF (Dusk Map file)
|
||||||
chunkFiles = []
|
fileRelative = getAssetRelativePath(asset['path'])
|
||||||
for fileName in os.listdir(asset['path']):
|
fileNameWithoutExt = os.path.splitext(os.path.basename(fileRelative))[0]
|
||||||
if not fileName.endswith('.json'):
|
outputMapRelative = os.path.join(os.path.dirname(fileRelative), f"{fileNameWithoutExt}.dmf")
|
||||||
continue
|
outputMapPath = os.path.join(args.output_assets, outputMapRelative)
|
||||||
result = processChunk(os.path.join(asset['path'], fileName))
|
os.makedirs(os.path.dirname(outputMapPath), exist_ok=True)
|
||||||
chunkFiles.extend(result['files'])
|
with open(outputMapPath, "wb") as f:
|
||||||
|
f.write(outBuffer)
|
||||||
|
|
||||||
outMap = {
|
outMap = {
|
||||||
'files': chunkFiles
|
'files': chunkFiles
|
||||||
}
|
}
|
||||||
|
outMap['files'].append(outputMapPath)
|
||||||
return assetCache(asset['path'], outMap)
|
return assetCache(asset['path'], outMap)
|
||||||
+4
-4
@@ -131,12 +131,12 @@ class Chunk:
|
|||||||
return self.dirty
|
return self.dirty
|
||||||
|
|
||||||
def getFilename(self):
|
def getFilename(self):
|
||||||
if not self.map or not hasattr(self.map, 'getMapDirectory'):
|
if not self.map or not hasattr(self.map, 'getChunkDirectory'):
|
||||||
return None
|
return None
|
||||||
dir_path = self.map.getMapDirectory()
|
dirPath = self.map.getChunkDirectory()
|
||||||
if dir_path is None:
|
if dirPath is None:
|
||||||
return None
|
return None
|
||||||
return f"{dir_path}/{self.x}_{self.y}_{self.z}.json"
|
return f"{dirPath}/{self.x}_{self.y}_{self.z}.json"
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.vertexBuffer.draw()
|
self.vertexBuffer.draw()
|
||||||
|
|||||||
+10
-3
@@ -1,4 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
from dusk.event import Event
|
from dusk.event import Event
|
||||||
from PyQt5.QtWidgets import QFileDialog, QMessageBox
|
from PyQt5.QtWidgets import QFileDialog, QMessageBox
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
@@ -129,10 +130,16 @@ class Map:
|
|||||||
return self.mapFileName if self.mapFileName and os.path.exists(self.mapFileName) else None
|
return self.mapFileName if self.mapFileName and os.path.exists(self.mapFileName) else None
|
||||||
|
|
||||||
def getMapDirectory(self):
|
def getMapDirectory(self):
|
||||||
fname = self.getMapFilename()
|
if self.mapFileName is None:
|
||||||
if not fname or not fname.endswith('.json'):
|
|
||||||
return None
|
return None
|
||||||
return fname[:-5] # Remove '.json' extension
|
dirname = os.path.dirname(self.mapFileName)
|
||||||
|
return dirname
|
||||||
|
|
||||||
|
def getChunkDirectory(self):
|
||||||
|
dirName = self.getMapDirectory()
|
||||||
|
if dirName is None:
|
||||||
|
return None
|
||||||
|
return os.path.join(dirName, 'chunks')
|
||||||
|
|
||||||
def anyChunksDirty(self):
|
def anyChunksDirty(self):
|
||||||
for chunk in self.chunks.values():
|
for chunk in self.chunks.values():
|
||||||
|
|||||||
Reference in new issue
Block a user