ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
(Generate patch)

Comparing deliantra/Deliantra-Client/Client.xs (file contents):
Revision 1.174 by root, Fri Apr 6 07:45:34 2007 UTC vs.
Revision 1.185 by root, Sat Apr 21 09:21:03 2007 UTC

163typedef struct { 163typedef struct {
164 int name; 164 int name;
165 int w, h; 165 int w, h;
166 float s, t; 166 float s, t;
167 uint8_t r, g, b, a; 167 uint8_t r, g, b, a;
168 tileid smoothtile;
169 uint8_t smoothlevel;
168} maptex; 170} maptex;
169 171
170typedef struct { 172typedef struct {
171 uint32_t player; 173 uint32_t player;
172 tileid tile[3]; 174 tileid tile[3];
173 uint16_t darkness; 175 uint16_t darkness;
174 uint8_t stat_width, stat_hp, flags; 176 uint8_t stat_width, stat_hp, flags, smoothmax;
175} mapcell; 177} mapcell;
176 178
177typedef struct { 179typedef struct {
178 int32_t c0, c1; 180 int32_t c0, c1;
179 mapcell *col; 181 mapcell *col;
335 cell->player = 0; 337 cell->player = 0;
336 } 338 }
337 } 339 }
338} 340}
339 341
342typedef struct {
343 tileid tile;
344 uint8_t x, y, level;
345} smooth_key;
346
347static void
348smooth_or_bits (HV *hv, smooth_key *key, IV bits)
349{
350 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1);
351
352 if (SvIOK (*sv))
353 SvIV_set (*sv, SvIVX (*sv) | bits);
354 else
355 sv_setiv (*sv, bits);
356}
357
340static void 358static void
341music_finished (void) 359music_finished (void)
342{ 360{
343 SDL_UserEvent ev; 361 SDL_UserEvent ev;
344 362
382 400
383/* SDL should provide this, really. */ 401/* SDL should provide this, really. */
384#define SDLK_MODIFIER_MIN 300 402#define SDLK_MODIFIER_MIN 300
385#define SDLK_MODIFIER_MAX 314 403#define SDLK_MODIFIER_MAX 314
386 404
405static AV *texture_av;
406
387MODULE = CFPlus PACKAGE = CFPlus 407MODULE = CFPlus PACKAGE = CFPlus
388 408
389PROTOTYPES: ENABLE 409PROTOTYPES: ENABLE
390 410
391BOOT: 411BOOT:
392{ 412{
413 texture_av = newAV ();
414 AvREAL_off (texture_av);
415
393 HV *stash = gv_stashpv ("CFPlus", 1); 416 HV *stash = gv_stashpv ("CFPlus", 1);
394 static const struct { 417 static const struct {
395 const char *name; 418 const char *name;
396 IV iv; 419 IV iv;
397 } *civ, const_iv[] = { 420 } *civ, const_iv[] = {
683Mix_AllocateChannels (int numchans = -1) 706Mix_AllocateChannels (int numchans = -1)
684 707
685void 708void
686lowdelay (int fd, int val = 1) 709lowdelay (int fd, int val = 1)
687 CODE: 710 CODE:
688#ifndef _WIN32
689 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val)); 711 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&val, sizeof (val));
690#endif
691 712
692void 713void
693win32_proxy_info () 714win32_proxy_info ()
694 PPCODE: 715 PPCODE:
695{ 716{
1295 need_facenum (self, face); self->face2tile [face] = tile; 1316 need_facenum (self, face); self->face2tile [face] = tile;
1296 need_texid (self, tile); 1317 need_texid (self, tile);
1297} 1318}
1298 1319
1299void 1320void
1321set_smooth (CFPlus::Map self, int face, int smooth, int level)
1322 CODE:
1323{
1324 tileid texid;
1325 maptex *tex;
1326
1327 if (face < 0 || face >= self->faces)
1328 return;
1329
1330 if (smooth < 0 || smooth >= self->faces)
1331 return;
1332
1333 texid = self->face2tile [face];
1334
1335 if (!texid)
1336 return;
1337
1338 tex = self->tex + texid;
1339 tex->smoothtile = self->face2tile [smooth];
1340 tex->smoothlevel = level;
1341}
1342
1343void
1300set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1344set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1301 CODE: 1345 CODE:
1302{ 1346{
1303 need_texid (self, texid); 1347 need_texid (self, texid);
1304 1348
1421 } 1465 }
1422 else if (cmd == 6) // monster width 1466 else if (cmd == 6) // monster width
1423 cell->stat_width = *data++ + 1; 1467 cell->stat_width = *data++ + 1;
1424 else if (cmd == 0x47) 1468 else if (cmd == 0x47)
1425 { 1469 {
1426 if (*data == 8) 1470 if (*data == 4)
1427 ; // decode player uuid 1471 ; // decode player count
1428 1472
1429 data += *data + 1; 1473 data += *data + 1;
1430 } 1474 }
1431 else if (cmd == 8) // cell flags 1475 else if (cmd == 8) // cell flags
1432 cell->flags = *data++; 1476 cell->flags = *data++;
1524 1568
1525void 1569void
1526draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T) 1570draw (CFPlus::Map self, int mx, int my, int sw, int sh, int T)
1527 CODE: 1571 CODE:
1528{ 1572{
1573 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1574 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1575 static uint8_t smooth_max[256][256]; // egad, fats and wasteful on memory (64k)
1576 smooth_key skey;
1529 int x, y, z; 1577 int x, y, z;
1530 int last_name; 1578 int last_name;
1579
1580 // thats current max. sorry.
1581 if (sw > 255) sw = 255;
1582 if (sh > 255) sh = 255;
1583
1584 // clear key, in case of extra padding
1585 memset (&skey, 0, sizeof (skey));
1531 1586
1532 glColor4ub (255, 255, 255, 255); 1587 glColor4ub (255, 255, 255, 255);
1533 1588
1534 glEnable (GL_BLEND); 1589 glEnable (GL_BLEND);
1535 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1590 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541 last_name = 0; 1596 last_name = 0;
1542 1597
1543 mx += self->x; 1598 mx += self->x;
1544 my += self->y; 1599 my += self->y;
1545 1600
1601 // first pass: determine smooth_max
1602 // rather ugly, if you ask me
1603 // could also be stored inside mapcell and updated on change
1604 memset (smooth_max, 0, sizeof (smooth_max));
1605 memset (smooth_level, 0, sizeof (smooth_level));
1606
1607 for (y = 0; y < sh; y++)
1608 if (0 <= y + my && y + my < self->rows)
1609 {
1610 maprow *row = self->row + (y + my);
1611
1612 for (x = 0; x < sw; x++)
1613 if (row->c0 <= x + mx && x + mx < row->c1)
1614 {
1615 mapcell *cell = row->col + (x + mx - row->c0);
1616
1617 smooth_max[x + 1][y + 1] =
1618 MAX (self->tex [cell->tile [0]].smoothlevel,
1619 MAX (self->tex [cell->tile [1]].smoothlevel,
1620 self->tex [cell->tile [2]].smoothlevel));
1621 }
1622 }
1623
1546 for (z = 0; z < 3; z++) 1624 for (z = 0; z <= 2; z++)
1625 {
1547 for (y = 0; y < sh; y++) 1626 for (y = 0; y < sh; y++)
1548 if (0 <= y + my && y + my < self->rows) 1627 if (0 <= y + my && y + my < self->rows)
1549 { 1628 {
1550 maprow *row = self->row + (y + my); 1629 maprow *row = self->row + (y + my);
1551 1630
1552 for (x = 0; x < sw; x++) 1631 for (x = 0; x < sw; x++)
1553 if (row->c0 <= x + mx && x + mx < row->c1) 1632 if (row->c0 <= x + mx && x + mx < row->c1)
1633 {
1634 mapcell *cell = row->col + (x + mx - row->c0);
1635 tileid tile = cell->tile [z];
1636
1637 if (tile)
1638 {
1639 maptex tex = self->tex [tile];
1640 int px = (x + 1) * T - tex.w;
1641 int py = (y + 1) * T - tex.h;
1642
1643 // suppressing texture state switches here
1644 // is only moderately effective, but worth the extra effort
1645 if (last_name != tex.name)
1646 {
1647 if (!tex.name)
1648 tex = self->tex [2]; /* missing, replace by noface */
1649
1650 glEnd ();
1651 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1652 glBegin (GL_QUADS);
1653 }
1654
1655 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1656 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1657 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1658 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1659
1660 if (cell->flags && z == 2)
1661 {
1662 if (cell->flags & 1)
1663 {
1664 maptex tex = self->tex [1];
1665 int px = x * T + T * 2 / 32;
1666 int py = y * T - T * 6 / 32;
1667
1668 glEnd ();
1669 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1670 glBegin (GL_QUADS);
1671
1672 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1673 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T);
1674 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T);
1675 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py );
1676 }
1677 }
1678
1679 // update smooth hash
1680 if (tex.smoothtile)
1681 {
1682 skey.tile = tex.smoothtile;
1683 skey.level = tex.smoothlevel;
1684
1685 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31);
1686
1687 // add bits to current tile and all neighbours. skey.x|y is
1688 // shifted +1|+1 so we always stay positive.
1689
1690 // bits is ___n cccc CCCC bbbb
1691 // n do not draw borders&corners
1692 // c draw these corners, but...
1693 // C ... not these
1694 // b draw these borders
1695
1696 // borders: 1 ┃· 2 ━━ 4 ·┃ 8 ··
1697 // ┃· ·· ·┃ ━━
1698
1699 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1700 // ·· ·· ·┏ ┓·
1701
1702 // full tile
1703 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000);
1704
1705 // borders
1706 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091);
1707 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032);
1708 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064);
1709 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8);
1710
1711 // corners
1712 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1713 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1714 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1715 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
1716 }
1717 }
1718 }
1719 }
1720 }
1721
1722 // go through all smoothlevels, lowest to highest, then draw.
1723 // this is basically counting sort
1724 {
1725 int w, b;
1726
1727 for (w = 0; w < 256 / 32; ++w)
1728 {
1729 uint32_t smask = smooth_level [w];
1730 if (smask)
1731 for (b = 0; b < 32; ++b)
1732 if (smask & (((uint32_t)1) << b))
1554 { 1733 {
1555 mapcell *cell = row->col + (x + mx - row->c0); 1734 int level = (w << 5) | b;
1556 tileid tile = cell->tile [z];
1557 1735 HE *he;
1558 if (tile) 1736
1737 hv_iterinit (smooth);
1738 while ((he = hv_iternext (smooth)))
1559 { 1739 {
1560 maptex tex = self->tex [tile]; 1740 smooth_key *skey = (smooth_key *)HeKEY (he);
1561 int px = (x + 1) * T - tex.w; 1741 IV bits = SvIVX (HeVAL (he));
1562 int py = (y + 1) * T - tex.h;
1563 1742
1564 if (last_name != tex.name) 1743 if (!(bits & 0x1000)
1744 && skey->level == level
1745 && level >= smooth_max [skey->x][skey->y])
1565 { 1746 {
1747 maptex tex = self->tex [skey->tile];
1748 int px = (((int)skey->x) - 1) * T;
1749 int py = (((int)skey->y) - 1) * T;
1750 int border = bits & 15;
1751 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1752 float dx = tex.s * .0625f; // 16 images/row
1753 float dy = tex.t * .5f ; // 2 images/column
1754
1755 // this time naively avoiding texture state changes
1756 // save gobs of state changes.
1566 if (!tex.name) 1757 if (last_name != tex.name)
1567 tex = self->tex [2]; /* missing, replace by noface */
1568
1569 glEnd ();
1570 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1571 glBegin (GL_QUADS);
1572 }
1573
1574 glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1575 glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1576 glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1577 glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1578
1579 if (cell->flags && z == 2)
1580 {
1581 if (cell->flags & 1)
1582 { 1758 {
1583 maptex tex = self->tex [1]; 1759 if (!tex.name)
1584 int px = x * T + T * 2 / 32; 1760 continue; // smoothing not yet available
1585 int py = y * T - T * 6 / 32;
1586 1761
1587 glEnd (); 1762 glEnd ();
1588 glBindTexture (GL_TEXTURE_2D, last_name = tex.name); 1763 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1589 glBegin (GL_QUADS); 1764 glBegin (GL_QUADS);
1765 }
1590 1766
1767 if (border)
1768 {
1769 float ox = border * dx;
1770
1771 glTexCoord2f (ox , 0.f ); glVertex2f (px , py );
1772 glTexCoord2f (ox , dy ); glVertex2f (px , py + T);
1773 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py + T);
1774 glTexCoord2f (ox + dx, 0.f ); glVertex2f (px + T, py );
1775 }
1776
1777 if (corner)
1778 {
1779 float ox = corner * dx;
1780
1591 glTexCoord2f (0 , 0 ); glVertex2f (px , py ); 1781 glTexCoord2f (ox , dy ); glVertex2f (px , py );
1592 glTexCoord2f (0 , tex.t); glVertex2f (px , py + T); 1782 glTexCoord2f (ox , dy * 2.f); glVertex2f (px , py + T);
1593 glTexCoord2f (tex.s, tex.t); glVertex2f (px + T, py + T); 1783 glTexCoord2f (ox + dx, dy * 2.f); glVertex2f (px + T, py + T);
1594 glTexCoord2f (tex.s, 0 ); glVertex2f (px + T, py ); 1784 glTexCoord2f (ox + dx, dy ); glVertex2f (px + T, py );
1595 } 1785 }
1596 } 1786 }
1597 } 1787 }
1598 } 1788 }
1599 } 1789 }
1790 }
1791
1792 //hv_clear (smooth);
1600 1793
1601 glEnd (); 1794 glEnd ();
1602 1795
1603 glDisable (GL_TEXTURE_2D); 1796 glDisable (GL_TEXTURE_2D);
1604 glDisable (GL_BLEND); 1797 glDisable (GL_BLEND);
1856 2049
1857 for (z = 0; z <= 2; z++) 2050 for (z = 0; z <= 2; z++)
1858 { 2051 {
1859 tileid t = tile [z]; 2052 tileid t = tile [z];
1860 2053
1861 if (t >= self->texs || !self->tex [t].name) 2054 if (t >= self->texs || (t && !self->tex [t].name))
1862 { 2055 {
1863 XPUSHs (sv_2mortal (newSViv (t))); 2056 XPUSHs (sv_2mortal (newSViv (t)));
1864 need_texid (self, t); 2057 need_texid (self, t);
1865 } 2058 }
1866 2059
2181 2374
2182int glGenTexture () 2375int glGenTexture ()
2183 CODE: 2376 CODE:
2184{ 2377{
2185 GLuint name; 2378 GLuint name;
2379 if (AvFILL (texture_av) >= 0)
2380 name = (GLuint)av_pop (texture_av);
2381 else
2186 glGenTextures (1, &name); 2382 glGenTextures (1, &name);
2187 RETVAL = name; 2383 RETVAL = name;
2188} 2384}
2189 OUTPUT: 2385 OUTPUT:
2190 RETVAL 2386 RETVAL
2191 2387
2192void glDeleteTexture (int name) 2388void glDeleteTexture (int name)
2193 CODE: 2389 CODE:
2194{ 2390{
2195 GLuint name_ = name; 2391 /* make a half-assed attempt at returning the memory used by the texture */
2392 /* textures are frequently being reused by cfplus anyway */
2393 glBindTexture (GL_TEXTURE_2D, name);
2394 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
2395 av_push (texture_av, (SV *)name);
2196 glDeleteTextures (1, &name_); 2396 /*glDeleteTextures (1, &name_);*/
2197} 2397}
2198 2398
2199int glGenList () 2399int glGenList ()
2200 CODE: 2400 CODE:
2201 RETVAL = glGenLists (1); 2401 RETVAL = glGenLists (1);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines