Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added custom json configs and improved autotiles #327

Merged
merged 31 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a340aab
updated install script to use `npm ci` to avoid issues with dependencies
Vegita2 Jul 19, 2024
0dc1c92
show selected tile in "Tile selector" when copying tiles on the map (…
Vegita2 Jul 19, 2024
1fbfe11
refactored tile drawer and tile-selector to remove duplicates
Vegita2 Jul 19, 2024
b75ccf8
improved performance when rendering tile selector
Vegita2 Jul 19, 2024
8f84b69
refactored autotile naming and added 4x4 type
Vegita2 Jul 19, 2024
13e0225
show the user if an autotile is currently selected
Vegita2 Jul 20, 2024
27a6944
added custom json loader to include json's from mods
Vegita2 Jul 20, 2024
967b1f3
tilsets.json now loaded through json-loader
Vegita2 Jul 20, 2024
621009c
added simple cache to json loader
Vegita2 Jul 20, 2024
f702440
abstract-faces.json now loaded through json-loader
Vegita2 Jul 20, 2024
c5f71a6
changed default for "mergeWithEmpty" to false. Can't find anything wh…
Vegita2 Jul 21, 2024
075b50d
updated autotiles for some tilesets
Vegita2 Jul 21, 2024
9a76063
Merge branch 'refs/heads/master' into autotiles
Vegita2 Jul 25, 2024
971fda3
updated autotiles for most maps
Vegita2 Jul 25, 2024
e537a01
fixed autotile error if tileset config doesn't exist for specific til…
Vegita2 Jul 25, 2024
ffa902b
actions.json and events.json now loaded through json-loader
Vegita2 Jul 26, 2024
d744068
entities.json now loaded through json-loader
Vegita2 Jul 26, 2024
d3df072
map-styles.json now loaded through json-loader
Vegita2 Jul 26, 2024
059c96a
tilesets.json now loaded through json-loader
Vegita2 Jul 26, 2024
0c27fc8
destructibles.json and destructible-types.json now loaded through jso…
Vegita2 Jul 26, 2024
8b8576d
updated changelog
Vegita2 Jul 26, 2024
9117898
simplified interface ConfigExtension
Vegita2 Jul 28, 2024
d30247d
added support for directories inside mod folder "map-editor"
Vegita2 Jul 28, 2024
7024698
renamed ConfigExtension interface
Vegita2 Jul 28, 2024
e5b9580
fixed autotile issue
Vegita2 Jul 28, 2024
ca654f3
fixed BaseTileDrawer having issues when deleting layers
Vegita2 Jul 28, 2024
8ec1416
added comment to explain tile selector scene highlight logic
Vegita2 Jul 28, 2024
ea2c3f4
removed unused jsonLoader
Vegita2 Jul 28, 2024
0a7ae46
improved map styles definitions
Vegita2 Jul 28, 2024
f624445
fixed selection not showing in tile selector when changing layers
Vegita2 Jul 28, 2024
48a8364
set z-index on floating window to fix some ordering issues
Vegita2 Jul 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ yarn-error.log
Thumbs.db

# scripts
*.bat
*.bat
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]
### Added
- Added overrideable JSON configs, see [#327](https://github.com/CCDirectLink/crosscode-map-editor/pull/327) for more details
- Added most definitions to autotiles.json
- Added new autotile type 4x4

## [1.7.1] 2024-07-21
### Fixed
- Fixed Event editor not working
Expand Down
1 change: 1 addition & 0 deletions backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ app.get('/api/allTilesets', async (_, res) => res.json(await api.getAllTilesets(
app.get('/api/allMaps', async (req, res) => res.json(await api.getAllMaps(config.pathToCrosscode, req.query['includeVanillaMaps'] == 'true')));
app.get('/api/allFilesInFolder', async (req, res) => res.json(await api.getAllFilesInFolder(config.pathToCrosscode, req.query['folder'] as string, req.query['extension'] as string)));
app.get('/api/allMods', async (_, res) => res.json(await api.getAllMods(config.pathToCrosscode)));
app.get('/api/allModMapEditorConfigs', async (_, res) => res.json(await api.getAllModMapEditorConfigs(config.pathToCrosscode)));
app.post('/api/get', async (req, res) => {
res.json(await api.get(config.pathToCrosscode, req.body.path));
});
Expand Down
80 changes: 55 additions & 25 deletions common/src/controllers/api.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { fsPromise, pathPromise } from '../require.js';
import { saveFile as save } from './saveFile.js';

export interface ModEditorConfig {
filename: string;
mod: string;
file: string;
}

const mods: string[] = [];
let packagesCache: Record<string, { folderName: string, displayName: string, ccmodDependencies?: Map<string, string> }>;

async function listAllFiles(dir: string, filelist: string[], ending: string, root?: string): Promise<string[]> {
if (root === undefined) {
root = dir;
}

const files = await tryReadDir(dir);
const promises: Promise<void>[] = [];
for (const file of files) {
Expand Down Expand Up @@ -48,7 +54,7 @@ async function searchFile(file: string, dir: string, filelist: string[], ending:
.resolve(dir, file)
.split(path.normalize(root))[1]
.replace(/\\/g, '/');

const result = normalized.startsWith('/') ? normalized.substr(1) : normalized;
if (!filelist.includes(result)) {
filelist.push(result);
Expand Down Expand Up @@ -84,12 +90,12 @@ function selectMod(name: string, packages: Record<string, { folderName: string,
if (!pkg) {
return;
}

result.push(pkg.folderName);
if (!pkg.ccmodDependencies) {
return;
}

for (const depName of Object.keys(pkg.ccmodDependencies)) {
selectMod(depName, packages, result);
}
Expand Down Expand Up @@ -125,16 +131,16 @@ async function readMods(dir: string) {
if (packagesCache) {
return packagesCache;
}

const fs = await fsPromise;
const path = await pathPromise;

const modFolder = path.join(dir, 'mods/');
const files = await searchSubFolder(modFolder, 'package.json');
const filesCCMod = await searchSubFolder(modFolder, 'ccmod.json');

const ccmodFolderNames = new Set(filesCCMod.map(file => path.basename(path.dirname(file))));

const promises: Promise<[string, Buffer]>[] = [];
for (const file of files) {
const folderName = path.basename(path.dirname(file));
Expand All @@ -146,7 +152,7 @@ async function readMods(dir: string) {
}
const rawPackages = await Promise.all(promises);
const packages: Record<string, { folderName: string, displayName: string, ccmodDependencies?: Map<string, string> }> = {};

for (const [name, pkg] of rawPackages) {
try {
const parsed = JSON.parse(pkg as unknown as string);
Expand All @@ -159,13 +165,13 @@ async function readMods(dir: string) {
console.error('Invalid json data in package.json of mod: ' + name, err);
}
}

const promisesCCMod: Promise<[string, Buffer]>[] = [];
for (const file of filesCCMod) {
promisesCCMod.push((async (): Promise<[string, Buffer]> => [path.basename(path.dirname(file)), await fs.promises.readFile(file)])());
}
const rawCCMods = await Promise.all(promisesCCMod);

for (const [name, pkg] of rawCCMods) {
try {
const parsed = JSON.parse(pkg as unknown as string);
Expand All @@ -178,7 +184,7 @@ async function readMods(dir: string) {
console.error('Invalid json data in ccmod.json of mod: ' + name, err);
}
}

packagesCache = packages;
return packages;
}
Expand All @@ -187,43 +193,43 @@ export async function getAllFiles(dir: string) {
const path = await pathPromise;
const images = await listAllFiles(path.resolve(dir, 'media/'), [], 'png', path.resolve(dir));
const data = await listAllFiles(path.resolve(dir, 'data/'), [], 'json', path.resolve(dir));

for (const mod of mods) {
const modDir = path.join(dir, 'mods', mod, 'assets');
await listAllFiles(path.resolve(modDir, 'media/'), images, 'png', path.resolve(modDir));
await listAllFiles(path.resolve(modDir, 'data/'), data, 'json', path.resolve(modDir));
}

images.sort();
data.sort();

return { images, data };
return {images, data};
}

export async function getAllTilesets(dir: string) {
const path = await pathPromise;
const result = await listAllFiles(path.resolve(dir, 'media/map/'), [], 'png', path.resolve(dir));

for (const mod of mods) {
const modDir = path.join(dir, 'mods', mod, 'assets');
await listAllFiles(path.resolve(modDir, 'media/map/'), result, 'png', path.resolve(modDir));
}

return result.sort();
}

export async function getAllMaps(dir: string, includeVanillaMaps: boolean) {
const path = await pathPromise;
const paths: string[] = [];

if (mods.length === 0 || includeVanillaMaps) {
await listAllFiles(path.resolve(dir, 'data/maps/'), paths, 'json', path.resolve(dir));
}
if (mods.length > 0) {
const modDir = path.join(dir, 'mods', mods[0], 'assets');
await listAllFiles(path.resolve(modDir, 'data/maps/'), paths, 'json', path.resolve(modDir));
}

return paths
.sort()
.map(p => p.substring('data/maps/'.length, p.length - '.json'.length))
Expand All @@ -233,23 +239,47 @@ export async function getAllMaps(dir: string, includeVanillaMaps: boolean) {
export async function getAllFilesInFolder(dir: string, folder: string, extension: string) {
const path = await pathPromise;
const result = await listAllFiles(path.resolve(dir, folder), [], extension, path.resolve(dir));

for (const mod of mods) {
const modDir = path.join(dir, 'mods', mod, 'assets');
await listAllFiles(path.resolve(modDir, folder), result, extension, path.resolve(modDir));
}

return result.sort()
.map(p => p.substring(folder.length, p.length - `.${extension}`.length));
}

export async function getAllMods(dir: string) {
const packages = await readMods(dir);
return Object.entries(packages)
.map(([id, pkg]) => ({ id, displayName: pkg.displayName as string }))
.map(([id, pkg]) => ({id, displayName: pkg.displayName as string}))
.sort((a, b) => a.displayName.localeCompare(b.displayName));
}

export async function getAllModMapEditorConfigs(dir: string): Promise<ModEditorConfig[]> {
const packages = await readMods(dir);

const fs = await fsPromise;
const path = await pathPromise;

const configs: ModEditorConfig[] = [];

for (const mod of Object.values(packages)) {
const modName = mod.folderName;
const mapEditorPath = path.join(dir, 'mods', modName, 'map-editor');
const files = await listAllFiles(mapEditorPath, [], 'json', path.resolve(dir));
for (const filename of files) {
const file = await fs.promises.readFile(path.join(dir, filename), 'utf-8');
configs.push({
filename: path.basename(filename),
mod: modName,
file: file
});
}
}
return configs;
}

export async function selectedMod(dir: string, modName: string) {
const packages = await readMods(dir);
mods.splice(0); // Clear array
Expand All @@ -264,7 +294,7 @@ export async function get<T>(dir: string, file: string): Promise<T> {
promises.push(getAsync(modFile));
}
promises.push(getAsync(path.join(dir, file)));

const results = await Promise.all(promises);
for (const result of results) {
if (result) {
Expand All @@ -282,7 +312,7 @@ export async function resolve(dir: string, file: string): Promise<string> {
promises.push(resolveAsync(modFile));
}
promises.push(resolveAsync(path.join(dir, file)));

const results = await Promise.all(promises);
for (const result of results) {
if (result) {
Expand Down
6 changes: 3 additions & 3 deletions install_all.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/bin/bash

cd common
npm install
npm ci
npm run build
cd ../backend
npm install
npm ci
cd ../webapp
npm install
npm ci
10 changes: 3 additions & 7 deletions webapp/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,12 @@ export class AppComponent {
constructor(
private readonly eventsService: GlobalEventsService,
private readonly overlayService: OverlayService,
private readonly router: Router
) {
this.router.events.subscribe(event => {
console.log(event.constructor.name, event);
});
) {
}

@HostListener('window:beforeunload', ['$event'])
onUnload($event: any) {
if(this.eventsService.hasUnsavedChanges.getValue()) {
if (this.eventsService.hasUnsavedChanges.getValue()) {
$event.returnValue = 'Are you sure you want to discard your changes?';

const dialogRef = this.overlayService.open(ConfirmCloseComponent, {
Expand Down
10 changes: 5 additions & 5 deletions webapp/src/app/components/captions/captions.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<p class="version caption">{{ version }}</p>
<p class="bottom-elements caption">
<p class="bottom-container version caption">{{ version }}</p>
<p class="bottom-container bottom-elements">
<ng-container *ngFor="let el of uiElements">
<ng-container *ngIf="el.active">
{{el.text}}
</ng-container>
<span class="caption" *ngIf="el.active">
{{ el.text }}
</span>
</ng-container>
</p>
19 changes: 14 additions & 5 deletions webapp/src/app/components/captions/captions.component.scss
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
@use '@angular/material' as mat;

.caption {
.bottom-container {
bottom: 0;
padding: 5px;
color: white;

z-index: 9999;
position: absolute;
pointer-events: none;
//pointer-events: none;
}

.caption {
padding: 5px;
color: white;
}

.version {
right: 0;
}

.bottom-elements {
background-color: #0005;
display: flex;
gap: 8px;

&:empty {
display: none;
}

& .caption {
background-color: #0005;
}
}
10 changes: 9 additions & 1 deletion webapp/src/app/components/captions/captions.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ export class CaptionsComponent implements OnInit {
version = environment.version;
coords: BottomUiElement = {};
selectionSize: BottomUiElement = {};
autotile: BottomUiElement = {
text: 'Autotile'
};

uiElements: BottomUiElement[] = [
this.coords,
this.selectionSize
this.selectionSize,
this.autotile,
];

ngOnInit(): void {
Expand All @@ -32,5 +36,9 @@ export class CaptionsComponent implements OnInit {
this.selectionSize.text = `${size?.x}x${size?.y}`;
this.selectionSize.active = !!size;
});

Globals.globalEventsService.isAutotile.subscribe(show => {
this.autotile.active = show;
});
}
}
Loading
Loading