Skip to content

Commit 8623577

Browse files
author
web3blind
committed
Make temple replay award-authoritative
1 parent c6bef18 commit 8623577

7 files changed

Lines changed: 46 additions & 10 deletions

File tree

app/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@
120120
<script src="js/config.js?v=20260712a"></script>
121121

122122
<!-- I18n -->
123-
<script src="js/i18n/ru.js?v=20260712h"></script>
124-
<script src="js/i18n/en.js?v=20260712h"></script>
123+
<script src="js/i18n/ru.js?v=20260712i"></script>
124+
<script src="js/i18n/en.js?v=20260712i"></script>
125125

126126
<!-- Utilities -->
127127
<script src="js/utils/helpers.js?v=20260621l"></script>
@@ -170,7 +170,7 @@
170170
<script src="js/engine/quest-system.js?v=20260621e"></script>
171171
<script src="js/engine/loci.js"></script>
172172
<script src="js/engine/npc-framework.js"></script>
173-
<script src="js/engine/state-engine.js?v=20260712b"></script>
173+
<script src="js/engine/state-engine.js?v=20260712c"></script>
174174
<script src="js/engine/daily-leaderboard-storage.js"></script>
175175
<script src="js/engine/daily-leaderboard.js"></script>
176176

app/js/engine/state-engine.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ var StateEngine = (function() {
266266
events = events.concat(_handleHuntArmageddon(sender, action.data, blockNum));
267267
break;
268268
case AT.TEMPLE_OFFERING:
269-
events = events.concat(_handleTempleOffering(sender, action.data, blockNum));
269+
// Temple rewards are granted only from the real VIZ award memo in _processAward.
270+
// The VM custom op remains a public audit/link record, but cannot mint blessings alone.
270271
break;
271272
case AT.ITEM_EQUIP:
272273
events = events.concat(_handleEquip(sender, action.data, blockNum));
@@ -699,7 +700,33 @@ var StateEngine = (function() {
699700
_rememberAccount(award.receiver);
700701

701702
var memo = award.memo || '';
702-
var isBless = String(memo).indexOf('viz://vm/bless/') === 0;
703+
var memoText = String(memo);
704+
var isBless = memoText.indexOf('viz://vm/bless/') === 0;
705+
var isTemple = memoText.indexOf('viz://vm/temple/') === 0;
706+
707+
if (isTemple) {
708+
var prefix = 'viz://vm/temple/';
709+
var rest = memoText.substring(prefix.length);
710+
var dashIdx = rest.indexOf(' — ');
711+
var deity = dashIdx >= 0 ? rest.substring(0, dashIdx) : rest.split(' ')[0];
712+
var prayer = dashIdx >= 0 ? rest.substring(dashIdx + 3) : '';
713+
var templeEvents = _handleTempleOffering(award.initiator, {
714+
deity: deity,
715+
target: award.receiver,
716+
energy: award.energy,
717+
prayer: prayer
718+
}, blockNum);
719+
worldState.recentActions.push({
720+
type: AT.TEMPLE_OFFERING,
721+
sender: award.initiator,
722+
blockNum: blockNum,
723+
energy: award.energy,
724+
memo: memo,
725+
events: templeEvents,
726+
timestamp: Date.now()
727+
});
728+
return;
729+
}
703730

704731
if (!isBless) return;
705732

app/js/i18n/en.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ var LangEN = {
244244
chronicle_narrative_hunt_lose: '{name} fell in battle with {creature}.',
245245
chronicle_narrative_awaken: '{name} awakened in the World of Viz!',
246246
chronicle_narrative_rest: '{name} rests by the campfire.',
247+
chronicle_narrative_temple: '{name} offered a prayer at the Temple: {deity} heard the call.',
247248
chronicle_narrative_bless: '{name} blesses mage {target}.',
248249
chronicle_narrative_duel_win: '{winner} defeated {loser} in a duel ({winsA}:{winsB})!',
249250
chronicle_narrative_duel_draw: '{nameA} and {nameB} fought to a draw.',

app/js/i18n/ru.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ var LangRU = {
244244
chronicle_narrative_hunt_lose: '{name} пал в бою с {creature}.',
245245
chronicle_narrative_awaken: '{name} пробудился в Мире Виз!',
246246
chronicle_narrative_rest: '{name} отдыхает у костра.',
247+
chronicle_narrative_temple: '{name} принёс молитву в Храме: {deity} услышал зов.',
247248
chronicle_narrative_bless: '{name} благословляет мага {target}.',
248249
chronicle_narrative_duel_win: '{winner} победил {loser} в дуэли ({winsA}:{winsB})!',
249250
chronicle_narrative_duel_draw: '{nameA} и {nameB} сошлись в ничьей.',

app/js/ui/screens/chronicle.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,11 @@ var ChronicleScreen = (function() {
484484
case 'guild.accept':
485485
var gJoin = _guildDisplayName(ev0 && ev0.guildId, ev0 && ev0.guildName);
486486
return t('chronicle_narrative_guild_join', { name: name, guild: gJoin });
487+
case 'temple.offering':
488+
if (ev0 && ev0.type === 'temple_offering') {
489+
return t('chronicle_narrative_temple', { name: name, deity: t('temple_' + ev0.deity + '_name') });
490+
}
491+
return null;
487492
case 'boss.attack':
488493
return name + ' ' + (t('boss_attack') || 'attacks the boss') + '!';
489494
case 'challenge':

app/sw.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Viz Magic — Service Worker
2-
var CACHE_NAME = 'viz-magic-v41';
2+
var CACHE_NAME = 'viz-magic-v42';
33
var ASSETS = [
44
'/',
55
'/index.html',

tests/player-bug-regressions.test.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ test('high-traffic UI narration, screen announcements, and inventory stat labels
342342

343343
test('service worker updates quickly and keeps navigations network-first', function () {
344344
const swJs = read('app/sw.js');
345-
assert.ok(/viz-magic-v41/.test(swJs), 'service worker cache version should be bumped');
345+
assert.ok(/viz-magic-v42/.test(swJs), 'service worker cache version should be bumped');
346346
assert.ok(/self\.skipWaiting\(\)/.test(swJs), 'service worker should activate new cache without waiting for all tabs to close');
347347
assert.ok(/self\.clients\.claim\(\)/.test(swJs), 'service worker should claim clients after activation');
348348
assert.ok(/event\.request\.mode === 'navigate'[\s\S]*fetch\(event\.request\)/.test(swJs), 'navigation requests should prefer network to avoid stale cached index');
@@ -391,7 +391,7 @@ test('mobile entry helpers cover keyboard paste, home-screen shortcut, nav parit
391391
assert.ok(/SoundManager\.setVolume\(sfxVolume \/ 100\)/.test(read('app/js/ui/screens/settings.js')), 'settings should apply stored SFX volume on render');
392392
assert.ok(/localStorage\.setItem\(STORAGE_PREFIX \+ 'sfx_volume'/.test(read('app/js/ui/sound.js')), 'sound manager should persist SFX volume');
393393
assert.ok(/var volume = _getStoredNumber\('sfx_volume', 0\.5\)/.test(read('app/js/ui/sound.js')), 'sound manager should restore persisted SFX volume');
394-
assert.ok(/viz-magic-v41/.test(read('app/sw.js')), 'service worker cache should be bumped for UI changes');
394+
assert.ok(/viz-magic-v42/.test(read('app/sw.js')), 'service worker cache should be bumped for UI changes');
395395
});
396396

397397

@@ -449,8 +449,8 @@ test('magical weather is labelled and affects hunts', function () {
449449
assert.ok(/forecast-card-effect/.test(homeJs + mainCss), 'forecast effect column needs its own thematic icon/card');
450450
assert.ok(/function getCurrentFestival/.test(worldEventsJs), 'magical holidays should sometimes appear in the forecast');
451451
assert.ok(/festival_today_prefix/.test(homeJs + ruJs + enJs), 'forecast holidays should have localized copy');
452-
assert.ok(/i18n\/ru.js\?v=20260712h/.test(indexHtml), 'Russian weather copy must be cache-busted');
453-
assert.ok(/i18n\/en.js\?v=20260712h/.test(indexHtml), 'English weather copy must be cache-busted');
452+
assert.ok(/i18n\/ru.js\?v=20260712i/.test(indexHtml), 'Russian weather copy must be cache-busted');
453+
assert.ok(/i18n\/en.js\?v=20260712i/.test(indexHtml), 'English weather copy must be cache-busted');
454454
assert.ok(/home.js\?v=20260712g/.test(indexHtml), 'home forecast layout must be cache-busted');
455455
assert.ok(/world-events.js\?v=20260712g/.test(indexHtml), 'world events forecast pool must be cache-busted');
456456
assert.ok(/main.css\?v=20260712h/.test(indexHtml), 'forecast grid CSS must be cache-busted');
@@ -486,6 +486,8 @@ test('temple tab uses balanced on-chain offerings without direct pay-to-win stat
486486
assert.ok(/function _handleTempleOffering/.test(stateEngineJs), 'temple offering handler should exist');
487487
assert.ok(/cooldown = 28800/.test(stateEngineJs), 'temple offerings should be cooldown-limited');
488488
assert.ok(/function getTempleBlessing/.test(stateEngineJs), 'temple should expose small temporary blessings');
489+
assert.ok(/Temple rewards are granted only from the real VIZ award memo/.test(stateEngineJs), 'temple replay should not mint rewards from custom proof alone');
490+
assert.ok(/viz:\/\/vm\/temple\//.test(stateEngineJs), 'temple award memos should be recognized during replay');
489491
assert.ok(/templeBlessing/.test(combatJs), 'temple blessings should be used by combat without direct item stats');
490492
assert.ok(/flame_votive_mark/.test(itemsJs) && /labor_votive_mark/.test(itemsJs), 'temple relics should be registered item templates');
491493
assert.ok(/baseStats:\s*\{\}/.test(itemsJs), 'temple relics should not add direct combat stats');

0 commit comments

Comments
 (0)