@@ -106,14 +106,12 @@ var ActionValidator = (function() {
106106 function _validateDuelChallenge ( action , worldState , sender , blockNum ) {
107107 var data = action . data || { } ;
108108 var duels = worldState . duels || { pending : { } , active : { } } ;
109- var account = worldState . characters [ sender ] ;
110- if ( ! account ) {
111- return { valid : false , error : 'no_character' } ;
112- }
113- if ( ! data . target || ! worldState . characters [ data . target ] ) {
114- return { valid : false , error : 'invalid_duel_target' } ;
115- }
116- if ( data . target === sender ) {
109+
110+ // Duel actions are ingested from chain history and must not depend on
111+ // whether local character hydration has already happened on this client.
112+ // The duel state manager creates deterministic character stubs when the
113+ // action is accepted into state.
114+ if ( ! data . target || data . target === sender ) {
117115 return { valid : false , error : 'invalid_duel_target' } ;
118116 }
119117 if ( ! data . strategy_hash ) {
@@ -135,9 +133,6 @@ var ActionValidator = (function() {
135133 var data = action . data || { } ;
136134 var duels = worldState . duels || { pending : { } } ;
137135 var duel = duels . pending && duels . pending [ String ( data . challenge_ref ) ] ;
138- if ( ! worldState . characters [ sender ] ) {
139- return { valid : false , error : 'no_character' } ;
140- }
141136 if ( ! duel ) {
142137 return { valid : false , error : 'duel_not_found' } ;
143138 }
@@ -156,9 +151,6 @@ var ActionValidator = (function() {
156151 function _validateDuelCommit ( action , worldState , sender ) {
157152 var data = action . data || { } ;
158153 var duel = _getActiveDuel ( worldState , data . combat_ref ) ;
159- if ( ! worldState . characters [ sender ] ) {
160- return { valid : false , error : 'no_character' } ;
161- }
162154 if ( ! duel ) {
163155 return { valid : false , error : 'duel_not_found' } ;
164156 }
@@ -177,9 +169,6 @@ var ActionValidator = (function() {
177169 function _validateDuelReveal ( action , worldState , sender ) {
178170 var data = action . data || { } ;
179171 var duel = _getActiveDuel ( worldState , data . combat_ref ) ;
180- if ( ! worldState . characters [ sender ] ) {
181- return { valid : false , error : 'no_character' } ;
182- }
183172 if ( ! duel ) {
184173 return { valid : false , error : 'duel_not_found' } ;
185174 }
@@ -198,9 +187,6 @@ var ActionValidator = (function() {
198187 function _validateDuelForfeit ( action , worldState , sender ) {
199188 var data = action . data || { } ;
200189 var duel = _getAnyDuel ( worldState , data . combat_ref ) ;
201- if ( ! worldState . characters [ sender ] ) {
202- return { valid : false , error : 'no_character' } ;
203- }
204190 if ( ! duel ) {
205191 return { valid : false , error : 'duel_not_found' } ;
206192 }
0 commit comments