summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Diebold <flodiebold@gmail.com>2012-11-14 19:59:46 +0100
committerFlorian Diebold <flodiebold@gmail.com>2012-11-14 20:02:44 +0100
commitb0df2b25b2c3b0232a0ace8dcd06b1bb15e69d7a (patch)
tree08bbae956110f6d962ab52041ba7e3070641f084
parent68bdec137909c3b2cdb8f57b60552cc0b8fd0ff0 (diff)
downloadcrawl-ref-b0df2b25b2c3b0232a0ace8dcd06b1bb15e69d7a.tar.gz
crawl-ref-b0df2b25b2c3b0232a0ace8dcd06b1bb15e69d7a.zip
Webtiles: Improve JSON generation functions; always send proper JSON.
-rw-r--r--crawl-ref/source/menu.cc8
-rw-r--r--crawl-ref/source/tileweb-text.cc14
-rw-r--r--crawl-ref/source/tileweb.cc375
-rw-r--r--crawl-ref/source/tileweb.h38
-rw-r--r--crawl-ref/source/webserver/game_data/static/cell_renderer.js18
5 files changed, 260 insertions, 193 deletions
diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc
index 7901fb1749..a55c4490df 100644
--- a/crawl-ref/source/menu.cc
+++ b/crawl-ref/source/menu.cc
@@ -1486,7 +1486,7 @@ void Menu::webtiles_handle_item_request(int start, int end)
tiles.json_close_array();
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void Menu::webtiles_update_item(int index) const
@@ -1511,7 +1511,7 @@ void Menu::webtiles_update_item(int index) const
tiles.json_close_array();
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void Menu::webtiles_update_title() const
@@ -1520,7 +1520,7 @@ void Menu::webtiles_update_title() const
tiles.json_write_string("msg", "update_menu");
webtiles_write_title();
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void Menu::webtiles_update_scroll_pos() const
@@ -1529,7 +1529,7 @@ void Menu::webtiles_update_scroll_pos() const
tiles.json_write_string("msg", "menu_scroll");
tiles.json_write_int("first", first_entry);
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void Menu::webtiles_write_title() const
diff --git a/crawl-ref/source/tileweb-text.cc b/crawl-ref/source/tileweb-text.cc
index 84faad14f5..3dcd349184 100644
--- a/crawl-ref/source/tileweb-text.cc
+++ b/crawl-ref/source/tileweb-text.cc
@@ -172,19 +172,23 @@ void WebTextArea::send(bool force)
{
if (!sending)
{
- tiles.write_message("{msg:'txt',id:'%s'",
+ tiles.write_message("{\"msg\":\"txt\",\"id\":\"%s\"",
m_client_side_name.c_str());
if (force)
- tiles.write_message(",clear:1");
- tiles.write_message(",lines:{");
+ tiles.write_message(",\"clear\":true");
+ tiles.write_message(",\"lines\":{");
sending = true;
}
- tiles.write_message("%u:\"%s\",", y, html.c_str());
+ tiles.json_write_comma();
+ tiles.write_message("\"%u\":\"%s\"", y, html.c_str());
}
}
if (sending)
- tiles.send_message("}}");
+ {
+ tiles.write_message("}}");
+ tiles.finish_message();
+ }
}
void WebTextArea::on_resize()
diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc
index b56ae285f0..c2032b1525 100644
--- a/crawl-ref/source/tileweb.cc
+++ b/crawl-ref/source/tileweb.cc
@@ -149,17 +149,8 @@ bool TilesFramework::initialise()
return true;
}
-void TilesFramework::write_message()
-{
- for (unsigned int i = 0; i < m_prefixes.size(); ++i)
- m_msg_buf.append(m_prefixes[i].data());
- m_prefixes.clear();
-}
-
void TilesFramework::write_message(const char *format, ...)
{
- write_message(); // prefixes
-
char buf[2048];
int len;
@@ -179,7 +170,6 @@ void TilesFramework::write_message(const char *format, ...)
void TilesFramework::finish_message()
{
- m_prefixes.clear();
if (m_msg_buf.size() == 0)
return;
@@ -223,16 +213,8 @@ void TilesFramework::finish_message()
m_msg_buf.clear();
}
-void TilesFramework::send_message()
-{
- write_message();
- finish_message();
-}
-
void TilesFramework::send_message(const char *format, ...)
{
- write_message();
-
char buf[2048];
int len;
@@ -404,28 +386,16 @@ bool TilesFramework::await_input(wint_t& c, bool block)
}
}
-void TilesFramework::push_prefix(const string& prefix)
-{
- m_prefixes.push_back(prefix);
-}
-
-void TilesFramework::pop_prefix(const string& suffix)
-{
- if (!m_prefixes.empty())
- m_prefixes.pop_back();
- else
- write_message("%s", suffix.c_str());
-}
-
-bool TilesFramework::prefix_popped()
-{
- return m_prefixes.empty();
-}
-
void TilesFramework::dump()
{
fprintf(stderr, "Webtiles message buffer: %s\n", m_msg_buf.c_str());
- fprintf(stderr, "Webtiles prefix count: %d\n", (int) m_prefixes.size());
+ fprintf(stderr, "Webtiles JSON stack:\n");
+ for (unsigned int i = 0; i < m_json_stack.size(); ++i)
+ {
+ fprintf(stderr, "start: %d end: %d type: %c\n",
+ m_json_stack[i].start, m_json_stack[i].prefix_end,
+ m_json_stack[i].type);
+ }
}
void TilesFramework::_send_version()
@@ -436,7 +406,7 @@ void TilesFramework::_send_version()
#endif
string title = CRAWL " " + Version::Long();
- send_message("{msg:\"version\",text:\"%s\"}", title.c_str());
+ send_message("{\"msg\":\"version\",\"text\":\"%s\"}", title.c_str());
}
void TilesFramework::push_menu(Menu* m)
@@ -445,7 +415,7 @@ void TilesFramework::push_menu(Menu* m)
mi.menu = m;
m_menu_stack.push_back(mi);
m->webtiles_write_menu();
- tiles.send_message();
+ tiles.finish_message();
}
void TilesFramework::push_crt_menu(string tag)
@@ -460,7 +430,7 @@ void TilesFramework::push_crt_menu(string tag)
json_write_string("type", "crt");
json_write_string("tag", tag);
json_close_object();
- send_message();
+ finish_message();
}
void TilesFramework::pop_menu()
@@ -468,7 +438,7 @@ void TilesFramework::pop_menu()
if (m_menu_stack.empty()) return;
MenuInfo mi = m_menu_stack.back();
m_menu_stack.pop_back();
- send_message("{msg:'close_menu'}");
+ send_message("{\"msg\":\"close_menu\"}");
}
void TilesFramework::close_all_menus()
@@ -483,7 +453,7 @@ static void _send_ui_state(WebtilesUIState state)
tiles.json_write_string("msg", "ui_state");
tiles.json_write_int("state", state);
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void TilesFramework::set_ui_state(WebtilesUIState state)
@@ -549,7 +519,7 @@ static void _send_doll(const dolls_data &doll, bool submerged, bool ghost)
flags[TILEP_PART_BOOTS] = is_cent ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE;
}
- tiles.write_message("doll:[");
+ tiles.json_open_array("doll");
for (int i = 0; i < TILEP_PART_MAX; ++i)
{
@@ -569,35 +539,40 @@ static void _send_doll(const dolls_data &doll, bool submerged, bool ghost)
ymax = 18;
}
- tiles.write_message("[%u,%d],", (unsigned int) doll.parts[p], ymax);
+ tiles.json_write_comma();
+ tiles.write_message("[%u,%d]", (unsigned int) doll.parts[p], ymax);
}
- tiles.write_message("],");
+ tiles.json_close_array();
}
static void _send_mcache(mcache_entry *entry, bool submerged)
{
bool trans = entry->transparent();
if (trans)
- tiles.write_message("trans:true,");
+ tiles.json_write_int("trans", 1);
const dolls_data *doll = entry->doll();
if (doll)
_send_doll(*doll, submerged, trans);
else
- tiles.write_message("doll:[],");
+ {
+ tiles.json_write_comma();
+ tiles.write_message("\"doll\":[]");
+ }
- tiles.write_message("mcache:[");
+ tiles.json_open_array("mcache");
tile_draw_info dinfo[mcache_entry::MAX_INFO_COUNT];
int draw_info_count = entry->info(&dinfo[0]);
for (int i = 0; i < draw_info_count; i++)
{
- tiles.write_message("[%u,%d,%d],", (unsigned int) dinfo[i].idx,
+ tiles.json_write_comma();
+ tiles.write_message("[%u,%d,%d]", (unsigned int) dinfo[i].idx,
dinfo[i].ofs_x, dinfo[i].ofs_y);
}
- tiles.write_message("],");
+ tiles.json_close_array();
}
static bool _in_water(const packed_cell &cell)
@@ -649,30 +624,33 @@ void TilesFramework::_send_cell(const coord_def &gc,
bool force_full)
{
if (current_mc.feat() != next_mc.feat())
- write_message("f:%d,", next_mc.feat());
+ json_write_int("f", next_mc.feat());
if (next_mc.monsterinfo())
_send_monster(gc, next_mc.monsterinfo(), new_monster_locs, force_full);
else if (current_mc.monsterinfo())
- write_message("mon:null,");
+ {
+ json_write_null("mon");
+ }
map_feature mf = get_cell_map_feature(next_mc);
if (get_cell_map_feature(current_mc) != mf)
- write_message("mf:%u,", mf);
+ json_write_int("mf", mf);
// Glyph and colour
ucs_t glyph = next_sc.glyph;
if (current_sc.glyph != glyph)
{
+ json_write_comma();
if (glyph == '\\')
- write_message("g:'\\\\',");
- else if (glyph == '\'')
- write_message("g:'\\'',");
+ write_message("\"g\":\"\\\\\"");
+ else if (glyph == '"')
+ write_message("\"g\":\"\\\"\"");
else
{
char buf[5];
buf[wctoutf8(buf, glyph)] = 0;
- write_message("g:'%s',", buf);
+ write_message("\"g\":\"%s\"", buf);
}
}
if ((current_sc.colour != next_sc.colour
@@ -680,10 +658,10 @@ void TilesFramework::_send_cell(const coord_def &gc,
{
int col = next_sc.colour;
col = (_get_brand(col) << 4) | (col & 0xF);
- write_message("col:%d,", col);
+ json_write_int("col", col);
}
- push_prefix("t:{");
+ json_open_object("t");
{
// Tile data
const packed_cell &next_pc = next_sc.tile;
@@ -698,61 +676,59 @@ void TilesFramework::_send_cell(const coord_def &gc,
{
fg_changed = true;
- write_message("fg:");
+ json_write_name("fg");
_write_tileidx(next_pc.fg);
- write_message(",");
if (fg_idx && fg_idx <= TILE_MAIN_MAX)
- write_message("base:%u,", (unsigned int) tileidx_known_base_item(fg_idx));
+ json_write_int("base", (int) tileidx_known_base_item(fg_idx));
}
if (next_pc.bg != current_pc.bg)
{
- write_message("bg:");
+ json_write_name("bg");
_write_tileidx(next_pc.bg);
- write_message(",");
}
if (next_pc.is_bloody != current_pc.is_bloody)
- write_message("bloody:%u,", next_pc.is_bloody);
+ json_write_bool("bloody", next_pc.is_bloody);
if (next_pc.old_blood != current_pc.old_blood)
- write_message("old_blood:%u,", next_pc.old_blood);
+ json_write_bool("old_blood", next_pc.old_blood);
if (next_pc.is_silenced != current_pc.is_silenced)
- write_message("silenced:%u,", next_pc.is_silenced);
+ json_write_bool("silenced", next_pc.is_silenced);
if (next_pc.is_suppressed != current_pc.is_suppressed)
- write_message("suppressed:%u,", next_pc.is_suppressed);
+ json_write_bool("suppressed", next_pc.is_suppressed);
if (next_pc.halo != current_pc.halo)
- write_message("halo:%u,", next_pc.halo);
+ json_write_int("halo", next_pc.halo);
if (next_pc.is_moldy != current_pc.is_moldy)
- write_message("moldy:%u,", next_pc.is_moldy);
+ json_write_bool("moldy", next_pc.is_moldy);
if (next_pc.glowing_mold != current_pc.glowing_mold)
- write_message("glowing_mold:%u,", next_pc.glowing_mold);
+ json_write_bool("glowing_mold", next_pc.glowing_mold);
if (next_pc.is_sanctuary != current_pc.is_sanctuary)
- write_message("sanctuary:%u,", next_pc.is_sanctuary);
+ json_write_bool("sanctuary", next_pc.is_sanctuary);
if (next_pc.is_liquefied != current_pc.is_liquefied)
- write_message("liquefied:%u,", next_pc.is_liquefied);
+ json_write_bool("liquefied", next_pc.is_liquefied);
if (next_pc.orb_glow != current_pc.orb_glow)
- write_message("orb_glow:%u,", next_pc.orb_glow);
+ json_write_int("orb_glow", next_pc.orb_glow);
if (next_pc.quad_glow != current_pc.quad_glow)
- write_message("quad_glow:%u,", next_pc.quad_glow);
+ json_write_bool("quad_glow", next_pc.quad_glow);
if (next_pc.mangrove_water != current_pc.mangrove_water)
- write_message("swtree:%u,", next_pc.mangrove_water);
+ json_write_bool("mangrove_water", next_pc.mangrove_water);
if (next_pc.blood_rotation != current_pc.blood_rotation)
- write_message("bloodrot:%d,", next_pc.blood_rotation);
+ json_write_int("blood_rotation", next_pc.blood_rotation);
if (next_pc.travel_trail != current_pc.travel_trail)
- write_message("tt:%d,", next_pc.travel_trail);
+ json_write_int("travel_trail", next_pc.travel_trail);
if (_needs_flavour(next_pc) &&
(next_pc.flv.floor != current_pc.flv.floor
@@ -760,10 +736,11 @@ void TilesFramework::_send_cell(const coord_def &gc,
|| !_needs_flavour(current_pc)
|| force_full))
{
- write_message("flv:{f:%d,", next_pc.flv.floor);
+ json_open_object("flv");
+ json_write_int("f", next_pc.flv.floor);
if (next_pc.flv.special)
- write_message("s:%d,", next_pc.flv.special);
- write_message("},");
+ json_write_int("s", next_pc.flv.special);
+ json_close_object();
}
if (fg_idx >= TILEP_MCACHE_START)
@@ -774,7 +751,10 @@ void TilesFramework::_send_cell(const coord_def &gc,
if (entry)
_send_mcache(entry, in_water);
else
- write_message("doll:[[%d,%d]],", TILEP_MONS_UNKNOWN, TILE_Y);
+ {
+ json_write_comma();
+ write_message("\"doll\":[[%d,%d]]", TILEP_MONS_UNKNOWN, TILE_Y);
+ }
}
}
else if (fg_idx == TILEP_PLAYER)
@@ -794,7 +774,8 @@ void TilesFramework::_send_cell(const coord_def &gc,
{
if (fg_changed)
{
- write_message("doll:[[%u,%d]],", (unsigned int) fg_idx, TILE_Y);
+ json_write_comma();
+ write_message("\"doll\":[[%u,%d]]", (unsigned int) fg_idx, TILE_Y);
// TODO: _transform_add_weapon
}
}
@@ -817,13 +798,13 @@ void TilesFramework::_send_cell(const coord_def &gc,
if (overlays_changed)
{
- write_message("ov:[");
+ json_open_array("ov");
for (int i = 0; i < next_pc.num_dngn_overlay; ++i)
- write_message("%d,", next_pc.dngn_overlay[i]);
- write_message("],");
+ json_write_int(next_pc.dngn_overlay[i]);
+ json_close_array();
}
}
- pop_prefix("},");
+ json_close_object(true);
}
void TilesFramework::_send_map(bool force_full)
@@ -833,10 +814,12 @@ void TilesFramework::_send_map(bool force_full)
force_full = force_full || m_need_full_map;
m_need_full_map = false;
- push_prefix("{msg:\"map\",");
+ json_open_object();
+ json_write_string("msg", "map");
+ json_treat_as_empty();
if (force_full)
- write_message("clear:1,");
+ json_write_bool("clear", true);
screen_cell_t default_cell;
default_cell.tile.bg = TILE_FLAG_UNSEEN;
@@ -847,7 +830,7 @@ void TilesFramework::_send_map(bool force_full)
coord_def last_gc(0, 0);
bool send_gc = true;
- push_prefix("cells:[");
+ json_open_array("cells");
for (int y = 0; y < GYM; y++)
for (int x = 0; x < GXM; x++)
{
@@ -870,14 +853,15 @@ void TilesFramework::_send_map(bool force_full)
if (m_origin.equals(-1, -1))
m_origin = gc;
+ json_open_object();
if (send_gc
|| last_gc.x + 1 != gc.x
|| last_gc.y != gc.y)
{
- push_prefix(make_stringf("{x:%d,y:%d,", (x - m_origin.x), (y - m_origin.y)));
+ json_write_int("x", x - m_origin.x);
+ json_write_int("y", y - m_origin.y);
+ json_treat_as_empty();
}
- else
- push_prefix("{");
const screen_cell_t& sc = force_full ? default_cell
: m_current_view(gc);
@@ -889,15 +873,16 @@ void TilesFramework::_send_map(bool force_full)
mc, env.map_knowledge(gc),
new_monster_locs, force_full);
- if (prefix_popped())
+ if (!json_is_empty())
{
send_gc = false;
last_gc = gc;
}
- pop_prefix("},");
+ json_close_object(true);
}
- pop_prefix("]");
- pop_prefix("}");
+ json_close_array(true);
+
+ json_close_object(true);
m_current_map_knowledge = env.map_knowledge;
m_current_view = m_next_view;
@@ -909,13 +894,13 @@ void TilesFramework::_send_monster(const coord_def &gc, const monster_info* m,
map<uint32_t, coord_def>& new_monster_locs,
bool force_full)
{
+ json_open_object("mon");
if (m->client_id)
{
- push_prefix(make_stringf("mon:{id:%d,", m->client_id));
+ json_write_int("id", m->client_id);
+ json_treat_as_empty();
new_monster_locs[m->client_id] = gc;
}
- else
- push_prefix("mon:{");
const monster_info* last = NULL;
map<uint32_t, coord_def>::const_iterator it =
@@ -925,14 +910,14 @@ void TilesFramework::_send_monster(const coord_def &gc, const monster_info* m,
last = m_current_map_knowledge(gc).monsterinfo();
if (last && (last->client_id != m->client_id))
- write_message(); // Force sending at least the id
+ json_treat_as_nonempty(); // Force sending at least the id
}
else
{
last = m_current_map_knowledge(it->second).monsterinfo();
if (it->second != gc)
- write_message(); // As above
+ json_treat_as_nonempty(); // As above
}
if (last == NULL)
@@ -940,37 +925,36 @@ void TilesFramework::_send_monster(const coord_def &gc, const monster_info* m,
if (force_full || (last->full_name() != m->full_name()))
{
- write_message("name:'%s',",
- replace_all_of(m->full_name(), "'", "\\'").c_str());
+ json_write_string("name", m->full_name());
}
if (force_full || (last->pluralised_name() != m->pluralised_name()))
{
- write_message("plural:'%s',",
- replace_all_of(m->pluralised_name(), "'", "\\'").c_str());
+ json_write_string("plural", m->pluralised_name());
}
if (force_full || (last->type != m->type))
{
- write_message("type:%d,", m->type);
+ json_write_int("type", m->type);
// TODO: get this information to the client in another way
- write_message("typedata:{avghp:%d,", mons_avg_hp(m->type));
+ json_open_object("typedata");
+ json_write_int("avghp", mons_avg_hp(m->type));
if (mons_class_flag(m->type, M_NO_EXP_GAIN))
- write_message("no_exp:1,");
- write_message("},");
+ json_write_bool("no_exp", true);
+ json_close_object();
}
if (force_full || (last->attitude != m->attitude))
- write_message("att:%d,", m->attitude);
+ json_write_int("att", m->attitude);
if (force_full || (last->base_type != m->base_type))
- write_message("btype:%d,", m->base_type);
+ json_write_int("btype", m->base_type);
if (force_full || (last->threat != m->threat))
- write_message("threat:%d,", m->threat);
+ json_write_int("threat", m->threat);
- pop_prefix("},");
+ json_close_object(true);
}
void TilesFramework::load_dungeon(const crawl_view_buffer &vbuf,
@@ -1055,7 +1039,7 @@ static void _send_layout_data()
tiles.json_close_object();
- tiles.send_message();
+ tiles.finish_message();
}
void TilesFramework::resize()
@@ -1077,14 +1061,14 @@ void TilesFramework::_send_everything()
_send_version();
_send_layout_data();
- send_message("{msg:\"vgrdc\",x:%d,y:%d}",
+ send_message("{\"msg\":\"vgrdc\",\"x\":%d,\"y\":%d}",
m_current_gc.x - m_origin.x, m_current_gc.y - m_origin.y);
- send_message("{msg:\"flash\",col:%d}", m_current_flash_colour);
+ send_message("{\"msg\":\"flash\",\"col\":%d}", m_current_flash_colour);
_send_map(true);
finish_message();
- send_message("{msg:'redraw'}");
+ send_message("{\"msg\":\"redraw\"}");
// UI State
_send_ui_state(m_ui_state);
@@ -1108,7 +1092,7 @@ void TilesFramework::_send_everything()
}
json_close_array();
json_close_object();
- send_message();
+ finish_message();
m_text_crt.send(true);
m_text_stat.send(true);
@@ -1173,12 +1157,15 @@ void TilesFramework::redraw()
if (m_need_redraw)
{
- push_prefix("{msg:'multi',msgs:[");
+ json_open_object();
+ json_write_string("msg", "multi");
+ json_treat_as_empty();
+ json_open_array("msgs");
if (m_current_gc != m_next_gc)
{
if (m_origin.equals(-1, -1))
m_origin = m_next_gc;
- write_message("{msg:'vgrdc',x:%d,y:%d},",
+ write_message("{\"msg\":\"vgrdc\",\"x\":%d,\"y\":%d}",
m_next_gc.x - m_origin.x,
m_next_gc.y - m_origin.y);
m_current_gc = m_next_gc;
@@ -1186,18 +1173,24 @@ void TilesFramework::redraw()
if (m_current_flash_colour != m_next_flash_colour)
{
- write_message("{msg:'flash',col:%d},",
+ json_write_comma();
+ write_message("{\"msg\":\"flash\",\"col\":%d}",
m_next_flash_colour);
m_current_flash_colour = m_next_flash_colour;
}
if (m_view_loaded)
{
- push_prefix("");
_send_map(false);
- pop_prefix(",");
}
- pop_prefix("{msg:'redraw'}]}");
+
+ if (!json_is_empty())
+ {
+ json_write_comma();
+ write_message("{\"msg\":\"redraw\"}");
+ }
+ json_close_array(true);
+ json_close_object(true);
finish_message();
}
@@ -1264,13 +1257,13 @@ void TilesFramework::place_cursor(cursor_type type, const coord_def &gc)
if (result == NO_CURSOR)
{
- send_message("{msg:\"cursor\",id:%d}", type);
+ send_message("{\"msg\":\"cursor\",\"id\":%d}", type);
return;
}
else
{
- send_message("{msg:\"cursor\",id:%d,loc:{x:%d,y:%d}}", type,
- result.x - m_origin.x, result.y - m_origin.y);
+ send_message("{\"msg\":\"cursor\",\"id\":%d,\"loc\":{\"x\":%d,\"y\":%d}}",
+ type, result.x - m_origin.x, result.y - m_origin.y);
}
}
}
@@ -1300,14 +1293,14 @@ void TilesFramework::add_overlay(const coord_def &gc, tileidx_t idx)
m_has_overlays = true;
- send_message("{msg:'overlay',idx:%u,x:%d,y:%d}", (unsigned int) idx,
- gc.x - m_origin.x, gc.y - m_origin.y);
+ send_message("{\"msg\":\"overlay\",\"idx\":%u,\"x\":%d,\"y\":%d}",
+ (unsigned int) idx, gc.x - m_origin.x, gc.y - m_origin.y);
}
void TilesFramework::clear_overlays()
{
if (m_has_overlays)
- send_message("{msg:'clear_overlays'}");
+ send_message("{\"msg\":\"clear_overlays\"}");
m_has_overlays = false;
}
@@ -1430,49 +1423,84 @@ void TilesFramework::write_message_escaped(const string& s)
}
}
-void TilesFramework::json_open_object(const string& name)
+void TilesFramework::json_open(const string& name, char opener, char type)
{
+ m_json_stack.resize(m_json_stack.size() + 1);
+ JsonFrame& fr = m_json_stack.back();
+ fr.start = m_msg_buf.size();
+
json_write_comma();
if (!name.empty())
json_write_name(name);
- write_message("{");
- json_object_level++;
- need_comma = false;
+ m_msg_buf.append(1, opener);
+
+ fr.prefix_end = m_msg_buf.size();
+ fr.type = type;
}
-void TilesFramework::json_close_object()
+void TilesFramework::json_treat_as_empty()
{
- write_message("}");
- json_object_level--;
- need_comma = true;
+ if (m_json_stack.empty())
+ die("json error: empty stack");
+ m_json_stack.back().prefix_end = m_msg_buf.size();
}
-void TilesFramework::json_open_array(const string& name)
+void TilesFramework::json_treat_as_nonempty()
{
- json_write_comma();
- if (!name.empty())
- json_write_name(name);
+ if (m_json_stack.empty())
+ die("json error: empty stack");
+ m_json_stack.back().prefix_end = -1;
+}
- write_message("[");
- json_object_level++;
- need_comma = false;
+bool TilesFramework::json_is_empty()
+{
+ if (m_json_stack.empty())
+ die("json error: empty stack");
+ return m_json_stack.back().prefix_end == (int) m_msg_buf.size();
+}
+
+void TilesFramework::json_close(bool erase_if_empty, char type)
+{
+ if (m_json_stack.empty())
+ die("json error: attempting to close object/array on empty stack");
+ if (m_json_stack.back().type != type)
+ die("json error: attempting to close wrong type");
+
+ if (erase_if_empty && json_is_empty())
+ m_msg_buf.resize(m_json_stack.back().start);
+ else
+ m_msg_buf.append(1, type);
+
+ m_json_stack.pop_back();
+}
+
+void TilesFramework::json_open_object(const string& name)
+{
+ json_open(name, '{', '}');
}
-void TilesFramework::json_close_array()
+void TilesFramework::json_close_object(bool erase_if_empty)
{
- write_message("]");
- json_object_level--;
- need_comma = true;
+ json_close(erase_if_empty, '}');
+}
+
+void TilesFramework::json_open_array(const string& name)
+{
+ json_open(name, '[', ']');
+}
+
+void TilesFramework::json_close_array(bool erase_if_empty)
+{
+ json_close(erase_if_empty, ']');
}
void TilesFramework::json_write_comma()
{
- if (json_object_level > 0 && need_comma)
- {
- write_message(",");
- need_comma = false;
- }
+ if (m_msg_buf.empty()) return;
+ char last = m_msg_buf[m_msg_buf.size() - 1];
+ if (last == '{' || last == '[' || last == ',' || last == ':') return;
+ write_message(",");
}
void TilesFramework::json_write_name(const string& name)
@@ -1489,8 +1517,6 @@ void TilesFramework::json_write_int(int value)
json_write_comma();
write_message("%d", value);
-
- need_comma = true;
}
void TilesFramework::json_write_int(const string& name, int value)
@@ -1501,6 +1527,39 @@ void TilesFramework::json_write_int(const string& name, int value)
json_write_int(value);
}
+void TilesFramework::json_write_bool(bool value)
+{
+ json_write_comma();
+
+ if (value)
+ write_message("true");
+ else
+ write_message("false");
+}
+
+void TilesFramework::json_write_bool(const string& name, bool value)
+{
+ if (!name.empty())
+ json_write_name(name);
+
+ json_write_bool(value);
+}
+
+void TilesFramework::json_write_null()
+{
+ json_write_comma();
+
+ write_message("null");
+}
+
+void TilesFramework::json_write_null(const string& name)
+{
+ if (!name.empty())
+ json_write_name(name);
+
+ json_write_null();
+}
+
void TilesFramework::json_write_string(const string& value)
{
json_write_comma();
@@ -1508,8 +1567,6 @@ void TilesFramework::json_write_string(const string& value)
write_message("\"");
write_message_escaped(value);
write_message("\"");
-
- need_comma = true;
}
void TilesFramework::json_write_string(const string& name, const string& value)
diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h
index 77d0ded425..00969068a3 100644
--- a/crawl-ref/source/tileweb.h
+++ b/crawl-ref/source/tileweb.h
@@ -81,10 +81,8 @@ public:
void pop_menu();
void close_all_menus();
- void write_message();
void write_message(PRINTF(1, ));
void finish_message();
- void send_message();
void send_message(PRINTF(1, ));
bool has_receivers() { return !m_dest_addrs.empty(); }
@@ -109,27 +107,28 @@ public:
void check_for_control_messages();
- /* Adds a prefix that will be written before any other
- data that is sent after this call, unless no other
- data is sent until pop_prefix is called. The suffix
- passed to pop_prefix will only be sent if the prefix
- was sent. */
- void push_prefix(const string& prefix);
- void pop_prefix(const string& suffix);
- bool prefix_popped();
-
// Helper functions for writing JSON
void write_message_escaped(const string& s);
void json_open_object(const string& name = "");
- void json_close_object();
+ void json_close_object(bool erase_if_empty = false);
void json_open_array(const string& name = "");
- void json_close_array();
+ void json_close_array(bool erase_if_empty = false);
void json_write_comma();
void json_write_name(const string& name);
void json_write_int(int value);
void json_write_int(const string& name, int value);
+ void json_write_bool(bool value);
+ void json_write_bool(const string& name, bool value);
+ void json_write_null();
+ void json_write_null(const string& name);
void json_write_string(const string& value);
void json_write_string(const string& name, const string& value);
+ /* Causes the current object/array to be erased if it is closed
+ with erase_if_empty without writing any other content after
+ this call */
+ void json_treat_as_empty();
+ void json_treat_as_nonempty();
+ bool json_is_empty();
string m_sock_name;
bool m_await_connection;
@@ -155,9 +154,16 @@ protected:
wint_t _handle_control_message(sockaddr_un addr, string data);
wint_t _receive_control_message();
- vector<string> m_prefixes;
- int json_object_level;
- bool need_comma;
+ struct JsonFrame
+ {
+ int start;
+ int prefix_end;
+ char type; // '}' or ']'
+ };
+ vector<JsonFrame> m_json_stack;
+
+ void json_open(const string& name, char opener, char type);
+ void json_close(bool erase_if_empty, char type);
struct MenuInfo
{
diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js
index 8a674b4e62..1b64704974 100644
--- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js
+++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js
@@ -389,14 +389,14 @@ function ($, view_data, main, player, icons, dngn, enums, map_knowledge, tileinf
}
else if (cell.bloody)
{
- cell.bloodrot = cell.bloodrot || 0;
+ cell.blood_rotation = cell.blood_rotation || 0;
var basetile;
if (is_wall)
{
basetile = cell.old_blood ? dngn.WALL_OLD_BLOOD : dngn.WALL_BLOOD_S;
- basetile += dngn.tile_count(basetile) * cell.bloodrot;
+ basetile += dngn.tile_count(basetile) * cell.blood_rotation;
basetile = dngn.WALL_BLOOD_S + dngn.tile_count(dngn.WALL_BLOOD_S)
- * cell.bloodrot;
+ * cell.blood_rotation;
}
else
basetile = dngn.BLOOD;
@@ -420,7 +420,7 @@ function ($, view_data, main, player, icons, dngn, enums, map_knowledge, tileinf
var bg = cell.bg;
var bg_idx = cell.bg.value;
- if (cell.swtree && bg_idx > dngn.DNGN_UNSEEN)
+ if (cell.mangrove_water && bg_idx > dngn.DNGN_UNSEEN)
this.draw_dngn(dngn.DNGN_SHALLOW_WATER, x, y);
else if (bg_idx >= dngn.DNGN_FIRST_TRANSPARENT)
this.draw_dngn(cell.flv.f, x, y); // f = floor
@@ -429,7 +429,7 @@ function ($, view_data, main, player, icons, dngn, enums, map_knowledge, tileinf
if (bg_idx > dngn.WALL_MAX)
this.draw_blood_overlay(x, y, cell);
- if (cell.swtree) // Draw the tree submerged
+ if (cell.mangrove_water) // Draw the tree submerged
{
this.ctx.save();
try
@@ -721,15 +721,15 @@ function ($, view_data, main, player, icons, dngn, enums, map_knowledge, tileinf
this.draw_icon(icons.CURSOR3, x, y);
}
- if (cell.tt & 0xF)
+ if (cell.travel_trail & 0xF)
{
this.draw_icon(icons.TRAVEL_PATH_FROM +
- (cell.tt & 0xF) - 1, x, y);
+ (cell.travel_trail & 0xF) - 1, x, y);
}
- if (cell.tt & 0xF0)
+ if (cell.travel_trail & 0xF0)
{
this.draw_icon(icons.TRAVEL_PATH_TO +
- ((cell.tt & 0xF0) >> 4) - 1, x, y);
+ ((cell.travel_trail & 0xF0) >> 4) - 1, x, y);
}
if (fg.MDAM_LIGHT)