Skip to content

Commit

Permalink
Version 0.1.1 - generate frame animations, PNG to GIF converter
Browse files Browse the repository at this point in the history
  • Loading branch information
gesior committed Jun 11, 2020
1 parent 4b473e5 commit 447c9eb
Show file tree
Hide file tree
Showing 19 changed files with 2,087 additions and 1,430 deletions.
42 changes: 42 additions & 0 deletions itemImageFramesGenerator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<html>
<head>
<title>Item Image Frames Generator - OpenTibiaLibrary</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
</head>
<body>
<h2>Item image frames generator (for animated items PHP script)</h2>
<blockquote>
How to use:<br/><br/>
1. Type version of Tibia client.<br/>
2. Select SPR, DAT and OTB files.<br/>
3. Click "LOAD FILES", watch "Progress".<br/>
4. Click "GENERATE IMAGES", wait for ZIP file download.<br/>
5. Convert generated PNG images into animations using:<br/>
<a href="https://item-images.ots.me/png-to-gif-converter/">https://item-images.ots.me/png-to-gif-converter/</a><br/>
You can also download <a href="https://github.com/gesior/open-tibia-library">https://github.com/gesior/open-tibia-library</a>
and use command line PHP script <b>"tools/item-image-frames-to-animated-gif-converter/cli_convert.php"</b>
to convert it to animations on your PC<br/>
<br/>
<b>FILES ARE NOT SEND TO SERVER! EVERYTHING IS GENERATED ON YOUR COMPUTER.</b><br/>
<br/>
(Enable Developer console in webbrowser to get more information about problems/progress)
</blockquote>
Client Version: <input type="number" id="clientversion" value="860"/> (format 860, NOT 8.60)<br/>
Sprite file: <input type="file" id="spr"/><br/>
Dat file: <input type="file" id="dat"/><br/>
Otb file: <input type="file" id="otb"/><br/>
Only pickable items: <input type="checkbox" id="onlyPickupable" checked/><br/>
Force enable extended sprites: <input type="checkbox" id="forceEnableExtendedSprites"/> (for old clients .dat and .spr
with this feature enabled)<br/>
<br/>
<button id="loadFiles">LOAD FILES</button>
<br/>
<br/>
<button id="generateImages">GENERATE IMAGES</button>
<br/>
<br/>
<b>Progress:</b> <span id="progressBar">Not running</span><br/>
<script src="js/vendor.js"></script>
<script src="js/itemImageFramesGenerator.js"></script>
</body>
</html>
111 changes: 111 additions & 0 deletions itemImageFramesGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {DatManager} from "./modules/datFile/datManager";
import {OtbManager} from "./modules/otbFile/otbManager";
import {SpriteManager} from "./modules/sprFile/spriteManager";
import {ImageGenerator} from "./modules/imageGenerator/imageGenerator";
import {GameFeature} from "./modules/constants/const";
import {WebsiteImageGeneratorBase} from "./websiteImageGeneratorBase";

class ItemImageGenerator extends WebsiteImageGeneratorBase {
private onlyPickupableCheckbox: HTMLInputElement;
private forceEnableExtendedSpritesCheckbox: HTMLInputElement;

private onlyPickupable = true;
private forceEnableExtendedSprites = false;

init() {
super.init();
this.onlyPickupableCheckbox = <HTMLInputElement>document.getElementById('onlyPickupable');
this.forceEnableExtendedSpritesCheckbox = <HTMLInputElement>document.getElementById('forceEnableExtendedSprites');
}

afterSetClientVersion() {
if (this.forceEnableExtendedSpritesCheckbox.checked) {
this.client.enableFeature(GameFeature.GameSpritesU32);
}
}

startImageGenerator(imageGenerator: ImageGenerator, otbManager: OtbManager, datManager: DatManager, spriteManager: SpriteManager, zip) {
this.onlyPickupable = this.onlyPickupableCheckbox.checked;
this.generateItemImage(imageGenerator, zip, 0);
}

generateItemImage(imageGenerator: ImageGenerator, zip, serverId: number) {
const self = this;
this.progressValue(serverId, this.otbManager.getLastId());
if (serverId > this.otbManager.getLastId()) {
this.progressText('Packing images to ZIP file, please wait (it may take a while)');
zip.generateAsync({type: "blob"}).then(function (blob: Blob) {
console.log('zip size', blob.size);
self.progressText('ZIP generated, it should start download now.');
self.downloadBlob('items.zip', blob);
});
return;
}

if (!this.otbManager.isValidOtbId(serverId)) {
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);
return;
}

const clientItemId = this.otbManager.getItem(serverId).getClientId();
if (!clientItemId) {
console.log('otb ID not mapped to any dat ID', serverId);
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);
return;
}
let itemThingType = this.datManager.getItem(clientItemId);
if (!itemThingType) {
console.log('dat ID not found in dat file', serverId, clientItemId);
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);
return;
}
if (this.onlyPickupable && !itemThingType.isPickupable()) {
console.log('skip not pickupable', serverId);
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);
return;
}

const itemSprites = imageGenerator.generateItemImagesByServerId(serverId);
if (!itemSprites || itemSprites.length == 0) {
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);
return;
}

const firstItemSprite = itemSprites[0];
const canvas = <HTMLCanvasElement>document.createElement('canvas');
canvas.width = firstItemSprite.getWidth() * itemSprites.length;
canvas.height = firstItemSprite.getHeight();
document.getElementsByTagName('body')[0].appendChild(canvas);
const ctx = canvas.getContext("2d");

for (let animationFrame = 0; animationFrame < itemSprites.length; animationFrame++) {
const palette = ctx.getImageData(firstItemSprite.getWidth() * animationFrame, 0, firstItemSprite.getWidth(), firstItemSprite.getHeight());
const itemSprite = itemSprites[animationFrame];
palette.data.set(new Uint8ClampedArray(itemSprite.getPixels().m_buffer.buffer));
ctx.putImageData(palette, firstItemSprite.getWidth() * animationFrame, 0);
}

const callback = function (blob) {
canvas.remove();
zip.file('items/' + serverId + '_' + itemSprites.length + '.png', blob);
setTimeout(function () {
self.generateItemImage(imageGenerator, zip, serverId + 1);
}, 1);

};
canvas.toBlob(callback);
}
}

const itemImageGenerator = new ItemImageGenerator();
itemImageGenerator.init();
52 changes: 24 additions & 28 deletions itemImageGenerator.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,36 @@
<head>
<title>Item Image Generator - OpenTibiaLibrary</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<style>
* {
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
image-rendering: crisp-edges;
}
</style>
</head>
<body>
<h2>Item images generator</h2>
<blockquote>
How to use:<br /><br />
1. Type version of Tibia client.<br />
2. Select SPR, DAT and OTB files.<br />
3. Click "LOAD FILES", watch "Progress".<br />
4. Click "GENERATE IMAGES", wait for ZIP file download.<br />
<br />
<b>FILES ARE NOT SEND TO SERVER! EVERYTHING IS GENERATED ON YOUR COMPUTER.</b><br />
<br />
How to use:<br/><br/>
1. Type version of Tibia client.<br/>
2. Select SPR, DAT and OTB files.<br/>
3. Click "LOAD FILES", watch "Progress".<br/>
4. Click "GENERATE IMAGES", wait for ZIP file download.<br/>
<br/>
<b>FILES ARE NOT SEND TO SERVER! EVERYTHING IS GENERATED ON YOUR COMPUTER.</b><br/>
<br/>
(Enable Developer console in webbrowser to get more information about problems/progress)
</blockquote>
Client Version: <input type="number" id="clientversion" /> (format 860, NOT 8.60)<br />
Sprite file: <input type="file" id="spr" /><br />
Dat file: <input type="file" id="dat" /><br />
Otb file: <input type="file" id="otb" /><br />
Only pickable items: <input type="checkbox" id="onlyPickupable" checked/><br />
<br />
<button id="loadFiles">LOAD FILES</button><br />
<br />
<button id="generateImages">GENERATE IMAGES</button><br />
<br />
<b>Progress:</b> <span id="progressBar">Not running</span><br />
Client Version: <input type="number" id="clientversion" value="860"/> (format 860, NOT 8.60)<br/>
Sprite file: <input type="file" id="spr"/><br/>
Dat file: <input type="file" id="dat"/><br/>
Otb file: <input type="file" id="otb"/><br/>
Only pickable items: <input type="checkbox" id="onlyPickupable" checked/><br/>
Force enable extended sprites: <input type="checkbox" id="forceEnableExtendedSprites"/> (for old clients .dat and .spr
with this feature enabled)<br/>
<br/>
<button id="loadFiles">LOAD FILES</button>
<br/>
<br/>
<button id="generateImages">GENERATE IMAGES</button>
<br/>
<br/>
<b>Progress:</b> <span id="progressBar">Not running</span><br/>
<script src="js/vendor.js"></script>
<script src="js/itemImageGenerator.js"></script>


</body>
</html>
Loading

0 comments on commit 447c9eb

Please sign in to comment.