Skip to content

Commit

Permalink
Merge pull request #349 from MichaelEbert/multimerge
Browse files Browse the repository at this point in the history
Multimerge
  • Loading branch information
MichaelEbert authored Dec 19, 2024
2 parents f065b5f + 8fb04ba commit d08a870
Show file tree
Hide file tree
Showing 18 changed files with 506 additions and 125 deletions.
23 changes: 22 additions & 1 deletion js/progressCalculation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export{
import { totalweight, getJsonData, findCell, runOnTree, progressClasses } from './obliviondata.mjs';
import {saveProgressToCookie} from './userdata.mjs';
import {uploadCurrentSave} from './sharing.mjs';
import { uploadPartialSave } from './sharing.mjs';
import { compressSaveData, decompressSaveData, saveCookie } from './userdata.mjs';

/**
* Update save progress for the specified element.
Expand Down Expand Up @@ -151,6 +153,13 @@ function updateChecklistProgressInternal(cell, newValue, skipSave){
}
}
else{
// sometimes we mess up the savedata completely.
// this is a recovery.
if(savedata[cell.hive.classname] == null)
{
console.log("savedata messed up: hive doesnt exist.");
savedata[cell.hive.classname] = {};
}
savedata[cell.hive.classname][cell.id] = valueAsCorrectType;
}
}
Expand All @@ -164,7 +173,19 @@ function updateChecklistProgressInternal(cell, newValue, skipSave){
if(!skipSave){
saveProgressToCookie();
if(settings.autoUploadCheck){
uploadCurrentSave(false);
// idk this might result in torn savedata
uploadPartialSave(cell).then((result)=>{
//new data:
const returnedSaveData = decompressSaveData(JSON.parse(result.response));
const oldData = JSON.stringify(compressSaveData(savedata));
const newData = JSON.stringify(compressSaveData(returnedSaveData));
if(oldData != newData)
{
savedata = returnedSaveData;
saveCookie("progress",returnedSaveData);
document.dispatchEvent(new Event("progressLoad"));
}
});
}
}
return true;
Expand Down
2 changes: 2 additions & 0 deletions js/saveReader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export {parseSave}

import { loadJsonData, jsondata, progressClasses, runOnTree, findCell } from './obliviondata.mjs'
import { uploadCurrentSave } from './sharing.mjs';
import { initShareSettings, stopSpectating } from './sharing.mjs';
import { saveProgressToCookie } from './userdata.mjs';

Expand Down Expand Up @@ -340,6 +341,7 @@ function parseSave(e){

window.savedata = dataFromSave;
saveProgressToCookie();
uploadCurrentSave();
window.location.reload();
});
}
Expand Down
153 changes: 141 additions & 12 deletions js/sharing.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export {
uploadSave,
downloadSave,
uploadCurrentSave,
uploadPartialSave,
startSpectating,
stopSpectating,
setRemoteUrl,
Expand Down Expand Up @@ -85,9 +86,24 @@ async function uploadSave(uploadUrl, saveData, myShareCode, myShareKey){
req.setRequestHeader("Content-Type","application/json");

req.onload = function () {
let newCode;
//first get url...
const share = "share/";
var start = this.responseURL.indexOf(share);
if(start == -1){
newCode = this.response;
}
else{
start += share.length;
newCode = this.responseURL.substring(start);
newCode = newCode.substring(0, newCode.indexOf('/'));
if(newCode.length < 6){
newCode = this.response;
}
}
if(this.status == 200){
//yay.
resolve(this.response);
resolve({"code": newCode, "response":this.response});
}
else{
reject(this);
Expand Down Expand Up @@ -157,15 +173,17 @@ async function uploadCurrentSave(notifyOnUpdate = true){
return uploadSave(settings.serverUrl, compressedData, settings.myShareCode, settings.shareKey)
.then((result)=>{
if(result){
if(settings.myShareCode != result){
console.log("my share code changed from '"+settings.myShareCode+"' to '"+result+"'");
settings.myShareCode = result;
if(settings.myShareCode != result.code){
console.log("my share code changed from '"+settings.myShareCode+"' to '"+result.code+"'");
settings.myShareCode = result.code;
saveCookie("settings",settings);
}
//todo: parse new savedata?

//do this every time we upload:
document.dispatchEvent(new Event("progressShared"));
if(window.debug){
console.log("progress shared: "+result);
console.log("progress shared: "+result.code);
}
if(notifyOnUpdate){
//?????
Expand All @@ -175,6 +193,61 @@ async function uploadCurrentSave(notifyOnUpdate = true){
});
}

/**
* Upload partial changes to a savefile.
* @param partialJsonData jsondata hive to upload.
*/
async function uploadPartialSave(partialJsonData){
if(settings.remoteShareCode){
//if we're viewing remote, don't upload.
console.log("viewing remote data, will not upload.");
return;
}
initShareSettings();

//currently only support single element or single hive.
if(partialJsonData.hive == null)
{
console.error("cannot upload, no hive found.");
}

//hive:
let hive = partialJsonData.hive;
if(!hive.class.containsUserProgress)
{
return;
}

//get savedata format
let dataToUpload = savedata[hive.classname];
let uploadPath = hive.classname;

if(partialJsonData.elements == null && partialJsonData.id != null)
{
//leaf node. we can upload just this.
dataToUpload = savedata[hive.classname][partialJsonData.id];
if(hive.class.standard)
{
//compress if we need to
dataToUpload = dataToUpload == 1 ? 1:0;
}
uploadPath = `${hive.classname}/${partialJsonData.id}`;
}
else{
if(hive.class.standard)
{
let compressed = [];
for(const elementPropName in dataToUpload){
compressed[parseInt(elementPropName)] = dataToUpload[elementPropName] == 1 ?1:0;
}
dataToUpload = compressed;
}
}

let fullUrl = `${settings.serverUrl}/${settings.myShareCode}/d/${uploadPath}`;
return uploadSave(fullUrl, dataToUpload, settings.myShareCode, settings.shareKey);
}

/**
* @returns {boolean} is user currently spectating
*/
Expand Down Expand Up @@ -223,6 +296,10 @@ var autoUpdateIntervalId = null;
* @param {boolean} updateGlobalSaveData Should we decompress spectating data (true) or just write it to localStorage?
*/
async function startSpectating(notifyOnUpdate = true, updateGlobalSaveData = true){
if((new Date() - settings.shareDownloadTimeInternal) < (settings.spectateAutoRefreshInterval*1000))
{
return;
}
if(window.debug){
console.log("spectate update");
}
Expand Down Expand Up @@ -344,17 +421,69 @@ function createSpectateBanner(){
* Call this on a page to do all the sharing stuff. Create topbar, start autorefresh, etc.
*/
function initSharingFeature(){
if(settings.remoteShareCode == null || settings.remoteShareCode == ""){
if(!isSpectating() && (settings.myShareCode == null || settings.myShareCode == "")){
return;
}

if(!document.getElementById("spectateBanner")){
let spectateBanner = createSpectateBanner();
document.getElementById("topbar")?.insertBefore(spectateBanner, document.getElementById("topbar").firstChild);
document.getElementById("sidebarFloaty")?.classList.add("screenHeight2");
if(isSpectating())
{
if(!document.getElementById("spectateBanner")){
let spectateBanner = createSpectateBanner();
document.getElementById("topbar")?.insertBefore(spectateBanner, document.getElementById("topbar").firstChild);
document.getElementById("sidebarFloaty")?.classList.add("screenHeight2");
}
if(settings.spectateAutoRefresh == true){
startSpectating(false, true);
}
}
if(settings.spectateAutoRefresh == true){
startSpectating(false, true);
else{
if(settings.spectateAutoRefresh)
{
startSync(true);
}
}
}

function startSync(updateGlobalSaveData)
{
if((new Date() - settings.shareDownloadTimeInternal) < (settings.spectateAutoRefreshInterval*1000))
{
return;
}
let downloadUrl = settings.serverUrl + "/" + settings.myShareCode;
return downloadSave(downloadUrl)
.then((dl)=>{
if(dl){
//we can't serialize the date object so we convert it to a pretty print string here
let dlTime = new Date();
settings.shareDownloadTimeInternal = dlTime.toUTCString();
settings.shareDownloadTime = dlTime.toDateString() + " " + dlTime.toTimeString().substring(0,8);
saveCookie("settings",settings);

saveCookie("progress",dl);
if(updateGlobalSaveData){
savedata = decompressSaveData(dl);
upgradeSaveData(false);

}
document.dispatchEvent(new Event("progressLoad"));
}
else{
if(window.debug){
console.log("304 content unchanged");
}
}

//AFTER everything else, attach an auto listener to update spectating.
if(autoUpdateListener == null && settings.spectateAutoRefresh == true){
if(window.debug){
console.log("Attaching auto update listener");
}
autoUpdateListener = ()=>{
startSync(true);
}
autoUpdateIntervalId = setInterval(autoUpdateListener, Math.max(settings.spectateAutoRefreshInterval*1000, 1000));
}
});
}

20 changes: 16 additions & 4 deletions js/userdata.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { runOnTree, progressClasses } from "./obliviondata.mjs";
import { initShareSettings } from "./sharing.mjs";

import {clearProgressCache} from './progressCalculation.mjs'
import { downloadSave } from "./sharing.mjs";

//functions that save and load user progess and settings.
export{
Expand Down Expand Up @@ -159,9 +160,14 @@ function decompressSaveData(compressedSaveData){
if(matchingClass != null && matchingClass.standard) {
decompressedSaveData[propname] = {};
let elements = compressedSaveData[propname];
for(let i = 0; i < elements.length; i++){
let length = elements.length;
if(elements.length == undefined)
{
length = Object.keys(elements).length;
}
for(let i = 0; i < length; i++){
if(elements[i] != null){
decompressedSaveData[propname][i] = (elements[i] == 1);
decompressedSaveData[propname][i] = (elements[i] == 1) || (elements[i] === true);
}
}
}
Expand Down Expand Up @@ -269,7 +275,13 @@ function initSettings(){
* @returns {boolean} true if progress was been successfully loaded. False if new savedata was created.
*/
function loadProgressFromCookie(){
loadSettingsFromCookie();
loadSettingsFromCookie();
if(settings.myShareCode != null || settings.remoteShareCode != null)
{
//TODO: try reloading from remote
//TODO: what if we wipe save#s tho
//downloadSave(...)
}
var compressed = loadCookie("progress");

if(compressed && Object.getOwnPropertyNames(compressed).length != 0){
Expand All @@ -286,7 +298,7 @@ function loadProgressFromCookie(){
else{
//could not find savedata. create new savedata.
if(window.debug){
console.log("could not find dsavedata. resetting progress.");
console.log("could not find savedata. resetting progress.");
}
resetProgress(false);
return false;
Expand Down
82 changes: 82 additions & 0 deletions server/Controllers/DataController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.VisualBasic;
using System;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Xml;
using System.Xml.Linq;

namespace ShareApi.Controllers
{
[ApiController]
[Route("share/{url}/d/{**jsonPath}")]
public class DataController : Controller
{


[HttpGet]
public ActionResult<string> HandleGet(string url, string? jsonPath)
{
var saveEditor = new SaveDataEditor(url);
return Ok(saveEditor.HandleData(new HttpMethod(Request.Method), jsonPath, null));
}

[HttpPut]
[HttpPost]
public ActionResult<string> Handle(ProgressUpdate update, string url, string? jsonPath)
{
ProgressUpdateValidator.Validate(update, out ValidationFailedReason validationFailedReason);
if(validationFailedReason != ValidationFailedReason.NONE)
{
ModelState.AddModelError("error", validationFailedReason.ToString());
return BadRequest(ModelState);
}
var saveEditor = new SaveDataEditor(url, update);
if(saveEditor.ReadOnly)
{
return Unauthorized();
}
return Ok(saveEditor.HandleData(new HttpMethod(Request.Method), jsonPath, JsonNode.Parse(update.SaveData)));
}
}

public class JsonProxyNode
{
public JsonNode? parent;
public string Name;
public JsonNode? contents;

public JsonProxyNode(string name)
{
this.Name = name;
}

/// <summary>
/// Update the json tree and return the changed tree.
/// </summary>
/// <returns></returns>
public JsonNode Commit()
{
if (parent != null)
{
if (parent.GetValueKind() == System.Text.Json.JsonValueKind.Object)
{
parent[Name] = contents;
}
else
{
parent[int.Parse(Name)] = contents;
}

return parent.Root ?? parent;
}
else
{
return contents;
}

}
}
}
File renamed without changes.
Loading

0 comments on commit d08a870

Please sign in to comment.