Compare commits

..

No commits in common. "master" and "snapshot-360" have entirely different histories.

79 changed files with 392 additions and 414 deletions

6
.github/build.sh vendored
View File

@ -199,7 +199,7 @@ meson_configure+=$'\t'-Dapp_exe=$APP_EXE
meson_configure+=$'\t'-Dapp_id=$APP_ID
meson_configure+=$'\t'-Dapp_data=$APP_DATA
meson_configure+=$'\t'-Dapp_vendor=$APP_VENDOR
meson_configure+=$'\t'-Dstrip=false
meson_configure+=$'\t'-Db_strip=false
meson_configure+=$'\t'-Db_staticpic=false
meson_configure+=$'\t'-Dmod_id=$MOD_ID
case $BSH_HOST_ARCH-$BSH_HOST_PLATFORM-$BSH_HOST_LIBC-$BSH_DEBUG_RELEASE in
@ -290,10 +290,6 @@ if [[ $RELEASE_TYPE == snapshot ]] && [[ $MOD_ID != 0 ]]; then
fi
if [[ $RELEASE_TYPE == snapshot ]] || [[ $MOD_ID != 0 ]]; then
meson_configure+=$'\t'-Dupdate_server=starcatcher.us/TPT
if [[ $BSH_HOST_PLATFORM == emscripten ]]; then
meson_configure+=$'\t'-Dserver=tptserv.starcatcher.us
meson_configure+=$'\t'-Dstatic_server=tptserv.starcatcher.us/Static
fi
fi
if [[ $RELEASE_TYPE != dev ]]; then
meson_configure+=$'\t'-Dignore_updates=false

2
.github/prepare.py vendored
View File

@ -114,7 +114,7 @@ for arch, platform, libc, statdyn, bplatform, runso
( 'x86_64', 'windows', 'msvc', 'static', 'windows', 'windows-2019', '.exe', False, False, None, None, None, 'debug', 0 ), # priority = 0: static debug build
( 'x86_64', 'windows', 'msvc', 'static', 'windows', 'windows-2019', '.exe', True, True, '.pdb', None,'x86_64-win-msvc-static', 'release', 10 ),
( 'x86_64', 'windows', 'msvc', 'dynamic', 'windows', 'windows-2019', '.exe', False, False, None, None, None, 'debug', 10 ),
# ( 'x86_64', 'windows', 'msvc', 'dynamic', 'windows', 'windows-2019', '.exe', False, False, None, 'backendvs', None, 'debug', 0 ), # priority = 0: backend=vs build
( 'x86_64', 'windows', 'msvc', 'dynamic', 'windows', 'windows-2019', '.exe', False, False, None, 'backendvs', None, 'debug', 0 ), # priority = 0: backend=vs build
( 'x86_64', 'windows', 'msvc', 'dynamic', 'windows', 'windows-2019', '.exe', False, False, None, None, None, 'release', 10 ),
( 'x86', 'windows', 'msvc', 'static', 'windows', 'windows-2019', '.exe', False, False, None, None, None, 'debug', 0 ), # priority = 0: static debug build
( 'x86', 'windows', 'msvc', 'static', 'windows', 'windows-2019', '.exe', True, True, '.pdb', None, 'i686-win-msvc-static', 'release', 10 ),

View File

@ -13,8 +13,6 @@ chmod 660 ~/.netrc
mountpoint=ftpmnt
mkdir $mountpoint
curlftpfs "$PUBLISH_HOSTPORT" $mountpoint -o ssl,ciphers='ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256'
if [[ -z ${PUBLISH_ACCESSCHECK-} ]]; then
cp $PUBLISH_FILENAME $mountpoint/${PUBLISH_DIRECTORY:-.}/
fi
cp $PUBLISH_FILENAME $mountpoint/${PUBLISH_DIRECTORY:-.}/
fusermount -u $mountpoint
rmdir $mountpoint

View File

@ -41,13 +41,6 @@ jobs:
env:
PUBLISH_HOSTPORT: ${{ secrets.STARCATCHER_PUBLISH_HOSTPORT }}
GITHUB_REF: ${{ github.ref }}
- if: steps.prepare.outputs.do_publish == 'yes'
run: sudo apt update && sudo apt install curlftpfs && bash -c './.github/starcatcher-publish.sh'
env:
PUBLISH_HOSTPORT: ${{ secrets.STARCATCHER_PUBLISH_HOSTPORT }}
PUBLISH_USERNAME: ${{ secrets.STARCATCHER_PUBLISH_USERNAME }}
PUBLISH_PASSWORD: ${{ secrets.STARCATCHER_PUBLISH_PASSWORD }}
PUBLISH_ACCESSCHECK: yes
- if: steps.prepare.outputs.do_release == 'yes'
id: create_release
env:

View File

@ -1,4 +1,4 @@
The Powder Toy - April 2024
The Powder Toy - January 2023
==========================
Get the latest version [from the Powder Toy website](https://powdertoy.co.uk/Download.html).
@ -108,7 +108,6 @@ Controls
| Shift + R | Horizontal mirror for selected area when pasting stamps |
| Ctrl + Shift + R | Vertical mirror for selected area when pasting stamps |
| R | Rotate selected area counterclockwise when pasting stamps |
| F11 | Toggle fullscreen |
Command Line
---------------------------------------------------------------------------

View File

@ -376,22 +376,6 @@ if host_platform == 'emscripten'
'-o', app_exe + '.js', # so we get a .wasm, and a .js
]
endif
if get_option('export_lua_symbols')
if is_static and lua_variant != 'none' and not project_export_dynamic
if host_platform == 'windows'
error('Lua symbols are currently impossible to export correctly on Windows')
elif c_compiler.has_link_argument('-Wl,--export-dynamic-symbol')
project_link_args += [
'-Wl,--export-dynamic-symbol=lua_*',
'-Wl,--export-dynamic-symbol=luaL_*',
'-Wl,--export-dynamic-symbol=luaopen_*',
]
else
warning('your linker does not support -Wl,--export-dynamic-symbol so Meson will be instructed to export all symbols in order to enable loading Lua shared modules, which may blow up the size of the resulting binary')
project_export_dynamic = true
endif
endif
endif
if get_option('build_powder')
powder_deps += project_deps + [

View File

@ -40,42 +40,42 @@ option(
'display_version_major',
type: 'integer',
min: 0,
value: 98,
value: 97,
description: 'Major component of the display version, should more or less map to the MINOR version in semantic versioning'
)
option(
'display_version_minor',
type: 'integer',
min: 0,
value: 2,
value: 0,
description: 'Minor component of the display version, should more or less map to the PATCH version in semantic versioning'
)
option(
'build_num',
type: 'integer',
min: 0,
value: 365,
value: 360,
description: 'Build number, should be strictly monotonously increasing across public releases'
)
option(
'upstream_version_major',
type: 'integer',
min: 0,
value: 98,
value: 97,
description: 'Major component of the upstream display version, mod owners should not change this but merge upstream changes to it'
)
option(
'upstream_version_minor',
type: 'integer',
min: 0,
value: 2,
value: 0,
description: 'Minor component of the upstream display version, mod owners should not change this but merge upstream changes to it'
)
option(
'upstream_build_num',
type: 'integer',
min: 0,
value: 365,
value: 360,
description: 'Upstream build number, mod owners should not change this but merge upstream changes to it'
)
option(
@ -305,9 +305,3 @@ option(
value: true,
description: 'Ask Windows nicely for UTF-8 as the codepage'
)
option(
'export_lua_symbols',
type: 'boolean',
value: false,
description: 'Export Lua symbols to enable loading of Lua shared modules'
)

View File

@ -445,20 +445,19 @@ int Main(int argc, char *argv[])
engine.Begin();
engine.SetFastQuit(prefs.Get("FastQuit", true));
engine.TouchUI = prefs.Get("TouchUI", DEFAULT_TOUCH_UI);
engine.windowFrameOps = windowFrameOps;
SDLOpen();
if (Client::Ref().IsFirstRun() && FORCE_WINDOW_FRAME_OPS == forceWindowFrameOpsNone)
{
auto guessed = GuessBestScale();
if (engine.windowFrameOps.scale != guessed)
if (windowFrameOps.scale != guessed)
{
engine.windowFrameOps.scale = guessed;
windowFrameOps.scale = guessed;
prefs.Set("Scale", windowFrameOps.scale);
showLargeScreenDialog = true;
}
}
engine.windowFrameOps = windowFrameOps;
SDLOpen();
bool enableBluescreen = USE_BLUESCREEN && !true_arg(arguments["disable-bluescreen"]);
if (enableBluescreen)

View File

@ -22,8 +22,6 @@ int main(int argc, char *argv[])
auto inputFilename = ByteString(argv[1]);
auto outputFilename = ByteString(argv[2]) + ".png";
auto simulationData = std::make_unique<SimulationData>();
std::vector<char> fileData;
if (!Platform::ReadFile(fileData, inputFilename))
{
@ -42,6 +40,7 @@ int main(int argc, char *argv[])
throw e;
}
auto simulationData = std::make_unique<SimulationData>();
Simulation * sim = new Simulation();
Renderer * ren = new Renderer(sim);
@ -64,7 +63,6 @@ int main(int argc, char *argv[])
}
else
{
ren->clearScreen();
int w = Graphics::TextSize("Save file invalid").X + 15, x = (XRES-w)/2, y = (YRES-24)/2;
ren->DrawRect(RectSized(Vec2{ x, y }, Vec2{ w, 24 }), 0xC0C0C0_rgb);
ren->BlendText({ x+8, y+8 }, "Save file invalid", 0xC0C0F0_rgb .WithAlpha(255));

View File

@ -3,6 +3,7 @@
#include "client/http/StartupRequest.h"
#include "ClientListener.h"
#include "Format.h"
#include "MD5.h"
#include "client/GameSave.h"
#include "client/SaveFile.h"
#include "client/SaveInfo.h"
@ -117,7 +118,7 @@ void Client::Tick()
{
if (versionCheckRequest->StatusCode() == 618)
{
AddServerNotification({ "Failed to load SSL certificates", ByteString::Build(SCHEME, SERVER, "/FAQ.html") });
AddServerNotification({ "Failed to load SSL certificates", ByteString(SCHEME) + "powdertoy.co.uk/FAQ.html" });
}
try
{
@ -377,6 +378,7 @@ void Client::RescanStamps()
newStampIDs.push_back(stampID);
}
}
auto oldCount = newStampIDs.size();
auto stampIDsSet = std::set<ByteString>(stampIDs.begin(), stampIDs.end());
for (auto &stampID : stampFilesSet)
{
@ -388,6 +390,8 @@ void Client::RescanStamps()
}
if (changed)
{
// Move newly discovered stamps to front.
std::rotate(newStampIDs.begin(), newStampIDs.begin() + oldCount, newStampIDs.end());
stampIDs = newStampIDs;
WriteStamps();
}

View File

@ -51,18 +51,9 @@ GameSave::GameSave(const std::vector<char> &data, bool newWantAuthors)
void GameSave::MapPalette()
{
int partMap[PT_NUM];
bool ignoreMissingErrors[PT_NUM];
for(int i = 0; i < PT_NUM; i++)
{
partMap[i] = i;
ignoreMissingErrors[i] = false;
}
if (version <= Version(98, 2))
{
ignoreMissingErrors[PT_ICEI] = true;
ignoreMissingErrors[PT_SNOW] = true;
ignoreMissingErrors[PT_RSST] = true;
ignoreMissingErrors[PT_RSSS] = true;
}
auto &sd = SimulationData::CRef();
@ -99,14 +90,12 @@ void GameSave::MapPalette()
}
}
}
auto paletteLookup = [this, &partMap](int type, bool ignoreMissingErrors) {
auto paletteLookup = [this, &partMap](int type) {
if (type > 0 && type < PT_NUM)
{
auto carriedType = partMap[type];
if (!carriedType) // type is not 0 so this shouldn't be 0 either
{
if (ignoreMissingErrors)
return type;
missingElements.ids.insert(type);
}
type = carriedType;
@ -124,7 +113,7 @@ void GameSave::MapPalette()
{
continue;
}
tempPart.type = paletteLookup(tempPart.type, false);
tempPart.type = paletteLookup(tempPart.type);
for (auto index : possiblyCarriesType)
{
if (elements[tempPart.type].CarriesTypeIn & (1U << index))
@ -132,7 +121,7 @@ void GameSave::MapPalette()
auto *prop = reinterpret_cast<int *>(reinterpret_cast<char *>(&tempPart) + properties[index].Offset);
auto carriedType = *prop & int(pmapmask);
auto extra = *prop >> pmapbits;
carriedType = paletteLookup(carriedType, ignoreMissingErrors[tempPart.type]);
carriedType = paletteLookup(carriedType);
*prop = PMAP(extra, carriedType);
}
}
@ -2347,14 +2336,6 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
{
RESTRICTVERSION(97, 0);
}
if (particles[i].type == PT_RSST || particles[i].type == PT_RSSS)
{
RESTRICTVERSION(98, 0);
}
if (particles[i].type == PT_ETRD && (particles[i].tmp || particles[i].tmp2))
{
RESTRICTVERSION(98, 0);
}
//Get the pmap entry for the next particle in the same position
i = partsPosLink[i];

231
src/client/MD5.cpp Normal file
View File

@ -0,0 +1,231 @@
// based on public-domain code from Colin Plumb (1993)
#include "MD5.h"
#include <cstring>
static unsigned getu32(const unsigned char *addr)
{
return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
}
static void putu32(unsigned data, unsigned char *addr)
{
addr[0] = (unsigned char)data;
addr[1] = (unsigned char)(data >> 8);
addr[2] = (unsigned char)(data >> 16);
addr[3] = (unsigned char)(data >> 24);
}
void md5_init(struct md5_context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
void md5_update(struct md5_context *ctx, unsigned char const *buf, unsigned len)
{
unsigned t;
// update bit count
t = ctx->bits[0];
if ((ctx->bits[0] = (t + ((unsigned)len << 3)) & 0xffffffff) < t)
ctx->bits[1]++; // carry
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f;
// use leading data to top up the buffer
if (t)
{
unsigned char *p = ctx->in + t;
t = 64-t;
if (len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
md5_transform(ctx->buf, ctx->in);
buf += t;
len -= t;
}
// following 64-byte chunks
while (len >= 64)
{
memcpy(ctx->in, buf, 64);
md5_transform(ctx->buf, ctx->in);
buf += 64;
len -= 64;
}
// save rest of bytes for later
memcpy(ctx->in, buf, len);
}
void md5_final(unsigned char digest[16], struct md5_context *ctx)
{
unsigned count;
unsigned char *p;
// #bytes mod64
count = (ctx->bits[0] >> 3) & 0x3F;
// first char of padding = 0x80
p = ctx->in + count;
*p++ = 0x80;
// calculate # of bytes to pad
count = 64 - 1 - count;
// Pad out to 56 mod 64
if (count < 8)
{
// we need to finish a whole block before padding
memset(p, 0, count);
md5_transform(ctx->buf, ctx->in);
memset(ctx->in, 0, 56);
}
else
{
// just pad to 56 bytes
memset(p, 0, count-8);
}
// append length & final transform
putu32(ctx->bits[0], ctx->in + 56);
putu32(ctx->bits[1], ctx->in + 60);
md5_transform(ctx->buf, ctx->in);
putu32(ctx->buf[0], digest);
putu32(ctx->buf[1], digest + 4);
putu32(ctx->buf[2], digest + 8);
putu32(ctx->buf[3], digest + 12);
memset(&ctx, 0, sizeof(ctx));
}
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
void md5_transform(unsigned buf[4], const unsigned char inraw[64])
{
unsigned a, b, c, d;
unsigned in[16];
int i;
for (i = 0; i < 16; ++i)
in[i] = getu32 (inraw + 4 * i);
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
static char hexChars[] = "0123456789abcdef";
void md5_ascii(char *result, unsigned char const *buf, unsigned len)
{
struct md5_context md5;
unsigned char hash[16];
int i;
if (len==0)
len = strlen((char *)buf);
md5_init(&md5);
md5_update(&md5, buf, len);
md5_final(hash, &md5);
for (i=0; i<16; i++)
{
result[i*2] = hexChars[(hash[i]>>4)&0xF];
result[i*2+1] = hexChars[hash[i]&0x0F];
}
result[32] = 0;
}

15
src/client/MD5.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
struct md5_context
{
unsigned buf[4];
unsigned bits[2];
unsigned char in[64];
};
void md5_init(struct md5_context *context);
void md5_update(struct md5_context *context, unsigned char const *buf, unsigned len);
void md5_final(unsigned char digest[16], struct md5_context *context);
void md5_transform(unsigned buf[4], const unsigned char in[64]);
void md5_ascii(char *result, unsigned char const *buf, unsigned len);

View File

@ -14,13 +14,4 @@ namespace http
sortByVotes,
sortByDate,
};
enum Period
{
allSaves,
todaySaves,
weekSaves,
monthSaves,
yearSaves,
};
}

View File

@ -1,4 +1,3 @@
#include <ctime>
#include "SearchSavesRequest.h"
#include "Config.h"
#include "client/Client.h"
@ -7,7 +6,7 @@
namespace http
{
static ByteString Url(int start, int count, ByteString query, Period period, Sort sort, Category category)
static ByteString Url(int start, int count, ByteString query, Sort sort, Category category)
{
ByteStringBuilder builder;
builder << SCHEME << SERVER << "/Browse.json?Start=" << start << "&Count=" << count;
@ -18,38 +17,6 @@ namespace http
}
query += str;
};
time_t currentTime = time(NULL);
if(period)
{
switch (period)
{
case todaySaves:
currentTime -= 60*60*24; // One day
break;
case weekSaves:
currentTime -= 60*60*24*7; // One week
break;
case monthSaves:
currentTime -= 60*60*24*31; // One month
break;
case yearSaves:
currentTime -= 60*60*24*365; // One year
break;
default:
break;
}
struct tm currentTimeData = *localtime(&currentTime);
ByteStringBuilder afterQuery;
afterQuery << "after:" << currentTimeData.tm_year+1900 << "-" <<
(currentTimeData.tm_mon < 9 ? "0" : "") << currentTimeData.tm_mon+1 << "-" <<
(currentTimeData.tm_mday < 10 ? "0" : "") << currentTimeData.tm_mday;
appendToQuery(afterQuery.Build());
}
switch (sort)
{
case sortByDate:
@ -81,7 +48,7 @@ namespace http
return builder.Build();
}
SearchSavesRequest::SearchSavesRequest(int start, int count, ByteString query, Period period, Sort sort, Category category) : APIRequest(Url(start, count, query, period, sort, category), authUse, false)
SearchSavesRequest::SearchSavesRequest(int start, int count, ByteString query, Sort sort, Category category) : APIRequest(Url(start, count, query, sort, category), authUse, false)
{
}

View File

@ -8,7 +8,7 @@ namespace http
class SearchSavesRequest : public APIRequest
{
public:
SearchSavesRequest(int start, int count, ByteString query, Period period, Sort sort, Category category);
SearchSavesRequest(int start, int count, ByteString query, Sort sort, Category category);
std::pair<int, std::vector<std::unique_ptr<SaveInfo>>> Finish();
};

View File

@ -52,10 +52,6 @@ namespace http
return;
}
auto &info = versions[key];
if (info.isNull())
{
return;
}
auto getOr = [&info](ByteString key, int defaultValue) -> int {
if (!info.isMember(key))
{
@ -63,7 +59,7 @@ namespace http
}
return info[key].asInt();
};
auto build = getOr(key == "Snapshot" ? "Snapshot" : "Build", 0);
auto build = getOr(key == "Snapshot" ? "Snapshot" : "Build", -1);
if (!updateAvailableFunc(build))
{
return;
@ -72,8 +68,8 @@ namespace http
channel,
ByteString::Build(SCHEME, alternate ? UPDATESERVER : SERVER, info["File"].asString()),
ByteString(info["Changelog"].asString()).FromUtf8(),
getOr("Major", 0),
getOr("Minor", 0),
getOr("Major", -1),
getOr("Minor", -1),
build,
};
};

View File

@ -1,4 +1,5 @@
client_files = files(
'MD5.cpp',
'SaveFile.cpp',
'SaveInfo.cpp',
'ThumbnailRendererTask.cpp',

View File

@ -112,14 +112,6 @@ struct Vec2
);
}
Vec2<T> Min(Vec2<T> other) const
{
return Vec2<T>(
std::min(X, other.X),
std::min(Y, other.Y)
);
}
// Return a rectangle starting at origin, whose dimensions match this vector
template<typename S = T, typename = std::enable_if_t<std::is_integral_v<S>>>
constexpr inline Rect<T> OriginRect() const

View File

@ -58,7 +58,7 @@ bool ReadFile(std::vector<char> &fileData, ByteString filename)
if (f) f.seekg(0, std::ios::end);
if (f) fileData.resize(f.tellg());
if (f) f.seekg(0);
if (f && fileData.size()) f.read(&fileData[0], fileData.size());
if (f) f.read(&fileData[0], fileData.size());
if (!f)
{
std::cerr << "ReadFile: " << filename << ": " << strerror(errno) << std::endl;

View File

@ -183,8 +183,6 @@ void Renderer::render_parts()
gfctx.pipeSubcallTpart = nullptr;
int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y;
int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
int drawing_budget = 1000000; //Serves as an upper bound for costly effects such as SPARK, FLARE and LFLARE
if(!sim)
return;
auto *parts = sim->parts;
@ -635,7 +633,7 @@ void Renderer::render_parts()
{
auto flicker = float(gfctx.rng()%20);
auto gradv = 4*sim->parts[i].life + flicker;
for (x = 0; (gradv>0.5) && (drawing_budget > 0); x++) {
for (x = 0; gradv>0.5; x++) {
auto col = RGBA<uint8_t>(
std::min(0xFF, colr * int(gradv) / 255),
std::min(0xFF, colg * int(gradv) / 255),
@ -646,7 +644,6 @@ void Renderer::render_parts()
AddPixel({ nx, ny+x }, col);
AddPixel({ nx, ny-x }, col);
gradv = gradv/1.5f;
drawing_budget--;
}
}
if(pixel_mode & PMODE_FLARE)
@ -663,13 +660,12 @@ void Renderer::render_parts()
BlendPixel({ nx-1, ny-1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
BlendPixel({ nx+1, ny+1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
BlendPixel({ nx-1, ny+1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
for (x = 1; (gradv>0.5) && (drawing_budget > 0); x++) {
for (x = 1; gradv>0.5; x++) {
AddPixel({ nx+x, ny }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx-x, ny }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx, ny+x }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx, ny-x }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
gradv = gradv/1.2f;
drawing_budget--;
}
}
if(pixel_mode & PMODE_LFLARE)
@ -686,13 +682,12 @@ void Renderer::render_parts()
BlendPixel({ nx-1, ny-1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
BlendPixel({ nx+1, ny+1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
BlendPixel({ nx-1, ny+1 }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
for (x = 1; (gradv>0.5) && (drawing_budget > 0); x++) {
for (x = 1; gradv>0.5; x++) {
AddPixel({ nx+x, ny }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx-x, ny }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx, ny+x }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
AddPixel({ nx, ny-x }, RGBA<uint8_t>(colr, colg, colb, int(gradv)));
gradv = gradv/1.01f;
drawing_budget--;
}
}
if (pixel_mode & EFFECT_GRAVIN)

View File

@ -192,11 +192,7 @@ void ElementSearchActivity::searchTools(String query)
}
}
if (current.X == 0)
{
current.Y -= 19;
}
scrollPanel->InnerSize = ui::Point(scrollPanel->Size.X, current.Y + 20);
scrollPanel->InnerSize = ui::Point(scrollPanel->Size.X, current.Y + 1);
}
void ElementSearchActivity::SetActiveTool(int selectionState, Tool * tool)

View File

@ -39,7 +39,7 @@ class LoadFilesTask: public Task
bool doWork() override
{
std::vector<ByteString> files = Platform::DirectorySearch(directory, search, { ".cps" });
std::sort(files.rbegin(), files.rend(), [](ByteString a, ByteString b) { return a.ToLower() > b.ToLower(); });
std::sort(files.rbegin(), files.rend(), [](ByteString a, ByteString b) { return a.ToLower() < b.ToLower(); });
notifyProgress(-1);
for(std::vector<ByteString>::iterator iter = files.begin(), end = files.end(); iter != end; ++iter)

View File

@ -552,7 +552,7 @@ bool GameController::MouseUp(int x, int y, unsigned button, MouseupReason reason
}
break;
case sign::Type::Thread:
Platform::OpenURI(ByteString::Build(SCHEME, SERVER, "/Discussions/Thread/View.html?Thread=", str.Substr(3, si.first - 3).ToUtf8()));
Platform::OpenURI(ByteString::Build(SCHEME, "powdertoy.co.uk/Discussions/Thread/View.html?Thread=", str.Substr(3, si.first - 3).ToUtf8()));
break;
case sign::Type::Search:
OpenSearch(str.Substr(3, si.first - 3));
@ -1111,11 +1111,8 @@ void GameController::SetActiveTool(int toolSelection, Tool * tool)
gameModel->SetLastTool(tool);
for(int i = 0; i < 3; i++)
{
auto *activeTool = gameModel->GetActiveTool(i);
if (activeTool && activeTool->Identifier == "DEFAULT_WL_GRVTY")
{
if(gameModel->GetActiveTool(i) == gameModel->GetMenuList().at(SC_WALL)->GetToolList().at(WL_GRAV))
gameModel->GetRenderer()->gravityZonesEnabled = true;
}
}
if (tool->Identifier == "DEFAULT_UI_PROPERTY")
{

View File

@ -76,7 +76,7 @@ inline ByteString IntroText()
}
else
{
sb << "\bgTo use online features such as saving, you need to register at: \brhttps://" << SERVER << "/Register.html\n";
sb << "\bgTo use online features such as saving, you need to register at: \brhttps://powdertoy.co.uk/Register.html\n";
}
sb << "\n\bt" << VersionInfo();
return sb.Build();

View File

@ -15,8 +15,7 @@ class DropDownWindow : public ui::Window
public:
DropDownWindow(DropDown * dropDown):
Window(dropDown->GetScreenPos() + ui::Point(-1, -1 - (dropDown->optionIndex*16 < dropDown->GetScreenPos().Y ? dropDown->optionIndex*16 : 0)),
ui::Point(dropDown->Size.X+2, 2+dropDown->options.size()*16)),
Window(dropDown->GetScreenPos() + ui::Point(-1, -1 - dropDown->optionIndex * 16), ui::Point(dropDown->Size.X+2, 2+dropDown->options.size()*16)),
dropDown(dropDown),
appearance(dropDown->Appearance)
{

View File

@ -83,8 +83,6 @@ void Engine::ShowWindow(Window * window)
{
window->Position.Y = (g->Size().Y - window->Size.Y) / 2;
}
window->Size = window->Size.Min(g->Size());
window->Position = window->Position.Clamp(RectBetween<int>({0, 0}, g->Size()));
/*if(window->Position.Y > 0)
{
windowTargetPosition = window->Position;

View File

@ -114,35 +114,32 @@ void Panel::OnMouseClick(int localx, int localy, unsigned button)
void Panel::OnMouseDown(int x, int y, unsigned button)
{
if (MouseDownInside)
auto localx = x - Position.X;
auto localy = y - Position.Y;
//check if clicked a child
for(int i = children.size()-1; i >= 0 ; --i)
{
auto localx = x - Position.X;
auto localy = y - Position.Y;
//check if clicked a child
for(int i = children.size()-1; i >= 0 ; --i)
//child must be enabled
if(children[i]->Enabled)
{
//child must be enabled
if(children[i]->Enabled)
//is mouse inside?
if( localx >= children[i]->Position.X + ViewportPosition.X &&
localy >= children[i]->Position.Y + ViewportPosition.Y &&
localx < children[i]->Position.X + ViewportPosition.X + children[i]->Size.X &&
localy < children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y )
{
//is mouse inside?
if( localx >= children[i]->Position.X + ViewportPosition.X &&
localy >= children[i]->Position.Y + ViewportPosition.Y &&
localx < children[i]->Position.X + ViewportPosition.X + children[i]->Size.X &&
localy < children[i]->Position.Y + ViewportPosition.Y + children[i]->Size.Y )
{
GetParentWindow()->FocusComponent(children[i]);
children[i]->MouseDownInside = true;
break;
}
GetParentWindow()->FocusComponent(children[i]);
children[i]->MouseDownInside = true;
break;
}
}
}
XOnMouseDown(x, y, button);
for (size_t i = 0; i < children.size(); ++i)
{
if(children[i]->Enabled)
children[i]->OnMouseDown(x - Position.X - ViewportPosition.X, y - Position.Y - ViewportPosition.Y, button);
}
XOnMouseDown(x, y, button);
for (size_t i = 0; i < children.size(); ++i)
{
if(children[i]->Enabled)
children[i]->OnMouseDown(x - Position.X - ViewportPosition.X, y - Position.Y - ViewportPosition.Y, button);
}
}
@ -153,14 +150,12 @@ void Panel::OnMouseHover(int localx, int localy)
{
if (children[i]->Enabled)
{
auto px = children[i]->Position.X + ViewportPosition.X;
auto py = children[i]->Position.Y + ViewportPosition.Y;
if( localx >= px &&
localy >= py &&
localx < px + children[i]->Size.X &&
localy < py + children[i]->Size.Y )
if( localx >= children[i]->Position.X &&
localy >= children[i]->Position.Y &&
localx < children[i]->Position.X + children[i]->Size.X &&
localy < children[i]->Position.Y + children[i]->Size.Y )
{
children[i]->OnMouseHover(localx - px, localy - py);
children[i]->OnMouseHover(localx - children[i]->Position.X, localy - children[i]->Position.Y);
break;
}
}

View File

@ -361,10 +361,10 @@ void SaveButton::OnMouseMoved(int x, int y)
isMouseInsideHistory = false;
if (MouseInside)
{
if (y > Size.Y-11)
if(y > Size.Y-11)
isMouseInsideAuthor = true;
if (y > Size.Y-29 && y < Size.Y - 18 && x > 0 && x < 9)
if(showVotes && y > Size.Y-29 && y < Size.Y - 18 && x > 0 && x < 9)
isMouseInsideHistory = true;
}
}

View File

@ -75,7 +75,6 @@ void ScrollPanel::XOnMouseDown(int x, int y, unsigned int button)
{
if (MouseDownInside)
{
CancelPanning();
if (isMouseInsideScrollbar)
{
scrollbarSelected = true;
@ -87,31 +86,24 @@ void ScrollPanel::XOnMouseDown(int x, int y, unsigned int button)
}
}
void ScrollPanel::CancelPanning()
{
panning = false;
panHistory = {};
yScrollVel = 0;
}
void ScrollPanel::XOnMouseUp(int x, int y, unsigned int button)
{
scrollbarSelected = false;
auto oldPanHistory = panHistory;
CancelPanning();
panning = false;
{
auto it = oldPanHistory.end();
while (it != oldPanHistory.begin() && *(it - 1))
auto it = panHistory.end();
while (it != panHistory.begin() && *(it - 1))
{
--it;
}
if (it < oldPanHistory.end())
if (it < panHistory.end())
{
auto offsetYDiff = oldPanHistory.back()->offsetY - (*it)->offsetY;
auto tickDiff = oldPanHistory.back()->ticks - (*it)->ticks;
auto offsetYDiff = panHistory.back()->offsetY - (*it)->offsetY;
auto tickDiff = panHistory.back()->ticks - (*it)->ticks;
yScrollVel += offsetYDiff / tickDiff * (1000.f / Engine::Ref().GetFps());
}
}
panHistory = {};
isMouseInsideScrollbarArea = false;
scrollbarClickLocation = 0;
}

View File

@ -7,8 +7,6 @@ namespace ui
{
class ScrollPanel: public Panel
{
void CancelPanning();
protected:
int scrollBarWidth;
Point maxOffset;

View File

@ -50,11 +50,8 @@ void Slider::OnMouseMoved(int x, int y)
void Slider::OnMouseDown(int x, int y, unsigned button)
{
if (MouseDownInside)
{
isMouseDown = true;
updatePosition(x - Position.X);
}
isMouseDown = true;
updatePosition(x - Position.X);
}
void Slider::OnMouseUp(int x, int y, unsigned button)

View File

@ -59,8 +59,6 @@ void LocalBrowserModel::OpenSave(int index)
{
stamp = std::move(savesList[index]);
savesList.clear();
notifyPageChanged();
notifySavesListChanged();
}
bool LocalBrowserModel::GetMoveToFront()

View File

@ -1,6 +1,5 @@
#include "LoginModel.h"
#include "LoginView.h"
#include "Config.h"
#include "client/Client.h"
#include "client/http/LoginRequest.h"
#include "client/http/LogoutRequest.h"
@ -9,7 +8,7 @@ void LoginModel::Login(ByteString username, ByteString password)
{
if (username.Contains("@"))
{
statusText = String::Build("Use your Powder Toy account to log in, not your email. If you don't have a Powder Toy account, you can create one at https://", SERVER, "/Register.html");
statusText = "Use your Powder Toy account to log in, not your email. If you don't have a Powder Toy account, you can create one at https://powdertoy.co.uk/Register.html";
loginStatus = loginIdle;
notifyStatusChanged();
return;

View File

@ -76,13 +76,13 @@ OptionsView::OptionsView() : ui::Window(ui::Point(-1, -1), ui::Point(320, 340))
auto *checkbox = new ui::Checkbox(ui::Point(8 + indent * 15, currentY), ui::Point(1, 16), text, "");
autoWidth(checkbox, 0);
checkbox->SetActionCallback({ action });
scrollPanel->AddChild(checkbox);
currentY += 14;
if (info.size())
{
addLabel(indent, info);
}
currentY += 4;
scrollPanel->AddChild(checkbox);
return checkbox;
};
auto addDropDown = [this, &currentY, &autoWidth](String info, std::vector<std::pair<String, int>> options, std::function<void ()> action) {
@ -137,11 +137,10 @@ OptionsView::OptionsView() : ui::Window(ui::Point(-1, -1), ui::Point(320, 340))
ambientAirTemp->SetDefocusCallback({ [this] {
UpdateAirTemp(ambientAirTemp->GetText(), true);
}});
ambientAirTemp->SetLimit(9);
scrollPanel->AddChild(ambientAirTemp);
ambientAirTempPreview = new ui::Button(ui::Point(Size.X-31, currentY), ui::Point(16, 16), "", "Preview");
scrollPanel->AddChild(ambientAirTempPreview);
auto *label = new ui::Label(ui::Point(8, currentY), ui::Point(Size.X-105, 16), "Ambient air temperature");
auto *label = new ui::Label(ui::Point(8, currentY), ui::Point(Size.X-96, 16), "Ambient air temperature");
label->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
label->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
scrollPanel->AddChild(label);

View File

@ -147,7 +147,7 @@ void PreviewModel::OnSaveReady()
{
auto gameSave = std::make_unique<GameSave>(*saveData);
if (gameSave->fromNewerVersion)
new ErrorMessage("This save is from a newer version", String::Build("Please update TPT in game or at https://", SERVER));
new ErrorMessage("This save is from a newer version", "Please update TPT in game or at https://powdertoy.co.uk");
saveInfo->SetGameSave(std::move(gameSave));
}
catch(ParseException &e)

View File

@ -111,9 +111,9 @@ PreviewView::PreviewView(std::unique_ptr<VideoBuffer> newSavePreview):
AddComponent(missingElementsButton);
if(showAvatars)
saveNameLabel = new ui::Label(ui::Point(39, (YRES/2)+4), ui::Point(265, 16), "");
saveNameLabel = new ui::Label(ui::Point(39, (YRES/2)+4), ui::Point(180, 16), "");
else
saveNameLabel = new ui::Label(ui::Point(5, (YRES/2)+4), ui::Point(300, 16), "");
saveNameLabel = new ui::Label(ui::Point(5, (YRES/2)+4), ui::Point(200, 16), "");
saveNameLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
saveNameLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(saveNameLabel);
@ -129,9 +129,9 @@ PreviewView::PreviewView(std::unique_ptr<VideoBuffer> newSavePreview):
AddComponent(saveDescriptionLabel);
if(showAvatars)
authorDateLabel = new ui::Label(ui::Point(39, (YRES/2)+4+15), ui::Point(200, 16), "");
authorDateLabel = new ui::Label(ui::Point(39, (YRES/2)+4+15), ui::Point(180, 16), "");
else
authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15), ui::Point(220, 16), "");
authorDateLabel = new ui::Label(ui::Point(5, (YRES/2)+4+15), ui::Point(200, 16), "");
authorDateLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
authorDateLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(authorDateLabel);
@ -148,7 +148,7 @@ PreviewView::PreviewView(std::unique_ptr<VideoBuffer> newSavePreview):
AddComponent(avatarButton);
}
viewsLabel = new ui::Label(ui::Point((XRES/2)-88, (YRES/2)+4+15), ui::Point(88, 16), "");
viewsLabel = new ui::Label(ui::Point((XRES/2)-80, (YRES/2)+4+15), ui::Point(80, 16), "");
viewsLabel->Appearance.HorizontalAlign = ui::Appearance::AlignRight;
viewsLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(viewsLabel);
@ -644,7 +644,6 @@ void PreviewView::NotifyCommentBoxEnabledChanged(PreviewModel * sender)
} });
addCommentBox->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
addCommentBox->SetMultiline(true);
addCommentBox->SetLimit(1000);
AddComponent(addCommentBox);
submitCommentButton = new ui::Button(ui::Point(Size.X-40, Size.Y-19), ui::Point(40, 19), "Submit");
submitCommentButton->SetActionCallback({ [this] { submitComment(); } });

View File

@ -70,7 +70,7 @@ void ProfileActivity::setUserInfo(UserInfo newInfo)
int currentY = 5;
// username label
ui::Label * title = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8-(40+16+75), 15), info.username.FromUtf8());
ui::Label * title = new ui::Label(ui::Point(4, currentY), ui::Point(Size.X-8-(40+8+75), 15), info.username.FromUtf8());
title->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(title);
@ -90,13 +90,13 @@ void ProfileActivity::setUserInfo(UserInfo newInfo)
currentY += 23;
// age
ui::Label * ageTitle = new ui::Label(ui::Point(4, currentY), ui::Point(23, 15), "Age:");
ui::Label * ageTitle = new ui::Label(ui::Point(4, currentY), ui::Point(18, 15), "Age:");
ageTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
ageTitle->SetTextColour(ui::Colour(180, 180, 180));
scrollPanel->AddChild(ageTitle);
// can't figure out how to tell a null from a 0 in the json library we use
ui::Label *age = new ui::Label(ui::Point(5+ageTitle->Size.X, currentY), ui::Point(Size.X-ageTitle->Size.X-56, 15), info.age ? String::Build(info.age) : "\bgNot Provided");
ui::Label *age = new ui::Label(ui::Point(8+ageTitle->Size.X, currentY), ui::Point(40, 15), info.age ? String::Build(info.age) : "\bgNot Provided");
age->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(age);
currentY += 2+age->Size.Y;
@ -108,25 +108,20 @@ void ProfileActivity::setUserInfo(UserInfo newInfo)
scrollPanel->AddChild(locationTitle);
if (editable)
{
location = new ui::Textbox(ui::Point(5+locationTitle->Size.X, currentY), ui::Point(Size.X-locationTitle->Size.X-16, 17), info.location);
((ui::Textbox*)location)->SetLimit(40);
}
location = new ui::Textbox(ui::Point(8+locationTitle->Size.X, currentY), ui::Point(Size.X-locationTitle->Size.X-16, 17), info.location);
else
{
location = new ui::Label(ui::Point(5+locationTitle->Size.X, currentY), ui::Point(Size.X-locationTitle->Size.X-14, 17), info.location);
}
location = new ui::Label(ui::Point(4+locationTitle->Size.X, currentY), ui::Point(Size.X-locationTitle->Size.X-14, 17), info.location);
location->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(location);
currentY += 2+location->Size.Y;
// website
ui::Label * websiteTitle = new ui::Label(ui::Point(1, currentY), ui::Point(42, 15), "Website:");
ui::Label * websiteTitle = new ui::Label(ui::Point(4, currentY), ui::Point(38, 15), "Website:");
websiteTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
websiteTitle->SetTextColour(ui::Colour(180, 180, 180));
scrollPanel->AddChild(websiteTitle);
ui::Label *website = new ui::Label(ui::Point(2+websiteTitle->Size.X, currentY), ui::Point(Size.X-websiteTitle->Size.X-16, 15), info.website.FromUtf8());
ui::Label *website = new ui::Label(ui::Point(8+websiteTitle->Size.X, currentY), ui::Point(Size.X-websiteTitle->Size.X-16, 15), info.website.FromUtf8());
website->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(website);
currentY += 2+website->Size.Y;
@ -139,34 +134,34 @@ void ProfileActivity::setUserInfo(UserInfo newInfo)
currentY += savesTitle->Size.Y;
// saves count
ui::Label * saveCountTitle = new ui::Label(ui::Point(12, currentY), ui::Point(32, 15), "Count:");
ui::Label * saveCountTitle = new ui::Label(ui::Point(12, currentY), ui::Point(30, 15), "Count:");
saveCountTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
saveCountTitle->SetTextColour(ui::Colour(180, 180, 180));
scrollPanel->AddChild(saveCountTitle);
ui::Label *savesCount = new ui::Label(ui::Point(13+saveCountTitle->Size.X, currentY), ui::Point(Size.X-saveCountTitle->Size.X-24, 15), String::Build(info.saveCount));
ui::Label *savesCount = new ui::Label(ui::Point(12+saveCountTitle->Size.X, currentY), ui::Point(Size.X-saveCountTitle->Size.X-16, 15), String::Build(info.saveCount));
savesCount->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(savesCount);
currentY += savesCount->Size.Y;
// average score
ui::Label * averageScoreTitle = new ui::Label(ui::Point(12, currentY), ui::Point(72, 15), "Average Score:");
ui::Label * averageScoreTitle = new ui::Label(ui::Point(12, currentY), ui::Point(70, 15), "Average Score:");
averageScoreTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
averageScoreTitle->SetTextColour(ui::Colour(180, 180, 180));
scrollPanel->AddChild(averageScoreTitle);
ui::Label *averageScore = new ui::Label(ui::Point(13+averageScoreTitle->Size.X, currentY), ui::Point(Size.X-averageScoreTitle->Size.X-24, 15), String::Build(info.averageScore));
ui::Label *averageScore = new ui::Label(ui::Point(12+averageScoreTitle->Size.X, currentY), ui::Point(Size.X-averageScoreTitle->Size.X-16, 15), String::Build(info.averageScore));
averageScore->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(averageScore);
currentY += averageScore->Size.Y;
// highest score
ui::Label * highestScoreTitle = new ui::Label(ui::Point(12, currentY), ui::Point(71, 15), "Highest Score:");
ui::Label * highestScoreTitle = new ui::Label(ui::Point(12, currentY), ui::Point(69, 15), "Highest Score:");
highestScoreTitle->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
highestScoreTitle->SetTextColour(ui::Colour(180, 180, 180));
scrollPanel->AddChild(highestScoreTitle);
ui::Label *highestScore = new ui::Label(ui::Point(13+highestScoreTitle->Size.X, currentY), ui::Point(Size.X-highestScoreTitle->Size.X-24, 15), String::Build(info.highestScore));
ui::Label *highestScore = new ui::Label(ui::Point(12+highestScoreTitle->Size.X, currentY), ui::Point(Size.X-highestScoreTitle->Size.X-16, 15), String::Build(info.highestScore));
highestScore->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
scrollPanel->AddChild(highestScore);
currentY += 2+highestScore->Size.Y;

View File

@ -79,7 +79,6 @@ ServerSaveActivity::ServerSaveActivity(std::unique_ptr<SaveInfo> newSave, OnUplo
nameField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
nameField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
nameField->SetActionCallback({ [this] { CheckName(nameField->GetText()); } });
nameField->SetLimit(50);
AddComponent(nameField);
FocusComponent(nameField);

View File

@ -136,32 +136,6 @@ void SearchController::SetPageRelative(int offset)
searchModel->UpdateSaveList(page, searchModel->GetLastQuery());
}
void SearchController::ChangePeriod(int period)
{
switch(period)
{
case 0:
searchModel->SetPeriod(http::allSaves);
break;
case 1:
searchModel->SetPeriod(http::todaySaves);
break;
case 2:
searchModel->SetPeriod(http::weekSaves);
break;
case 3:
searchModel->SetPeriod(http::monthSaves);
break;
case 4:
searchModel->SetPeriod(http::yearSaves);
break;
default:
searchModel->SetPeriod(http::allSaves);
}
searchModel->UpdateSaveList(1, searchModel->GetLastQuery());
}
void SearchController::ChangeSort()
{
if(searchModel->GetSort() == http::sortByDate)

View File

@ -37,7 +37,6 @@ public:
void Refresh();
void SetPage(int page);
void SetPageRelative(int offset);
void ChangePeriod(int period);
void ChangeSort();
void ShowOwn(bool show);
void ShowFavourite(bool show);

View File

@ -11,7 +11,6 @@
#include <cmath>
SearchModel::SearchModel():
currentPeriod(http::allSaves),
currentSort(http::sortByVotes),
currentPage(1),
resultCount(0),
@ -31,11 +30,11 @@ bool SearchModel::GetShowTags()
return showTags;
}
void SearchModel::BeginSearchSaves(int start, int count, String query, http::Period period, http::Sort sort, http::Category category)
void SearchModel::BeginSearchSaves(int start, int count, String query, http::Sort sort, http::Category category)
{
lastError = "";
resultCount = 0;
searchSaves = std::make_unique<http::SearchSavesRequest>(start, count, query.ToUtf8(), period, sort, category);
searchSaves = std::make_unique<http::SearchSavesRequest>(start, count, query.ToUtf8(), sort, category);
searchSaves->Start();
}
@ -96,7 +95,7 @@ bool SearchModel::UpdateSaveList(int pageNumber, String query)
//resultCount = 0;
currentPage = pageNumber;
if(pageNumber == 1 && !showOwn && !showFavourite && currentPeriod == http::allSaves && currentSort == http::sortByVotes && query == "")
if(pageNumber == 1 && !showOwn && !showFavourite && currentSort == http::sortByVotes && query == "")
SetShowTags(true);
else
SetShowTags(false);
@ -121,7 +120,7 @@ bool SearchModel::UpdateSaveList(int pageNumber, String query)
{
category = http::categoryMyOwn;
}
BeginSearchSaves((currentPage-1)*20, 20, lastQuery, currentPeriod, currentSort, category);
BeginSearchSaves((currentPage-1)*20, 20, lastQuery, currentSort, category);
return true;
}
return false;
@ -179,7 +178,6 @@ void SearchModel::AddObserver(SearchView * observer)
observers.push_back(observer);
observer->NotifySaveListChanged(this);
observer->NotifyPageChanged(this);
observer->NotifyPeriodChanged(this);
observer->NotifySortChanged(this);
observer->NotifyShowOwnChanged(this);
observer->NotifyTagListChanged(this);
@ -260,15 +258,6 @@ void SearchModel::notifyPageChanged()
}
}
void SearchModel::notifyPeriodChanged()
{
for (size_t i = 0; i < observers.size(); i++)
{
SearchView* cObserver = observers[i];
cObserver->NotifyPeriodChanged(this);
}
}
void SearchModel::notifySortChanged()
{
for (size_t i = 0; i < observers.size(); i++)
@ -307,7 +296,7 @@ void SearchModel::notifySelectedChanged()
int SearchModel::GetPageCount()
{
if (!showOwn && !showFavourite && currentPeriod == http::allSaves && currentSort == http::sortByVotes && lastQuery == "")
if (!showOwn && !showFavourite && currentSort == http::sortByVotes && lastQuery == "")
return std::max(1, (int)(ceil(resultCount/20.0f))+1); //add one for front page (front page saves are repeated twice)
else
return std::max(1, (int)(ceil(resultCount/20.0f)));

View File

@ -18,7 +18,7 @@ class SearchModel
{
private:
std::unique_ptr<http::SearchSavesRequest> searchSaves;
void BeginSearchSaves(int start, int count, String query, http::Period period, http::Sort sort, http::Category category);
void BeginSearchSaves(int start, int count, String query, http::Sort sort, http::Category category);
std::vector<std::unique_ptr<SaveInfo>> EndSearchSaves();
void BeginGetTags(int start, int count, String query);
@ -26,7 +26,6 @@ private:
std::unique_ptr<http::SearchTagsRequest> getTags;
std::unique_ptr<SaveInfo> loadedSave;
http::Period currentPeriod;
http::Sort currentSort;
String lastQuery;
String lastError;
@ -43,7 +42,6 @@ private:
void notifyTagListChanged();
void notifySelectedChanged();
void notifyPageChanged();
void notifyPeriodChanged();
void notifySortChanged();
void notifyShowOwnChanged();
void notifyShowFavouriteChanged();
@ -63,8 +61,6 @@ public:
int GetPageCount();
int GetPageNum() { return currentPage; }
String GetLastQuery() { return lastQuery; }
void SetPeriod(http::Period period) { if(!searchSaves) { currentPeriod = period; } notifyPeriodChanged(); }
http::Period GetPeriod() { return currentPeriod; }
void SetSort(http::Sort sort) { if(!searchSaves) { currentSort = sort; } notifySortChanged(); }
http::Sort GetSort() { return currentSort; }
void SetShowOwn(bool show) { if(!searchSaves) { if(show!=showOwn) { showOwn = show; } } notifyShowOwnChanged(); }

View File

@ -9,7 +9,6 @@
#include "gui/interface/RichLabel.h"
#include "gui/interface/Textbox.h"
#include "gui/interface/Spinner.h"
#include "gui/interface/DropDown.h"
#include "PowderToySDL.h"
#include "graphics/Graphics.h"
#include "SimulationConfig.h"
@ -44,25 +43,13 @@ SearchView::SearchView():
AddComponent(pageCountLabel);
AddComponent(pageTextbox);
searchField = new ui::Textbox(ui::Point(60, 10), ui::Point(WINDOWW-283, 17), "", "[search]");
searchField = new ui::Textbox(ui::Point(60, 10), ui::Point(WINDOWW-238, 17), "", "[search]");
searchField->Appearance.icon = IconSearch;
searchField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
searchField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
searchField->SetActionCallback({ [this] { doSearch(); } });
searchField->SetLimit(100);
FocusComponent(searchField);
dateRange = new ui::DropDown(ui::Point(WINDOWW-185, 10), ui::Point(36, 17));
dateRange->SetActionCallback({ [this] { c->ChangePeriod(dateRange->GetOption().second); } });
dateRange->AddOption({"All", 0});
dateRange->AddOption({"Day", 1});
dateRange->AddOption({"Week", 2});
dateRange->AddOption({"Month", 3});
dateRange->AddOption({"Year", 4});
dateRange->Appearance.HorizontalAlign = ui::Appearance::AlignCentre;
dateRange->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(dateRange);
sortButton = new ui::Button(ui::Point(WINDOWW-140, 10), ui::Point(61, 17), "Sort");
sortButton->SetIcon(IconVoteSort);
sortButton->SetTogglable(true);
@ -214,11 +201,6 @@ void SearchView::Search(String query)
c->DoSearch(query, true);
}
void SearchView::NotifyPeriodChanged(SearchModel * sender)
{
dateRange->SetOption(sender->GetPeriod());
}
void SearchView::NotifySortChanged(SearchModel * sender)
{
if(sender->GetSort() == http::sortByVotes)
@ -507,7 +489,7 @@ void SearchView::NotifySaveListChanged(SearchModel * sender)
loadingSpinner->Visible = false;
if (!errorLabel)
{
errorLabel = new ui::Label(ui::Point(0, (WINDOWH/2)-6), ui::Point(WINDOWW, 12), "Error");
errorLabel = new ui::Label(ui::Point((WINDOWW/2)-100, (WINDOWH/2)-6), ui::Point(200, 12), "Error");
AddComponent(errorLabel);
}
if (!sender->GetSavesLoaded())

View File

@ -11,7 +11,6 @@ namespace ui
class Label;
class Spinner;
class Textbox;
class DropDown;
}
class SearchModel;
@ -33,7 +32,6 @@ private:
ui::Label * pageCountLabel;
ui::Label * tagsLabel;
ui::RichLabel * motdLabel = nullptr;
ui::DropDown * dateRange;
ui::Button * sortButton;
ui::Button * ownButton;
ui::Spinner * loadingSpinner;
@ -54,7 +52,6 @@ public:
void NotifySaveListChanged(SearchModel * sender);
void NotifySelectedChanged(SearchModel * sender);
void NotifyPageChanged(SearchModel * sender);
void NotifyPeriodChanged(SearchModel * sender);
void NotifySortChanged(SearchModel * sender);
void NotifyShowOwnChanged(SearchModel * sender);
void NotifyShowFavouriteChanged(SearchModel * sender);

View File

@ -30,7 +30,6 @@ TagsView::TagsView():
tagInput->Appearance.icon = IconTag;
tagInput->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
tagInput->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
tagInput->SetLimit(16);
AddComponent(tagInput);
FocusComponent(tagInput);

View File

@ -151,7 +151,7 @@ void UpdateActivity::NotifyError(Task * sender)
new ConfirmPrompt("Autoupdate failed", sb.Build(), { [this] {
if constexpr (!USE_UPDATESERVER)
{
Platform::OpenURI(ByteString::Build(SCHEME, SERVER, "/Download.html"));
Platform::OpenURI(ByteString(SCHEME) + "powdertoy.co.uk/Download.html");
}
Exit();
}, [this] { Exit(); } });

View File

@ -856,7 +856,7 @@ void LuaElements::Open(lua_State *L)
LCONST(TYPE_GAS);
LCONST(TYPE_ENERGY);
LCONST(PROP_CONDUCTS);
LCONST(PROP_PHOTPASS);
LCONST(PROP_BLACK);
LCONST(PROP_NEUTPENETRATE);
LCONST(PROP_NEUTABSORB);
LCONST(PROP_NEUTPASS);

View File

@ -50,10 +50,7 @@ static int beginMessageBox(lua_State *L)
auto message = PickIfType(L, 2, String("Message"));
auto large = PickIfType(L, 3, false);
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
if (lua_gettop(L))
{
cb->Assign(L, lua_gettop(L));
}
cb->Assign(L, lua_gettop(L));
new InformationMessage(title, message, large, { [cb]() {
auto *lsi = GetLSI();
auto L = lsi->L;
@ -77,10 +74,7 @@ static int beginThrowError(lua_State *L)
{
auto errorMessage = PickIfType(L, 1, String("Error text"));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
if (lua_gettop(L))
{
cb->Assign(L, lua_gettop(L));
}
cb->Assign(L, lua_gettop(L));
new ErrorMessage("Error", errorMessage, { [cb]() {
auto *lsi = GetLSI();
auto L = lsi->L;
@ -107,10 +101,7 @@ static int beginInput(lua_State *L)
auto text = PickIfType(L, 3, String(""));
auto shadow = PickIfType(L, 4, String(""));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
if (lua_gettop(L))
{
cb->Assign(L, lua_gettop(L));
}
cb->Assign(L, lua_gettop(L));
auto handle = [cb](std::optional<String> input) {
auto *lsi = GetLSI();
auto L = lsi->L;
@ -149,10 +140,7 @@ static int beginConfirm(lua_State *L)
auto message = PickIfType(L, 2, String("Message"));
auto buttonText = PickIfType(L, 3, String("Confirm"));
auto cb = std::make_shared<LuaSmartRef>(); // * Bind to main lua state (might be different from L).
if (lua_gettop(L))
{
cb->Assign(L, lua_gettop(L));
}
cb->Assign(L, lua_gettop(L));
auto handle = [cb](int result) {
auto *lsi = GetLSI();
auto L = lsi->L;

View File

@ -1960,11 +1960,9 @@ void LuaSimulation::Open(lua_State *L)
};
lua_newtable(L);
luaL_register(L, NULL, reg);
#define LCONST(v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, #v)
#define LCONSTF(v) lua_pushnumber(L, float(v)); lua_setfield(L, -2, #v)
#define LCONSTAS(k, v) lua_pushinteger(L, int(v)); lua_setfield(L, -2, k)
LCONST(CELL);
LCONST(XCELLS);
LCONST(YCELLS);
@ -1989,7 +1987,6 @@ void LuaSimulation::Open(lua_State *L)
LCONST(ISTP);
LCONSTF(CFDS);
LCONSTF(MAX_VELOCITY);
LCONST(TOOL_HEAT);
LCONST(TOOL_COOL);
LCONST(TOOL_VAC);
@ -1999,7 +1996,6 @@ void LuaSimulation::Open(lua_State *L)
LCONST(TOOL_MIX);
LCONST(TOOL_CYCL);
LCONSTAS("TOOL_WIND", sd.tools.size());
LCONST(DECO_DRAW);
LCONST(DECO_CLEAR);
LCONST(DECO_ADD);
@ -2007,45 +2003,32 @@ void LuaSimulation::Open(lua_State *L)
LCONST(DECO_MULTIPLY);
LCONST(DECO_DIVIDE);
LCONST(DECO_SMUDGE);
LCONST(FLAG_STAGNANT);
LCONST(FLAG_SKIPMOVE);
LCONST(FLAG_MOVABLE);
LCONST(FLAG_PHOTDECO);
LCONST(PMAPBITS);
LCONST(PMAPMASK);
LCONST(BRUSH_CIRCLE);
LCONST(BRUSH_SQUARE);
LCONST(BRUSH_TRIANGLE);
LCONST(NUM_DEFAULTBRUSHES);
LCONSTAS("NUM_BRUSHES", lsi->gameModel->BrushListSize());
LCONST(EDGE_VOID);
LCONST(EDGE_SOLID);
LCONST(EDGE_LOOP);
LCONST(NUM_EDGEMODES);
LCONST(AIR_ON);
LCONST(AIR_PRESSUREOFF);
LCONST(AIR_VELOCITYOFF);
LCONST(AIR_OFF);
LCONST(AIR_NOUPDATE);
LCONST(NUM_AIRMODES);
LCONST(GRAV_VERTICAL);
LCONST(GRAV_OFF);
LCONST(GRAV_RADIAL);
LCONST(GRAV_CUSTOM);
LCONST(NUM_GRAVMODES);
LCONST(DECOSPACE_SRGB);
LCONST(DECOSPACE_LINEAR);
LCONST(DECOSPACE_GAMMA22);
LCONST(DECOSPACE_GAMMA18);
LCONST(NUM_DECOSPACES);
{
lua_newtable(L);
for (int i = 0; i < UI_WALLCOUNT; i++)

View File

@ -9,7 +9,6 @@ elem.FLAG_MOVABLE = sim.FLAG_MOVABLE
elem.FLAG_PHOTDECO = sim.FLAG_PHOTDECO
elem.FLAG_SKIPMOVE = sim.FLAG_SKIPMOVE
elem.FLAG_STAGNANT = sim.FLAG_STAGNANT
elem.PROP_BLACK = 0
elem.PROP_DRAWONCTYPE = 0
elem.ST_GAS = 0
elem.ST_LIQUID = 0

View File

@ -20,11 +20,6 @@ void Prefs::Read()
Json::CharReaderBuilder rbuilder;
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
ByteString errs;
if (!data.size())
{
std::cerr << "no json data" << std::endl;
return;
}
if (!reader->parse(&data[0], &data[0] + data.size(), &root, &errs))
{
std::cerr << errs << std::endl;

View File

@ -17,7 +17,7 @@ constexpr auto TYPE_GAS = UINT32_C(0x00000008); //8 Gases (Includes p
constexpr auto TYPE_ENERGY = UINT32_C(0x00000010); //16 Energy (Thunder, Light, Neutrons etc.)
constexpr auto STATE_FLAGS = UINT32_C(0x0000001F);
constexpr auto PROP_CONDUCTS = UINT32_C(0x00000020); //32 Conducts electricity
constexpr auto PROP_PHOTPASS = UINT32_C(0x00000040); //64 Photons pass through (may refract as in glass)
constexpr auto PROP_BLACK = UINT32_C(0x00000040); //64 Absorbs Photons (not currently implemented or used, a photwl attribute might be better)
constexpr auto PROP_NEUTPENETRATE = UINT32_C(0x00000080); //128 Penetrated by neutrons
constexpr auto PROP_NEUTABSORB = UINT32_C(0x00000100); //256 Absorbs neutrons, reflect is default
constexpr auto PROP_NEUTPASS = UINT32_C(0x00000200); //512 Neutrons pass through, such as with glass

View File

@ -186,14 +186,16 @@ void SimulationData::init_can_move()
if (elements[movingType].Properties & TYPE_PART)
can_move[movingType][PT_SAWD] = 0;
}
//a list of lots of things PHOT can move through
// TODO: replace with property
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
{
//a list of lots of things PHOT can move through
if (elements[destinationType].Properties & PROP_PHOTPASS)
if (destinationType == PT_GLAS || destinationType == PT_PHOT || destinationType == PT_FILT || destinationType == PT_INVIS
|| destinationType == PT_CLNE || destinationType == PT_PCLN || destinationType == PT_BCLN || destinationType == PT_PBCN
|| destinationType == PT_WATR || destinationType == PT_DSTW || destinationType == PT_SLTW || destinationType == PT_GLOW
|| destinationType == PT_ISOZ || destinationType == PT_ISZS || destinationType == PT_QRTZ || destinationType == PT_PQRT
|| destinationType == PT_H2 || destinationType == PT_BGLA || destinationType == PT_C5 || destinationType == PT_RSST)
can_move[PT_PHOT][destinationType] = 2;
//Things PROT and GRVT cannot move through
if (destinationType != PT_DMND && destinationType != PT_INSL && destinationType != PT_VOID && destinationType != PT_PVOD && destinationType != PT_VIBR && destinationType != PT_BVBR && destinationType != PT_PRTI && destinationType != PT_PRTO)
{
can_move[PT_PROT][destinationType] = 2;

View File

@ -31,7 +31,7 @@ void Element::Element_BCLN()
HeatConduct = 251;
Description = "Breakable Clone.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC | PROP_NOCTYPEDRAW;
Properties = TYPE_SOLID | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC | PROP_NOCTYPEDRAW;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;

View File

@ -29,7 +29,7 @@ void Element::Element_BGLA()
HeatConduct = 150;
Description = "Broken Glass, heavy particles formed when glass breaks under pressure. Meltable. Bagels.";
Properties = TYPE_PART | PROP_NEUTPASS | PROP_PHOTPASS | PROP_HOT_GLOW;
Properties = TYPE_PART | PROP_NEUTPASS | PROP_HOT_GLOW;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,7 +32,7 @@ void Element::Element_C5()
HeatConduct = 88;
Description = "Cold explosive, set off by anything cold.";
Properties = TYPE_SOLID | PROP_NEUTPENETRATE | PROP_PHOTPASS | PROP_LIFE_DEC;
Properties = TYPE_SOLID | PROP_NEUTPENETRATE | PROP_LIFE_DEC;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -31,7 +31,7 @@ void Element::Element_CLNE()
HeatConduct = 251;
Description = "Clone. Duplicates any particles it touches.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_NOCTYPEDRAW;
Properties = TYPE_SOLID | PROP_NOCTYPEDRAW;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;

View File

@ -33,7 +33,7 @@ void Element::Element_DSTW()
LatentHeat = 7500;
Description = "Distilled water, does not conduct electricity.";
Properties = TYPE_LIQUID | PROP_NEUTPASS | PROP_PHOTPASS;
Properties = TYPE_LIQUID|PROP_NEUTPASS;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -33,7 +33,7 @@ void Element::Element_FILT()
HeatConduct = 251;
Description = "Filter for photons, changes the color.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_NOAMBHEAT | PROP_LIFE_DEC;
Properties = TYPE_SOLID | PROP_NOAMBHEAT | PROP_LIFE_DEC;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,7 +32,7 @@ void Element::Element_GLAS()
HeatConduct = 150;
Description = "Glass. Meltable. Shatters under pressure, and refracts photons.";
Properties = TYPE_SOLID | PROP_NEUTPASS | PROP_PHOTPASS | PROP_HOT_GLOW | PROP_SPARKSETTLE;
Properties = TYPE_SOLID | PROP_NEUTPASS | PROP_HOT_GLOW | PROP_SPARKSETTLE;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -33,7 +33,7 @@ void Element::Element_GLOW()
HeatConduct = 44;
Description = "Glow, Glows under pressure.";
Properties = TYPE_LIQUID | PROP_PHOTPASS | PROP_LIFE_DEC;
Properties = TYPE_LIQUID | PROP_LIFE_DEC;
LowPressure = IPL;
LowPressureTransition = NT;
@ -59,21 +59,17 @@ static int update(UPDATE_FUNC_ARGS)
auto r = pmap[y+ry][x+rx];
if (!r)
continue;
if (TYP(r)==PT_WATR && sim->rng.chance(1, 400))
{
sim->kill_part(i);
sim->part_change_type(ID(r),x+rx,y+ry,PT_DEUT);
parts[ID(r)].life = 10;
return 1;
}
else if (TYP(r) == PT_GEL) //GLOW + GEL = RSST
{
sim->kill_part(i);
sim->part_change_type(ID(r),x+rx,y+ry,PT_RSST);
parts[ID(r)].tmp = 0;
return 1;
}
}

View File

@ -31,7 +31,7 @@ void Element::Element_H2()
HeatConduct = 251;
Description = "Hydrogen. Combusts with OXYG to make WATR. Undergoes fusion at high temperature and pressure.";
Properties = TYPE_GAS | PROP_PHOTPASS;
Properties = TYPE_GAS;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -34,7 +34,6 @@ void Element::Element_ICEI()
Description = "Crushes under pressure. Cools down air.";
Properties = TYPE_SOLID|PROP_LIFE_DEC|PROP_NEUTPASS;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,7 +32,7 @@ void Element::Element_INVIS()
HeatConduct = 164;
Description = "Invisible to particles while under pressure.";
Properties = TYPE_SOLID | PROP_NEUTPASS | PROP_PHOTPASS;
Properties = TYPE_SOLID | PROP_NEUTPASS;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,7 +32,7 @@ void Element::Element_ISOZ()
HeatConduct = 29;
Description = "Isotope-Z. Radioactive liquid, decays into photons when touching PHOT or under negative pressure.";
Properties = TYPE_LIQUID | PROP_NEUTPENETRATE | PROP_PHOTPASS;
Properties = TYPE_LIQUID|PROP_NEUTPENETRATE;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,7 +32,7 @@ void Element::Element_ISZS()
HeatConduct = 251;
Description = "Solid form of ISOZ, slowly decays into PHOT.";
Properties = TYPE_SOLID | PROP_PHOTPASS;
Properties = TYPE_SOLID;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -54,8 +54,6 @@ void Element::Element_NEUT()
static int update(UPDATE_FUNC_ARGS)
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
unsigned int pressureFactor = 3 + (int)sim->pv[y/CELL][x/CELL];
for (int rx = -1; rx <= 1; rx++)
{
@ -180,7 +178,7 @@ static int update(UPDATE_FUNC_ARGS)
sim->create_part(ID(r), x, y, ct_under);
//If there's a correct tmp set, use it for ctype
if((tmp_under > 0) && (tmp_under < PT_NUM) && (elements[ct_under].CarriesTypeIn & (1U << FIELD_CTYPE)))
if(tmp_under > 0 && ct_under < PT_NUM)
parts[ID(r)].ctype = tmp_under;
}
else

View File

@ -33,7 +33,7 @@ void Element::Element_PBCN()
HeatConduct = 251;
Description = "Powered breakable clone.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_NOCTYPEDRAW;
Properties = TYPE_SOLID | PROP_NOCTYPEDRAW;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;

View File

@ -33,7 +33,7 @@ void Element::Element_PCLN()
HeatConduct = 251;
Description = "Powered clone. When activated, duplicates any particles it touches.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_NOCTYPEDRAW;
Properties = TYPE_SOLID | PROP_NOCTYPEDRAW;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;

View File

@ -36,7 +36,7 @@ void Element::Element_PHOT()
HeatConduct = 251;
Description = "Photons. Refracts through glass, scattered by quartz, and color-changed by different elements. Ignites flammable materials.";
Properties = TYPE_ENERGY | PROP_PHOTPASS | PROP_LIFE_DEC | PROP_LIFE_KILL_DEC;
Properties = TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC;
LowPressure = IPL;
LowPressureTransition = NT;
@ -57,9 +57,6 @@ void Element::Element_PHOT()
static int update(UPDATE_FUNC_ARGS)
{
auto &sd = SimulationData::CRef();
auto &elements = sd.elements;
if (!(parts[i].ctype&0x3FFFFFFF)) {
sim->kill_part(i);
return 1;
@ -124,7 +121,7 @@ static int update(UPDATE_FUNC_ARGS)
sim->create_part(ID(r), x, y, ct_under);
//If there's a correct tmp set, use it for ctype
if((tmp_under > 0) && (tmp_under < PT_NUM) && (elements[ct_under].CarriesTypeIn & (1U << FIELD_CTYPE)))
if(tmp_under > 0 && ct_under < PT_NUM)
parts[ID(r)].ctype = tmp_under;
}
else

View File

@ -32,7 +32,7 @@ void Element::Element_PQRT()
HeatConduct = 3;
Description = "Powdered quartz, broken form of QRTZ.";
Properties = TYPE_PART | PROP_PHOTPASS | PROP_HOT_GLOW;
Properties = TYPE_PART| PROP_HOT_GLOW;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -238,7 +238,7 @@ static int update(UPDATE_FUNC_ARGS)
break;
case PT_RSST: // RSST -> BIZR
sim->create_part(ID(r), x + rx, y + ry, PT_BIZR);
sim->part_change_type(ID(r), x + rx, y + ry, PT_BIZR);
break;
}
}

View File

@ -32,7 +32,7 @@ void Element::Element_QRTZ()
HeatConduct = 3;
Description = "Quartz, breakable mineral. Conducts but becomes brittle at lower temperatures.";
Properties = TYPE_SOLID | PROP_PHOTPASS | PROP_HOT_GLOW | PROP_LIFE_DEC;
Properties = TYPE_SOLID|PROP_HOT_GLOW|PROP_LIFE_DEC;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -33,7 +33,6 @@ void Element::Element_RSSS()
Description = "Solidified resist. Blocks pressure and insulates electricity. Liquefies on contact with neutrons.";
Properties = TYPE_SOLID|PROP_NEUTPASS;
CarriesTypeIn = (1U << FIELD_CTYPE) | (1U << FIELD_TMP);
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -32,8 +32,7 @@ void Element::Element_RSST()
HeatConduct = 55;
Description = "Resist. Solidifies on contact with photons, is destroyed by electrons and spark.";
Properties = TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPASS | PROP_PHOTPASS;
CarriesTypeIn = (1U << FIELD_CTYPE) | (1U << FIELD_TMP);
Properties = TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPASS;
LowPressure = IPL;
LowPressureTransition = NT;
@ -61,7 +60,7 @@ int update(UPDATE_FUNC_ARGS)
// RSST + GUNP = FIRW
if(TYP(r) == PT_GUNP)
{
sim->create_part(i, x, y, PT_FIRW);
sim->part_change_type(i, x, y, PT_FIRW);
sim->kill_part(ID(r));
return 1;
}
@ -69,7 +68,7 @@ int update(UPDATE_FUNC_ARGS)
// RSST + BCOL = FSEP
if(TYP(r) == PT_BCOL)
{
sim->create_part(i, x, y, PT_FSEP);
sim->part_change_type(i, x, y, PT_FSEP);
parts[i].life = 50;
sim->kill_part(ID(r));
return 1;
@ -81,13 +80,6 @@ int update(UPDATE_FUNC_ARGS)
if(parts[ID(r)].ctype != PT_RSST)
parts[i].ctype = parts[ID(r)].ctype;
}
// Set RSST tmp from nearby breakable clone
if((TYP(r) == PT_BCLN) || (TYP(r) == PT_PBCN))
{
if(parts[ID(r)].ctype != PT_RSST)
parts[i].tmp = parts[ID(r)].ctype;
}
}
}

View File

@ -32,7 +32,7 @@ void Element::Element_SLTW()
LatentHeat = 7500;
Description = "Saltwater, conducts electricity, difficult to freeze.";
Properties = TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPENETRATE | PROP_PHOTPASS;
Properties = TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -35,7 +35,6 @@ void Element::Element_SNOW()
Description = "Light particles. Created when ICE breaks under pressure.";
Properties = TYPE_PART|PROP_NEUTPASS;
CarriesTypeIn = 1U << FIELD_CTYPE;
LowPressure = IPL;
LowPressureTransition = NT;

View File

@ -33,7 +33,7 @@ void Element::Element_WATR()
LatentHeat = 7500;
Description = "Water. Conducts electricity, freezes, and extinguishes fires.";
Properties = TYPE_LIQUID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_NEUTPASS | PROP_PHOTPASS;
Properties = TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPASS;
LowPressure = IPL;
LowPressureTransition = NT;