Skip to content

Commit

Permalink
Merge pull request #206 from Bam4d/better_error_messages
Browse files Browse the repository at this point in the history
Better error messages
  • Loading branch information
Bam4d authored Jul 17, 2022
2 parents 098857a + b375ab5 commit 2d5822c
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 112 deletions.
4 changes: 4 additions & 0 deletions js/bindings/GriddlyJS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ std::shared_ptr<GriddlyJSGDYWrapper> GriddlyJS::loadString(std::string levelStri
std::istringstream s(levelString);
gdyFactory->parseFromStream(s);
return std::make_shared<GriddlyJSGDYWrapper>(GriddlyJSGDYWrapper(gdyFactory));
}

std::string GriddlyJS::getExceptionMessage(intptr_t exceptionPtr) {
return std::string(reinterpret_cast<std::exception *>(exceptionPtr)->what());
}
6 changes: 5 additions & 1 deletion js/bindings/GriddlyJS.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class GriddlyJS {
public:
GriddlyJS();
std::shared_ptr<GriddlyJSGDYWrapper> loadString(std::string levelString);
std::string getExceptionMessage(intptr_t exceptionPtr);
};

template <typename K, typename V>
Expand All @@ -25,11 +26,14 @@ e::class_<std::unordered_map<K, V>> register_unordered_map(const char* name) {
.function("keys", e::internal::MapAccess<MapType>::keys);
}


EMSCRIPTEN_BINDINGS(GriddlyJS) {
// Classes
e::class_<GriddlyJS>("GriddlyJS")
.constructor()
.function("loadString", &GriddlyJS::loadString);
.function("loadString", &GriddlyJS::loadString)
.function("getExceptionMessage", &GriddlyJS::getExceptionMessage);


e::class_<GriddlyJSGDYWrapper>("GriddlyJSGDYWrapper")
.smart_ptr<std::shared_ptr<GriddlyJSGDYWrapper>>("GriddlyJSGDYWrapper")
Expand Down
Binary file modified js/griddlyjs-app/public/js/griddlyjs.wasm
Binary file not shown.
176 changes: 125 additions & 51 deletions js/griddlyjs-app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// import logo from './logo.svg';
import yaml from "js-yaml";
import yaml, { YAMLException } from "js-yaml";
import React, { Component } from "react";
import "./App.scss";
import GriddlyJSCore from "./GriddlyJSCore";
Expand Down Expand Up @@ -107,6 +107,9 @@ class App extends Component {

setCurrentLevel = (levelId) => {
this.setState((state) => {
if (!state.gdy || !this.griddlyjs) {
return state;
}
const levelString = state.gdy.Environment.Levels[levelId];

try {
Expand Down Expand Up @@ -175,7 +178,10 @@ class App extends Component {
levelString,
this.state.selectedLevelId
);
this.editorStateHandler.loadLevelString(levelString, this.state.selectedLevelId);
this.editorStateHandler.loadLevelString(
levelString,
this.state.selectedLevelId
);
this.griddlyjs.reset(levelString);
this.setState((state) => {
return {
Expand Down Expand Up @@ -206,7 +212,10 @@ class App extends Component {

saveNewLevel = () => {
const savedLevelId = this.saveLevelString(this.state.levelString);
this.editorStateHandler.loadLevelString(this.state.levelString, this.state.selectedLevelId);
this.editorStateHandler.loadLevelString(
this.state.levelString,
this.state.selectedLevelId
);
this.griddlyjs.reset(this.state.levelString);
this.setState((state) => {
return {
Expand All @@ -221,7 +230,10 @@ class App extends Component {
this.state.levelString,
this.state.selectedLevelId
);
this.editorStateHandler.loadLevelString(this.state.levelString, this.state.selectedLevelId);
this.editorStateHandler.loadLevelString(
this.state.levelString,
this.state.selectedLevelId
);
this.griddlyjs.reset(this.state.levelString);

this.setState((state) => {
Expand Down Expand Up @@ -424,31 +436,27 @@ class App extends Component {
this.setState((state) => {
return {
...state,
loading: true
}
loading: true,
};
});

setTimeout(() => {
try {
this.updateGDY(gdyString, projectName);
this.setCurrentLevel(lastLevelId);
} catch (e) {
this.displayMessage("Could not load GDY", "error", e);
this.setState((state) => {
return {
...state,
projectName,
gdyHash: hashString(gdyString),
gdyString: gdyString,
gdy: gdy,
editorStateHandler: this.editorStateHandler,
selectedLevelId: lastLevelId,
};
});
}
}, 100);


try {
this.updateGDY(gdyString, projectName);
this.setCurrentLevel(lastLevelId);
} catch (e) {
this.displayMessage("Could not load GDY", "error", e);
this.setState((state) => {
return {
...state,
projectName,
gdyHash: hashString(gdyString),
gdyString: gdyString,
gdy: gdy,
editorStateHandler: this.editorStateHandler,
selectedLevelId: lastLevelId,
};
});
}
} catch (e) {
this.displayMessage("Could not load GDY", "error", e);
this.setState((state) => {
Expand Down Expand Up @@ -488,31 +496,82 @@ class App extends Component {
});
};

checkGriddlyJSCompatibility = (gdy) => {
// Check for avatar object
if (
!("Player" in gdy.Environment) ||
!("AvatarObject" in gdy.Environment.Player)
) {
throw new Error(
"Currently only Single-Player environments where an avatar is controlled by the agent are compatible with GriddlyJS. \n\n Perhaps you forgot to set the AvatarObject?"
);
}

if (!("Levels" in gdy.Environment)) {
throw new Error("Please define at least one level.");
}
};

updateGDY = (gdyString, projectName) => {
const gdy = yaml.load(gdyString);
this.editorHistory.updateState(projectName, { gdy });
this.closeAllMessages();

try {
this.griddlyjs.unloadGDY();
this.griddlyjs.loadGDY(gdyString);
} catch (e) {
this.displayMessage("Unable to load GDY", "error", e);
}
this.editorStateHandler.loadGDY(gdy);
const gdy = yaml.load(gdyString);
this.checkGriddlyJSCompatibility(gdy);
this.editorHistory.updateState(projectName, { gdy });
try {
this.griddlyjs.unloadGDY();
this.griddlyjs.loadGDY(gdyString);

this.loadRenderers(gdy);
this.editorStateHandler.loadGDY(gdy);

this.setState((state) => {
return {
...state,
projectName,
gdyHash: hashString(gdyString),
gdyString: gdyString,
gdy: gdy,
griddlyjs: this.griddlyjs,
editorStateHandler: this.editorStateHandler,
loading: false
};
});
this.loadRenderers(gdy);
this.setState((state) => {
return {
...state,
projectName,
gdyHash: hashString(gdyString),
gdyString: gdyString,
gdy: gdy,
griddlyjs: this.griddlyjs,
editorStateHandler: this.editorStateHandler,
loading: false,
};
});
} catch (e) {
this.displayMessage("Unable to load GDY \n\n" + e.message, "error", e);
this.setState((state) => {
return {
...state,
projectName,
// gdyHash: hashString(gdyString),
// gdy: gdy,
gdyString: gdyString,
editorStateHandler: this.editorStateHandler,
loading: false,
};
});
}
} catch (e) {
this.setState((state) => {
return {
...state,
projectName,
gdyHash: hashString(gdyString),
gdyString: gdyString,
loading: false,
};
});
if (e instanceof YAMLException) {
this.displayMessage(
"There are syntax errors in your GDY: " + e.message,
"error",
e
);
} else {
this.displayMessage("Unable to load GDY \n\n" + e.message, "error", e);
}
}
};

updatePhaserCanvasSize = () => {
Expand Down Expand Up @@ -710,12 +769,18 @@ class App extends Component {
});
};

closeAllMessages = () => {
Object.entries(this.state.messages).map(([key, message]) => {
this.closeMessage(key);
});
};

render() {
return (
<Container fluid className="griddlyjs-ide-container">
<Intro onClose={this.closeIntroModal} show={this.state.showIntro} />
<Modal show={this.state.loading} backdrop="static">
<Modal.Header>
<Modal.Header>
<Modal.Title>Loading Project.....</Modal.Title>
</Modal.Header>
</Modal>
Expand Down Expand Up @@ -751,7 +816,7 @@ class App extends Component {
</Button>
</Modal.Footer>
</Modal>
<ToastContainer className="p-3" position="top-left">
<ToastContainer className="p-5" position="top-start">
{Object.entries(this.state.messages).map(([key, message]) => {
let icon;
switch (message.type) {
Expand Down Expand Up @@ -799,7 +864,16 @@ class App extends Component {
}}
>
<Toast.Header closeButton={true}>{icon}</Toast.Header>
<Toast.Body>{message.content}</Toast.Body>
<Toast.Body className="message-text">
{message.content.split("\n").map(function (item, idx) {
return (
<span key={idx}>
{item}
<br />
</span>
);
})}
</Toast.Body>
</Toast>
);
})}
Expand Down
6 changes: 6 additions & 0 deletions js/griddlyjs-app/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@
text-align: center;
margin: 20px;
}

.message-text {
white-space: pre-wrap;
text-align: left;
font-family: monospace;
}
34 changes: 24 additions & 10 deletions js/griddlyjs-app/src/GriddlyJSCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,27 @@ class GriddlyJSCore {
};

loadGDY = (gdyString) => {
this.gdy = this.griddlyjs.loadString(gdyString);
this.game = this.gdy.createGame("Vector");
try {
this.gdy = this.griddlyjs.loadString(gdyString);
this.game = this.gdy.createGame("Vector");

this.playerCount = this.gdy.getPlayerCount();
this.playerCount = this.gdy.getPlayerCount();

this.players = [];
this.players = [];

for (let p = 0; p < this.playerCount; p++) {
const player = this.game.registerPlayer("Player " + p, "Vector");
this.players.push(player);
}
for (let p = 0; p < this.playerCount; p++) {
const player = this.game.registerPlayer("Player " + p, "Vector");
this.players.push(player);
}

this.game.init();
this.game.reset();
this.game.init();
this.game.reset();
} catch(e) {
if(!isNaN(e)) {
throw Error(this.griddlyjs.getExceptionMessage(e));
}
throw e;
}
};

unloadGDY = () => {
Expand Down Expand Up @@ -97,6 +104,9 @@ class GriddlyJSCore {
};

reset = (levelStringOrId) => {
if(!this.game) {
return;
}
if (levelStringOrId) {
this.levelStringOrId = levelStringOrId;
if (isNaN(levelStringOrId)) {
Expand All @@ -115,6 +125,10 @@ class GriddlyJSCore {
seed = (seed) => {
this.game.seedRandomGenerator(seed);
}

getExceptionMessage = (messagePtr) => {
return this.griddlyjs.getExceptionMessage(messagePtr);
}
}

export default GriddlyJSCore;
2 changes: 1 addition & 1 deletion js/griddlyjs-app/src/wasm/griddlyjs.js

Large diffs are not rendered by default.

Loading

0 comments on commit 2d5822c

Please sign in to comment.