diff --git a/GM Online Save.yyp b/GM Online Save.yyp new file mode 100644 index 0000000..b0f7c7b --- /dev/null +++ b/GM Online Save.yyp @@ -0,0 +1,37 @@ +{ + "resourceType": "GMProject", + "resourceVersion": "1.6", + "name": "GM Online Save", + "resources": [ + {"id":{"name":"rmGMOnlineSaveSample","path":"rooms/rmGMOnlineSaveSample/rmGMOnlineSaveSample.yy",},"order":2,}, + {"id":{"name":"objGMOnlineSave","path":"objects/objGMOnlineSave/objGMOnlineSave.yy",},"order":0,}, + {"id":{"name":"scrGMOnlineSave","path":"scripts/scrGMOnlineSave/scrGMOnlineSave.yy",},"order":1,}, + ], + "Options": [ + {"name":"operagx","path":"options/operagx/options_operagx.yy",}, + {"name":"Main","path":"options/main/options_main.yy",}, + {"name":"Windows","path":"options/windows/options_windows.yy",}, + ], + "defaultScriptType": 1, + "isEcma": false, + "configs": { + "name": "Default", + "children": [], + }, + "RoomOrderNodes": [ + {"roomId":{"name":"rmGMOnlineSaveSample","path":"rooms/rmGMOnlineSaveSample/rmGMOnlineSaveSample.yy",},}, + ], + "Folders": [ + {"resourceType":"GMFolder","resourceVersion":"1.0","name":"GMOnlineSave","folderPath":"folders/GMOnlineSave.yy","order":4,}, + ], + "AudioGroups": [ + {"resourceType":"GMAudioGroup","resourceVersion":"1.3","name":"audiogroup_default","targets":-1,}, + ], + "TextureGroups": [ + {"resourceType":"GMTextureGroup","resourceVersion":"1.3","name":"Default","isScaled":true,"compressFormat":"bz2","loadType":"default","directory":"","autocrop":true,"border":2,"mipsToGenerate":0,"groupParent":null,"targets":-1,}, + ], + "IncludedFiles": [], + "MetaData": { + "IDEVersion": "2022.11.0.54", + }, +} \ No newline at end of file diff --git a/objects/objGMOnlineSave/Other_62.gml b/objects/objGMOnlineSave/Other_62.gml new file mode 100644 index 0000000..cff0c69 --- /dev/null +++ b/objects/objGMOnlineSave/Other_62.gml @@ -0,0 +1,15 @@ +var result = "error"; + +if( ds_map_find_value(async_load, "id") == rid){ + if(ds_map_find_value(async_load, "status") == 0){ + result = ds_map_find_value(async_load, "result"); + try{ + result = json_parse(result); + }catch(ignore){} + } + + if(is_method(func_onsuccess) && result != "error") + func_onsuccess(result) + else if(is_method(func_onfailed)) + func_onfailed(result) +} diff --git a/objects/objGMOnlineSave/objGMOnlineSave.yy b/objects/objGMOnlineSave/objGMOnlineSave.yy new file mode 100644 index 0000000..747c051 --- /dev/null +++ b/objects/objGMOnlineSave/objGMOnlineSave.yy @@ -0,0 +1,37 @@ +{ + "resourceType": "GMObject", + "resourceVersion": "1.0", + "name": "objGMOnlineSave", + "spriteId": null, + "solid": false, + "visible": true, + "managed": true, + "spriteMaskId": null, + "persistent": false, + "parentObjectId": null, + "physicsObject": false, + "physicsSensor": false, + "physicsShape": 1, + "physicsGroup": 1, + "physicsDensity": 0.5, + "physicsRestitution": 0.1, + "physicsLinearDamping": 0.1, + "physicsAngularDamping": 0.1, + "physicsFriction": 0.2, + "physicsStartAwake": true, + "physicsKinematic": false, + "physicsShapePoints": [], + "eventList": [ + {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","isDnD":false,"eventNum":62,"eventType":7,"collisionObjectId":null,}, + ], + "properties": [ + {"resourceType":"GMObjectProperty","resourceVersion":"1.0","name":"rid","varType":0,"value":"0","rangeEnabled":false,"rangeMin":0.0,"rangeMax":10.0,"listItems":[],"multiselect":false,"filters":[],}, + {"resourceType":"GMObjectProperty","resourceVersion":"1.0","name":"func_onsuccess","varType":0,"value":"-1","rangeEnabled":false,"rangeMin":0.0,"rangeMax":10.0,"listItems":[],"multiselect":false,"filters":[],}, + {"resourceType":"GMObjectProperty","resourceVersion":"1.0","name":"func_onfailed","varType":0,"value":"-1","rangeEnabled":false,"rangeMin":0.0,"rangeMax":10.0,"listItems":[],"multiselect":false,"filters":[],}, + ], + "overriddenProperties": [], + "parent": { + "name": "GMOnlineSave", + "path": "folders/GMOnlineSave.yy", + }, +} \ No newline at end of file diff --git a/options/android/options_android.yy b/options/android/options_android.yy new file mode 100644 index 0000000..513b3c1 --- /dev/null +++ b/options/android/options_android.yy @@ -0,0 +1,76 @@ +{ + "resourceType": "GMAndroidOptions", + "resourceVersion": "1.0", + "name": "Android", + "option_android_sync_amazon": false, + "option_android_display_name": "Created with GameMaker", + "option_android_version": "1.0.0.0", + "option_android_tools_from_version": false, + "option_android_build_tools": "", + "option_android_support_lib": "", + "option_android_target_sdk": "", + "option_android_minimum_sdk": "", + "option_android_compile_sdk": "", + "option_android_package_domain": "com", + "option_android_package_company": "company", + "option_android_package_product": "game", + "option_android_arch_armv7": false, + "option_android_arch_arm64": true, + "option_android_arch_x86_64": false, + "option_android_orient_portrait": true, + "option_android_orient_portrait_flipped": true, + "option_android_orient_landscape": true, + "option_android_orient_landscape_flipped": true, + "option_android_gamepad_support": true, + "option_android_lint": false, + "option_android_install_location": 0, + "option_android_sleep_margin": 4, + "option_android_splash_screens_landscape": "${base_options_dir}/android/splash/landscape.png", + "option_android_splash_screens_portrait": "${base_options_dir}/android/splash/portrait.png", + "option_android_splash_time": 0, + "option_android_launchscreen_fill": 0, + "option_android_splashscreen_background_colour": 255, + "option_android_tv_banner": "${base_options_dir}/android/tv_banner.png", + "option_android_interpolate_pixels": false, + "option_android_screen_depth": 0, + "option_android_device_support": 0, + "option_android_scale": 0, + "option_android_texture_page": "2048x2048", + "option_android_icon_ldpi": "${base_options_dir}/android/icons/ldpi.png", + "option_android_icon_mdpi": "${base_options_dir}/android/icons/mdpi.png", + "option_android_icon_hdpi": "${base_options_dir}/android/icons/hdpi.png", + "option_android_icon_xhdpi": "${base_options_dir}/android/icons/xhdpi.png", + "option_android_icon_xxhdpi": "${base_options_dir}/android/icons/xxhdpi.png", + "option_android_icon_xxxhdpi": "${base_options_dir}/android/icons/xxxhdpi.png", + "option_android_icon_adaptive_generate": false, + "option_android_icon_adaptive_ldpi": "${base_options_dir}/android/icons_adaptive/ldpi.png", + "option_android_icon_adaptive_mdpi": "${base_options_dir}/android/icons_adaptive/mdpi.png", + "option_android_icon_adaptive_hdpi": "${base_options_dir}/android/icons_adaptive/hdpi.png", + "option_android_icon_adaptive_xhdpi": "${base_options_dir}/android/icons_adaptive/xhdpi.png", + "option_android_icon_adaptive_xxhdpi": "${base_options_dir}/android/icons_adaptive/xxhdpi.png", + "option_android_icon_adaptive_xxxhdpi": "${base_options_dir}/android/icons_adaptive/xxxhdpi.png", + "option_android_icon_adaptivebg_ldpi": "${base_options_dir}/android/icons_adaptivebg/ldpi.png", + "option_android_icon_adaptivebg_mdpi": "${base_options_dir}/android/icons_adaptivebg/mdpi.png", + "option_android_icon_adaptivebg_hdpi": "${base_options_dir}/android/icons_adaptivebg/hdpi.png", + "option_android_icon_adaptivebg_xhdpi": "${base_options_dir}/android/icons_adaptivebg/xhdpi.png", + "option_android_icon_adaptivebg_xxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxhdpi.png", + "option_android_icon_adaptivebg_xxxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxxhdpi.png", + "option_android_use_facebook": false, + "option_android_facebook_id": "", + "option_android_facebook_app_display_name": "", + "option_android_google_cloud_saving": false, + "option_android_google_services_app_id": "", + "option_android_permission_write_external_storage": false, + "option_android_permission_read_phone_state": false, + "option_android_permission_network_state": false, + "option_android_permission_internet": true, + "option_android_permission_bluetooth": true, + "option_android_permission_record_audio": false, + "option_android_application_tag_inject": "", + "option_android_google_apk_expansion": false, + "option_android_google_dynamic_asset_delivery": false, + "option_android_google_licensing_public_key": "", + "option_android_tv_isgame": true, + "option_android_proguard_minifying": false, + "option_android_proguard_shrinking": false, +} \ No newline at end of file diff --git a/options/html5/options_html5.yy b/options/html5/options_html5.yy new file mode 100644 index 0000000..e9ba8bc --- /dev/null +++ b/options/html5/options_html5.yy @@ -0,0 +1,33 @@ +{ + "resourceType": "GMHtml5Options", + "resourceVersion": "1.0", + "name": "HTML5", + "option_html5_browser_title": "Created with GameMaker", + "option_html5_version": "1.0.0.0", + "option_html5_foldername": "html5game", + "option_html5_outputname": "index.html", + "option_html5_splash_png": "${base_options_dir}/html5/splash.png", + "option_html5_usesplash": false, + "option_html5_outputdebugtoconsole": true, + "option_html5_display_cursor": true, + "option_html5_localrunalert": true, + "option_html5_index": "", + "option_html5_loadingbar": "", + "option_html5_jsprepend": "", + "option_html5_icon": "${base_options_dir}/html5/fav.ico", + "option_html5_allow_fullscreen": true, + "option_html5_interpolate_pixels": true, + "option_html5_centregame": false, + "option_html5_usebuiltinparticles": true, + "option_html5_usebuiltinfont": true, + "option_html5_webgl": 2, + "option_html5_scale": 0, + "option_html5_texture_page": "2048x2048", + "option_html5_use_facebook": false, + "option_html5_facebook_id": "", + "option_html5_facebook_app_display_name": "", + "option_html5_flurry_enable": false, + "option_html5_flurry_id": "", + "option_html5_google_analytics_enable": false, + "option_html5_google_tracking_id": "", +} \ No newline at end of file diff --git a/options/ios/options_ios.yy b/options/ios/options_ios.yy new file mode 100644 index 0000000..64c726b --- /dev/null +++ b/options/ios/options_ios.yy @@ -0,0 +1,46 @@ +{ + "resourceType": "GMiOSOptions", + "resourceVersion": "1.3", + "name": "iOS", + "option_ios_display_name": "Created with GameMaker", + "option_ios_bundle_name": "com.company.game", + "option_ios_version": "1.0.0.0", + "option_ios_output_dir": "~/gamemakerstudio2", + "option_ios_team_id": "", + "option_ios_min_version": "10.0", + "option_ios_cocoapods_checkbox": true, + "option_ios_orientation_portrait": true, + "option_ios_orientation_portrait_flipped": true, + "option_ios_orientation_landscape": true, + "option_ios_orientation_landscape_flipped": true, + "option_ios_devices": 2, + "option_ios_defer_home_indicator": false, + "option_ios_icon_iphone_app_120": "${base_options_dir}/ios/icons/app/iphone_120.png", + "option_ios_icon_iphone_app_180": "${base_options_dir}/ios/icons/app/iphone_180.png", + "option_ios_icon_ipad_app_76": "${base_options_dir}/ios/icons/app/ipad_76.png", + "option_ios_icon_ipad_app_152": "${base_options_dir}/ios/icons/app/ipad_152.png", + "option_ios_icon_ipad_pro_app_167": "${base_options_dir}/ios/icons/app/ipad_pro_167.png", + "option_ios_icon_iphone_notification_40": "${base_options_dir}/ios/icons/notification/iphone_40.png", + "option_ios_icon_iphone_notification_60": "${base_options_dir}/ios/icons/notification/iphone_60.png", + "option_ios_icon_ipad_notification_20": "${base_options_dir}/ios/icons/notification/ipad_20.png", + "option_ios_icon_ipad_notification_40": "${base_options_dir}/ios/icons/notification/ipad_40.png", + "option_ios_icon_iphone_spotlight_80": "${base_options_dir}/ios/icons/spotlight/iphone_80.png", + "option_ios_icon_iphone_spotlight_120": "${base_options_dir}/ios/icons/spotlight/iphone_120.png", + "option_ios_icon_ipad_spotlight_40": "${base_options_dir}/ios/icons/spotlight/ipad_40.png", + "option_ios_icon_ipad_spotlight_80": "${base_options_dir}/ios/icons/spotlight/ipad_80.png", + "option_ios_icon_iphone_settings_58": "${base_options_dir}/ios/icons/settings/iphone_58.png", + "option_ios_icon_iphone_settings_87": "${base_options_dir}/ios/icons/settings/iphone_87.png", + "option_ios_icon_ipad_settings_29": "${base_options_dir}/ios/icons/settings/ipad_29.png", + "option_ios_icon_ipad_settings_58": "${base_options_dir}/ios/icons/settings/ipad_58.png", + "option_ios_icon_itunes_artwork_1024": "${base_options_dir}/ios/icons/itunes/itunes_1024.png", + "option_ios_splashscreen_background_colour": 255, + "option_ios_launchscreen_image": "${base_options_dir}/ios/splash/launchscreen.png", + "option_ios_launchscreen_image_landscape": "${base_options_dir}/ios/splash/launchscreen-landscape.png", + "option_ios_launchscreen_fill": 0, + "option_ios_interpolate_pixels": false, + "option_ios_half_ipad1_textures": false, + "option_ios_scale": 0, + "option_ios_texture_page": "2048x2048", + "option_ios_podfile_path": "${options_dir}/ios/Podfile", + "option_ios_podfile_lock_path": "${options_dir}/ios/Podfile.lock", +} \ No newline at end of file diff --git a/options/linux/options_linux.yy b/options/linux/options_linux.yy new file mode 100644 index 0000000..d3575b0 --- /dev/null +++ b/options/linux/options_linux.yy @@ -0,0 +1,24 @@ +{ + "resourceType": "GMLinuxOptions", + "resourceVersion": "1.0", + "name": "Linux", + "option_linux_display_name": "Created with GameMaker", + "option_linux_version": "1.0.0.0", + "option_linux_maintainer_email": "", + "option_linux_homepage": "http://www.yoyogames.com", + "option_linux_short_desc": "", + "option_linux_long_desc": "", + "option_linux_splash_screen": "${base_options_dir}/linux/splash/splash.png", + "option_linux_display_splash": false, + "option_linux_icon": "${base_options_dir}/linux/icons/64.png", + "option_linux_start_fullscreen": false, + "option_linux_allow_fullscreen": false, + "option_linux_interpolate_pixels": true, + "option_linux_display_cursor": true, + "option_linux_sync": false, + "option_linux_resize_window": false, + "option_linux_scale": 0, + "option_linux_texture_page": "2048x2048", + "option_linux_enable_steam": false, + "option_linux_disable_sandbox": false, +} \ No newline at end of file diff --git a/options/mac/options_mac.yy b/options/mac/options_mac.yy new file mode 100644 index 0000000..cd91596 --- /dev/null +++ b/options/mac/options_mac.yy @@ -0,0 +1,35 @@ +{ + "resourceType": "GMMacOptions", + "resourceVersion": "1.0", + "name": "macOS", + "option_mac_display_name": "Created with GameMaker", + "option_mac_app_id": "com.company.game", + "option_mac_version": "1.0.0.0", + "option_mac_output_dir": "~/gamemakerstudio2", + "option_mac_team_id": "", + "option_mac_signing_identity": "Developer ID Application:", + "option_mac_copyright": "", + "option_mac_splash_png": "${base_options_dir}/mac/splash/splash.png", + "option_mac_icon_png": "${base_options_dir}/mac/icons/1024.png", + "option_mac_installer_background_png": "${base_options_dir}/mac/splash/installer_background.png", + "option_mac_menu_dock": false, + "option_mac_display_cursor": true, + "option_mac_start_fullscreen": false, + "option_mac_allow_fullscreen": false, + "option_mac_interpolate_pixels": true, + "option_mac_vsync": false, + "option_mac_resize_window": false, + "option_mac_enable_retina": false, + "option_mac_scale": 0, + "option_mac_texture_page": "2048x2048", + "option_mac_build_app_store": false, + "option_mac_allow_incoming_network": false, + "option_mac_allow_outgoing_network": false, + "option_mac_app_category": "Games", + "option_mac_enable_steam": false, + "option_mac_disable_sandbox": false, + "option_mac_x86_64": true, + "option_mac_arm64": true, + "option_mac_apple_sign_in": false, + "option_mac_min_version": "10.10", +} \ No newline at end of file diff --git a/options/main/options_main.yy b/options/main/options_main.yy new file mode 100644 index 0000000..d3a96f0 --- /dev/null +++ b/options/main/options_main.yy @@ -0,0 +1,20 @@ +{ + "resourceType": "GMMainOptions", + "resourceVersion": "1.4", + "name": "Main", + "option_gameguid": "71919190-9da0-4c28-a0ec-98c6d72e02ee", + "option_gameid": "0", + "option_game_speed": 60, + "option_mips_for_3d_textures": false, + "option_draw_colour": 4294967295, + "option_window_colour": 255, + "option_steam_app_id": "0", + "option_sci_usesci": true, + "option_author": "", + "option_collision_compatibility": false, + "option_copy_on_write_enabled": false, + "option_spine_licence": false, + "option_template_image": "${base_options_dir}/main/template_image.png", + "option_template_icon": "${base_options_dir}/main/template_icon.png", + "option_template_description": "", +} \ No newline at end of file diff --git a/options/operagx/options_operagx.yy b/options/operagx/options_operagx.yy new file mode 100644 index 0000000..e4f3f26 --- /dev/null +++ b/options/operagx/options_operagx.yy @@ -0,0 +1,18 @@ +{ + "resourceType": "GMOperaGXOptions", + "resourceVersion": "1.0", + "name": "operagx", + "option_operagx_version": "1.0.0.0", + "option_operagx_next_version": "1.0.0.1", + "option_operagx_game_name": "GM Online Save", + "option_operagx_interpolate_pixels": true, + "option_operagx_scale": 0, + "option_operagx_texture_page": "2048x2048", + "option_operagx_display_cursor": true, + "option_operagx_guid": "efe3b863-dfae-4072-a530-a9f2f4d918d2", + "option_operagx_team_name": "GX", + "option_operagx_team_id": "2faa0ee2-a735-451e-b197-ccf90264d138", + "option_operagx_editUrl": "https://create.gx.games/game/efe3b863-dfae-4072-a530-a9f2f4d918d2/edit", + "option_operagx_internalShareUrl": "", + "option_operagx_publicShareUrl": "", +} \ No newline at end of file diff --git a/options/tvos/options_tvos.yy b/options/tvos/options_tvos.yy new file mode 100644 index 0000000..4dca9da --- /dev/null +++ b/options/tvos/options_tvos.yy @@ -0,0 +1,28 @@ +{ + "resourceType": "GMtvOSOptions", + "resourceVersion": "1.3", + "name": "tvOS", + "option_tvos_display_name": "Made in GameMaker", + "option_tvos_bundle_name": "com.company.game", + "option_tvos_version": "1.0.0.0", + "option_tvos_output_dir": "~/GameMakerStudio2/tvOS", + "option_tvos_team_id": "", + "option_tvos_min_version": "10.0", + "option_tvos_cocoapods_checkbox": true, + "option_tvos_icon_400": "${base_options_dir}/tvos/icons/400.png", + "option_tvos_icon_400_2x": "${base_options_dir}/tvos/icons/400_2x.png", + "option_tvos_icon_1280": "${base_options_dir}/tvos/icons/1280.png", + "option_tvos_topshelf": "${base_options_dir}/tvos/topshelf/topshelf.png", + "option_tvos_topshelf_2x": "${base_options_dir}/tvos/topshelf/topshelf_2x.png", + "option_tvos_topshelf_wide": "${base_options_dir}/tvos/topshelf/topshelf_wide.png", + "option_tvos_topshelf_wide_2x": "${base_options_dir}/tvos/topshelf/topshelf_wide_2x.png", + "option_tvos_splashscreen": "${base_options_dir}/tvos/splash/splash.png", + "option_tvos_splashscreen_2x": "${base_options_dir}/tvos/splash/splash_2x.png", + "option_tvos_splash_time": 0, + "option_tvos_interpolate_pixels": true, + "option_tvos_scale": 0, + "option_tvos_texture_page": "2048x2048", + "option_tvos_display_cursor": false, + "option_tvos_podfile_path": "${options_dir}\\tvos\\Podfile", + "option_tvos_podfile_lock_path": "${options_dir}\\tvos\\Podfile.lock", +} \ No newline at end of file diff --git a/options/windows/options_windows.yy b/options/windows/options_windows.yy new file mode 100644 index 0000000..adc34c3 --- /dev/null +++ b/options/windows/options_windows.yy @@ -0,0 +1,34 @@ +{ + "resourceType": "GMWindowsOptions", + "resourceVersion": "1.1", + "name": "Windows", + "option_windows_display_name": "GM Online Save", + "option_windows_executable_name": "${project_name}.exe", + "option_windows_version": "0.0.0.1", + "option_windows_company_info": "septn", + "option_windows_product_info": "", + "option_windows_copyright_info": "", + "option_windows_description_info": "", + "option_windows_display_cursor": true, + "option_windows_icon": "${base_options_dir}/windows/icons/icon.ico", + "option_windows_save_location": 0, + "option_windows_splash_screen": "${base_options_dir}/windows/splash/splash.png", + "option_windows_use_splash": false, + "option_windows_start_fullscreen": false, + "option_windows_allow_fullscreen_switching": false, + "option_windows_interpolate_pixels": false, + "option_windows_vsync": false, + "option_windows_resize_window": false, + "option_windows_borderless": false, + "option_windows_scale": 0, + "option_windows_copy_exe_to_dest": false, + "option_windows_sleep_margin": 10, + "option_windows_texture_page": "2048x2048", + "option_windows_installer_finished": "${base_options_dir}/windows/installer/finished.bmp", + "option_windows_installer_header": "${base_options_dir}/windows/installer/header.bmp", + "option_windows_license": "${base_options_dir}/windows/installer/license.txt", + "option_windows_nsis_file": "${base_options_dir}/windows/installer/nsis_script.nsi", + "option_windows_enable_steam": false, + "option_windows_disable_sandbox": false, + "option_windows_steam_use_alternative_launcher": false, +} \ No newline at end of file diff --git a/rooms/rmGMOnlineSaveSample/RoomCreationCode.gml b/rooms/rmGMOnlineSaveSample/RoomCreationCode.gml new file mode 100644 index 0000000..86d4336 --- /dev/null +++ b/rooms/rmGMOnlineSaveSample/RoomCreationCode.gml @@ -0,0 +1,29 @@ +playerdata = { + name: "Hawk Eye", + job: "Archer", + level: 55, + gold: 2000 +} + + +// Sample writing a save +gmos_init("00000000-0000-0000-0000-000000000000","testUser1"); +gmos_write("player.json", playerdata) +/// + + + return; +// Sample loading that save (comment the ^return above) +gmos_read("player.json", + function(result){ + show_message("load success!"); + show_message(result.name); + show_message(result.job); + show_message(result.level); + }, + function(result){ + show_message("load failed!"); + show_message(result); + } +); +/// \ No newline at end of file diff --git a/rooms/rmGMOnlineSaveSample/rmGMOnlineSaveSample.yy b/rooms/rmGMOnlineSaveSample/rmGMOnlineSaveSample.yy new file mode 100644 index 0000000..c931cb6 --- /dev/null +++ b/rooms/rmGMOnlineSaveSample/rmGMOnlineSaveSample.yy @@ -0,0 +1,51 @@ +{ + "resourceType": "GMRoom", + "resourceVersion": "1.0", + "name": "rmGMOnlineSaveSample", + "isDnd": false, + "volume": 1.0, + "parentRoom": null, + "views": [ + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,}, + ], + "layers": [ + {"resourceType":"GMRInstanceLayer","resourceVersion":"1.0","name":"Instances","instances":[],"visible":true,"depth":0,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritVisibility":true,"inheritSubLayers":true,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"effectEnabled":true,"effectType":null,"properties":[],}, + {"resourceType":"GMRBackgroundLayer","resourceVersion":"1.0","name":"Background","spriteId":null,"colour":4278190080,"x":0,"y":0,"htiled":false,"vtiled":false,"hspeed":0.0,"vspeed":0.0,"stretch":false,"animationFPS":15.0,"animationSpeedType":0,"userdefinedAnimFPS":false,"visible":true,"depth":100,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritVisibility":true,"inheritSubLayers":true,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"effectEnabled":true,"effectType":null,"properties":[],}, + ], + "inheritLayers": false, + "creationCodeFile": "${project_dir}/rooms/rmGMOnlineSaveSample/RoomCreationCode.gml", + "inheritCode": false, + "instanceCreationOrder": [], + "inheritCreationOrder": false, + "sequenceId": null, + "roomSettings": { + "inheritRoomSettings": false, + "Width": 1366, + "Height": 768, + "persistent": false, + }, + "viewSettings": { + "inheritViewSettings": false, + "enableViews": false, + "clearViewBackground": false, + "clearDisplayBuffer": true, + }, + "physicsSettings": { + "inheritPhysicsSettings": false, + "PhysicsWorld": false, + "PhysicsWorldGravityX": 0.0, + "PhysicsWorldGravityY": 10.0, + "PhysicsWorldPixToMetres": 0.1, + }, + "parent": { + "name": "GMOnlineSave", + "path": "folders/GMOnlineSave.yy", + }, +} \ No newline at end of file diff --git a/scripts/scrGMOnlineSave/scrGMOnlineSave.gml b/scripts/scrGMOnlineSave/scrGMOnlineSave.gml new file mode 100644 index 0000000..1a5855f --- /dev/null +++ b/scripts/scrGMOnlineSave/scrGMOnlineSave.gml @@ -0,0 +1,69 @@ +#macro GMOS_DEFAULT_URL "https://load.pythonanywhere.com" +#macro GMOS_DEFAULT_FUNC function(result){ show_message(result) } + +global.__gmos_gameid = ""; +global.__gmos_userid = ""; +global.__gmos_url = GMOS_DEFAULT_URL; + +/** + * Initialize GM Online Save + * @param {string} gameid Unique GUID identifier for your game. Generate one at https://www.uuidgenerator.net + * @param {string} userid Unique identifier for your user. ie: that player username + * @param {string} [url]="https://debug.pythonanywhere.com" URL to your backend server + */ +function gmos_init(gameid, userid, url=GMOS_DEFAULT_URL){ + global.__gmos_gameid = gameid; + global.__gmos_userid = userid; + global.__gmos_url = url; +} + + +/** + * Write the data to the cloud + * @param {string} filename Filename for the save + * @param {Struct} data The content/data that you want to be saved + * @param {function} [on_success] Callback function that will be called when save is successful + * @param {function} [on_failed] Callback function that will be called when save is failed + */ +function gmos_write(filename, data, on_success=GMOS_DEFAULT_FUNC, on_failed=GMOS_DEFAULT_FUNC){ + request_url = __gmos_get_request_url(filename); + var header = ds_map_create(); + ds_map_add(header, "Content-Type", "application/json"); + request_id = http_request(request_url, "POST", header, json_stringify(data)); + + instance_create_depth(0,0,0, objGMOnlineSave, { + rid : request_id, + func_onsuccess : on_success, + func_onfailed : on_failed + }); + ds_map_destroy(header); +} + + +/** + * Read data from the cloud + * @param {any} filename Filename for the save + * @param {function} [on_success] Callback function that will be called when save is successful + * @param {function} [on_failed] Callback function that will be called when save is failed + */ +function gmos_read(filename, on_success=GMOS_DEFAULT_FUNC, on_failed=GMOS_DEFAULT_FUNC){ + request_url = __gmos_get_request_url(filename); + request_id = http_get(request_url); + instance_create_depth(0,0,0, objGMOnlineSave, { + rid : request_id, + func_onsuccess : on_success, + func_onfailed : on_failed + }); +} + + +/** + * Helper function that compose the request url + */ +function __gmos_get_request_url(filename){ + var result = global.__gmos_url; + result += "/game/" + global.__gmos_gameid; + result += "/user/" + global.__gmos_userid; + result += "/file/" + string(filename); + return result; +} \ No newline at end of file diff --git a/scripts/scrGMOnlineSave/scrGMOnlineSave.yy b/scripts/scrGMOnlineSave/scrGMOnlineSave.yy new file mode 100644 index 0000000..b676771 --- /dev/null +++ b/scripts/scrGMOnlineSave/scrGMOnlineSave.yy @@ -0,0 +1,11 @@ +{ + "resourceType": "GMScript", + "resourceVersion": "1.0", + "name": "scrGMOnlineSave", + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "GMOnlineSave", + "path": "folders/GMOnlineSave.yy", + }, +} \ No newline at end of file diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..e8703e3 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +test +data \ No newline at end of file diff --git a/server/main.py b/server/main.py new file mode 100644 index 0000000..120dff2 --- /dev/null +++ b/server/main.py @@ -0,0 +1,39 @@ +from flask import Flask, request +from flask_cors import CORS, cross_origin +from markupsafe import escape +import os + + +def save(filename, data): + os.makedirs(os.path.dirname(filename), exist_ok=True) + with open(filename, 'w') as f: + f.write(str(data)) + + +def load(filename): + with open(filename, 'r') as f: + data = f.read() + return data + + +app = Flask(__name__) +cors = CORS(app) +app.config['CORS_HEADERS'] = 'Content-Type' + + +@app.route('/game//user//file/', methods=['GET', 'POST']) +@cross_origin() +def router(game_id, user_id, file_name): + try: + gameid = escape(game_id) + userid = escape(user_id) + filename = escape(file_name) + + path = "data/{}/{}/{}".format(gameid, userid, filename) + if request.method == 'POST': + save(path, request.json) + return "ok" + else: + return load(path) + except: + return "error" diff --git a/server/requirements.txt b/server/requirements.txt new file mode 100644 index 0000000..cda449d --- /dev/null +++ b/server/requirements.txt @@ -0,0 +1,9 @@ +click==8.1.3 +colorama==0.4.6 +Flask==2.2.2 +Flask-Cors==3.0.10 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.1 +six==1.16.0 +Werkzeug==2.2.2