License Test.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. bool Demo=false;
  5. Str ServerLicenseKey;
  6. /******************************************************************************
  7. bool Demo=true;
  8. Str LicenseKey, ServerLicenseKey;
  9. Cipher1 LicenseCipher(238, 123, 68, 117, 43, 237, 67, 33, 144, 32, 234, 40, 101, 92, 179, 226, 153, 64, 199, 128, 181, 204, 9, 125, 7, 152, 30, 118, 174, 248, 148, 33, 173, 248, 57, 248, 97, 225, 63, 122, 21, 43, 155, 162, 243, 47, 144, 145, 169, 90, 85, 14, 16, 193, 127, 140, 182, 29, 147, 136, 239, 244, 253, 184, 247, 203, 253, 81, 10, 200, 174, 93, 1, 200, 202, 10, 188, 89, 149, 164, 92, 216, 182, 30, 52, 248, 21, 82, 251, 156, 153, 21, 170, 51, 80, 180, 61, 216, 138, 135, 251, 63, 193, 113, 62, 111, 81, 89, 202, 172, 50, 207, 239, 234, 228, 84, 188, 65, 56, 116, 200, 60, 80, 135, 244, 51, 165, 24, 74, 8, 146, 91, 207, 219, 51, 198, 162, 73, 25, 162, 177, 25, 224, 150, 173, 232, 135, 202, 172, 220, 125, 149, 39, 252, 151, 185, 54, 82, 224, 140, 55, 145, 0, 144, 140, 50, 240, 213, 56, 150, 158, 214, 217, 171, 208, 241, 248, 135, 157, 13, 101, 228, 78, 216, 253, 90, 137, 234, 22, 91, 220, 21, 231, 25, 40, 26, 165, 161, 97, 124, 231, 116, 99, 225, 118, 72, 210, 126, 18, 126, 105, 64, 234, 50, 246, 207, 167, 245, 223, 44, 235, 198, 224, 123, 82, 74, 225, 168, 57, 21, 106, 193, 239, 4, 1, 80, 29, 178, 138, 191, 134, 92, 66, 48, 94, 5, 80, 241, 168, 245, 123, 240, 217, 160, 73, 141);
  10. /******************************************************************************
  11. void SetServerLicenseKey()
  12. {
  13. Str license_key;
  14. if(LicenseKey.is())license_key=LicenseKey; // prefer regular license key first
  15. #if STEAM
  16. else if(LicenseCheck.steamSubValid())license_key=S+"Steam:"+Steam.userID();
  17. #endif
  18. if(ServerLicenseKey!=license_key)
  19. {
  20. ServerLicenseKey=license_key;
  21. Server.licenseKey(ServerLicenseKey);
  22. }
  23. }
  24. void SetDemo()
  25. {
  26. bool full=(LicenseKey.is() || LicenseCheck.steamSubValid());
  27. if(Demo==full)
  28. {
  29. Demo^=1;
  30. if(Demo!=Buy.is())if(Buy.is())Buy.del();else Buy.create();
  31. bool editor_network_interface=(full && Projs.editor_network_interface()); if(editor_network_interface!=EditServer.is())if(EditServer.is())EditServer.del();else EditServer.create();
  32. SetServerLicenseKey();
  33. }
  34. }
  35. void SetLicenseKey(C Str &key)
  36. {
  37. if(LicenseKey!=key)
  38. {
  39. LicenseKey=key;
  40. SetServerLicenseKey();
  41. SetDemo();
  42. }
  43. }
  44. void SaveLicenseKey(C Str &license_key)
  45. {
  46. File f; if(f.writeTry(SettingsPath+"data", &LicenseCipher))
  47. {
  48. f.cmpUIntV(0); // version
  49. char8 key[29]; REPAO(key)=license_key[i];
  50. f<<key;
  51. }
  52. }
  53. Str LoadLicenseKey()
  54. {
  55. char8 key[29+1]; Zero(key);
  56. File f; if(f.readStdTry(SettingsPath+"data", &LicenseCipher))switch(f.decUIntV())
  57. {
  58. case 0:
  59. {
  60. f.getN(key, 29);
  61. }break;
  62. }
  63. return key;
  64. }
  65. /******************************************************************************
  66. #if STEAM
  67. void SteamCallback(SteamWorks.RESULT result, ULong order_id, C Str &error_message, C SteamWorks.Purchase *purchase, C SteamWorks.Subscription *subscription)
  68. {
  69. Str msg;
  70. switch(result)
  71. {
  72. case SteamWorks.ORDER_REQUEST_FAILED : LicenseCheck.steam_ordering=false; msg="Failed to request an order."; break;
  73. case SteamWorks.ORDER_USER_CANCELED : LicenseCheck.steam_ordering=false; break;
  74. case SteamWorks.ORDER_FINALIZE_FAILED : LicenseCheck.steam_ordering=false; msg="Failed to finalize the order."; break;
  75. case SteamWorks.ORDER_FINALIZE_OK : LicenseCheck.steam_ordering=false; if(Steam.subscriptionState()==SteamWorks.WAITING)LicenseCheck.steam_checking=true; break; // once order was finalized re-check the status of the subscription to remove demo limitations
  76. case SteamWorks.SUBSCRIPTION_STATUS_FAILED: LicenseCheck.steam_checking=false; LicenseCheck.steam_sub_known=false; LicenseCheck.setSteamSub("Can't connect to Steam.\nPlease check if you have Internet connection.", false); SetDemo(); if(Demo && !LicenseCheck.checking())LicenseCheck.fadeIn(); break;
  77. case SteamWorks.SUBSCRIPTION_STATUS_OK : LicenseCheck.steam_checking=false; LicenseCheck.steam_sub_known=true ; if(LicenseCheck.steam_sub_is=(subscription!=null))LicenseCheck.steam_sub=*subscription; SetDemo(); if(Demo && !LicenseCheck.checking())LicenseCheck.fadeIn(); break;
  78. }
  79. if(error_message.is())msg.line()+=S+"Message from Steam: "+error_message;
  80. if(msg.is())
  81. {
  82. if(!error_message.is())msg.line()+="Please check if you have Internet connection.";
  83. Gui.msgBox("Steam", msg);
  84. }
  85. }
  86. #endif
  87. /******************************************************************************
  88. class LicenseCheckClass : ClosableWindow
  89. {
  90. class DeviceIDWindow : ClosableWindow
  91. {
  92. Text text;
  93. Button copy, open, retry;
  94. int item_id=-1;
  95. static void Copy (DeviceIDWindow &cw) {ClipSet(EsenthelStore.DeviceID());}
  96. static void Open (DeviceIDWindow &cw) {Explore(S+"http://www.esenthel.com/?id=store&item="+cw.item_id);}
  97. static void Retry(DeviceIDWindow &cw) {cw.del(); LicenseCheck.check(LicenseCheck.es[0].licenseKey(), true);}
  98. void create(int item_id)
  99. {
  100. T.item_id=item_id;
  101. Gui+=super.create(Rect_C(0, 0, 1, 0.37), "License Check"); button[2].show();
  102. T+=text .create(Vec2(clientWidth()/2, -0.10), S+"Please log in to Esenthel Store\nand set this Computer ID for your license:\n"+EsenthelStore.DeviceID());
  103. T+=copy .create(Rect_U(text.rect().down()+Vec2(-0.3, -0.11), 0.25, 0.06), "Copy ID" ).func(Copy , T).focusable(false);
  104. T+=open .create(Rect_U(text.rect().down()+Vec2( 0.0, -0.11), 0.27, 0.06), "Open Store").func(Open , T).focusable(false);
  105. T+=retry.create(Rect_U(text.rect().down()+Vec2( 0.3, -0.11), 0.26, 0.06), "Try Again" ).func(Retry, T).focusable(false);
  106. text.activate(); // to disable kb focus
  107. activate();
  108. }
  109. }
  110. bool notify=false, steam_checking=false, steam_sub_known=false, steam_sub_is=false, steam_ordering=false;
  111. int steam_item_id=0;
  112. TextBlack ts;
  113. Text text, t_get_sub, t_cur_sub;
  114. TextLine license_key;
  115. Button ok, buy, buy_steam_monthly, buy_steam_yearly;
  116. EsenthelStore es[ELMS(EsenthelStoreEngineLicense)];
  117. DeviceIDWindow window;
  118. Download steam_order_id;
  119. #if STEAM
  120. SteamWorks.Subscription steam_sub;
  121. #endif
  122. static void BuySteamMonthly(LicenseCheckClass &lc) {lc.getSteamOrderID(1);}
  123. static void BuySteamYearly (LicenseCheckClass &lc) {lc.getSteamOrderID(4);}
  124. static void Changed(LicenseCheckClass &lc) {lc.ok.text=(ValidLicenseKey(lc.license_key()) ? "OK" : "Run as Demo");}
  125. static void OK (LicenseCheckClass &lc) {SaveLicenseKey(lc.license_key()); lc.check(lc.license_key(), true);}
  126. bool steamSubValid()C
  127. {
  128. #if STEAM
  129. return steam_sub_known && steam_sub_is && steam_sub.valid();
  130. #else
  131. return false;
  132. #endif
  133. }
  134. bool checking()
  135. {
  136. REPA(es)if(es[i].licenseResult()==EsenthelStore.CONNECTING)return true;
  137. if(steam_checking)return true;
  138. return false;
  139. }
  140. void getSteamOrderID(int item_id)
  141. {
  142. #if STEAM
  143. if( Steam.overlayAvailableMsgBox())
  144. if(!Steam.userID())Gui.msgBox(S, "Unknown Steam User ID");else
  145. if(!Steam. appID())Gui.msgBox(S, "Unknown Steam App ID" );else
  146. {
  147. if(steam_item_id!=item_id)
  148. {
  149. steam_item_id=item_id;
  150. steam_order_id.del();
  151. }
  152. if(steam_order_id.state()==DWNL_NONE)
  153. {
  154. Memt<HTTPParam> p;
  155. p.New().set("u", S+Steam.userID(), HTTP_POST);
  156. p.New().set("a", S+Steam. appID(), HTTP_POST);
  157. p.New().set("i", S+ item_id , HTTP_POST);
  158. steam_order_id.create("http://esenthel.com/steam_order.php", p);
  159. }
  160. }
  161. #endif
  162. }
  163. void testLicense(C Str &license_key) // initialize test license download
  164. {
  165. REPAO(es).licenseTest(EsenthelStoreEngineLicense[i], license_key, S, true);
  166. }
  167. void check(C Str &license_key, bool notify)
  168. {
  169. hide();
  170. if(ValidLicenseKey(license_key))
  171. {
  172. if(license_key!=LicenseKey)
  173. {
  174. T.notify=notify; testLicense(license_key);
  175. }
  176. }else
  177. {
  178. SetLicenseKey(S); clear();
  179. }
  180. }
  181. virtual Window& show()override
  182. {
  183. if(hidden())license_key.clear();
  184. return super.show();
  185. }
  186. void clear(bool params=true)
  187. {
  188. REPAO(es).licenseClear(params);
  189. }
  190. void setSteamSub(C Str &text, bool buy_visible)
  191. {
  192. t_cur_sub.set(S+"Current Subscription: "+text);
  193. buy_steam_monthly.visible(buy_visible);
  194. buy_steam_yearly .visible(buy_visible);
  195. }
  196. void create()
  197. {
  198. Gui+=super.create(Rect_C(0, 0, 1, STEAM ? 0.79 : 0.37), "License Check").level(256); button[2].show();
  199. T+=text.create(Vec2(clientWidth()/2, -0.05), STEAM ? "Please enter a license key, if you already own one:" : "Please enter your license key");
  200. T+=license_key.create(Rect_U(text.pos()+Vec2(0, STEAM ? -0.04 : -0.05), 0.8, 0.06)).func(Changed, T).maxLength(29);
  201. if(!STEAM)T+=buy.create(Rect_U(license_key.rect().down()+Vec2(-0.2, -0.04), 0.3, 0.06), "Buy").func(MiscRegion.BuyLicense);
  202. T+=ok.create(Rect_U(license_key.rect().down()+Vec2(STEAM ? 0 : 0.2, STEAM ? -0.02 : -0.04), 0.3, 0.06)).func(OK, T); Changed(T);
  203. Str key=LoadLicenseKey(); if(ValidLicenseKey(key))check(key, false);
  204. #if STEAM
  205. Steam.callback=SteamCallback;
  206. ts.reset().align.set(0, -1);
  207. T+=t_get_sub.create(Vec2(clientWidth()/2, ok.rect().down().y-0.09), "-- Or get a Steam Subscription --");
  208. T+=t_cur_sub.create(Vec2(clientWidth()/2, t_get_sub.pos().y -0.09), S, &ts);
  209. T+=buy_steam_monthly.create(Rect_U(clientWidth()/2, t_cur_sub .pos().y -0.075, 0.9, 0.06), "Buy Monthly Subscription 11.40 USD/Month" ).func(BuySteamMonthly, T);
  210. T+=buy_steam_yearly .create(Rect_U(clientWidth()/2, buy_steam_monthly.rect().min.y-0.030, 0.9, 0.12), "Buy Yearly Subscription 114 USD/Year\n(20% Savings - Only 9.50 USD/Month)").func(BuySteamYearly , T); buy_steam_yearly.text_size/=2;
  211. #include "../../../../my.h"
  212. switch(Steam.subscriptionState())
  213. {
  214. case SteamWorks.STEAM_NOT_INITIALIZED: setSteamSub("'SteamAPI_Init' failed.\nPlease run the App using the Steam Client.", false); break;
  215. case SteamWorks.STEAM_NOT_SETUP : setSteamSub("Web API Key not specified", false); break;
  216. case SteamWorks. APP_ID_UNAVAILABLE : setSteamSub("Steam App ID unknown" , false); break;
  217. case SteamWorks.USER_ID_UNAVAILABLE : setSteamSub("Steam User ID unknown" , false); break;
  218. case SteamWorks.WAITING : setSteamSub("Checking" , false); steam_checking=true; hide(); break;
  219. default : setSteamSub("Unknown Error" , false); break;
  220. }
  221. #endif
  222. }
  223. virtual void update(C GuiPC &gpc)override
  224. {
  225. super.update(gpc);
  226. int fail=0; REPA(es)switch(es[i].licenseResult())
  227. {
  228. case EsenthelStore.INVALID_ITEM : Gui.msgBox(S, "Invalid Item ID" ); SetLicenseKey(S); clear(); break;
  229. case EsenthelStore.INVALID_LICENSE_KEY_FORMAT: Gui.msgBox(S, "Invalid License Key Format"); SetLicenseKey(S); clear(); break;
  230. case EsenthelStore.CANT_CONNECT:
  231. {
  232. Gui.msgBox(S, "Can't connect to Esenthel Authentication Server.\nPlease try again in a moment or check if you have Internet connection.");
  233. SetLicenseKey(S); clear(false); // keep license key in memory in case "retry" would be added
  234. }break;
  235. case EsenthelStore.INVALID_RESPONSE:
  236. {
  237. Gui.msgBox(S, "Received an invalid response from Esenthel Authentication Server.\nPlease make sure that you're connected to the Internet, you're using latest Esenthel Software or try again in a moment.");
  238. SetLicenseKey(S); clear();
  239. }break;
  240. case EsenthelStore.LICENSE_KEY_FAIL: fail++; break;
  241. case EsenthelStore.DEVICE_ID_FAIL:
  242. {
  243. window.create(es[i].licenseItemID());
  244. SetLicenseKey(S); clear(false); // keep license key in memory because it's used for "retry"
  245. }break;
  246. case EsenthelStore.CONFIRM_CODE_FAIL:
  247. {
  248. Gui.msgBox(S, "Received an invalid confirmation code from Esenthel Authentication Server.\nPlease make sure that your computer has correct date, hour and time zone set.");
  249. SetLicenseKey(S); clear();
  250. }break;
  251. case EsenthelStore.OK:
  252. {
  253. if(notify)Gui.msgBox(S, "License Key OK");
  254. SetLicenseKey(es[i].licenseKey()); clear();
  255. }break;
  256. }
  257. if(fail==Elms(es)) // all tests failed
  258. {
  259. activate(); Gui.msgBox(S, "Invalid License Key");
  260. SetLicenseKey(S); clear();
  261. }
  262. #if STEAM
  263. SetDemo(); // in case subscription expires while the Editor is running
  264. if(visible())
  265. {
  266. if(steam_sub_known)
  267. {
  268. if(steam_sub_is)
  269. {
  270. if(steam_sub.valid())
  271. {
  272. if(steam_sub.active)setSteamSub("Active" , false);
  273. else setSteamSub("Canceled", false);
  274. }else setSteamSub("Expired" , true );
  275. }else setSteamSub("None" , true );
  276. }
  277. buy_steam_monthly.enabled(steam_order_id.state()==DWNL_NONE && !steam_ordering);
  278. buy_steam_yearly .enabled(steam_order_id.state()==DWNL_NONE && !steam_ordering);
  279. }
  280. switch(steam_order_id.state())
  281. {
  282. case DWNL_ERROR:
  283. case DWNL_DONE:
  284. {
  285. ulong order_id=0;
  286. TextData td; if(td.load(FileText().readMem(steam_order_id.data(), steam_order_id.size())))if(C TextNode *p=td.findNode("order_id"))order_id=p.asULong();
  287. steam_order_id.del();
  288. if(order_id)
  289. {
  290. bool monthly=(steam_item_id==1);
  291. switch(Steam.subscribe(order_id, steam_item_id, "Esenthel Engine License", monthly ? 1140 : 11400, monthly ? SteamWorks.MONTH : SteamWorks.YEAR, 1))
  292. {
  293. case SteamWorks.WAITING : steam_ordering=true; break;
  294. case SteamWorks.STEAM_NOT_INITIALIZED: Gui.msgBox(S, "Steam Client not found" ); break;
  295. case SteamWorks.STEAM_NOT_SETUP : Gui.msgBox(S, "Web API Key not specified"); break;
  296. case SteamWorks. APP_ID_UNAVAILABLE : Gui.msgBox(S, "Steam App ID unknown" ); break;
  297. case SteamWorks.USER_ID_UNAVAILABLE : Gui.msgBox(S, "Steam User ID unknown" ); break;
  298. default : Gui.msgBox(S, "Unknown Error" ); break;
  299. }
  300. }else Gui.msgBox(S, "Can't create a Steam Order ID, please try again in a moment and check if you have Internet connection.");
  301. }break;
  302. }
  303. #endif
  304. }
  305. void draw()
  306. {
  307. #if 0
  308. switch(down.state())
  309. {
  310. case DWNL_WAIT:
  311. case DWNL_DOWNLOAD: {TextStyleParams ts; ts.size=0.04; ts.color=BLACK; ts.shadow=0; ts.align.set(-1, 1); D.text(ts, D.w(), -D.h(), "Checking License..");} break;
  312. }
  313. #endif
  314. }
  315. }
  316. LicenseCheckClass LicenseCheck;
  317. /******************************************************************************
  318. class BuyClass : Window
  319. {
  320. TextNoTest text;
  321. Button yes, no;
  322. flt time=0;
  323. static void Yes(ptr) {LicenseCheck.activate();}
  324. void create()
  325. {
  326. Gui+=super.create(Rect_C(0, 0, 1.2, 0.49), "Buy Full Version").level(LicenseCheck.level()-1).hide(); FlagDisable(flag, WIN_MOVABLE);
  327. T+=text.create(Rect_C(clientWidth()/2, -0.15, clientWidth()*0.95, 0.1), "You're running a demo version.\nWould you like to purchase full version?\n\nBy purchasing the license you're contributing to making the engine better."); text.auto_line=AUTO_LINE_SPACE_SPLIT;
  328. T+= yes.create(Rect_C(clientWidth()*1/3, -0.35, 0.29, 0.07), "Yes").focusable(false).func(Yes);
  329. T+= no.create(Rect_C(clientWidth()*2/3, -0.35, 0.29, 0.07), "No" ).focusable(false).func(HideEditAct, SCAST(GuiObj, T));
  330. }
  331. virtual Window& show()override
  332. {
  333. if(hidden())time=Time.appTime()+10;
  334. return super.show();
  335. }
  336. virtual Window& hide()override
  337. {
  338. if(visible())time=Time.appTime()+BuyFullVersionTime;
  339. return super.hide();
  340. }
  341. virtual GuiObj* test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel)override
  342. {
  343. if(visible() && gpc.visible)
  344. {
  345. GuiObj *go=super.test(gpc, pos, mouse_wheel); if(!contains(go)){mouse_wheel=null; go=this;}
  346. return go;
  347. }
  348. return null;
  349. }
  350. virtual void update(C GuiPC &gpc)override
  351. {
  352. super.update(gpc);
  353. if(visible() && gpc.visible)
  354. {
  355. flt t=time-Time.appTime();
  356. if(t>=0){no.disabled(true ); no.text=S+"No ("+Ceil(t)+')';}
  357. else {no.disabled(false); no.text= "No";}
  358. }else
  359. {
  360. if(Time.appTime()>=time)activate();
  361. }
  362. }
  363. virtual void draw(C GuiPC &gpc)override
  364. {
  365. if(visible() && gpc.visible)
  366. {
  367. D.clip();
  368. Rect(-D.w(), -D.h(), D.w(), D.h()).draw(ColorAlpha(BLACK, 0.4));
  369. super.draw(gpc);
  370. }
  371. }
  372. }
  373. BuyClass Buy;
  374. /******************************************************************************/
  375. /******************************************************************************/