Showing posts with label abiathar-online. Show all posts
Showing posts with label abiathar-online. Show all posts

Thursday, June 15, 2017

Abiathar Online - Render links

Sometimes I open up levels in Abiathar just to see where the switches and doors go. I've been missing that feature in Abiathar Online. So today, I updated it to have a "draw links" checkbox, which when checked causes infoplane values greater than 255 to render as links. It uses the traditional Abiathar line style and color.


As far as I can tell, it renders identically to the real Abiathar links except that the connecting lines are antialiased.

Updating the level when links are showing is much slower because the entire level has to be rerendered (there might be a link crossing) due to the lack of planes. I will see about the possibility of having multiple canvases on top of each other.

There is currently no convenient way to create a link, but showing links is progress. The changes are live - check it out online!

Monday, June 5, 2017

Abiathar Online - Enter ID

The desktop Abiathar program has long had the ability to enter a tile ID to select it. That's a fairly simple feature and one that comes in handy occasionally, so today I added it to Abiathar Online. Clicking the selected tile image for a plane brings up the ID entry form. A "hexadecimal" check box controls whether the text box's contents should be treated as hex.

I also removed the copy-pasted plane control HTML in favor of generating in with JavaScript. That way, it'll be easier and less repetitive to add more plane-related features.

Sunday, June 4, 2017

Abiathar Online - Graphics fixed on Chrome

The last time I worked on Abiathar Online, I found that its graphics were messed up on Chrome - the first time a tile was requested, it wouldn't necessarily display until the level was refreshed. I'm still not sure why it was doing that, or why it worked before, but today I made a change that fixed the problem. This Stack Overflow answer taught me that I don't have to make an Image out of the temporary canvas before using it to draw on the main one. Canvases can be drawn on other canvases just fine. So I switched to caching canvases, only converting them to Base64 URLs when displaying them in the selected tile bay. Abiathar Online now appears as it should in both Chrome and Edge.

Tuesday, May 30, 2017

Abiathar Online - Open by link

It might be useful for people to share links to Abiathar Online level sets so that others can easily browse or fork the levels. So today I added a bit of code that checks for query parameters on the load of the editor page. If all four resources are specified there, the level editing mode launches. It even takes an optional parameter to set the ID of the level to show first.

All of that works perfectly fine, but I started seeing weird graphical artifacts today - it's like only a few tiles get carved out and the rest need a refresh of the level to show up properly. I didn't change anything related to the graphics, and I didn't test before making my changes, and everything looks fine in Edge, so maybe there's something up with Chrome. I will investigate.

Monday, January 2, 2017

Abiathar Online - Remember the scroll position

The real Abiathar remembers the viewport positioning of each level when switching between them. That's especially important when going to the tileset to fetch a tile; resetting the level view back to the upper left upon return is jarring. So today I made Abiathar Online keep track of the scrollbar positions for each level and tileset. It required a little refactoring to make sure that all "change the current level" calls go through the part that stores the current X and Y in the level, but overall it was an easy and worthwhile change, and is now live on GitHub.

Sunday, January 1, 2017

Abiathar Online - Dropbox Saver now supports data URLs

Over a year ago, when I last tinkered with Abiathar Online (the web-based Keen Galaxy editor), I was greatly inconvenienced by the Dropbox Saver's inability to deal with data URLs. Without those, I had to put up a server to store the files until Dropbox can download them.

As of several months ago, that feature has finally been added! I already updated Abiathar Online to make use of it, so I can dispose of the echo server's code. The only parties involved in Abiathar Online I/O are now just the client web page and Dropbox.

The changes are live on GitHub.

Thursday, August 20, 2015

Abiathar Online - Actually Online

Today I read up on GitHub Pages, which is GitHub's web hosting service. Each repository (project) can have a special branch that contains the project's web page(s). I created that branch after some fiddling around with the command line, and copied the important client-side files into it. My plan for that branch is to update it only when I have a "stable" release or a milestone; day-to-day development will be done on the main "master" branch.

So, Abiathar Online is actually online now, and you can try it if you like. (Requires a Dropbox account, and existing level files. Those requirements may eventually be lifted.) I noticed that it's kind of broken on mobile devices, so my next goal is to address that.

Wednesday, August 19, 2015

Abiathar Online - Saving!

After yesterday's discovery of URL length limitations, I had to figure out some way to get the level data to Dropbox via a real URL but not in the query string. Some thinking and two quick-and-dirty PHP scripts later, I had a way to upload levels and a page that Dropbox can hit to download them, which causes the server to delete the file to save space. Unique IDs for each file are generated by JavaScript. Security isn't super tight (this is PHP after all), but I do prefix the filenames with "OpenThar" to prevent easy exploits, and if it gets hacked, nothing is lost.

Some problems were had in the XMLHttpRequest upload. At first I didn't realize that the equals signs sometimes added by Base64 could cause issues for x-www-form-urlencoded data. That was easily solved with an encodeURIComponent call in JavaScript. Then there was the baffling issue of the XHR's readyState property always being 1. Apparently, that property will not work correctly in Chrome if any of the following are true:
  • The server doesn't send all of the necessary headers (I had PHP explicitly set the Access-Control-Allow-Origin header so the JavaScript could export data to it)
  • No handler is hooked up to the onreadystatechange event (a while loop that checks the state will not work)
  • The main thread is busy (e.g. in an infinite loop, or waiting for the state to change)
I thought at first that the Dropbox Saver wouldn't appear if I had its invocation in an XMLHttpRequest completion handler, but it seems to be working. If it doesn't, people can just add an exception in their pop-up blocker for my place.

After a good while of fiddling around with JavaScript and PHP, I finally got it to save to my Dropbox. There was a bit of corruption in the level headers in the GAMEMAPS, but I think that was from the lack of URL encoding, which has since been added. I added some extra padding at the end just in case. It seems to be working consistently now. Abiathar Online can load, modify, and save levels!

Tuesday, August 18, 2015

Abiathar Online - Saving, Kind Of

Today I hammered out the level serialization code for Abiathar Online. Data arrangement and compression were easy thanks to my already having implemented them in FleexCore2. However, there was still the problem of how to get the data to Dropbox.

I did indeed decide to take advantage of a free PHP host to perform the conversion/echo of a Base64 query string to a binary response. One quick PHP script later (my first ever), I had an echo server up and running. Well, it was almost that simple. The hosting service injects a bit of HTML and JavaScript so they can provide me with analytics, but the snippet was getting injected into binary files as well, which is clearly not good. I fixed the problem with an exit; statement to halt execution after dumping the binary data down the wire.

The echo server is available at abiathar.site40.net/echo.php?data= (fill in your own Base64 data after the equals sign). For good measure, I had it also supply a downloaded file name, which can be specified with a filename parameter.

I wired up the serialization function to the Dropbox Saver and the PHP server, and quickly discovered that there is definitely a limit on URL length. The URL for the main maps file is so long that even Chrome won't display the entire thing, no matter how hard I try to scroll right in the address bar. The map header one works, though, and came out unscathed by the long process it went through! Tomorrow I will have to think of something clever to get around this URL length problem.

Monday, August 17, 2015

Abiathar Online - Functional Tile Palette

Today I added four lines of code to the mouseHappened function to handle clicks on the tile palette. That means it is now possible to choose tiles from the tilesets and place them in levels, the main activity in level editing. Sadly, switching between the level and tilesets is rather slow; Abiathar-style caching will almost certainly be necessary.

While I was not writing those four lines, I was researching binary file management for the saving component, which is pretty important for level editors. Dropbox still doesn't support data URLs in the Saver, the Datastore API which looked nice is deprecated, and the Core API is super complicated. It seems that I'll need an echo server to bounce data off of, but I cannot find a public server that does what I need.

Therefore, I have started researching PHP. PHP as a language is the exact opposite of everything I find reasonable, but there are ten zillion free hosting sites for PHP and none for ASP.NET, which I would strongly prefer. Fortunately, I'll only need to write a single PHP script to parse a URL- or Base64-encoded query string and respond with a binary file containing that data.

Sunday, August 16, 2015

Abiathar Online - Basic Editing, Now With Less Bafflement!

I noticed that in addition to the strange non-cursor-changing of links, the standard Chrome scrollbar had stopped functioning for Abiathar Online - it was there, but it could not be moved, but the arrow keys worked fine. I tried switching the context menu preventer to use only event.preventDefault() rather than doing that and returning false (which I read was problematic), and suddenly everything worked. The scrollbar was fixed, the cursor went back to normal, and best of all the canvas events started working again.

I then noticed that simply clicking (rather than holding/dragging) on the canvas did not result in actions being taken. That's a problem, especially for people who - unlike me - use a real mouse instead of a pen&touch. So I wired up a new event handler that translates the button values (which are for whatever reason different than those used in mouse-move events) into IDs that can be used in the main handler. When I tested it, I found that the strange symptoms had returned. Commenting out the handler wireup didn't help, but after a couple attempts at fiddling, Chrome froze and then crashed. When it came back up, it had apparently updated, and suddenly everything was working correctly. Maybe the problems weren't my fault!

Finally, I realized that having the tile IDs in the selected tile bay is actually very useful (e.g. to disambiguate bogus blanks from the zero tile). After a good while of fiddling with CSS, I got a monospaced hex representation displaying in the upper-right of each bay.

Abiathar Online now has basic tile tweaking functionality. Next, I'll see about getting tile palettes working.

Saturday, August 15, 2015

Abiathar Online - Editing Time

I started working on the editing parts of Abiathar Online, that is, the code that allows picking up and tweaking tiles. I am using the mousemove event of the canvas element to process user input, but I have run into some very strange problems. The context menu preventer (returning false from a contextmenu event) does not appear to work, but it does if I set that same anonymous function to the oncontextmenu property of the canvas. The mouse movement handler was working at one point, then it suddenly decided to only fire once for each level, and now it has stopped working completely. I do not understand.

I learned that the comparison operators have higher precedence than the bitwise operators, which is weird. Oh, and I no longer get the hand cursor over links on the editor page. I have no idea what I did to make that happen.

Wednesday, August 12, 2015

Abiathar Online - Tileset Rendering and Keyboard Shortcuts

The only "// TODO" comment I had after yesterday's development on Abiathar Online was in renderLevel, specifically in the branch that should display the tileset (tile palette). Rendering the tile palette requires knowing how many tiles there are, so I also added a little code to editorReady to figure out the number of tiles based on the tile sheet height and width (that is, which graphics program created it). I decided that 14 infoplane rows ought to be enough for anybody, and declared the number of infoplane icons to be constant: 252.

I then learned about DOM events to add a key-down handler. I basically copied Abiathar's plane state management key layout; 1-3 toggle editability, 4-6 toggle visibility, 7-9 show the tileset, and 1-3/4-6 show the tileset if a different tileset is already showing. PageUp and PageDown do exactly what they do in Abiathar (move between levels), as does Space (switch between last-seen level and last-seen tileset). The tilde shows the level list, but I don't know how I would make keyboard shortcuts for a variable number of levels, so the mouse still has to select which level to switch to.

I also noticed that Abiathar Online works very nicely as a full-screen web page. I'll try to make sure a good editing experience is always had in that mode.

Tuesday, August 11, 2015

Abiathar Online - Plane Controls

Today I made some serious additions to Abiathar Online's top pane, which is internally (and in my mind) called the editBar. There is now an Abiathar-style tile bay for each plane (using the inline-block CSS display type about which I learned today), containing an image for the selected tile, a label for the plane state, links to change the plane state, and a link to the tileset. When the tileset is showing, a new link appears above the current-level label to return to the level. There is not currently a way to change the selected tile, but I have the JavaScript function in place to deal with it.

I updated the renderer to respect plane states; it will no longer show hidden planes. I think that means I've completed all the important "reading" parts of a level editor, so next I'll have to get to "writing" features.

Monday, August 10, 2015

Abiathar Online - Level Viewing

The only thing missing from level rendering after my initial implementation yesterday was the hex composites for infoplane values that are not icons (very high values like FA17h, as seen in links). Today I wrote that part of carveImage. It uses a small "tileset" image containing the nybble images used in Abiathar.

I then gave function to the Switch Level link. When clicked, it hides the level-viewing canvas and shows a div containing a link for each level. (The level switching event handler was a bit tricky because JavaScript has no block scoping, only function scope. Combine that with closures and you get problems!) After using that feature to look at some horizontally wide levels, I noticed that the "editbar" div does not stay in view when the page is scrolled. So, I looked up some CSS tweaks to make it stay in one place.

Abiathar Online is now a working level viewer. Next, I'll see about plane states and tweaking tiles.

Sunday, August 9, 2015

Abiathar Online - Decompression and Rendering!

Today I finished up the decompression code for Abiathar Online. It wasn't terribly difficult, especially because I already had a working implementation in FleexCore2 and the ModdingWiki has a good description of the algorithm. There were a couple silly bugs in my first JavaScript implementation, but they were easily fixed with the Chrome debugging tools.

I then started on the tricky part, the rendering. After slapping a <canvas> tag onto editor.aconf, I started writing some drawing code. The new renderLevel method will be responsible for the drawing of levels and tilesets, but today I just wrote the level handling code. All the real work is done in the carveImage function, which carves an individual tile image out of the appropriate tileset and applies transparency as called for. That was actually fairly difficult to accomplish; it required tweaking image data with JavaScript. Getting the locations of tiles based on tile sheet width (i.e. graphics program) was fairly easy since I could copy it from Abiathar.

I have not yet implemented the infoplane hex composite part of carveImage, but everything else (background, foreground, infoplane icons) is rendering! Tomorrow I'll see about those hex composites and get level switching going.


Saturday, August 8, 2015

Abiathar Online - Byte Crunching JavaScript

Since the setup UI for Abiathar Online is done, it's time to start on the map loading code. I added two XMLHttpRequest usages to confirmSetup(), both of which call levelResReady() when complete. The duty of that latter function is to process the maps files and populate the levels array. Writing that function is very difficult because JavaScript doesn't seem to have a nice binary processing API. I'm making do with typed arrays (Uint8Array and Uint16Array). So far I've written the level header processing code (to get the level name and data pointers); next I'll finish the Carmack decompressor. Hopefully it won't be terribly slow.

Friday, August 7, 2015

Abiathar Online - Setup Complete

Today I completed the setup UI for Abiathar Online by writing the manual "pick each file manually" setup path. In that mode, the resource type confirmation table from the automatic path is reused and given a "Pick" link in each filename cell. Each of those links creates a single-select Dropbox Chooser window. I also made the "Launch Editor" button appear on its own line so it doesn't create inconsistencies between the setup paths when the button for the chosen path is removed.

The aforementioned user interface elements, minus the giant "Choose your files" title

I then started investigating JavaScript data processing. It appears that I'm going to have to get the data with an XMLHttpRequest and then get at its data with an ArrayBuffer. I do already have it grabbing the images from Dropbox using the Image class/thing. JavaScript seems to have typed arrays now, at least for certain widths of numbers, so that will help when loading levels.

Thursday, August 6, 2015

Abiathar Online - JavaScript Time

Today I jumped into the scripting component of Abiathar Online, which is definitely going to be the area in which I learn the most. I started implementing the "all together" path of the setup wizard, in which all four required resources are in the same folder and can be loaded in one invocation of the Dropbox Chooser. I got Dropbox file loading working; they have very nice API documentation with useful examples. (Very important for me, since I had no idea how to create a JavaScript object.)

After the four files are chosen, I have some script to identify what resource each file represents from its filename. It then displays its guesses in a table and waits for the user to press a button to confirm that the guesses were correct (or use manual load if they're not, which I haven't built yet). Once I get both setup paths working, I'll be ready to start doing things with HTML5, specifically the canvas.

I also made some adjustments to the CSS to remove the extra space above the main title that was pushing the whole content div down since it's centered vertically. A good deal of tinkering was also required to get the table looking nice, but I like what I have so far.

Tuesday, August 4, 2015

Abiathar Online - CSS Fiddling

Over the last few days I've made a start on Abiathar Online, my first serious foray into web development. What I have so far is a simple stylesheet and a couple pages that look nice but don't do anything yet. I've decided on a simple blue-centered design with square buttons for links/commands and cyan gradients for edges. The main font is Open Sans (embedded with CSS3, look at me with these fancy web features!), with Lucida Console for monospace texts.

There's a start/splash page with two buttons ("learn more" and start) that I'm not sure is actually useful. I guess people can bookmark the actual editor page to get there directly, since the opening of files has to be done on the same page as the editing anyway. No JavaScript has been written yet, but I am almost ready to start putting together the file opener, which is backed by Dropbox.

Check out the GitHub repository if you're interested. I'll take pull requests after the important parts of the application are written.