Skip to content
This repository was archived by the owner on Sep 19, 2021. It is now read-only.

Add new map format#1294

Closed
Ruin0x11 wants to merge 30 commits intoelonafoobar:developfrom
Ruin0x11:feature/foobar-map
Closed

Add new map format#1294
Ruin0x11 wants to merge 30 commits intoelonafoobar:developfrom
Ruin0x11:feature/foobar-map

Conversation

@Ruin0x11
Copy link
Contributor

@Ruin0x11 Ruin0x11 commented May 20, 2019

Summary

This PR implements a new map format, .fmp, that allows for much better modding support than the vanilla .map format.

  • All the data in .idx, .obj and .map is rolled into one file.
  • Data is compressed with zlib. (It is added as a new dependency). This gives a ~10x filesize reduction.
  • It is editor-agnostic, but supports saving/loading using Tiled's latest development branch. (Some bugs were present/features did not exist in the Python API of the latest official release. The features needed did not make it into the recent 1.2.4 release of Tiled, so ~2 months are needed before the official release is compatible.)
  • Tiles are still loaded based on tileset atlas. The Tiled plugin loads the correct atlas on startup based on the atlas property of the map.
  • Strings that repeat often in the file, like string IDs, are compressed using a string to integer mapping.
  • Modding is supported through an "object" system. Objects can be saved in the map, which contain a type, ID, name, position and extra properties. When the map is loaded a custom function belonging to an instance of core.tile_exporter is run for each object and passed the object's data. This function can then call something like Chara.create. This concept is generalizable to new data formats also (although currently unimplemented), as long as they have a map position. Since objects can be given arbitrary properties, the kinds of behavior that can be ran to instantiate objects is greatly increased.
    • As an example, core.map_object is added to support adding map features like stairs.
    • This should allow map initialization logic previously hardcoded, like setting extra properties of characters, to be moved into the map itself, allowing the same functionality without needing to write any code.
  • Layering is supported for object layers.
  • Lua code is not contained in the format. Any extra behavior needed could be run as a callback on an instance of core.map.

There is a new feature added to the game client to export the needed tilesets for Tiled to load. The tilesets and needed plugins will be output to Tiled's config directory, ~./tiled. Once this step is done, both vanilla (gzipped) .idx and .fmp files should be loadable as long as all the data they used was also loaded into Elona_foobar at the time of export. If mod data is changed afterward, then the tilesets need to be regenerated also. .fmp contains a list of mods and semver versions of the data used at the time of saving, so incompatibilities can be detected.

Although this is a replacement for the vanilla .map format, there is no effect on existing saves. .fmp is an interchange format, intended to be converted into the in-memory map representation.

No maps have been converted to the new format yet. The map initialization code should be moved to Lua first.

Other changes

  • zlib and libpng are added as dependencies. zlib is a dependency of libpng itself and is used for map compression. libpng is used to output the tile images displayed in Tiled.
  • boost version is changed to 1.69 because of an API incompatibility in Boost.GIL introduced in 1.68 (see here).
  • Boost.Locale is removed as a dependency and instead functions from sol2 are used to provide UTF-16 conversion on Windows (see here).
  • Windows dependencies are moved to a separate repo. lua is now prepatched for wstring support on Windows.
  • zstr is used for gzip decompression to avoid a dependency on Boost.Iostreams.
  • core.tile_exporter is created to handle export/instantiation logic of data from map files.
  • core.map_object is added.

Example

Here is Tiled with the format's plugin support.

2019-05-19-213902_1920x1200_scrot

Format

Following is the map format.

Details

char[4]                    - header
int                        - map format version
size:                      - mod count
  string                   - mod name & version (mod-0.1.0)
mapping                    - file-local ID -> property names
properties                 - mdata properties
int                        - width
int                        - height
mapped_int[width * height] - tiles (string ID)
size:                      - layer count
  int                      - layer ID
  int                      - layer kind
  string                   - layer name
  properties               - layer properties
  if kind == tile:
    skip
  elif kind == group:
    size:                  - child layer count
      int                  - child layer index
  elif kind == object:
    size:                  - object count
      mapped_int           - data type
      mapped_int           - data instance
      int                  - object x
      int                  - object y
      properties           - object properties
  elif kind == image:
    skip

size:
  also an int

string:
  null-terminated

mapping:
  size:                    - item count
    int                    - file-local ID
    string                 - real name

properties:
  size:                    - count
    mapped_int             - key
    typed_value            - value

mapped_int:
  index into mapping table, represents a string

typed_value:
  0 - int
  1 - bool
  2 - string

@ki-foobar ki-foobar self-requested a review May 20, 2019 14:48
@ki-foobar ki-foobar added the 2: Improvement Improvement label May 20, 2019
Ruin0x11 added 28 commits May 20, 2019 21:22
This reverts commit 96e0402.
- Support for implicit tile properties on objects
- Add instantiators of map tiles
- Correct logic for map objects in the case of traps/small medals
This helps avoid bringing in <codecvt> and Boost.Locale just for
converting between UTF-8 and UTF-16 on Windows in a locale-agnostic
way.

See also ThePhD/sol2#571.
@Ruin0x11 Ruin0x11 force-pushed the feature/foobar-map branch from ceb880c to 9b7c741 Compare May 21, 2019 04:22
%NEEDDEPENDS% mkdir %PREFIX%
%NEEDDEPENDS% cp deps\install.bat %PREFIX%
%NEEDDEPENDS% cd %PREFIX%
%NEEDDEPENDS% git clone https://www.github.com/Ruin0x11/foobar_windows_deps windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL should be changed to ElonaFoobar/windows_deps, too.

extra {
show_menu = "F1: 追加オプションの表示"
export_tilesets = "タイルセットを書き出す"
exporting = "${_1}の書き出し…"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"インポート" and "エクスポート" have become Japanese.

export_tilesets = "タイルセットをエクスポート"
exporting = "${_1}をエクスポート中…"

type = "core.buff",
id = "grow_" .. attribute_name,
legacy_id = attribute_index + 20,
id = attribute_index + 20,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be an unintended change.

@@ -0,0 +1,24 @@
local data = { _table = {} }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is for old-style data declaration, should be removed.


# Only enable tileset export on platforms besides Android to avoid a
# libpng dependency. There is no map editor on Android anyway.
if(NOT ANDROID_GENERATE_BUILD_FILES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if(ANDROID) is more suitable for just detection of Android.

return _map;
}

std::string MapLoader::read_string()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently we don't want to embed NUL character in a string at all, but it cannot be said that we never want to.


void init()
{
lib::Stopwatch watch;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused?


MainMenuResult main_title_menu()
{
// fmp::export_tsx(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this debug code.

cyinit = y_at_m167;
rc = chara_index;
chara_place();
std::cerr << "map place player " << chara_index << " " << entrance_type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this debug code.


// For get_executable_path()
#if BOOST_OS_WINDOWS
#include <codecvt> // std::codecvt_utf8_utf16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header looks unused.

@ki-foobar
Copy link
Contributor

Closed the PR because it is hard to merge it into the current develop.

@ki-foobar ki-foobar closed this Dec 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

2: Improvement Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants