Pol  Revision:3cfda13
unimod.cpp
Go to the documentation of this file.
1 
8 #include "unimod.h"
9 
10 #include <iostream>
11 #include <string.h>
12 
13 #include "../../bscript/berror.h"
14 #include "../../bscript/bobject.h"
15 #include "../../bscript/impstr.h"
16 #include "../../clib/clib_endian.h"
17 #include "../../clib/logfacility.h"
18 #include "../accounts/account.h"
19 #include "../item/item.h"
20 #include "../mobile/charactr.h"
21 #include "../network/cgdata.h"
22 #include "../network/client.h"
23 #include "../network/packethelper.h"
24 #include "../network/packets.h"
25 #include "../pktboth.h"
26 #include "../pktdef.h"
27 #include "../ufunc.h"
28 #include "../unicode.h"
29 #include "../uoexec.h"
30 #include "osmod.h"
31 
32 namespace Pol
33 {
34 namespace Core
35 {
36 using namespace Network;
37 
38 void send_unicode_prompt( Client* client, u32 serial )
39 {
41  msg->WriteFlipped<u16>( Core::PKTBI_C2::SERVER_MSGLEN );
42  msg->Write<u32>( serial ); // serial
43  msg->Write<u32>( serial ); // msg_id Server-"decided" message ID. o_O
44  msg->offset += 10; // 10x u8 unk
45  msg.Send( client );
46 }
47 
49 {
51  if ( uniemod == NULL )
52  return; // log it?
53 
54  int textlen = ( ( cfBEu16( msg->msglen ) - offsetof( Core::PKTBI_C2, wtext ) ) /
55  sizeof( msg->wtext[0] ) ); // note NO terminator!
56  if ( textlen < 0 )
57  textlen = 0;
58  if ( textlen > SPEECH_MAX_LEN )
59  {
60  textlen = SPEECH_MAX_LEN; // ENHANCE: May want to log this
61  msg->wtext[textlen] = 0x0000;
62  }
63 
64  bool ok = true;
65  Bscript::BObject* valstack = NULL;
66 
67 #if ( 0 )
68  // client version of the packet should always send this as a 1??
69  if ( cfBEu16( msg->unk ) != 0x01 )
70  {
71  // ENHANCE: May want to log this, too?
72  ok = false;
73  valstack = new BObject( new BError( "Malformed return-packet from client" ) );
74  }
75 #endif
76 
77  char lang[4];
78  memcpy( lang, msg->lang, 4 );
79 
80  if ( ok )
81  {
82  Bscript::ObjArray uc_text;
83  int i;
84  for ( i = 0; i < textlen; i++ )
85  {
86  u16 wc = msg->wtext[i]; // its not flipped!! ...i hate osi...
87  if ( wc < (u16)0x20 || wc == (u16)0x7F ) // control character! >_<
88  {
89  ok = false;
90  valstack = new Bscript::BObject(
91  new Bscript::BError( "Invalid control characters in text entry" ) );
92 
93  POLLOG_ERROR << "Client #" << static_cast<unsigned long>( client->instance_ )
94  << " (account "
95  << ( ( client->acct != NULL ) ? client->acct->name() : "unknown" )
96  << ") sent invalid unicode control characters (RequestInputUC)\n";
97  break; // for
98  }
99  uc_text.addElement( new Bscript::BLong( wc ) );
100  }
101 
102  if ( ok )
103  {
104  if ( uc_text.ref_arr.empty() )
105  valstack = new Bscript::BObject( new Bscript::BLong( 0 ) );
106  else
107  {
108  std::unique_ptr<Bscript::BStruct> retval( new Bscript::BStruct() );
109  retval->addMember( "lang", new Bscript::String( lang ) );
110  retval->addMember( "uc_text", uc_text.copy() );
111  valstack = new Bscript::BObject( retval.release() );
112  }
113  }
114  }
115 
116  uniemod->exec.ValueStack.back().set( valstack ); // error or struct, regardless.
117  uniemod->uoexec.os_module->revive();
118  uniemod->prompt_chr = NULL;
119  client->gd->prompt_uniemod = NULL;
120 }
121 
123 }
124 namespace Bscript
125 {
126 using namespace Module;
127 template <>
130  {"BroadcastUC", &UnicodeExecutorModule::mf_BroadcastUC},
131  {"PrintTextAboveUC", &UnicodeExecutorModule::mf_PrintTextAboveUC},
132  {"PrintTextAbovePrivateUC", &UnicodeExecutorModule::mf_PrivateTextAboveUC},
133  {"RequestInputUC", &UnicodeExecutorModule::mf_RequestInputUC},
134  {"SendSysMessageUC", &UnicodeExecutorModule::mf_SendSysMessageUC},
135  {"SendTextEntryGumpUC", &UnicodeExecutorModule::mf_SendTextEntryGumpUC}};
136 }
137 namespace Module
138 {
139 using namespace Bscript;
141 
143  : TmplExecutorModule<UnicodeExecutorModule>( "unicode", exec ),
144  uoexec( exec ),
145  prompt_chr( NULL )
146 {
147 }
148 
150 {
151  if ( prompt_chr != NULL )
152  {
154  prompt_chr = NULL;
155  }
156 }
157 
159 {
160  using std::wcout; // wcout rox :)
161 
162  ObjArray* oText;
163  const String* lang;
164  unsigned short font;
165  unsigned short color;
166  unsigned short requiredCmdLevel;
167  if ( getObjArrayParam( 0, oText ) && getStringParam( 1, lang ) &&
168  getParam( 2, font ) && // todo: getFontParam
169  getParam( 3, color ) && // todo: getColorParam
170  getParam( 4, requiredCmdLevel ) ) // todo: getRequiredCmdLevelParam
171  {
172  size_t textlen = oText->ref_arr.size();
173  if ( textlen > SPEECH_MAX_LEN )
174  return new BError( "Unicode array exceeds maximum size." );
175  if ( lang->length() != 3 )
176  return new BError( "langcode must be a 3-character code." );
177  // lang->toUpper(); // Language codes are in upper-case :)
178  if ( !Core::convertArrayToUC( oText, gwtext, textlen ) )
179  return new BError( "Invalid value in Unicode array." );
180  Core::broadcast( gwtext, Clib::strupper( lang->value() ).c_str(), font, color,
181  requiredCmdLevel );
182  return new BLong( 1 );
183  }
184  else
185  {
186  return new BError( "A parameter was invalid" );
187  }
188 }
189 
191 {
192  Core::UObject* obj;
193  ObjArray* oText;
194  const String* lang;
195  unsigned short font;
196  unsigned short color;
197  int journal_print;
198 
199  if ( getUObjectParam( 0, obj ) && getObjArrayParam( 1, oText ) && getStringParam( 2, lang ) &&
200  getParam( 3, font ) && getParam( 4, color ) && getParam( 5, journal_print ) )
201  {
202  size_t textlen = oText->ref_arr.size();
203  if ( textlen > SPEECH_MAX_LEN )
204  return new BError( "Unicode array exceeds maximum size." );
205  if ( lang->length() != 3 )
206  return new BError( "langcode must be a 3-character code." );
207  if ( !Core::convertArrayToUC( oText, gwtext, textlen ) )
208  return new BError( "Invalid value in Unicode array." );
209 
210  return new BLong( say_above( obj, gwtext, Clib::strupper( lang->value() ).c_str(), font, color,
211  journal_print ) );
212  }
213  else
214  {
215  return new BError( "A parameter was invalid" );
216  }
217 }
218 
220 {
221  Mobile::Character* chr;
222  Core::UObject* obj;
223  ObjArray* oText;
224  const String* lang;
225  unsigned short font;
226  unsigned short color;
227 
228  if ( getUObjectParam( 0, obj ) && getObjArrayParam( 1, oText ) && getStringParam( 2, lang ) &&
229  getCharacterParam( 3, chr ) && getParam( 4, font ) && getParam( 5, color ) )
230  {
231  size_t textlen = oText->ref_arr.size();
232  if ( textlen > SPEECH_MAX_LEN )
233  return new BError( "Unicode array exceeds maximum size." );
234  if ( lang->length() != 3 )
235  return new BError( "langcode must be a 3-character code." );
236  // lang->toUpper(); // Language codes are in upper-case :)
237  if ( !Core::convertArrayToUC( oText, gwtext, textlen ) )
238  return new BError( "Invalid value in Unicode array." );
239 
240  return new BLong( private_say_above( chr, obj, gwtext, Clib::strupper( lang->value() ).c_str(),
241  font, color ) );
242  }
243  else
244  {
245  return new BError( "A parameter was invalid" );
246  }
247 }
248 
250 {
251  Mobile::Character* chr;
252  Items::Item* item;
253  ObjArray* oPrompt;
254  const String* lang;
255  if ( getCharacterParam( 0, chr ) && getItemParam( 1, item ) && getObjArrayParam( 2, oPrompt ) &&
256  getStringParam( 3, lang ) )
257  {
258  if ( !chr->has_active_client() )
259  {
260  return new BError( "No client attached" );
261  }
262 
263  if ( chr->has_active_prompt() )
264  {
265  return new BError( "Another script has an active prompt" );
266  }
267 
268  size_t textlen = oPrompt->ref_arr.size();
269  if ( textlen > SPEECH_MAX_LEN )
270  return new BError( "Unicode array exceeds maximum size." );
271  if ( lang->length() != 3 )
272  return new BError( "langcode must be a 3-character code." );
273  if ( !Core::convertArrayToUC( oPrompt, gwtext, textlen ) )
274  return new BError( "Invalid value in Unicode array." );
275 
276  if ( !uoexec.suspend() )
277  {
278  DEBUGLOG << "Script Error in '" << scriptname() << "' PC=" << exec.PC << ": \n"
279  << "\tCall to function Unicode::RequestInputUC():\n"
280  << "\tThe execution of this script can't be blocked!\n";
281  return new Bscript::BError( "Script can't be blocked" );
282  }
283 
284  Core::send_sysmessage( chr->client, gwtext, Clib::strupper( lang->value() ).c_str() );
285 
286  chr->client->gd->prompt_uniemod = this;
287  prompt_chr = chr;
288 
290 
291  return new BLong( 0 );
292  }
293  else
294  {
295  return new BError( "A parameter was invalid" );
296  }
297 }
298 
300 {
301  Mobile::Character* chr;
302  ObjArray* oText;
303  const String* lang;
304  unsigned short font;
305  unsigned short color;
306 
307  if ( getCharacterParam( 0, chr ) && getObjArrayParam( 1, oText ) && getStringParam( 2, lang ) &&
308  getParam( 3, font ) && getParam( 4, color ) )
309  {
310  if ( chr->has_active_client() )
311  {
312  size_t textlen = oText->ref_arr.size();
313  if ( textlen > SPEECH_MAX_LEN )
314  return new BError( "Unicode array exceeds maximum size." );
315  if ( lang->length() != 3 )
316  return new BError( "langcode must be a 3-character code." );
317  // lang->toUpper(); // Language codes are in upper-case :)
318  if ( !Core::convertArrayToUC( oText, gwtext, textlen ) )
319  return new BError( "Invalid value in Unicode array." );
320 
321  Core::send_sysmessage( chr->client, gwtext, Clib::strupper( lang->value() ).c_str(), font,
322  color );
323  return new BLong( 1 );
324  }
325  else
326  {
327  return new BError( "Mobile has no active client" );
328  }
329  }
330  else
331  {
332  return new BError( "Invalid parameter type" );
333  }
334 }
335 
337 {
338  // SendTextEntryGumpUC(who, uc_text1, cancel := TE_CANCEL_ENABLE,
339  // style := TE_STYLE_NORMAL, maximum := 40, uc_text2 := {} );
340 
341  return new BError( "Function not implimented" );
342 }
343 }
344 }
void broadcast(const char *text, unsigned short font, unsigned short color, unsigned short requiredCmdLevel)
Definition: ufunc.cpp:1213
bool getItemParam(unsigned param, Items::Item *&itemptr)
Definition: unimod.h:76
const std::string & value() const
Definition: impstr.h:67
u16 gwtext[(SPEECH_MAX_LEN+1)]
Definition: unimod.cpp:140
bool has_active_prompt() const
Definition: charactr.cpp:453
ValueStackCont ValueStack
Definition: executor.h:120
UnicodeExecutorModule(Core::UOExecutor &exec)
Definition: unimod.cpp:142
Network::Client * client
Definition: charactr.h:871
Accounts::Account * acct
Definition: client.h:181
Core::UOExecutor & uoexec
Definition: unimod.h:52
#define SPEECH_MAX_LEN
Definition: pktdef.h:27
bool getParam(unsigned param, int &value)
Definition: execmodl.cpp:62
bool has_active_client() const
Definition: charactr.cpp:448
Bscript::BObjectImp * mf_BroadcastUC()
Definition: unimod.cpp:158
#define POLLOG_ERROR
Definition: logfacility.h:207
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:1032
Bscript::BObjectImp * mf_SendTextEntryGumpUC()
Definition: unimod.cpp:336
bool private_say_above(Character *chr, const UObject *obj, const char *text, unsigned short font, unsigned short color, unsigned int journal_print)
Definition: ufunc.cpp:1328
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
#define DEBUGLOG
Definition: logfacility.h:237
bool convertArrayToUC(Bscript::ObjArray *&in_text, u16 *out_wtext, size_t textlen, bool ConvToBE, bool nullterm)
Definition: unicode.cpp:21
void Send(Client *client, int len=-1) const
Definition: packethelper.h:69
const char * name() const
Definition: account.cpp:193
#define cfBEu16(x)
Definition: clib_endian.h:44
ClientGameData * gd
Definition: client.h:252
Module::UnicodeExecutorModule * prompt_uniemod
Definition: cgdata.h:68
const std::string & scriptname() const
Definition: execmodl.cpp:107
Bscript::BObjectImp * mf_RequestInputUC()
Definition: unimod.cpp:249
const String * getStringParam(unsigned param)
Definition: execmodl.cpp:36
#define ctBEu32(x)
Definition: clib_endian.h:45
void handle_unicode_prompt(Client *client, Core::PKTBI_C2 *msg)
Definition: unimod.cpp:48
Bscript::BObjectImp * mf_SendSysMessageUC()
Definition: unimod.cpp:299
Bscript::BObjectImp * mf_PrintTextAboveUC()
Definition: unimod.cpp:190
void addElement(BObjectImp *imp)
Definition: object.cpp:1399
void send_unicode_prompt(Client *client, u32 serial)
Definition: unimod.cpp:38
bool getObjArrayParam(unsigned param, ObjArray *&pobjarr)
Definition: execmodl.cpp:57
bool getCharacterParam(unsigned param, Mobile::Character *&chrptr)
Definition: unimod.h:71
std::string strupper(const std::string &str)
Definition: strutil.cpp:281
bool getUObjectParam(unsigned param, Core::UObject *&objptr)
Definition: unimod.h:81
Bscript::BObjectImp * mf_PrivateTextAboveUC()
Definition: unimod.cpp:219
bool say_above(const UObject *obj, const char *text, unsigned short font, unsigned short color, unsigned int journal_print)
Definition: ufunc.cpp:1258
Mobile::Character * prompt_chr
Definition: unimod.h:63
Definition: berror.cpp:12
size_t length() const
Definition: impstr.h:68
unsigned int instance_
Definition: client.h:253
void send_sysmessage(Network::Client *client, const char *text, unsigned short font, unsigned short color)
Definition: ufunc.cpp:1147
Module::OSExecutorModule * os_module
Definition: uoexec.h:37