Encodes and decodes towns in clipboard (text) into various other formats

Overview

Townsclipper NPM latest version

Townscaper clipboard data format converter.

Encodes and decodes towns in clipboard (text) into various other formats. For example, it can turn this...

FC5ADI3TQN

FC5ADI3TQN screenshot

...into this...

[
  {
    "x": -9,
    "y": 9,
    "voxels": {
      "0": 15,
      "1": 0
    }
  },
  {
    "x": 0,
    "y": 0,
    "voxels": {
      "1": 0,
      "2": 0
    }
  }
]

...and back again!

Concepts

  • Voxels: Each little cube that we build the town with.

  • Types: The different colors of voxels. Also empty (air) and ground.

  • Corners: Each possible construction point in the grid. Contains a column of voxels (or empty space) in a specific X and Y coordinate.

  • Clip string: Clipboard save string, as generated when clicking the "Save to Clipboard" button in Townscaper.

  • Bit string: Raw binary data decoded from clip strings.

  • Dense Representation: A JSON representation of the data inside a clip string. Some details are abstracted away since they can be calculated.

    Although multiple DRs can generate the same bit string (and vice versa) they can be transformed univocally as long as the least number of bits is used.

    Internally:

    • Corner positions are represented as deltas (x) and offsets (y).
    • Voxels are represented as a dense array of types (column in that corner) from lowest to highest.
    type Dense = {
      // The initial X and Y coordinates from corners.
      xInitial: number,
      yInitial: number,
      // Up to 15 colors. Absolute voxel types (0 = red, 14 = white, 15 = ground).
      // This is used as a lookup table later in DenseCorner's `voxels`.
      types: number[],
      // See below.
      corners: DenseCorner[],
    }
    
    type DenseCorner =  {
      // How much to advance `X` from last corner. Must be `null` on the first `Corner`.
      xDelta: number | null,
      // yPosition = yInitial + yOffset.
      yOffset: number,
      // Whether this corner's column has a ground voxel.
      hasGround: bool,
      // Index in `types` lookup table. `-1` for empty.
      voxels: number[],
    }
  • Scape files: Towns as stored in disk, in plain XML format. In Windows they are stored as a bunch of Town*.scape files in %appdata%\..\LocalLow\Oskar Stalberg\Townscaper\ (i.e. C:\Users\ \AppData\LocalLow\Oskar Stalberg\Townscaper\ ). Chris Love has a great writeup about these.

    Long story short: they are a list of corners (x, y, number of voxels) and another list of voxels (height, type) in order of appearance in corners.

  • Sparse Representation: JSON representation with voxels in sparse form (similar to Scape files).

    type Sparse = SparseCorner[]
    
    type SparseCorner = {
      // Absolute position
      x: number,
      y: number,
      // Map from height (0 = ground) to absolute voxel type (0 = red, 14 = white, 15 = ground)
      voxels: { [height: number] : number },
    }

CLI

Installation requires Node.js (latest LTS should work) and NPM or Yarn. First install globally (you might need root/admin permissions):

npm install -g townsclipper
# Or with Yarn
yarn global add townsclipper

It will install the townsc command-line tool. Use townsc --help for instructions.

You can also use it locally without -g or global, but you'll have to run it in that specific folder via ./node_modules/.bin/townsc.js.

Examples

  1. Inspect a save string as dense representation

    townsc clip dense --pretty ASJAJ6Za1TAa
  2. Same, but reading from a file (or any stdin for that matter)

    cat myFile | townsc clip dense --pretty
  3. Replace red blocks with blue

    townsc clip dense ASJAJ6Za1TAa |
    sed 's/"types":\[0]/"types":\[9]/' |
    townsc dense clip
  4. Edit savestring data as sparse in Vim

    tmpfile=$(mktemp) &&
    townsc clip sparse --pretty ASJAJ6Za1TAa > $tmpfile &&
    vim $tmpfile &&
    cat $tmpfile | townsc sparse clip &&
    rm $tmpfile

    (TIP: Make a shell alias out of this!)

Library

You can programatically use Townsclipper as a library (both NodeJS and browser via bundler should work). See ./lib/index.js.

npm install --save townsclipper
# Or with Yarn
yarn add townsclipper

Contributing MIT License

Just test the CLI and library! Use it! Break it! Enjoy it! And report any bugs :P

Pull requests are welcome. Fork this repository! For now we're just working on master since were aren't even v1.0.

Do a global search for TODO to see what's pending to do or discuss.

Rules:

  • Clipboard strings should match Townscaper's. If you can make them shorter, hide the behavior behind a flag (but make it on by default!)

  • JSON string output doesn't have to match exactly as long as it parses the same.

  • Be explicit in Dense Representation. I'd rather have a null value than a missing key (see xDelta).

  • When in doubt, do what Townscaper does.

  • yarn test shouldn't break, and you should add the relevant tests (if any) to your changes.

  • yarn test:diff outputs a test set into the test_out folder. Inspect differences (if any) in git diff to check that everything is working as intended. Feel free to add tests cases if needed. Remember to commit test_out so we can use git diff with your changes!

TODO

  • The grid is irregular and we need it if we want to generate valid coordinates. Chris Love has done some research on this (Twitter thread).

    Even though eventually the grid size is locked when you build enough, it's actually infinite. To see it in action, scroll before building any blocks.

    Some people have shared filled patches, and the code in http://scriptology.de/townscaper.html has a list of valid corners, but they are just a limited set. This library used to have a VALID_CORNERS list too but it was from a specific filled patch (before I realized the grid limits were arbitrary and procedurally infinite).

    I'd rather not encourage using a specific patch, hence why I removed the VALID_CORNERS. For now you'll have to generate your own list of valid corners if needed, but ideally we'd understand the algorithm.

    See https://www.youtube.com/watch?v=1hqt8JkYRdI for more info.

    • Maybe use this to check if corners are valid in dense and sparse (from and to)?
  • Test: denseToBits missing cases

  • Maybe don't implicitly remove empty corners and warn intead? Applies to various conversions in dense, sparse, bits.

    • This might require having a warning system versus just throwing.
  • Maybe be more lenient with input as long as it doesn't break output (e.g. from dense to sparse, why not accept too many types?) On the other hand, it might help catch bugs.

    More instances: accept 0 or undefined when expecting null, etc.

  • Online version for people that can't/won't use the CLI.

  • Some kind of random generator to showcase the possibilities.

  • /dev/clipboard example (what about MINGW64? I've been unable to make Node's stdout work)

  • Move test:diff to Jest

  • Remove trailing -1s in bitsToDense and denseToBits?

    • Can of worms? It would make sense to also do things like sort types in Townscaper order

    • OTOH we're already removing empty corners

    • Annotate might already be broken since bitsToDense might lose information

    • Maybe hide behind --optimize flag, or --no-optimize

You might also like...

front.phone is a Javascript library that identifies, validates and formats phone numbers.

front.phone front.phone is a Javascript library that identifies, validates and formats phone numbers. Demo The main goal of this project is to create

Oct 27, 2022

Formats message strings with number, date, plural, and select placeholders to create localized messages

Formats message strings with number, date, plural, and select placeholders to create localized messages. Small. Between 700 bytes and 1.3 kilobytes (m

Oct 30, 2022

This project is used to extract media from various posting platfroms like Twitter, Reddit, Pixiv, Youtube and many other

Social-Picker-API This project is used to extract media from various posting platfroms like Twitter, Reddit, Pixiv, Youtube and many others. It's writ

Nov 29, 2022

Adds links to Discogs pages from various sites. Auto search for music on torrent and other sites. Does multi auto-search on Artist/Discography pages. Auto search local HDDs/filelists using Voidtools Everything search engine.

Discogs Scout: Adds links to Discogs pages from various sites. Auto search for music on torrent and other sites. Does multi auto-search on Artist/Disc

Dec 27, 2022

Ordered lists, flat or nested, multiple formats ordered lists.

Ordered lists, flat or nested, multiple formats ordered lists.

logseq-plugin-ol 有序列表,单级或多级、多种样式的有序列表。 Ordered lists, flat or nested, multiple formats ordered lists. 使用展示 (Usage) 在想要展示为有序列表的块上添加一个以 #.ol 开头的标签就可以了。有

Jan 1, 2023

Downloads & formats all of your Roblox private messages.

Downloads & formats all of your Roblox private messages.

Roblox Message Downloader This tool was created due to the recent news sent out by Roblox. On April 22nd, 2022, all private messages sent by Roblox be

Apr 7, 2022

devDependency to test feed formats for ssb-db2

ssb-feed-format A tool that you install as a devDependency to check whether your feed format for SSB is correct and ready to be installed in ssb-db2.

Jun 18, 2022

Chromium extension for displaying all the available formats of an AppleMusic album.

Chromium extension for displaying all the available formats of an AppleMusic album.

AppleMusic-Formats-Extension Chromium extension for displaying all the available formats of an AppleMusic album. Before Vs After How to Install? From

Dec 16, 2022

Markdown Transformer. Transform markdown files to different formats

Mdtx Inspired by generative programming and weed :). So I was learning Elm language at home usually in the evening and now I am missing all this gener

Jan 2, 2023

A tool for collecting data and access camera, microphone and location and clipboard via link.

Snow Build malicious links. A tool for collecting data and access camera, microphone and location and clipboard via link.

Dec 12, 2022

A generative engine that takes various png layers on a sprite sheet format, combines them and then converts them into a .gif file

A generative engine that takes various png layers on a sprite sheet format, combines them and then converts them into a .gif file

Welcome to the Generative GIF Engine v2.0.4 🐤 [8 minute read] This python and node app generates layered-based gifs to create NFT gif art! It is fast

Jan 2, 2023

A generative engine that takes various png layers on a sprite sheet format, combines them and then converts them into a .gif file

A generative engine that takes various png layers on a sprite sheet format, combines them and then converts them into a .gif file

Welcome to the Generative Animated Engine v3.0.1 🐤 [8 minute read] This repo used to be called jalagar/Generative_Gif_Engine but because it now suppo

May 24, 2022

blog with angular made in sass and firebase auth with google, facebook and github also you can copy to clipboard

blog with angular made in sass and firebase auth with google, facebook and github also you can copy to clipboard

BlogAngular This project was generated with Angular CLI version 14.1.2. Development server Run ng serve for a dev server. Navigate to http://localhost

Oct 2, 2022

A fast and powerful http toolkit that take a list of domains to find active domains and other information such as status-code, title, response-time , server, content-type and many other

A fast and powerful http toolkit that take a list of domains to find active domains and other information such as status-code, title, response-time , server, content-type and many other

HTTPFY curently in beta so you may see problems. Please open a Issue on GitHub and report them! A Incredible fast and Powerful HTTP toolkit Report Bug

Dec 22, 2022

ln-charts parses the output of bos accounting commands into various charts for your Lightning Node.

ln-charts parses the output of bos accounting commands into various charts for your Lightning Node.

ln-charts ln-charts parses the output of bos accounting commands into various charts for your Lightning Node. It runs on Angular, JS, HTML, CSS, ngx-c

Dec 18, 2022

A simple way to share files and clipboard within a local network.

Shortcut Simple way to share files and clipboard with devices within a local network. Usage Run the ./shortcut executable. A browser window will be op

Mar 13, 2022

Lightweight library to copy PNG and JPG images to clipboard

Copy Image Clipboard Created with ❤️ by Luan Eduardo da Costa | Follow me on Linkedin 📃 About This library allows you to copy JPG and PNG images (onl

Nov 29, 2022

cross-platform Deno library for writing and reading clipboard.

deno-clippy This is cross-platform Deno library for writing and reading clipboard. You can read from/write image and text. This library uses Rust's ar

Dec 3, 2022

:clipboard: A schema-based form generator component for Vue.js

:clipboard: A schema-based form generator component for Vue.js

vue-form-generator A schema-based form generator component for Vue.js. Demo JSFiddle simple example CodePen simple example Features reactive forms bas

Dec 27, 2022
Owner
Álvaro Cuesta
Code is life. Rust. JavaScript, TypeScript, React. Music. Art.
Álvaro Cuesta
Knwl.js is a Javascript library that parses through text for dates, times, phone numbers, emails, places, and more.

Knwl.js Knwl.js is a Javascript library that parses through text for dates, times, phone numbers, emails, places, and more. Project Future The future

Ben Moore 5.3k Jan 1, 2023
Clock and task scheduler for node.js applications, providing extensive control of time and callback scheduling in prod and test code

#zeit A node.js clock and scheduler, intended to take place of the global V8 object for manipulation of time and task scheduling which would be handle

David Denton 12 Dec 21, 2021
A JavaScript library for binding keyboard combos without the pain of key codes and key combo conflicts.

KeyboardJS KeyboardJS is a library for use in the browser (node.js compatible). It Allows developers to easily setup key bindings. Use key combos to s

Robert Hurst 2k Dec 30, 2022
A javascript based whatsapp bot for downloading and sending media from youtube and facebook in different formats alongwith couple of other features.

Whatsmazan Available Features Downlaod youtube mp4 Video and send Downlaod youtube mp3 audio and send Search something from youtube Downlaod facebook

mazan labeeb 10 Oct 30, 2022
A Virtual Interactive Keyboard which replicates every key you press and a Text-Area in which everything is written and can be copied to the clipboard with a click of a button.

A Virtual Interactive Keyboard which replicates every key you press and a Text-Area in which everything is written and can be copied to the clipboard with a click of a button.

Devang Joshi 1 Mar 1, 2021
This project will be using various AI and Rule Engine algorithm to detect various attack against a company!

?? Introduction This project will be using various AI and Rule Engine algorithm to detect various attack against a website! ?? Mission After starting

Harish S.G 4 Apr 29, 2022
easier than regex string matching patterns for urls and other strings. turn strings into data or data into strings.

url-pattern easier than regex string matching patterns for urls and other strings. turn strings into data or data into strings. This is a great little

null 562 Jan 5, 2023
Obsidian plugin: Type text shortcuts that expand into javascript generated text.

Obsidian Plugin - Text Expander JS (open beta) This Obsidian plugin allows the user to type text shortcuts that are replaced by (or "expanded into") j

Jon Heard 79 Dec 27, 2022
Random Fractals stash of Observable Data Tools 🛠️ and Notebooks 📚 in ES Modules .js, .nb.json, .ojs, .omd, .html and .qmd document formats for Data Previews

Random Fractals stash of Observable Data Tools ??️ and Notebooks ?? in ES Modules .js, .nb.json, .ojs, .omd, .html and .qmd document formats for Data Previews in a browser and in VSCode IDE with Observable JS extension, Quarto extension, and new Quarto publishing tools.

Taras Novak 14 Nov 25, 2022