Closed andrewtheone closed 7 years ago
Hey!
a. This is planned eventually, but not in yet.
b. The engine currently keeps a name->id hash, but not the other way around, so there's no way to query a block name. This would be a straightforward feature if you want to try adding it though - all relevant code is inside /lib/registry
. Or the alternative is to just keep an id->name hash in your client code.
Thanks for all your help, here is my little contribution to the project, its a little library to manage blocks and block data. It can set block at world from 3 different type of argument.
{
name: 'material_name', // will be accessible via 'mat_material_name' hence: it gets a mat_ prefix
texture: 'texture.jpg', // or null
color: [1,1,1, 0.5], // or null
block_data_a: 'value',
block_data_b: 'value2' //these are accessible via BlockManager.getData(blockId) if it this object was passed to BlockManager.setBlock(pos, value, true), otherwise you have to call BlockManager.setData(blockID, data_object)
/*etc*/
}
Library code
var BlockManager = function(noa) {
this.noa = noa;
this.blockData = {};
this.textures = {}; //by name
this.textureIDMap = {}; //by id to name
}
BlockManager.prototype.addTexture = function(name, color, texture) {
name = 'mat_'+name;
console.log("Adding texture: "+name+", color: "+color+", texture: "+texture);
this.noa.registry.registerMaterial(name, color, texture)
var id = this.textures[name] = this.noa.registry.registerBlock(name, name);
this.textureIDMap[id] = name;
return id;
}
BlockManager.prototype.setData = function(blockId, data) {
this.blockData[blockId] = data;
}
BlockManager.prototype.hasTexture = function(name_or_id) {
if(typeof name_or_id == "string") {
return (this.textures.hasOwnProperty(name_or_id));
}
return (this.textureIDMap.hasOwnProperty(name_or_id));
}
BlockManager.prototype.getTextureID = function(name) {
return this.textures[name];
}
BlockManager.prototype.getData = function(blockId) {
return (this.blockData.hasOwnProperty(blockId)?this.blockData[blockId]:{});
}
BlockManager.prototype.setBlock = function(position, value, doSetData) {
var original_value = null;
if(typeof value == "object") {
original_value = value;
var possibleTextureName = "mat_"+value.name;
if(!this.hasTexture(possibleTextureName)) {
value = this.addTexture(possibleTextureName, (value.color?value.color:[1,1,1]), value.texture);
} else {
value = this.getTextureID(possibleTextureName);
}
// if texture name exists, then we modify value to possibleTextureName and let the algorithm go forward
}
if(typeof value == "string") {
value = this.getTextureID(value);
}
this.noa.setBlock(value, position);
var blockId = this.noa.world.getBlockID(position[0], position[1], position[2]);
if(doSetData == true) {
this.setData(blockId, original_value);
}
return blockId;
}
module.exports = BlockManager;
I have extended the above code with texture caching:
It uses: https://github.com/psayre23/WebSQL
TextureDB.js
var TextureDB = function(noa) {
this.noa = noa;
this.db = WebSQL('site');
this.db.query('CREATE TABLE textures (url, data)');
}
TextureDB.prototype.getBase64 = function(url, callback) {
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
if(typeof window.base64Canvas == "undefined")
window.base64Canvas = document.createElement('CANVAS');
var ctx = window.base64Canvas.getContext('2d');
var dataURL;
window.base64Canvas.height = this.height;
window.base64Canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = window.base64Canvas.toDataURL('image/png');
callback(dataURL);
};
img.src = url;
}
TextureDB.prototype.getTexture = function(texture, cb) {
if(texture == null) {
cb(null);
return;
}
this.db.query('SELECT data from textures where url = ?', [texture]).done(function(rows) {
if(rows.length == 0) {
this.getBase64(texture, function(data) {
this.db.query('INSERT INTO textures (url, data) VALUES (?,?)', [texture, data]);
cb(data);
}.bind(this))
return;
}
cb(rows[0].data);
}.bind(this))
}
module.exports = TextureDB;
BlockManager.js
var db = require('./texturedb.js');
var BlockManager = function(noa) {
this.noa = noa;
this.db = new db(this.noa);
this.blockData = {};
this.textures = {}; //by name
this.textureIDMap = {}; //by id to name
}
BlockManager.prototype.addTexture = function(name, color, texture, cb) {
var self = this;
this.db.getTexture(texture, function(data) {
self.noa.registry.registerMaterial(name, color, data)
var id = self.textures[name] = self.noa.registry.registerBlock(name, name);
self.textureIDMap[id] = name;
if(cb) cb(id);
})
}
BlockManager.prototype.setData = function(blockId, data) {
this.blockData[blockId] = data;
}
BlockManager.prototype.hasTexture = function(name_or_id) {
if(typeof name_or_id == "string") {
return (this.textures.hasOwnProperty(name_or_id));
}
return (this.textureIDMap.hasOwnProperty(name_or_id));
}
BlockManager.prototype.getTextureID = function(name) {
return this.textures[name];
}
BlockManager.prototype.getData = function(blockId) {
return (this.blockData.hasOwnProperty(blockId)?this.blockData[blockId]:{});
}
BlockManager.prototype.setBlock = function(position, value, cb) {
if(typeof value == "object") {
var possibleTextureName = value.name;
if(!this.hasTexture(possibleTextureName)) {
var self = this;
this.addTexture(possibleTextureName, (value.color?value.color:[1,1,1]), value.texture, function(mat_id) {
self.setBlock(position, mat_id, cb);
});
return;
} else {
value = this.getTextureID(possibleTextureName);
}
// if texture name exists, then we modify value to possibleTextureName and let the algorithm go forward
}
if(typeof value == "string") {
value = this.getTextureID(value);
}
this.noa.setBlock(value, position);
if(cb) cb(this.noa.world.getBlockID(position[0], position[1], position[2]))
}
module.exports = BlockManager;
And you have to edit rendering.js:515 to:
var tex = new BABYLON.Texture(url, self._scene, true,false, BABYLON.Texture.NEAREST_SAMPLINGMODE, null, null, url)
because of WebSQL I had to use asyncronous calls
Hey, sorry for leaving this in limbo so long; it dropped off my radar before I had time to review it. It's certainly interesting but I'd like to avoid adding a dependency on webSQL, and also Babylon caches textures internally as I understand it. If game clients want to have a robust DB-like way to manage materials, I think that code probably should live in the game client rather than inside the engine. Thanks for posting the code though!
Hey!
What are the opportunities to a, store addition block data and retrieve by block id b, get the name of block material ?