Skip to content

Commit

Permalink
Merge commit 'a21d73f8ad24b74dc5d78ddff814f690b5ed7f2f'
Browse files Browse the repository at this point in the history
  • Loading branch information
CosmoMyzrailGorynych committed Feb 18, 2024
2 parents 97423c4 + a21d73f commit 1650867
Show file tree
Hide file tree
Showing 33 changed files with 1,255 additions and 2,332 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ cache
tempChangelog.md
prev
trash
/Changelog.md

# tests
error_screenshots/
Expand Down
39 changes: 39 additions & 0 deletions app/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
## v4.0.1

*Sun Feb 18 2024*

### ⚡️ General Improvements

* Changed button text from Save to Apply (#495 by @AnukratiMehta)
* Improve migration script for v4 to handle cases when assets had broken references to groups

### 🐛 Bug Fixes

* Fix migration code for v4 throwing an error if a project did not use fittoscreen catmod.
* Fix `pointer.collides` method
* Tabs of deleted assets must automatically close. Closes #491
* Update copies in room editors if their linked text style has changed. Closes #493

### 🍱 Demos, Dependencies and Stuff

* :zap: JettyCat's example project should use a text base class for its highscore label in the defeat screen
* 🐛 Fix fullscreen switcher in Catformer example(#490 by @sk757a)

### 📝 Docs

* :hankey: Use a vanilla document search
* Drop `ct.` prefix in catmod docs (#494 by @ehanahamed)

### 🌐 Website

* :bento: Update screenshots in the presskit
* :bug: Remove downloads for MacOS ARM builds that no longer exist
* :zap: Update text in the presskit
* :zap: Update the changelog

### 😱 Misc

* :globe_with_meridians: Update Debug and Comments translation files
* :globe_with_meridians: Update Russian UI translation file
* Fix supabase catmod (#497 by @ehanahamed)

## v4.0.0

*Sat Feb 10 2024*
Expand Down
40 changes: 20 additions & 20 deletions app/data/ct.libs/fs/DOCS.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
## `ct.fs.forceLocal: boolean`
## `fs.forceLocal: boolean`

When set to `true`, any operations towards files outside the game's save directory will fail.
Set to `true` by default.

## `ct.fs.isAvailable: boolean`
## `fs.isAvailable: boolean`
When set to `false`, the game is running in a way that disallows access to the filesystem (such as a web release)

## `ct.fs.save(filename: string, data: object|Array): Promise<void>`
## `fs.save(filename: string, data: object|Array): Promise<void>`

Saves an object/array to a file.

## `ct.fs.load(filename: string): Promise<object|Array>`
## `fs.load(filename: string): Promise<object|Array>`

Loads an object/array from a file written by `ct.fs.save`.
Loads an object/array from a file written by `fs.save`.

## `ct.fs.saveText(filename: string, text: string): Promise<void>`
## `fs.saveText(filename: string, text: string): Promise<void>`

Converts any value to a string and puts it into a file.

## `ct.fs.loadText(filename: string): Promise<string>`
## `fs.loadText(filename: string): Promise<string>`

Loads a string from a file, previously written by ct.fs.saveText.
Loads a string from a file, previously written by fs.saveText.

## `ct.fs.makeDir(path: string): Promise<void>`
## `fs.makeDir(path: string): Promise<void>`

Creates a directory and all the preceding folders, if needed.

## `ct.fs.deleteDir(path: string): Promise<void>`
## `fs.deleteDir(path: string): Promise<void>`

Removes a given directory with all its contents.
If an EBUSY, EMFILE, ENFILE, ENOTEMPTY, or EPERM error is encountered,
it will try again at max 10 times in one second.

## `ct.fs.copy(filename: string, dest: string): Promise<void>`
## `fs.copy(filename: string, dest: string): Promise<void>`
Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location.

## `ct.fs.move(filename: string, dest: string): Promise<void>`
## `fs.move(filename: string, dest: string): Promise<void>`
Copies a file, then deletes the original. Does nothing if `filename` and `dest` point to one location.

## `ct.fs.listFiles(directory?: string): Promise<Array<string>>`
## `fs.listFiles(directory?: string): Promise<Array<string>>`
Returns a promise that resolves into an array of file names in a given directory

## `ct.fs.stat(filename: string): Promise<fs.Stats|boolean>`
## `fs.stat(filename: string): Promise<fs.Stats|boolean>`

Gets information about a given file.

See https://nodejs.org/api/fs.html#fs_class_fs_stats

**Alias:** `ct.fs.exists`
**Alias:** `fs.exists`

## `ct.fs.getPath(partial: string): string`
## `fs.getPath(partial: string): string`

When given a relative path, returns the absolute path equivalent
to the given one, resolving it relative to the game's save directory.

No need to use it with `ct.fs``getPath` is already used in all its methods.
The method is useful when working with other libraries, and for debugging.

## `ct.fs.rename(): Promise<void>`
An alias for `ct.fs.move`. Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location.
## `fs.rename(): Promise<void>`
An alias for `fs.move`. Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location.

## `ct.fs.exists(): Promise<fs.Stats|boolean>`
## `fs.exists(): Promise<fs.Stats|boolean>`

An alias for `ct.fs.stat`. Gets information about a given file.
An alias for `fs.stat`. Gets information about a given file.
See https://nodejs.org/api/fs.html#fs_class_fs_stats
34 changes: 17 additions & 17 deletions app/data/ct.libs/fs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ Within the application directory, ct.js will create a path using the defined Aut
> **For Example**: If a player with the name `naturecodevoid` was running the game `jettyCat` by `comigo` on Linux, the default directory would be:
`/home/naturecodevoid/.local/share/comigo/jettyCat`

You can verify this by calling `ct.fs.getPath('')` or by checking the variable `ct.fs.gameFolder`.
You can verify this by calling `fs.getPath('')` or by checking the variable `fs.gameFolder`.

It is not recommended, but you can set `ct.fs.gameFolder` to a different directory. This is useful if your meta fields (Author Name, Project Name) have changed, but you wish to preserve user data.
It is not recommended, but you can set `fs.gameFolder` to a different directory. This is useful if your meta fields (Author Name, Project Name) have changed, but you wish to preserve user data.

Also to note, operations outside of the game folder are not recommended and by default are not allowed, causing an error to appear in the game's console. To allow operations outside of the game folder set `ct.fs.forceLocal` to `false` first.
Also to note, operations outside of the game folder are not recommended and by default are not allowed, causing an error to appear in the game's console. To allow operations outside of the game folder set `fs.forceLocal` to `false` first.

Every action in `ct.fs` is asynchronous so that a game stays responsive even on heavy loads, and thus you have to use JS Promises. This is not hard, though:
Every action in `fs` is asynchronous so that a game stays responsive even on heavy loads, and thus you have to use JS Promises. This is not hard, though:

```js
// Here we store an object in a JSON file.
ct.fs.save('savedGame.json', this.gameData)
fs.save('savedGame.json', this.gameData)
.then(() => {
// Here our operation has completed, we can add a feedback now
ct.templates.copy('GenericNotification', 20, 20, {
templates.copy('GenericNotification', 20, 20, {
message: 'Game saved!'
});
});
Expand All @@ -37,49 +37,49 @@ this.kill = true;

## Determining if ct.fs is supported

Ct.fs is designed for use on desktop devices, and its methods won't work in browsers. You can check for `ct.fs.isAvailable` to determine what you can do:
Ct.fs is designed for use on desktop devices, and its methods won't work in browsers. You can check for `fs.isAvailable` to determine what you can do:

```js
if (ct.fs.isAvailable) {
if (fs.isAvailable) {
// All is well, we have an access to the filesystem.
ct.fs.save('saveData.cat', ct.game); // your file should not necessarily have `json` extension, btw ;)
fs.save('saveData.cat', game); // your file should not necessarily have `json` extension, btw ;)
} else {
// File system is not available; we can add a fallback to a browser's local storage instead.
// see https://docs.ctjs.rocks/localstorage.html
localStorage.saveData = JSON.stringify(ct.game);
localStorage.saveData = JSON.stringify(game);
}
```

## Hints

* If you store all your game progression info in one object, you can make your whole save/load system in about 2-3 lines of code with `ct.fs.save` and `ct.fs.load`.
* If you store all your game progression info in one object, you can make your whole save/load system in about 2-3 lines of code with `fs.save` and `fs.load`.
* You can't simply store copies inside a save file, but you can serialize them by using a bit of js magic:
```js
const hero = ct.templates.list['Hero'][0];
const hero = templates.list['Hero'][0];
const saveData = {
hero: {
x: hero.x,
y: hero.y
},
enemies: []
};
for (const enemy of ct.templates.list['Enemy']) {
for (const enemy of templates.list['Enemy']) {
saveData.enemies.push({
x: enemy.x,
y: enemy.y,
hp: enemy.hp
});
}
ct.fs.save('savegame.json', saveData);
fs.save('savegame.json', saveData);

// Later…

ct.fs.load('savegame.json', saveData => {
const hero = ct.templates.list['Hero'][0];
fs.load('savegame.json', saveData => {
const hero = templates.list['Hero'][0];
hero.x = saveData.hero.x;
hero.y = saveData.hero.y;
for (const enemy of saveData.enemies) {
ct.templates.copy('Enemy', enemy.x, enemy.y);
templates.copy('Enemy', enemy.x, enemy.y);
}
});
```
158 changes: 76 additions & 82 deletions app/data/ct.libs/fs/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,88 +26,82 @@ interface IStats {
isSymbolicLink(): boolean;
}

declare namespace ct {
/** A module that provides a uniform API for storing and loading data for your desktop games. */
namespace fs {

/**
* When set to `true`, any operations towards files outside the game's save directory will fail.
* Set to `true` by default.
*/
var forceLocal: boolean;

/**
* When set to `false`, the game is running in a way that disallows access to the filesystem (such as a web release)
*/
var isAvailable: boolean;

/**
* The base location for application data. Not for normal usage.
*/
var gameFolder: string;

/** Saves an object/array to a file. */
function save(filename: string, data: object|any[]): Promise<void>;

/** Loads an object/array from a file written by `ct.fs.save`. */
function load(filename: string): Promise<object|any[]>;

/** Converts any value to a string and puts it into a file. */
function saveText(filename: string, text: string): Promise<void>;

/** Loads a string from a file, previously written by ct.fs.saveText. */
function loadText(filename: string): Promise<string>;

/** Creates a directory and all the preceding folders, if needed. */
function makeDir(path: string): Promise<void>;

/**
* Removes a given directory with all its contents.
* If an EBUSY, EMFILE, ENFILE, ENOTEMPTY, or EPERM error is encountered,
* it will try again at max 10 times in one second.
*/
function deleteDir(path: string): Promise<void>;

/** Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location.*/
function copy(filename: string, dest: string): Promise<void>;

/** Copies a file, then deletes the original. Does nothing if `filename` and `dest` point to one location. */
function move(filename: string, dest: string): Promise<void>;

/** Returns a promise that resolves into an array of file names in a given directory */
function listFiles(directory?: string): Promise<void>;

/**
* Gets information about a given file.
* @see https://nodejs.org/api/fs.html#fs_class_fs_stats
*/
function stat(filename: string): Promise<IStats|boolean>;

/**
* When given a relative path, returns the absolute path equivalent
* to the given one, resolving it relative to the game's save directory.
*
* No need to use it with `ct.fs` — `getPath` is already used in all its methods.
* The method is useful when working with other libraries, and for debugging.
*/
function getPath(partial: string): string;

/** An alias for `ct.fs.move`. Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location. */
function rename(): Promise<void>;

/**
* An alias for `ct.fs.stat`. Gets information about a given file.
* @see https://nodejs.org/api/fs.html#fs_class_fs_stats
*/
function exists(): Promise<IStats|boolean>;

}
/** A module that provides a uniform API for storing and loading data for your desktop games. */
declare namespace fs {
/**
* When set to `true`, any operations towards files outside the game's save directory will fail.
* Set to `true` by default.
*/
var forceLocal: boolean;

/**
* When set to `false`, the game is running in a way that disallows access to the filesystem (such as a web release)
*/
var isAvailable: boolean;

/**
* The base location for application data. Not for normal usage.
*/
var gameFolder: string;

/** Saves an object/array to a file. */
function save(filename: string, data: object|any[]): Promise<void>;

/** Loads an object/array from a file written by `ct.fs.save`. */
function load(filename: string): Promise<object|any[]>;

/** Converts any value to a string and puts it into a file. */
function saveText(filename: string, text: string): Promise<void>;

/** Loads a string from a file, previously written by ct.fs.saveText. */
function loadText(filename: string): Promise<string>;

/** Creates a directory and all the preceding folders, if needed. */
function makeDir(path: string): Promise<void>;

/**
* Removes a given directory with all its contents.
* If an EBUSY, EMFILE, ENFILE, ENOTEMPTY, or EPERM error is encountered,
* it will try again at max 10 times in one second.
*/
function deleteDir(path: string): Promise<void>;

/** Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location.*/
function copy(filename: string, dest: string): Promise<void>;

/** Copies a file, then deletes the original. Does nothing if `filename` and `dest` point to one location. */
function move(filename: string, dest: string): Promise<void>;

/** Returns a promise that resolves into an array of file names in a given directory */
function listFiles(directory?: string): Promise<void>;

/**
* Gets information about a given file.
* @see https://nodejs.org/api/fs.html#fs_class_fs_stats
*/
function stat(filename: string): Promise<IStats|boolean>;

/**
* When given a relative path, returns the absolute path equivalent
* to the given one, resolving it relative to the game's save directory.
*
* No need to use it with `ct.fs` — `getPath` is already used in all its methods.
* The method is useful when working with other libraries, and for debugging.
*/
function getPath(partial: string): string;

/** An alias for `ct.fs.move`. Copies a file from one location to another. Does nothing if `filename` and `dest` point to one location. */
function rename(): Promise<void>;

/**
* An alias for `ct.fs.stat`. Gets information about a given file.
* @see https://nodejs.org/api/fs.html#fs_class_fs_stats
*/
function exists(): Promise<IStats|boolean>;
}

declare namespace ct {
namespace fs {
/** Removes a given file */
var _delete: function(string): Promise<void>;
export {_delete as delete};
}
declare namespace fs {
/** Removes a given file */
var _delete: function(string): Promise<void>;
export {_delete as delete};
}
Loading

0 comments on commit 1650867

Please sign in to comment.