· 5 years ago · Sep 28, 2020, 09:20 PM
1=begin
2 ==============================================================================
3 ■ Utility universali di Holy87
4 versione 1.8.0
5 Difficoltà utente: ★★★★★
6 Licenza: CC-BY. Chiunque può scaricare, modificare, distribuire e utilizzare
7 lo script nei propri progetti, sia amatoriali che commerciali. Vietata
8 l'attribuzione impropria.
9
10 ■ Questo modulo serve a espandere a nuovi livelli i vostri script e permetter-
11 vi di creare feature nel vostro gioco prima impensabili, nel modo più
12 semplice e immediato possibile. Cosa è possibile fare?
13 ● Salvare delle variabili indipendenti dal salvataggio
14 ● Ottenere informazioni dal sistema, quali la risoluzione dello schermo,
15 la lingua del sistema, la versione di Windows, il nome utente, il
16 percorso della cartella documenti ecc...
17 ● Scaricare un file e/o inviare una richiesta ed ottenere risposta da un web
18 server, anche in modo asincrono e nel modo più facile possibile
19 ● Ottenere informazioni sulla versione del gioco o impostarla
20 ● Codificare/decodificare una stringa in rot13 o Base64
21 ● Altro ancora!
22 ==============================================================================
23 ■ Changelog
24 ● V 1.8.0
25 - Ottiene informazioni sul mouse (posizione, click, visibilità...)
26 - Supporto HTTPS per richieste web POST
27 - HTTP.send_post_request DEPRECATO
28 - await_response_async DEPRECATO
29 - Nuovo sistema per gestire le richieste dal web! (vedi doc.)
30 - Nuovi metodi per richieste web:
31 HTTP.get, HTTP.post, HTTP.put, HTTP.delete
32 Queste restituiranno un oggetto Response (vedi documentazione sotto)
33 - Metodo per donwload dei file migliorato
34 - Cache.web_picture per caricare una picture direttamente da internet
35 - Aggiunta dei metodi minutes, hours e days negli integer (vedi esempi)
36 - La versione del gioco può essere inserita nel file Game.ini
37 invece che nel file dedicato Version.ini
38 - Nuovo metodo per ottenere la lingua del sistema: Win.locale_name al posto
39 di Win.language. A differenza di quest'ultimo, ora è possibile ottenere
40 direttamente la descrizione della lingua corrente (es. en-US, it-IT ecc...)
41 - Win.language DEPRECATO
42 - Win.temp_flush DEPRECATO
43 - Sistemazione e rifinitura del codice
44 - Aggiunti i metodi on_vx_ace? e on_vx? che determinano su che versione
45 di RPG Maker sta girando lo script.
46 - Molti miglioramenti e correzioni.
47 ● V 1.7.1
48 - Bugfix
49 - Win.get_folderPath deprecato. Al suo posto utilizzare il nuovo metodo
50 Win.get_folder_path
51 - Miglioramenti generali nel codice
52 ● V 1.7.0
53 - Possibilità di inviare richieste POST ad un servizio Web
54 - Possibilità di leggere un testo copiato negli appunti
55 - Possibilità di ottenere la bitmap dell'immagine del giorno di Bing
56 - Aggiunta di correzioni e robustezza
57 ● V 1.6.3
58 - Bugfix e correzioni generali
59 ● V 1.6.2
60 - Aggiunti metodi di download asincroni anche in Game_Interpreter per
61 avvio download da call script
62 ● V 1.6.1
63 - Bugfix che poteva mandare in crash il gioco se non si era connessi ad
64 internet
65 ● V 1.6.0
66 - aggiunti metodi al kernel base64_encode e base64_decode
67 - bugfix
68 ● V 1.5.0
69 - Puoi ottenere la lingua del sistema con Win.language
70 - Aggiunta possibilità di codificare o decodificare una stringa in Base64
71 - Puoi aggiungere in Game.ini la versione del gioco e richiamarla in
72 - $game_system.game_version
73 - aggiunti metodi asincroni per il download nelle finestre
74 ● V 1.4.0
75 - Possibilità di ottenere risposte da un sito web tramite GET
76 - metodi asincroni per gestire i download (vedere la documentazione)
77 - funzione per generare stringhe random di lunghezza arbitraria
78 - funzione per codificare una stringa in ROT13
79 - get_folderPath per ottenere i percorsi delle cartelle del PC
80 - fix problemi di download su VX Ace
81
82 ==============================================================================
83 ■ Compatibilità
84 DataManager -> alias load_normal_database, load_battle_test_database
85 Scene_Base -> alias update
86 Window_Base -> alias update
87 ==============================================================================
88 ■ Installazione
89 Installare questo script sotto Materials e prima del Main. Metterlo sopra a
90 tutti gli altri script che fanno uso di questo modulo.
91 ==============================================================================
92 ■ Istruzioni
93 Usare da script o da chiama evento le seguenti chiamate: quando vedi delle
94 parentesi quadre [] a dei valori significa che è facoltativo.
95
96 ▼ Valori universali di gioco
97 L'oggetto $game_settings è una classe universale che salva e conserva un
98 valore indipendentemente dal salvataggio. Può essere usato per memorizzare
99 impostazioni nella schermata del titolo, sbloccare gli extra o gestire gli
100 obiettivi, o qualsiasi cosa ti venga in mente.
101
102 ● $game_settings[quellochevuoi] = ilvalorechevuoi
103 memorizza il valore che vuoi, e viene automaticamente salvato nel file
104 game_settings.rvdata, che si trova nella cartella del gioco. Il valore
105 viene salvato anche se la partita non è stata salvata.
106
107 ● $game_settings[quellochevuoi]
108 restituisce il valore di quellochevuoi.
109
110 ● Puoi impostare la versione del gioco creando un file nel progetto con il
111 nome "version.ini", e all'interno scriverci la versione come 1.0.2.5
112 Puoi richiamare la versione dal gioco da $game_system.game_version
113 Es. versione = $game_system.game_version
114 print versione.major => 1
115 print versione.minor => 0
116 print versione.build => 2
117 print versione.revision => 5
118 print versione => 1.0.2.5
119 print versione > "1.0.1.7" => false
120
121 ▼ Chiamate di sistema
122
123 ● Win.version:
124 restituisce un decimale con il numero di versione di Windows in uso.
125 5.0 -> Windows 2000
126 5.1 -> Windows Xp
127 5.2 -> Windows Xp (64 bit)
128 6.0 -> Windows Vista
129 6.1 -> Windows 7
130 6.2 -> Windows 8
131 6.3 -> Windows 8.1
132 10.0-> Windows 10
133
134 ● Win.username
135 Restituisce una stringa con nome utente di Windows attualmente in uso
136
137 ● Win.homepath
138 Restituisce il percorso utente del computer. Esempio:
139 C:/Users/nomeutente/ in Windows Vista e succ.
140 C:/Documents and Settings/nomeutente in Windows 2000 e Xp
141
142 ● Win.get_folder_path([simbolo])
143 Restituisce il percorso di una cartella definita dal simbolo:
144 :docs -> cartella documenti dell'utente
145 :imgs -> cartella immagini dell'utente
146 :dskt -> destkop dell'utente
147 :musc -> cartella musica dell'utente
148 :vdeo -> cartella video dell'utente
149 :prog -> cartella dei programmi installati (C:\Programmi (x86))
150 * se non è definito un simbolo, viene preso :docs
151
152 ● Win.shutdown[(mode)]
153 Spegne il computer, a seconda di mode (se si omette è 0):
154 0: spegnimento normale
155 1: riavvio
156 2: ibernazione
157
158 ● Win.open(filepath)
159 Apre una cartella o un file sul PC. Specificare il percorso in filepath
160 Esempi:
161 Win.open(C:/Windows/system32/calc.exe) avvierà la calcolatrice
162 Win.open(Win.homepath+"/Desktop") aprirà la cartella del desktop
163
164 ● Win.temp_flush(nomefile) - DEPRECATO
165 elimina il file dai file temporanei di internet. Utilizzarlo prima di un
166 download di un file che viene aggiornato molto spesso.
167
168 ● Win.datenow[(partition)]
169 Restituisce la data attuale in stringa in formato "gg/mm/aaaa". Se
170 viene inserito partition come valore:
171 0: restituisce il numero del giorno in intero
172 1: restituisce il numero del mese attuale in intero
173 2: restituisce il numero dell'anno attuale in intero
174
175 ● Win.timenow[(partition)]
176 Restituisce l'ora attuale in formato "hh:mm" (h 0~24)
177 partition: 0 -> restituisce le ore in intero
178 partition: 1 -> restituisce il minuto attuale 0~59
179 partition: 2 -> restituisce i secondi 0~59
180
181 ● Win.locale_name
182 Restituisce la localizzazione corrente del sistema. Ad es.
183 Win.locale_name -> 'it-IT'
184
185 ● Win.screen_resolution
186 restituisce un array di due interi contenenti la risoluzione in lunghezza
187 e altezza dello schermo (es. [1024,730]). Ricordati che non restituisce
188 la risoluzione completa, ma solo la parte di schermo utilizzabile (cioè
189 quella non nascosta dalla barra delle applicazioni)
190
191 ● Screen.resize(lunghezza, larghezza)
192 ridimensiona la finestra di gioco. Ricordati che questa funzione non
193 aumenta la risoluzione del gioco, ma stretcha l'immagine.
194
195 ▼ Appunti
196 ● Clipboard.read_text
197 Restituisce una stringa di testo copiato dagli appunti (ad esempio,
198 quando si fa copia da un testo selezionato)
199
200 ▼ Funzioni per le stringhe
201
202 ● String.random([n_caratteri])
203 Restituisce una stringa casuale di n_caratteri. Se n_caratteri non è
204 definito, la stringa sarà di 4.
205 Esempi:
206 print String.random #=> ajpf
207 print String.random(7) #=> opetnpg
208
209 ● crypt_rot13
210 Cripta una stringa in rot13 in modo da essere illeggibile (sposta ogni
211 carattere di 13 posti nell'alfabeto). Richiamare il metodo alla stringa
212 crittografata per farla tornare normale. Esempi:
213 print "Casa".crypt_rot13 #=> "Pnfn"
214 print "Pnfn".crypt_rot13 #=> "Casa"
215
216 ● Base64.encode(stringa) e Base64.decode(stringa)
217 Restituisce una stringa in Base64 per l'interscambio di dati web
218 Per ulteriori informazioni: http://it.wikipedia.org/wiki/Base64
219
220 ● Integer #minutes, #hours, #days
221 restituiscono minuti, giorni ed ore come numero di secondi. Esempio:
222 5.minutes => 300 (300 secondi costituiscono 5 minuti)
223 10.hours => 36000
224 può essere comodo per calcolare il tempo di gioco da Graphics.frame_count.
225
226 ▼ Internet e HTTP
227
228 ● HTTP.domain
229 Restituisce il dominio principale del tuo gioco (configurabile in basso)
230 Questa opzione è molto utile quando devi trasferire il sito su un altro
231 dominio e non devi cambiare tutte le stringhe di gioco.
232
233 GET, POST, PUT, DELETE
234 In genere questi sono i metodi HTTP che vengono utilizzati per le richieste
235 web (ce ne sono altri, ma per semplificare ho limitato questi 4)
236 GET serve per ottenere le informazioni
237 POST serve per inviare delle informazioni (per la modifica, ad esempio)
238 PUT serve per creare qualcosa di nuovo
239 DELETE serve per cancellare
240
241 Questi metodi sono solo delle convenzioni, nulla ti vieta di usare GET
242 ovunque tu voglia (a patto di rispettare i requisiti del server che chiami)
243
244 ● HTTP.get(url[, parametri])
245 Invia una richiesta GET ad un server remoto tramite url e la restituisce
246 in un oggetto HTTP::Response (vedi in basso)
247 I parametri sono opzionali e consistono in un hash di valori. Esempio:
248 url = HTTP.domain + 'get_status.php'
249 params = {user_name: 'Pippo Baudo', password: '12345'}
250 response = HTTP.get(url, params)
251
252 La chiamata verrà converita in http://www.miosito.com/get_status.php?user_name=Pippo+Baudo&passord=12345
253 L'oggetto Response conterrà il risultato della richiesta.
254
255 ● HTTP.post, HTTP.put, HTTP.delete
256 Si usano allo stesso modo della get, con la differenza che i parametri
257 non vengono aggiunti all'URL ma nell'header della richiesta HTTP in modo da
258 non avere limiti di spazio e non rendere visibili le informazioni dall'url.
259
260 ● Come gestire le risposte
261 Come detto in precedenza, le chiamate HTTP restituiscono un oggetto Response.
262 response = response = HTTP.get(url, params)
263 - response.ok?: ti dice se la richiesta è andata a buon fine ed hai ottenuto
264 i dati della risposta (praticamente se il codice è 200)
265 - response.code: restituisce il codice della risposta (ad es., 200 se tutto
266 OK, 404 se non trovato ecc...)
267 - response.body: restituisce il contenuto della risposta (il messaggio)
268 - response.json?: ti dice se hai ricevuto un JSON come risposta
269 - response.description: ti stampa il codice e la sua spiegazione (es. 200 OK, 404 NOT FOUND...)
270
271 ● HTTP.download(url[, save_path, filename, secure])
272 - Scarica un file in modo asincrono (cioè che il gioco non attende che si scarica)
273 url: url del file da scaricare
274 - save_path: opzionale, indica la cartella dove scaricare il file (se non metti nulla,
275 è la cartella root del progetto)
276 - filename: opzionale, il nome del file scaricato. Se non inserito, lo script proverà
277 a ricavarlo dall'URL.
278 Il download restituirà un oggetto di tipo HTTP::Request.
279 Questo oggetto contiene la tracciabilità del download (stato di completamento, thread,
280 risposta ecc...)
281 request = HTTP.download('http://www.miosito.com/gallery/pippo.jpg', 'Pippo.jpg')
282 request.terminated indica se il download è terminato (true) oppure no (false)
283 request.size ti dirà (in Byte) quanto pesa il download.
284 request.download_rate ti indicherà la percentuale di completamento (da 0.0 a 1.0)
285 request.abort annullerà il download
286 request.response restituirà la risposta.
287
288 ● Browser.open(url)
289 apre il browser ad un sito scelto. Ricordati che se l'url è troppo grande,
290 potrebbe non avviare il sito. In questo caso ti consiglio di usare tinyurl
291 o goo.gl per rimpicciolire il link.
292
293 Questi sono metodi semplificati all'interno delle Scene_MenuBase, in quanto
294 non dovrai occuparti di gestire il download in modo complicato.
295
296 ● download_async(url, metodo[, cartella])
297 scarica dall'url. Quando il download termina, viene chiamato
298 il metodo definito da metodo. Se il metodo in questione accetta
299 un parametro, gli verrà passato l'url del file. Se ne accetta due,
300 gli verrà passato anche l'oggetto della risposta.
301 Ricordati che il riferimento al metodo viene dato con method(:nome_metodo).
302
303 ● abort_download(nomefile)
304 Annulla il download di nomefile.
305
306 ● download_status(filename)
307 Restituisce un numero intero da 0 a 100 rappresentante lo stato di download.
308
309 ● download_completed?(filename)
310 Determina se il download del file è stato completato.
311
312 ----------------------------------------------------------------------------
313 * Ottenere immagini dal web
314 ----------------------------------------------------------------------------
315 Hai presente quando, chiamando Cache.picture(nomefile) ottieni la bitmap
316 del file? Ecco, ora puoi fare lo stesso, ma invece di caricarla dal progetto,
317 la scarica direttamente da internet!
318
319 ● Cache.web_picture(url[, nomefile])
320 Scarica, mette in cache e restituisce l'immagine dal web come bitmap.
321 Se il nomefile non è specificato, verrà assegnato automaticamente.
322 Le immagini vengono salvate nella cartella Graphics/Cache.
323 Esempio
324 sprite = Sprite.new
325 sprite.bitmap = Cache.web_picture('www.miosito.com/foto_marmotta.jpg')
326 Ecco fatto! Semplice, no?
327
328 Puoi far cancellare la cache con Cache.clear_cache_folder.
329
330 ----------------------------------------------------------------------------
331 * Immagine del giorno di Bing
332 ----------------------------------------------------------------------------
333 Bing propone ogni giorno una nuova foto dal mondo. Puoi ottenere quest'im-
334 magine dal modulo Cache:
335
336 ● Cache.bing_daily
337 ti restituirà una Bitmap pronta per l'utilizzo (restituisce nil se ci sono
338 problemi di connessione)
339 La risoluzione predefinita è 640x480, ma puoi ottenerne altre impostando
340 la risoluzione nel secondo parametro:
341 Cache.bing_daily('1920x1080')
342 Non tutti i formati sono disponibili. Alcune delle risoluzioni sono:
343 QVGA (320x240, 4:3)
344 VGA (640x480, 4:3)
345 SVGA (800x600, 4:3)
346 XGA (1024x768, 4:3)
347 WXGA (1280x720 o 1280x800, 16:9)
348 HD768 (1366x768, 16:9)
349 FULLHD (1920x1080,16:9)
350 WUXGA (1920x1200, 16:10)
351 Puoi anche selezionare la risoluzione da Resolution. esempio:
352 Cache.bing_daily(Resolution::SVGA)
353 Cache.bing_daily(Resolution::WXGA)
354
355 ● Cache.bing_daily_copyright
356 Puoi ottenere l'origine dell'immagine (soggetto, autore e copyright)
357 Attenzione: da usare dopo aver preso l'immagine!
358=end
359
360#==============================================================================
361module H87_ModConfig
362 HTTPDOMAIN = 'http://miosito.com/' #dominio principale
363 SETTINGNAME = 'game_settings.rvdata2' #file impostazioni universali
364 VERSIONFILE = 'version.ini' #file versione di gioco
365 PROCESSNAME = 'RGSS Player' #nome del processo
366 RMUSERAGENT = 'RMVXA' #nome user agent per richieste POST
367end
368
369$imported = {} if $imported == nil
370$imported['H87_UniversalModule'] = 1.8
371
372#==============================================================================
373# ** Win
374#------------------------------------------------------------------------------
375# Questo modulo gestisce le chiamate di sistema e recupera informazioni sul
376# computer
377#==============================================================================
378module Win
379 # HOW TO HANDLE WINDOWS DATA TYPES:
380 # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
381 # | Type Name | Data Type | pack-unpack character |
382 # | BOOL | 32-bit signed integer (0/1) | l |
383 # | BOOLEAN | same as BYTE | C
384 # | BYTE | 8-bit unsigned char | C |
385 # | SHORT | 16-bit integer | s |
386 # | LONG | 32-bit signed integer | l |
387 # | WORD | 16-bit unsigned integer | S |
388 # | DWORD | 32-bit unsigned integer | L |
389 # | UINT | 32-bit unsigned integer | L |
390 # | WPARAM/UINT_PTR | 32/64-bit unsigned int | I_ |
391 # | LPARAM/LONG_PTR | 32/64-bit signed Long | l_ |
392 # | LPTSTR | null-terminated string pointer | A* |
393 # * note: Game.exe is 32-bit program, WPARAM and LPARAM are always 32-bit.
394
395
396 # Win32APIs
397 # noinspection RubyConstantNamingConvention
398 GetUserName = Win32API.new('advapi32', 'GetUserName', 'PP', 'I')
399 # noinspection RubyConstantNamingConvention
400 GetEnvironmentVariable = Win32API.new('kernel32', 'GetEnvironmentVariable', 'PPL', 'L')
401 # noinspection RubyConstantNamingConvention
402 SHGetFolderPath = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
403 # noinspection RubyConstantNamingConvention
404 GetSystemMetrics = Win32API.new('user32', 'GetSystemMetrics', 'I', 'I')
405 # noinspection RubyConstantNamingConvention
406 GetVersionEx = Win32API.new('kernel32', 'GetVersionEx', 'P', 'I')
407 # noinspection RubyConstantNamingConvention - deprecato
408 GetUserDefaultLCID = Win32API.new('kernel32', 'GetUserDefaultLCID', [], 'I')
409 # https://docs.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getsystemdefaultlocalename
410 GetSystemDefaultLocaleName = Win32API.new('kernel32', 'GetSystemDefaultLocaleName', 'PI', 'I')
411 # noinspection RubyConstantNamingConvention
412 GetWindowRect = Win32API.new('user32', 'GetWindowRect', 'PP', 'I')
413 # https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
414 GetLastError = Win32API.new('kernel32', 'GetLastError', '', 'I')
415
416 # useful error codes
417 ERROR_SUCCESS = 0
418 ERROR_INVALID_FUNCTION = 1
419 ERROR_FILE_NOT_FOUND = 2
420 ERROR_PATH_NOT_FOUND = 3
421 ERROR_TOO_MANY_OPEN_FILES = 4
422 ERROR_ACCESS_DENIED = 5
423 ERROR_INVALID_HANDLE = 6
424 ERROR_NOT_ENOUGH_MEMORY = 8
425 ERROR_OUTOFMEMORY = 14
426
427 # max length of filename
428 MAX_PATH = 255
429
430 # Constants
431 SM_CYFULLSCREEN = 17 # The height of the client area for a full-screen window
432 # on the primary display monitor, in pixels
433 SM_CXFULLSCREEN = 16 # The width of the client area for a full-screenwindow
434 # on the primary display monitor, in pixels
435 SM_CXHTHUMB = 10 # The width of the thumb box in a horizontal scroll bar
436 SM_CYCAPTION = 4 # The height of a caption area, in pixels.
437 SM_CXFIXEDFRAME = 7 # The thickness of the frame around the perimeter of a
438 # window that has a caption but is not sizable
439 SM_CYFIXEDFRAME = 8 # The width of the vertical border the perimeter of a
440 # window that has a caption but is not sizable
441 SM_CXSCREEN = 0 # The width of the screen of the primary display monitor
442
443 # Default locale name length
444 LOCALE_NAME_MAX_LENGTH = 85
445
446 # Restituisce il nome utente di Windows
447 # @return [String]
448 def self.username
449 name = ' ' * 128
450 size = '128'
451 GetUserName.call(name, size)
452 username = name.unpack('A*')
453 return username[0]
454 end
455
456 # Restituisce la cartella utente di Windows
457 # @return [String]
458 def self.homepath
459 username = ' ' * 256 #userprofile
460 GetEnvironmentVariable.call('userprofile', username, 256)
461 username.unpack('A*')[0].gsub('\\', '/')
462 end
463
464 # Restituisce il percorso di una cartella del computer
465 # @param [Symbol] symbol
466 # @return [String]
467 def self.get_folder_path(symbol = :docs)
468 case symbol
469 when :user
470 index = 40
471 when :docs, :documents
472 index = 5
473 when :imgs, :images, :pictures
474 index = 39
475 when :musc, :music
476 index = 13
477 when :vdeo, :video
478 index = 14
479 when :strp, :start_menu
480 index = 2
481 when :prog, :program_files
482 index = 38
483 when :appd, :app_data
484 index = 28
485 when :desktop
486 index = 0
487 when :favs, :favorites
488 index = 6
489 when :roaming
490 index = 26
491 else
492 index = 0
493 end
494 path = "\0" * 128
495 SHGetFolderPath.call(0, index, 0, 2, path)
496 path.unpack('A*')[0].gsub('\\', '/')
497 end
498
499 # Returns the Vista+ saved games folder
500 # @return [String]
501 def self.saved_games_folder
502 get_folder_path(:user) + '/Saved Games'
503 end
504
505 # Deprecated, left for compatibility
506 # @param [Symbol] symbol
507 # @return [String]
508 # @deprecated
509 def self.getFolderPath(symbol = :docs)
510 get_folder_path(symbol)
511 end
512
513 # Restituisce la larghezza della cornice della finestra
514 # @return [String]
515 def self.window_frame_width
516 GetSystemMetrics.call(SM_CXFIXEDFRAME)
517 end
518
519 # Restituisce l'altezza della barra del titolo
520 # @return [String]
521 def self.window_title_height
522 GetSystemMetrics.call(SM_CYCAPTION)
523 end
524
525 # Elimina il file temporaneo per aggiornarlo prima di un download.
526 # inserire il nome del file.
527 # @param [String] filename
528 # @deprecated non viene più utilizzato
529 def self.temp_flush(filename)
530 if version < 6
531 path = homepath + "/Impostazioni locali/Temporary Internet Files"
532 unless File.directory?(path)
533 path = homepath + "/Local Settings/Temporary Internet Files"
534 return unless File.directory?(path)
535 end
536 #noinspection Rails3Deprecated
537 fetch_folder_for_delete(path, filename)
538 else
539 path = homepath + '/AppData/Local/Microsoft/Windows/Temporary Internet Files/Content.IE5'
540 unless File.directory?(path)
541 path = homepath + '/AppData/Local/Microsoft/Windows/INetCache/IE'
542 end
543 return unless File.directory?(path)
544 Dir.foreach(path) { |x| #per ogni file nel percorso
545 next if x == "." or x == '..' #passa al prossimo se è ind.
546 if File.directory?(path + "/" + x) #se il file è una cartella
547 folder = path + "/" + x #entra nella cartella
548 #noinspection Rails3Deprecated
549 fetch_folder_for_delete(folder, filename)
550 end
551 }
552 end
553 end
554
555 # Cerca nella cartella il file da cancellare
556 # path: directory
557 # nomefile: file da cancellare
558 # @deprecated
559 def self.fetch_folder_for_delete(path, nomefile)
560 Dir.foreach(path) { |y| #per ogni file nella cartella
561 next if File.directory?(path + '/' + y) #passa al prossimo se è una c.
562 #noinspection Rails3Deprecated
563 if no_ext(nomefile) == y[0..no_ext(nomefile).size - 1] #se l'inizio del nome corrisp.
564 begin
565 File.delete(path + '/' + y) #eliminalo
566 rescue
567 next
568 end
569 end
570 }
571 end
572
573 # Restituisce la versione di Windows in uso
574 # @return [String]
575 def self.version
576 s = [20 + 128, 0, 0, 0, 0, ''].pack('LLLLLa128')
577 GetVersionEx.call(s)
578 a = s.unpack('LLLLLa128')
579 indice = a[1].to_f
580 dec = a[2].to_f / 10
581 return indice + dec
582 end
583
584 # Restituisce il nome del file senza estensione.
585 # @return [String]
586 # @deprecated
587 def self.no_ext(nomefile)
588 nome = nomefile.split(".")
589 return nome[0..nome.size - 2]
590 end
591
592 # Returns a rect containing the screen
593 # @return [Rect]
594 def self.screen
595 width = GetSystemMetrics.call(SM_CXFULLSCREEN)
596 height = GetSystemMetrics.call(SM_CYFULLSCREEN)
597 Rect.new(0, 0, width, height)
598 end
599
600 # Restituisce un array di larghezza e altezza della parte utilizzabile dello
601 # schermo: non conta lo spazio della barra delle applicazioni.
602 # @deprecated use Win::screen instead
603 def self.screen_resolution
604 x = GetSystemMetrics.call(SM_CXFULLSCREEN)
605 y = GetSystemMetrics.call(SM_CYFULLSCREEN)
606 return [x, y]
607 end
608
609 # returns the system locale name (ex. it-IT, en-US, ...)
610 # @return [String]
611 def self.locale_name
612 buff = " " * LOCALE_NAME_MAX_LENGTH
613 GetSystemDefaultLocaleName.call(buff, LOCALE_NAME_MAX_LENGTH)
614 buff.unpack('A' * LOCALE_NAME_MAX_LENGTH).delete_if { |x| x == "" } * ''
615 end
616
617 # Restituisce un intero come codice della lingua del sistema
618 # @deprecated use locale_name
619 def self.language
620 GetUserDefaultLCID.call
621 end
622
623 # Restituisce la data attuale
624 def self.datenow(partition = -1)
625 date = Time.now
626 case partition
627 when -1
628 return sprintf('%d/%d/%d', date.day, date.month, date.year)
629 when 0
630 return date.day
631 when 1
632 return date.month
633 when 2
634 return date.year
635 else
636 return -1
637 end
638 end
639
640 # Restituisce l'ora attuale
641 def self.timenow(partition = -1)
642 date = Time.now
643 case partition
644 when -1
645 return sprintf('%d:%d', date.hour, date.min)
646 when 0
647 return date.hour
648 when 1
649 return date.min
650 when 2
651 return date.sec
652 else
653 return -1
654 end
655 end
656
657 # arresta il computer in modalità diverse.
658 def self.shutdown(mode = 0)
659 string = 'system '
660 case mode
661 when 0
662 string += '-s'
663 when 1
664 string += '-r'
665 when 2
666 string += '-h'
667 else
668 return -1
669 end
670 system(string)
671 end
672
673 # this method should be used within Win32 API functions that need HWND
674 # parameters
675 # @return [Integer]
676 def self.current_window
677 Screen::FindWindowEx.call(0, 0, H87_ModConfig::PROCESSNAME, nil)
678 end
679
680 # gets the system window rect.
681 # @return [Rect]
682 def self.get_window_rect
683 w_rect = [0, 0, 0, 0].pack('l_l_l_l_')
684 this_window = current_window
685 GetWindowRect.call(this_window, w_rect)
686 rect = w_rect.unpack('l_l_l_l_')
687 Rect.new(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1])
688 end
689end #win
690
691#==============================================================================
692# ** Clipboard
693#------------------------------------------------------------------------------
694# This module handles the Windows clibpoard.
695#==============================================================================
696# noinspection ALL
697module Clipboard
698 # Clipboard types
699 CF_TEXT = 1 #plain text
700 CF_BITMAP = 2 #bitmap
701 CF_METAFILEPICT = 3 #metafile
702 CF_SYLK = 4 #symbolic link
703 CF_DIF = 5 #data interchange format
704 CF_TIFF = 6 #tiff text format
705 CF_OEMTEXT = 7 #OEM text format. Not sure it's useful
706 CF_DIB = 8 #Device Independent Bitmap Format
707
708 # Windows APIs
709 OpenClipboard = Win32API.new('user32', 'OpenClipboard', 'L', 'I')
710 GetClipboardData = Win32API.new('user32', 'GetClipboardData', 'I', 'I')
711 SetClipboardData = Win32API.new('user32', 'SetClipboardData', 'IP', 'p')
712 CloseClipboard = Win32API.new('user32', 'CloseClipboard', 'V', 'I')
713 GlobalLock = Win32API.new('kernel32', 'GlobalLock', 'L', 'L')
714 GlobalUnlock = Win32API.new('kernel32', 'GlobalUnlock', 'L', '')
715 GlobalSize = Win32API.new('kernel32', 'GlobalSize', 'L', 'L')
716 MemCpy = Win32API.new('ntdll', 'memcpy', 'PPL', 'L')
717 IsClipboardFormatAvailable = Win32API.new('user32', 'IsClipboardFormatAvailable', 'I', 'I')
718 # Returns a copied text from Windows clipboard. Can raise an error.
719 # @return [String]
720 # @raise [ClipboardDataAccessException]
721 def self.read_text
722 return '' unless open
723 begin
724 if format_avaiable?(CF_TEXT)
725 handle = get_clipboard_data(CF_TEXT)
726 buff_size = data_size(handle)
727 buffer = ' ' * (buff_size - 1)
728 copy_memory(buffer, handle, buff_size)
729 data = buffer.gsub('\0', '')
730 else
731 puts 'No text avaiable in clipboard'
732 data = ''
733 end
734 rescue
735 Logger.warning 'Read clipboard error!'
736 data = ''
737 ensure
738 CloseClipboard.call
739 end
740 data
741 end
742
743 # Returns a copied text from Windows clipboard without exceptions.
744 # @return [String]
745 def self.read_text_safe
746 read_text rescue ''
747 end
748
749 # Opens the clipboard
750 # @return [Integer]
751 def self.open
752 OpenClipboard.call(0)
753 end
754
755 # Closes the clipboard
756 def self.close
757 CloseClipboard.call
758 end
759
760 # @param [Integer] format
761 # @return [Integer]
762 def self.format_avaiable?(type)
763 IsClipboardFormatAvailable.call(type)
764 end
765
766 # @param [Object] handle
767 # @return [Integer]
768 def self.data_size(handle)
769 GlobalSize.call(handle)
770 end
771
772 # @param [Integer] type
773 # @return [Object]
774 def self.get_clipboard_data(type)
775 GetClipboardData.call(type)
776 end
777
778 # @param [String] data
779 # @param [Object] handle
780 # @param [Integer] size
781 # @return [String]
782 def self.copy_memory(data, handle, size)
783 MemCpy.call(data, handle, size)
784 end
785end #clipboard
786
787#==============================================================================
788# ** Screen
789#------------------------------------------------------------------------------
790# Questo modulo gestisce il ridimensionamento della finestra di gioco
791#==============================================================================
792module Screen
793 MoveWindow = Win32API.new("user32", "MoveWindow", 'LIIIIL', 'L')
794 FindWindowEx = Win32API.new("user32", "FindWindowEx", 'LLPP', 'I')
795
796 # ridimensiona la finestra e la centra
797 # @param[Integer] width nuova larghezza
798 # @param[Integer] height nuova altezza
799 def self.resize(width, height)
800 this_window = FindWindowEx.call(0, 0, H87_ModConfig::PROCESSNAME, nil)
801 res_x = Win.screen_resolution[0] #risoluzione x
802 res_y = Win.screen_resolution[1] #risoluzione y
803 width += Win.window_frame_width * 2
804 height += Win.window_frame_width * 2 + Win.window_title_height
805 new_x = [(res_x - width) / 2, 0].max #ottiene la nuova coordinata, ma non
806 new_y = [(res_y - height) / 2, 0].max #fa passare oltre il bordo
807 MoveWindow.call(this_window, new_x, new_y, width, height, 1)
808 end
809end #screen
810
811#==============================================================================
812# ** HTTP
813#------------------------------------------------------------------------------
814# Questo modulo permette di interfacciarsi ad internet e gestire i download.
815# Ringraziamenti: Berka (il codice è ispirato al suo)
816#==============================================================================
817module HTTP
818 # Connection types
819 INTERNET_OPEN_TYPE_PRECONFIG = 0
820 INTERNET_OPEN_TYPE_DIRECT = 1
821 INTERNET_OPEN_TYPE_PROXY = 3
822
823
824 # Internet service types
825 INTERNET_SERVICE_URL = 0
826 INTERNET_SERVICE_FTP = 1
827 INTERNET_SERVICE_GOPHER = 2
828 INTERNET_SERVICE_HTTP = 3
829
830 # Internet ports
831 INTERNET_INVALID_PORT_NUMBER = 0
832 INTERNET_DEFAULT_FTP_PORT = 21
833 INTERNET_DEFAULT_GOPHER_PORT = 70
834 INTERNET_DEFAULT_HTTP_PORT = 80
835 INTERNET_DEFAULT_HTTPS_PORT = 443
836 INTERNET_DEFAULT_SOCKS_PORT = 1080
837
838 # Internet flags
839
840 # Makes only asynchronous requests on handles descended from the
841 # handle returned from this function
842 INTERNET_FLAG_ASYNC = 0
843
844 # Forces a download of the requested file, object, or directory listing
845 # from the origin server, not from the cache. The FtpFindFirstFile,
846 # FtpGetFile, FtpOpenFile, FtpPutFile, HttpOpenRequest, and InternetOpenUrl
847 # functions use this flag.
848 INTERNET_FLAG_RELOAD = 0x80000000
849 INTERNET_FLAG_NO_CACHE_WRITE = 0x04000000
850
851 # Returns the data as a WIN32_FIND_DATA structure when retrieving
852 # FTP directory information. If this flag is not specified or if the call is made
853 # through a CERN proxy, InternetOpenUrl returns the HTML version of the directory.
854 # Only the InternetOpenUrl function uses this flag.
855 INTERNET_FLAG_RAW_DATA = 1073741824
856
857 # Uses secure transaction semantics.
858 # This translates to using Secure Sockets Layer/Private Communications Technology
859 # (SSL/PCT) and is only meaningful in HTTP requests.
860 # This flag is used by HttpOpenRequest and InternetOpenUrl, but this is redundant
861 # if https:// appears in the URL.The InternetConnect function uses this flag for
862 # HTTP connections; all the request handles created under this connection will
863 # inherit this flag.
864 INTERNET_FLAG_SECURE = 0x00800000
865
866 # Transfers file as ASCII (FTP only).
867 # This flag can be used by FtpOpenFile, FtpGetFile, and FtpPutFile.
868 INTERNET_FLAG_TRANSFER_ASCII = 0x00000001
869
870 # Transfers file as binary (FTP only).
871 # This flag can be used by FtpOpenFile, FtpGetFile, and FtpPutFile.
872 INTERNET_FLAG_TRANSFER_BINARY = 0x00000002
873
874 # Indicates that no callbacks should be made for that API.
875 # This is used for the dxContext parameter of the functions that allow asynchronous operations.
876 INTERNET_NO_CALLBACK = 0x00000000
877
878 # Attempts to use an existing InternetConnect object if one exists with the same attributes
879 # required to make the request. This is useful only with FTP operations, since FTP is the
880 # only protocol that typically performs multiple operations during the same session. WinINet
881 # caches a single connection handle for each HINTERNET handle generated by InternetOpen.
882 # The InternetOpenUrl and InternetConnect functions use this flag for Http and Ftp connections.
883 INTERNET_FLAG_EXISTING_CONNECT = 0x20000000
884
885 # Does not add the returned entity to the cache.
886 # This is identical to the preferred value, INTERNET_FLAG_NO_CACHE_WRITE.
887 INTERNET_FLAG_DONT_CACHE = 0x04000000
888
889 # Indicates that this is a Forms submission.
890 INTERNET_FLAG_FORMS_SUBMIT = 0x00000040
891
892 # Does not make network requests. All entities are returned from the cache.
893 # If the requested item is not in the cache, a suitable error, such as
894 # ERROR_FILE_NOT_FOUND, is returned. Only the InternetOpen function uses this flag.
895 INTERNET_FLAG_FROM_CACHE = 0x01000000
896
897 # Disables detection of this special type of redirect. When this flag is used,
898 # WinINet transparently allows redirects from HTTPS to HTTP URLs.
899 # This flag can be used by HttpOpenRequest and InternetOpenUrl (for HTTP requests).
900 INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP = 0x00008000
901
902 # Disables detection of this special type of redirect. When this flag is used,
903 # WinINet transparently allow redirects from HTTP to HTTPS URLs.
904 # This flag can be used by HttpOpenRequest and InternetOpenUrl (for HTTP requests).
905 INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS = 0x00004000
906
907 # Uses keep-alive semantics, if available, for the connection.
908 # This flag is used by HttpOpenRequest and InternetOpenUrl (for HTTP requests).
909 # This flag is required for Microsoft Network (MSN), NTLM, and other types of
910 # authentication.
911 INTERNET_FLAG_KEEP_CONNECTION = 0x00400000
912
913 # QUERY INFO FLAGS
914
915 # Retrieves the acceptable media types for the response.
916 HTTP_QUERY_ACCEPT = 24
917
918 # Retrieves the acceptable character sets for the response.
919 HTTP_QUERY_ACCEPT_CHARSET = 25
920
921 # Retrieves the acceptable content-coding values for the response.
922 HTTP_QUERY_ACCEPT_ENCODING = 26
923
924 # Retrieves the cache control directives.
925 HTTP_QUERY_CACHE_CONTROL = 49
926
927 # Retrieves the size of the resource, in bytes.
928 HTTP_QUERY_CONTENT_LENGTH = 5
929
930 # Retrieves an MD5 digest of the entity-body for the purpose of providing
931 # an end-to-end message integrity check (MIC) for the entity-body.
932 # For more information, see RFC1864, The Content-MD5 Header Field,
933 # at https://ftp.isi.edu/in-notes/rfc1864.txt.
934 HTTP_QUERY_CONTENT_MD5 = 52
935
936 # Receives the content type of the resource (such as text/html).
937 HTTP_QUERY_CONTENT_TYPE = 1
938
939 # Retrieves any cookies associated with the request.
940 HTTP_QUERY_COOKIE = 44
941
942 # Receives the status code returned by the server.
943 # For more information and a list of possible values, see HTTP Status Codes.
944 HTTP_QUERY_STATUS_CODE = 19
945
946
947 # HTTP Status Codes
948
949 # The request can be continued.
950 HTTP_STATUS_CONTINUE = 100
951
952 # The request completed successfully.
953 HTTP_STATUS_OK = 200
954
955 # The request has been fulfilled and resulted in the creation of a new resource.
956 HTTP_STATUS_CREATED = 201
957
958 # The request has been accepted for processing,
959 # but the processing has not been completed
960 HTTP_STATUS_ACCEPTED = 202
961
962 # The requested resource has been assigned to a new permanent URI
963 # (Uniform Resource Identifier), and any future references to this resource
964 # should be done using one of the returned URIs.
965 HTTP_STATUS_MOVED = 301
966
967 # The requested resource resides temporarily under a different URI
968 # (Uniform Resource Identifier).
969 HTTP_STATUS_REDIRECT = 302
970
971 # The request could not be processed by the server due to invalid syntax.
972 HTTP_STATUS_BAD_REQUEST = 400
973
974 # The requested resource requires user authentication.
975 HTTP_STATUS_DENIED = 401
976
977 # The server understood the request, but is refusing to fulfill it.
978 HTTP_STATUS_FORBIDDEN = 403
979
980 # The server has not found anything matching the requested
981 # URI (Uniform Resource Identifier).
982 HTTP_STATUS_NOT_FOUND = 404
983
984 # The HTTP verb used is not allowed.
985 HTTP_STATUS_BAD_METHOD = 405
986
987 # The server timed out waiting for the request.
988 HTTP_STATUS_REQUEST_TIMEOUT = 408
989
990 # The server encountered an unexpected condition that prevented it from fulfilling the request.
991 HTTP_STATUS_SERVER_ERROR = 500
992
993 # The server does not support the functionality required to fulfill the request.
994 HTTP_STATUS_NOT_SUPPORTED = 501
995
996 # The server, while acting as a gateway or proxy, received an invalid response
997 # from the upstream server it accessed in attempting to fulfill the request.
998 HTTP_STATUS_BAD_GATEWAY = 502
999
1000 # The service is temporarily overloaded.
1001 HTTP_STATUS_SERVICE_UNAVAIL = 503
1002
1003 RESPONSE_CODE_DESCRIPTIONS = {
1004 0 => 'HOST UNREACHABLE',
1005 HTTP_STATUS_OK => 'OK',
1006 HTTP_STATUS_BAD_REQUEST => 'BAD REQUEST',
1007 HTTP_STATUS_BAD_GATEWAY => 'BAD GATEWAY',
1008 HTTP_STATUS_MOVED => 'MOVED',
1009 HTTP_STATUS_REDIRECT => 'REDIRECTED',
1010 HTTP_STATUS_FORBIDDEN => 'FORBIDDEN',
1011 HTTP_STATUS_BAD_METHOD => 'BAD METHOD',
1012 HTTP_STATUS_NOT_FOUND => 'NOT FOUND',
1013 HTTP_STATUS_SERVER_ERROR => 'INTERNAL SERVER ERROR',
1014 HTTP_STATUS_SERVICE_UNAVAIL => 'SERVICE UNAVAILABLE',
1015 HTTP_STATUS_REQUEST_TIMEOUT => 'REQUEST TIMEOUT',
1016 HTTP_STATUS_BAD_GATEWAY => 'BAD GATEWAY'
1017 }
1018
1019
1020 #API Calls
1021 #SetPrClass = Win32API.new('kernel32','SetPriorityClass','pi','i').call(-1,128)
1022 InternetOpenA = Win32API.new("wininet", 'InternetOpenA', 'plppl', 'l').call(
1023 H87_ModConfig::RMUSERAGENT, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, INTERNET_FLAG_ASYNC)
1024 InternetConnectA = Win32API.new("wininet", 'InternetConnectA', 'lplpplll', 'l')
1025 InternetOpenUrl = Win32API.new("wininet", 'InternetOpenUrl', 'lppllp', 'l')
1026 InternetReadFile = Win32API.new("wininet", 'InternetReadFile', 'lpip', 'l')
1027 InternetCloseHandle = Win32API.new('wininet', 'InternetCloseHandle', 'l', 'l')
1028 HttpQueryInfo = Win32API.new('wininet', 'HttpQueryInfo', 'LLPPP', 'I')
1029 HttpOpenRequest = Win32API.new('wininet', 'HttpOpenRequestA', 'pppppplp', 'l')
1030 HttpSendRequest = Win32API.new('wininet', 'HttpSendRequestA', 'PPLPL', 'L')
1031
1032 # launches an HTTP GET request
1033 # @param [String] url
1034 # @param [Hash] params
1035 # @return [Response]
1036 def self.get(url, params = {}, secure = false)
1037 url += '?' + prepare_request(params) if params.size > 0
1038 send_request Request.new(url), :get, {}, secure
1039 end
1040
1041 # launches an HTTP POST request
1042 # @param [String] url
1043 # @param [Hash] params
1044 # @return [Response]
1045 def self.post(url, params, secure = false)
1046 send_request Request.new(url), :post, params, secure
1047 end
1048
1049 # launches an HTTP PUT request
1050 # @param [String] url
1051 # @param [Hash] params
1052 # @return [Response]
1053 def self.put(url, params, secure = false)
1054 send_request Request.new(url), :put, params, secure
1055 end
1056
1057 # launch an HTTP DELETE request
1058 # @param [String] url
1059 # @param [Hash] params
1060 # @return [Response]
1061 def self.delete(url, params, secure = false)
1062 send_request Request.new(url), :delete, params, secure
1063 end
1064
1065 # saves a file async and returns the data request.
1066 # Use
1067 # @return [HTTP::Request]
1068 # @param [String] url
1069 # @param [String] save_path
1070 # @param [String] filename
1071 def self.download(url, save_path = './', filename = nil, secure = false)
1072 request = Request.new(url, filename)
1073 filename = url_info(url)[:filename] if filename.nil?
1074 request.uri = url
1075 request.thread = Thread.start(request, save_path, filename, secure) do |request, save_path, filename, secure|
1076 begin
1077 send_request(request, :get, {}, secure)
1078 if request.response.ok?
1079 save_file(save_path, filename, request.response.body)
1080 request.terminated = true
1081 end
1082 rescue
1083 Logger.error($!)
1084 request.terminated = true
1085 end
1086 end
1087 request
1088 end
1089
1090
1091 # @return [HTTP::Request]
1092 # @param [String] url
1093 # @param [Boolean] secure
1094 def self.read_async(url, secure = false)
1095 request = Request.new(url)
1096 request.thread = Thread.start(request, secure) do |request, secure|
1097 begin
1098 send_request(request, :get, {}, secure)
1099 rescue => error
1100 Logger.error(error.class, error.message)
1101 ensure
1102 request.terminated = true
1103 end
1104 end
1105 request
1106 end
1107
1108 # launches a request with more options
1109 # @param [HTTP::Request] request
1110 # @param [Symbol, String] method
1111 # @param [Hash] params
1112 # @param [Array<Integer>] flags
1113 # @return [Response]
1114 def self.send_request(request, method = :get, params = {}, force_https = false, flags = [INTERNET_FLAG_RELOAD])
1115 url = request.uri
1116 Logger.info sprintf('%s -> %s', method.to_s.upcase, url)
1117 force_https = true if url =~ /^https:\/\//
1118 info = url_info(url)
1119 server = info[:server]
1120 root = info[:root]
1121 accept = '*/*'
1122 headers = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8'
1123 port = force_https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT
1124 service = INTERNET_SERVICE_HTTP
1125 request_params = prepare_request(params)
1126 flags.push(INTERNET_FLAG_SECURE) if force_https
1127 opts = flags.uniq.inject(0) { |o, flag| o | flag }
1128 response = Response.new
1129 request.response = response
1130
1131 session = InternetConnectA.call(InternetOpenA, server, port, nil, nil, service, 0, 1)
1132
1133 if session.nil?
1134 response.code = Win::GetLastError.call
1135 response.body = "Error while connecting to the server (code: #{response.code})"
1136 Logger.info response.description
1137 return response
1138 end
1139
1140 h_file = HttpOpenRequest.call(session, method.to_s.upcase, root, nil, nil, accept, opts, 0)
1141
1142 if HttpSendRequest.call(h_file, headers, headers.size, request_params, request_params.size)
1143 response.code = status_code h_file
1144 response.size = content_size h_file
1145 internet_read_file h_file, response.body
1146 else
1147 response.code = Win::GetLastError.call
1148 response.body = "Error while sending request (code: #{response.code})."
1149 end
1150 InternetCloseHandle.call(h_file)
1151 Logger.info response.description
1152 response
1153 end
1154
1155 # reads a resource from the web using HTTP protocol
1156 # @return [HTTP::Response]
1157 # @param [HTTP::Request] ref
1158 # @param [String] url
1159 # @param [Array<Integer>] flags
1160 def self.open_resource(ref, url, flags = [], force_https = false)
1161 force_https = true if url =~ /^https:\/\//
1162 info = url_info(url)
1163 server = info[:server]
1164 headers = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8'
1165 url += '?' + prepare_request(params)
1166 port = force_https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT
1167 service = INTERNET_SERVICE_HTTP
1168 flags.push(INTERNET_FLAG_SECURE) if force_https
1169 opts = flags.uniq.inject(0) { |o, flag| o | flag }
1170 response = ref.response
1171
1172 connection = InternetConnectA.call(InternetOpenA, server, port, '', '', service,
1173 INTERNET_FLAG_TRANSFER_ASCII, 0)
1174
1175 if connection.nil?
1176 Logger.error 'Error while connecting to the server.'
1177 raise InternetConnectionException.new 'Error while connecting to the server.'
1178 end
1179
1180 file = InternetOpenUrl.call(InternetOpenA, url, headers, headers.size, opts, nil)
1181 response.code = status_code file
1182 response.size = content_size file
1183 response.body = internet_read_file file, ref
1184 InternetCloseHandle.call(file)
1185 response
1186 end
1187
1188 # Sends a post-type request.
1189 # @param [String] url
1190 # @param [Hash] params
1191 # @param [Integer] method
1192 # @return [String]
1193 # @deprecated use HTTP::post instead
1194 def self.send_post_request(url, params = {}, force_https = false)
1195 post(url, params, force_https).body
1196 end
1197
1198 # Gets the url info
1199 # @param [String] uri
1200 # @return [Hash]
1201 def self.url_info(uri)
1202 address = uri.gsub(/^http[s]?:\/\//i, '').split('/')
1203 {
1204 :server => address[0],
1205 :root => address.size > 1 ? address[1..address.size].join('/') : address[0],
1206 :filename => address[-1],
1207
1208 }
1209 end
1210
1211 # Gets the request string
1212 # @param [Hash] request_array
1213 # @return [String]
1214 def self.prepare_request(request_array)
1215 array = []
1216 request_array.each_pair { |key, value|
1217 array.push(sprintf('%s=%s', key.to_s, value.to_s.gsub(' ', '+')))
1218 }
1219 array * '&'
1220 end
1221
1222 def self.save_file(folder, filename, data)
1223 if File.directory?(folder)
1224 obj = File.open(folder + filename, 'wb') << data
1225 obj.close #chiusura del file
1226 Logger.info("File saved: #{folder + filename}")
1227 else
1228 string = '%s is not a valid folder, so %s will not be saved.'
1229 Logger.warning sprintf(string, folder, filename)
1230 end
1231 end
1232
1233
1234 # @param [Object] h_file
1235 # @param [String] read buffer
1236 # @param [Integer] buffer_size
1237 # @return [String]
1238 def self.internet_read_file(h_file, response = '', buffer_size = 1024)
1239 loop do
1240 lp_buffer = ' ' * buffer_size
1241 bytes_read = [0].pack('i!')
1242 read_ok = InternetReadFile.call(h_file, lp_buffer, buffer_size, bytes_read)
1243 read_size = bytes_read.unpack('i!')[0]
1244 response << lp_buffer[0, read_size]
1245 break if read_ok and read_size == 0 or read_size == "NaN"
1246 end
1247 response
1248 end
1249
1250 # gets some (int) info from web resource
1251 # @param [Object] file the header file
1252 # @param [Integer] info_code the info code (see query constants)
1253 # @return [Integer]
1254 def self.http_query_info(file, info_code)
1255 buffer = "\0" * 128
1256 buffer_length = [buffer.size - 1].pack('l')
1257 status = HttpQueryInfo.call(file, info_code, buffer, buffer_length, nil)
1258 raise InternetConnectionException.new('Failed to receive the data') unless status
1259 buffer.delete!("\0").to_i
1260 end
1261
1262 # gets the status code (200 OK, 500 Server error, 404...)
1263 # @return [Integer]
1264 def self.status_code(file)
1265 http_query_info file, HTTP_QUERY_STATUS_CODE
1266 end
1267
1268 # gets the resource download size
1269 # @return [Integer]
1270 def self.content_size(file)
1271 http_query_info file, HTTP_QUERY_CONTENT_LENGTH
1272 end
1273
1274 # Ottiene la dimensione di un file remoto
1275 def self.get_file_size(url)
1276 file = InternetOpenUrl.call(InternetOpenA, url, nil, 0, 0, 0)
1277 size = content_size file
1278 InternetCloseHandle.call(file)
1279 size
1280 end
1281
1282 # Ottiene la risposta del server e la piazza nell'array delle rispose
1283 # url: indirizzo della richiesta
1284 # response_name: nome della risposta (per poterla leggere)
1285 # low_priority: priorità (false se normale, true se bassa)
1286 # @deprecated utilizza HTTP::read_async
1287 #noinspection RubyUnusedLocalVariable
1288 def self.get_server_response(url, _response_name, _low_priority = false)
1289 get(url)
1290 end
1291
1292 # Restituisce direttamente il testo di risposta dal server, interrompendo
1293 # l'esecuzione del gioco fino a quando non arriva la risposta.
1294 # url: indirizzo della richiesta
1295 # @deprecated utilizza HTTP.get
1296 def self.await_get_server_response(url)
1297 get(url).body
1298 end
1299
1300 class << self
1301 alias await_response await_get_server_response
1302 end
1303
1304 # Restituisce il dominio principale
1305 def self.domain
1306 H87_ModConfig::HTTPDOMAIN
1307 end
1308
1309 class Response
1310 attr_accessor :code
1311 attr_accessor :head
1312 # @return [String]
1313 attr_accessor :body
1314 attr_accessor :size
1315
1316 def initialize
1317 @code = 0
1318 @head = ''
1319 @body = ''
1320 @size = 0
1321 end
1322
1323 def ok?
1324 @code | HTTP_STATUS_OK == @code
1325 end
1326
1327 def progress
1328 @body.size.to_f / @size.to_f
1329 end
1330
1331 # the response code
1332 # @return [Integer]
1333 def code
1334 @code.to_i
1335 end
1336
1337 def json?
1338 return false if @body.nil?
1339 return false if @body.empty?
1340 #noinspection RegExpRedundantEscape
1341 @body =~ /^(\{.+\}|\[.*\])$/smi
1342 end
1343
1344 # @return [String]
1345 def description
1346 description = RESPONSE_CODE_DESCRIPTIONS[@code] || ''
1347 sprintf('%d %s', @code, description)
1348 end
1349
1350 def to_s
1351 @body
1352 end
1353 end
1354
1355
1356 class Request
1357 attr_accessor :terminated
1358 # @return [String]
1359 attr_accessor :uri
1360 # @return [Thread]
1361 attr_accessor :thread
1362 # @return [HTTP::Response]
1363 attr_accessor :response
1364 # @return [Method] the callback method when the resource is ready
1365 attr_accessor :callback_method
1366 # @return [String] the filename
1367 attr_accessor :filename
1368
1369
1370 def initialize(uri, filename = nil)
1371 @uri = uri
1372 @thread = nil
1373 @terminated = false
1374 @filename = filename || HTTP.url_info(uri)[:filename]
1375 end
1376
1377 def byte_downloaded
1378 return 0 if response.nil?
1379 response.body.size
1380 end
1381
1382 def size
1383 return 0 if response.nil?
1384 response.size
1385 end
1386
1387 def download_rate
1388 return 0 if size == 0
1389 [byte_downloaded.to_f / size, 1.0].min
1390 end
1391
1392 def abort
1393 return if @terminated
1394 return if self.thread.nil?
1395 self.thread.kill
1396 end
1397 end
1398end
1399
1400#==============================================================================
1401# ** Async_Downloads
1402#------------------------------------------------------------------------------
1403# Dev'essere incluso nelle classi che fanno uso dei metodi download_async.
1404#==============================================================================
1405module Async_Downloads
1406 # Scarica un file in modo asincrono lanciando automaticamente il metodo.
1407 # url: indirizzo del file
1408 # method_name: nome del metodo, in simbolo (ad es. :apri)
1409 # low: true se è a bassa incidenza, false altrimenti
1410 # folder: percorso del file di salvataggio
1411 # @param [String] url
1412 # @param [] method
1413 # @param [String] folder
1414 # @param [TrueClass] https
1415 # @return [HTTP::Request]
1416 def download_async(url, method, folder = "./", https = true)
1417 filename = url.split('/')[-1]
1418 if filename.downcase.include? ".php"
1419 Logger.warning 'This download is a call to a PHP File and should not be saved'
1420 return
1421 end
1422 @async_downloads = {} if @async_downloads.nil?
1423 @async_downloads[filename] = HTTP.download(url, folder, nil, https)
1424 @async_downloads[filename].callback_method = method
1425 @async_downloads[filename]
1426 end
1427
1428 # @return [Hash{Symbol->HTTP::Request}]
1429 def async_downloads
1430 @async_downloads = {}
1431 end
1432
1433 # Restituisce direttamente la stringa di risposta dal server
1434 # url: indirizzo della richiesta
1435 # @param [String] url
1436 # @return [String]
1437 # @raise [InternetConnectionException]
1438 # @deprecated use HTTP.get
1439 def await_response(url)
1440 HTTP.get(url).body
1441 end
1442
1443 # Controlla i download e lancia il metodo associato se completato.
1444 def check_async_downloads
1445 async_downloads.each_pair do |key, request|
1446 next unless request.terminated
1447 @async_downloads.delete(key)
1448 case request.callback_method.arity
1449 when 1
1450 request.callback_method.call(key)
1451 when 2
1452 request.callback_method.call(key, request.response)
1453 else
1454 request.callback_method.call
1455 end
1456 end
1457 end
1458
1459 # Cancella un download o l'attesa di una risposta
1460 # filename: nome del file o id della risposta
1461 def abort_download(filename)
1462 return if async_downloads[filename].nil?
1463 async_downloads[filename].abort
1464 end
1465
1466 # Restituisce la percentuale di download da 0 a 100
1467 # filename: nome del file
1468 # @param [String] filename
1469 # @return [Integer]
1470 def download_status(filename)
1471 return 1 if async_downloads[filename].nil?
1472 status = async_downloads[filename].download_rate * 100
1473 [[0, status].max, 100].min.to_i
1474 end
1475
1476 # @param [String] filename
1477 def download_completed?(filename)
1478 return true if async_downloads[filename].nil?
1479 async_downloads[filename].terminated
1480 end
1481
1482 # @param [String] url
1483 # @param [Object] method
1484 # @param [FalseClass] _priority
1485 # @deprecated use HTTP.get instead
1486 def get_response_async(url, method, _priority = false)
1487 method.call(HTTP.get(url).body)
1488 end
1489end
1490
1491#==============================================================================
1492# ** Modulo Browser per aprire il browser predefinito del PC
1493#==============================================================================
1494module Browser
1495 # apre il browser
1496 # url: url impostato
1497 # @param [String] url
1498 def self.open(url, avoid_protocol = false)
1499 #controlla che ci siano prefissi
1500 if url[0..6] != 'http://' and url[0..7] != 'https://' and !avoid_protocol
1501 open_url = 'http://' + url
1502 else
1503 open_url = url
1504 end
1505 shell = Win32API.new('Shell32', 'ShellExecute', %w(L P P P P L), 'L')
1506 Thread.new { shell.call(0, 'open', open_url, 0, 0, 1) }
1507 sleep(0.01)
1508 SceneManager.exit
1509 end
1510end #browser
1511
1512#==============================================================================
1513# ** Mouse
1514#==============================================================================
1515module Mouse
1516 CURRPOS = Win32API.new('User32', 'GetCursorPos', 'P', 'I')
1517 # gets the current cursor position
1518 # @return [MousePoint]
1519 def self.cursor_position
1520 lpoint = [0, 0].pack('l_l_')
1521 result = CURRPOS.call(lpoint)
1522 if result > 0
1523 ary = lpoint.unpack('l_l_')
1524 MousePoint.new(ary[0], ary[1])
1525 else
1526 raise GetMousePosException.new('Error occurred when obtaining cursor position')
1527 end
1528 end
1529end
1530
1531#==============================================================================
1532# ** MousePoint
1533# noinspection RubyInstanceVariableNamingConvention
1534#==============================================================================
1535class MousePoint
1536 # @attr[Fixnum] x
1537 # @attr[Fixnum] y
1538 attr_accessor :x
1539 attr_accessor :y
1540 # object initialization
1541 # @param [Fixnum] x
1542 # @param [Fixnum] y
1543 def initialize(x, y)
1544 @x = x
1545 @y = y
1546 end
1547end
1548
1549#==============================================================================
1550# ** Modulo Browser per la codifica/decodifica di stringhe in Base64
1551#==============================================================================
1552module Base64
1553 # Restituisce una stringa decodificata da Base64
1554 # string: stringa da decodificare
1555 # @param [String] string
1556 # @return [String]
1557 def self.decode(string)
1558 string.gsub(/\s+/, '').unpack('m')[0]
1559 end
1560
1561 # Restituisce una stringa codificata in Base64
1562 # string: stringa da codificare
1563 # @param [String] string
1564 # @return [String]
1565 def self.encode(string)
1566 [string].pack("m")
1567 end
1568end #base64
1569
1570#==============================================================================
1571# ** Classe Settings (per le impostazioni comuni ai salvataggi)
1572#==============================================================================
1573class H87_Settings
1574 # @return [Hash]
1575 attr_accessor :settings
1576
1577 # restituisce l'elemento corrispondente al parametro
1578 # @param [Object] param
1579 # @return [Object]
1580 def [](param)
1581 @settings ||= {}
1582 @settings[param]
1583 end
1584
1585 # inizializzazione
1586 def initialize
1587 @settings = {}
1588 end
1589
1590 # cambia o aggiunge un elemento dell'hash
1591 def []=(param_name, value)
1592 @settings[param_name] = value
1593 save
1594 end
1595
1596 # Registra i dati salvati
1597 def save
1598 save_data($game_settings, DataManager.settings_path)
1599 end
1600end
1601
1602#settings
1603
1604#==============================================================================
1605# ** Game_Version
1606#------------------------------------------------------------------------------
1607# Questa classe è d'appoggio per gestire la versione del gioco.
1608#==============================================================================
1609class Game_Version
1610 include Comparable #per la verifica delle versioni se maggiore o minore
1611 attr_accessor :major #numero di major release
1612 attr_accessor :minor #numero di minor release
1613 attr_accessor :build #numero di versione build
1614 attr_accessor :revision #numero di revisione
1615 # Inizializzazione
1616 # version_string: versione in stringa (ad es. 1.5.3.1)
1617 # @param [String] version_string
1618 # @param [Integer] starting_major
1619 def initialize(version_string, starting_major = 1)
1620 @major = starting_major
1621 @minor = 0
1622 @build = 0
1623 @revision = 0
1624 version_string.gsub!(/\s\n\r/, '')
1625 return unless version_string =~ /[\d]+([.\d]*)/
1626 version_string = version_string.split('.')
1627 @major = version_string[0].to_i
1628 return if version_string[1].nil?
1629 @minor = version_string[1].to_i
1630 return if version_string[2].nil?
1631 @build = version_string[2].to_i
1632 return if version_string[3].nil?
1633 @revision = version_string[3].to_i
1634 end
1635
1636 # Restituisce la versione attuale del gioco
1637 # @return [Game_Version]
1638 def self.now
1639 if File.exist?(H87_ModConfig::VERSIONFILE)
1640 file = File.open(H87_ModConfig::VERSIONFILE, 'r')
1641 str = file.read
1642 file.close
1643 Game_Version.new(str)
1644 elsif get_version_from_game_ini != nil
1645 get_version_from_game_ini
1646 else
1647 Game_Version.new('1.0.0.0')
1648 end
1649 end
1650
1651 # Ottiene la versione del gioco da Game.ini
1652 # @return [Game_Version]
1653 def self.get_version_from_game_ini
1654 return nil unless File.exist?('Game.ini')
1655 version = nil
1656 file = File.open('Game.ini', 'r')
1657 File.readlines.each { |line|
1658 if line =~ /version[ ]*=[ ]*([.\d]+)/i
1659 version = Game_Version.new($1)
1660 end
1661 }
1662 file.close
1663 version
1664 end
1665
1666 # Compara una versione o una stringa con se stessa
1667 def <=>(other)
1668 return self <=> Game_Version.new(other) if other.is_a?(String)
1669 return self.major <=> other.major if self.major != other.major
1670 return self.minor <=> other.minor if self.minor != other.minor
1671 return self.build <=> other.build if self.build != other.build
1672 self.revision <=> other.revision
1673 end
1674
1675 # restituisce la versione in stringa
1676 def to_s
1677 sprintf('%d.%d.%d.%d', @major, @minor, @build, @revision)
1678 end
1679end
1680
1681#game_version
1682
1683#==============================================================================
1684# ** RPG::System -> aggiunta del metodo per la versione del gioco
1685#==============================================================================
1686class Game_System
1687 # Restituisce la versione del gioco attuale
1688 def game_version
1689 Game_Version.now
1690 end
1691end
1692
1693#rpg_system
1694
1695#==============================================================================
1696# ** DataManager -> aggiunta dei metodi per caricare i settaggi
1697#==============================================================================
1698module DataManager
1699 # alias
1700 # noinspection RubyResolve
1701 class << self
1702 alias h87set_load_n_db load_normal_database
1703 alias h87set_load_b_db load_battle_test_database
1704 end
1705
1706 # caricamento nd
1707 def self.load_normal_database
1708 load_h87settings
1709 h87set_load_n_db
1710 end
1711
1712 # caricamento btd
1713 def self.load_battle_test_database
1714 load_h87settings
1715 h87set_load_b_db
1716 end
1717
1718 # restituisce il percorso delle impostazioni
1719 def self.settings_path
1720 H87_ModConfig::SETTINGNAME
1721 end
1722
1723 # carica le impostazioni universali
1724 def self.load_h87settings
1725 return if $game_settings
1726 if File.exist?(settings_path)
1727 $game_settings = load_data(settings_path)
1728 else
1729 $game_settings = H87_Settings.new
1730 save_data($game_settings, settings_path)
1731 end
1732 end
1733end #datamanager
1734
1735#==============================================================================
1736# ** Resolution
1737#------------------------------------------------------------------------------
1738# Un contenitore di risoluzioni
1739#==============================================================================
1740module Resolution
1741 QVGA = '320x240' # 4:3
1742 VGA = '640x480' # 4:3
1743 WSVGA = '1024x600' # 16:9
1744 SVGA = '800x600' # 4:3
1745 XGA = '1024x768' # 4:3
1746 SXGA = '1280x1024' # 4:3
1747 WXGA = '1280x720' # 16:9
1748 HD768 = '1366x768' # 16:9
1749 FULLHD = '1920x1080' # 16:9
1750 WUXGA = '1920x1200' # 16:10
1751end
1752
1753#==============================================================================
1754# ** Cache
1755#------------------------------------------------------------------------------
1756# Aggiunta della possibilità di scaricare l'immagine del giorno.
1757#==============================================================================
1758module Cache
1759 # downloads an image from the web.
1760 # @param [String] url
1761 # @param [String] filename
1762 # @return [Bitmap]
1763 def self.web_picture(url, filename = nil)
1764 filename = name_from_url(url) if filename.nil?
1765 @web_cache ||= {}
1766 @web_cache[filename] = web_bitmap(url, filename) unless in_download_cache?(filename)
1767 @web_cache[filename]
1768 end
1769
1770 def self.in_download_cache?(key)
1771 @web_cache[key] != nil and !@web_cache[key].disposed?
1772 end
1773
1774 # Restituisce l'immagine del giorno di Bing come bitmap.
1775 # È possibile specificare una risoluzione. Risoluzioni supportate:
1776 # QVGA, VGA, SVGA, XGA, WXGA, HD768, FULLHD, WUXGA
1777 # @param [String] resolution
1778 # @return [Bitmap]
1779 def self.bing_daily(resolution = Resolution::VGA)
1780 return empty_bitmap if bing_daily_metadata[:url_base].empty?
1781 url = "https://www.bing.com#{bing_daily_metadata[:url_base]}_#{resolution}.jpg"
1782 web_picture(url)
1783 end
1784
1785 # @return [String]
1786 def self.cache_folder
1787 './Graphics/Cache/'
1788 end
1789
1790 # delete ALL files in the Cache folder
1791 def self.clear_cache_folder
1792 Dir.foreach(cache_folder) do |file|
1793 next if file == '.'
1794 next if file == '..'
1795 next if File.directory?(cache_folder + '/' + file)
1796 File.delete(cache_folder + '/' + file)
1797 end
1798 end
1799
1800 # Restituisce il copyright dell'immagine del giorno. usare solo se già
1801 # scaricata l'immagine!
1802 # @return [String]
1803 def self.bing_daily_copyright
1804 @bing_metadata[:copyright]
1805 end
1806
1807 # Ottiene il feed xml dell'immagine di Bing e ne restituisce un hash con
1808 # informazioni, oppure nil se la connessione non è riuscita
1809 # @return [Hash]
1810 def self.bing_daily_metadata
1811 @bing_metadata ||= download_bing_daily_metadata
1812 end
1813
1814 private
1815
1816 # @param [String] url
1817 # @param [String] filename
1818 # @return [Bitmap]
1819 def self.web_bitmap(url, filename)
1820 Dir.mkdir(cache_folder) unless File.directory?(cache_folder)
1821 return load_bitmap(cache_folder, filename) if File.exist?(cache_folder + filename)
1822 request = HTTP.download(url, cache_folder, filename)
1823 loop { break if request.terminated }
1824 response = request.response
1825 if response.ok?
1826 bitmap = Bitmap.new(cache_folder + filename)
1827 else
1828 Logger.error 'Error downloading from ' + url
1829 bitmap = empty_bitmap
1830 end
1831 bitmap
1832 end
1833
1834 def self.download_bing_daily_metadata
1835 lang = Win.locale_name
1836 url = "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=#{lang}"
1837 response = HTTP.get(url, {}, true)
1838 if response.ok?
1839 info = {}
1840 info[:url_base] = read_xml(response.body, 'urlBase')
1841 info[:copyright] = read_xml(response.body, 'copyright')
1842 info[:headline] = read_xml(response.body, 'headline')
1843 info[:start_date] = read_xml(response.body, 'startdate')
1844 info
1845 else
1846 {}
1847 end
1848 end
1849
1850 # reads a node value from xml text
1851 # @param [String] xml_str
1852 # @param [Object] node
1853 def self.read_xml(xml_str, node)
1854 xml_str =~ /<#{node}>(.+)<\/#{node}>/i ? $1 : ''
1855 end
1856
1857 # @param [String] url
1858 # @return [String]
1859 def self.name_from_url(url)
1860 if url =~ /([A-Za-zÀ-ÖØ-öø-ÿ0-9]+).(png|jpg|jpeg|bmp)($|\?|&)/
1861 $1 + '.' + $2
1862 else
1863 # fallback method
1864 base64_encode(url) + '.jpg'
1865 end
1866 end
1867end
1868
1869#==============================================================================
1870# ** Aggiunta di alcuni metodi utili per le stringhe
1871#==============================================================================
1872class String
1873 # Metodo Random: restituisce una stringa a caso
1874 # size: numero di caratteri della stringa
1875 # @param [Integer] size
1876 # @return [String]
1877 def self.random(size = 4)
1878 rand(36 ** size).to_s(36)
1879 end
1880
1881 # Restituisce la stessa stringa ma crittografata in ROT13
1882 # http://it.wikipedia.org/wiki/ROT13
1883 # @return [String]
1884 def crypt_rot13
1885 self.tr('A-Za-z', 'N-ZA-Mn-za-m')
1886 end
1887end
1888
1889#fine della stringa
1890
1891#==============================================================================
1892# ** Inclusione dei metodi asincroni in Scene_Base
1893#==============================================================================
1894class Scene_Base
1895 include Async_Downloads # inclusione del modulo
1896 # Alias del metodo d'aggiornamento
1897 alias h87_module_update update unless $@
1898
1899 def update
1900 h87_module_update
1901 check_async_downloads #controlla i download
1902 end
1903end
1904
1905#==============================================================================
1906# ** Integer
1907#==============================================================================
1908class Integer
1909 # returns minutes in seconds
1910 # @return [Integer]
1911 def minutes
1912 self * 60
1913 end
1914
1915 # returns hours in seconds
1916 # @return [Integer]
1917 def hours
1918 self * 3600
1919 end
1920
1921 def seconds
1922 self
1923 end
1924
1925 # returns days in seconds
1926 # @return [Integer]
1927 def days
1928 hours * 24
1929 end
1930end
1931
1932#==============================================================================
1933# ** Object
1934#------------------------------------------------------------------------------
1935# Metodi universali di gioco
1936#==============================================================================
1937class Object
1938 # Metodo di stampa riga
1939 # @deprecated not used anymore. Please use puts instead
1940 def println(*args)
1941 puts *args
1942 end
1943
1944 # Metodi di conversione Base64
1945 # @param [String] string
1946 # @return [String]
1947 def base64_encode(string)
1948 Base64.encode(string)
1949 end
1950
1951 # @param [String] string
1952 # @return [String]
1953 def base64_decode(string)
1954 Base64.decode(string)
1955 end
1956
1957 # Restituisce direttamente la stringa di risposta dal server
1958 # url: indirizzo della richiesta
1959 # @param [String] url
1960 # @return [String]
1961 def await_response(url)
1962 HTTP.get(url).body
1963 end
1964
1965 # Restituisce direttamente la stringa di risposta dal server
1966 # url: indirizzo della richiesta
1967 # @param [String] url
1968 # @param [Hash] params
1969 # @return [String]
1970 # @raise [InternetConnectionException]
1971 def submit_post_request(url, params = {}, https = false)
1972 HTTP.post(url, params, https).body
1973 end
1974
1975 # Determina se il gioco è VX Ace
1976 def on_vx_ace?
1977 RUBY_VERSION == '1.9.2'
1978 end
1979
1980 # Determina se il gioco è VX
1981 def on_vx?
1982 RUBY_VERSION == '1.8.1'
1983 end
1984end
1985
1986#==============================================================================
1987# ** Time
1988#==============================================================================
1989class Time
1990 # @param [Date] date_str
1991 def self.from_string(date_str)
1992 if date_str =~ /(\d{4})-(\d{2})-(\d{2})/
1993 Time.new($1.to_i, $2.to_i, $3.to_i)
1994 else
1995 raise WrongDateFormatError('You must use format YYYY-MM-DD')
1996 end
1997 end
1998end
1999
2000if on_vx?
2001 #==============================================================================
2002 # ** Hash
2003 #------------------------------------------------------------------------------
2004 # changed to_s method to better print
2005 #==============================================================================
2006 class Hash
2007 # hsh.to_s -> string
2008 # hsh.inspect -> string
2009 #
2010 # Return the contents of this hash as a string.
2011 #
2012 # h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
2013 # h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"
2014 def to_s
2015 '{' + (self.inject([]) do |a, (key, value)|
2016 a.push(sprintf('%s=>%s', key, value))
2017 end * ',') + '}'
2018 end
2019 end
2020end
2021
2022
2023# launched when can't connect with the server
2024class InternetConnectionException < StandardError
2025 attr_accessor :code
2026
2027 # @param [String] message
2028 # @param [Fixnum] code
2029 def initialize(message, code = nil)
2030 super(message)
2031 @code = code
2032 end
2033
2034 # determines if the connection is not available
2035 def server_unreachable?
2036 @code == 0
2037 end
2038end
2039
2040# launched when can't read from the clipboard
2041class ClipboardDataAccessException < Exception; end
2042
2043# launched when fails to obtaining the mouse position
2044class GetMousePosException < Exception; end
2045
2046class WrongDateFormatError < StandardError
2047
2048end
2049
2050unless $imported['H87-ConsoleLogger']
2051 module Logger
2052 def self.info(*args)
2053 args[0] = '[INFO] ' + args[0].to_s
2054 puts args
2055 end
2056
2057 def self.error(*args)
2058 args[0] = '[ERROR] ' + args[0].to_s
2059 puts args
2060 end
2061
2062 def self.warning(*args)
2063 args[0] = '[WARNING] ' + args[0].to_s
2064 puts args
2065 end
2066 end
2067end