Split shaders into their own files
some unrelated directives thing too
This commit is contained in:
parent
4328119e1c
commit
6832c10ed5
38
assets/opensb/rendering/opengl20.config
Normal file
38
assets/opensb/rendering/opengl20.config
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"effectParameters" : {
|
||||||
|
"lightMapEnabled" : {
|
||||||
|
"type" : "bool",
|
||||||
|
"default" : false,
|
||||||
|
"uniform" : "lightMapEnabled"
|
||||||
|
},
|
||||||
|
"lightMapScale" : {
|
||||||
|
"type" : "vec2",
|
||||||
|
"default" : [1, 1],
|
||||||
|
"uniform" : "lightMapScale"
|
||||||
|
},
|
||||||
|
"lightMapOffset" : {
|
||||||
|
"type" : "vec2",
|
||||||
|
"default" : [0, 0],
|
||||||
|
"uniform" : "lightMapOffset"
|
||||||
|
},
|
||||||
|
"lightMapMultiplier" : {
|
||||||
|
"type" : "float",
|
||||||
|
"default" : 1.0,
|
||||||
|
"uniform" : "lightMapMultiplier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"effectTextures" : {
|
||||||
|
"lightMap" : {
|
||||||
|
"textureUniform" : "lightMap",
|
||||||
|
"textureSizeUniform" : "lightMapSize",
|
||||||
|
"textureAddressing" : "clamp",
|
||||||
|
"textureFiltering" : "linear"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"effectShaders" : {
|
||||||
|
"vertex" : "opengl20.vert",
|
||||||
|
"fragment" : "opengl20.frag"
|
||||||
|
}
|
||||||
|
}
|
75
assets/opensb/rendering/opengl20.frag
Normal file
75
assets/opensb/rendering/opengl20.frag
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform sampler2D texture1;
|
||||||
|
uniform sampler2D texture2;
|
||||||
|
uniform sampler2D texture3;
|
||||||
|
uniform bool lightMapEnabled;
|
||||||
|
uniform vec2 lightMapSize;
|
||||||
|
uniform sampler2D lightMap;
|
||||||
|
uniform float lightMapMultiplier;
|
||||||
|
|
||||||
|
varying vec2 fragmentTextureCoordinate;
|
||||||
|
varying float fragmentTextureIndex;
|
||||||
|
varying vec4 fragmentColor;
|
||||||
|
varying float fragmentLightMapMultiplier;
|
||||||
|
varying vec2 fragmentLightMapCoordinate;
|
||||||
|
|
||||||
|
vec4 cubic(float v) {
|
||||||
|
vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
|
||||||
|
vec4 s = n * n * n;
|
||||||
|
float x = s.x;
|
||||||
|
float y = s.y - 4.0 * s.x;
|
||||||
|
float z = s.z - 4.0 * s.y + 6.0 * s.x;
|
||||||
|
float w = 6.0 - x - y - z;
|
||||||
|
return vec4(x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 bicubicSample(sampler2D texture, vec2 texcoord, vec2 texscale) {
|
||||||
|
texcoord = texcoord - vec2(0.5, 0.5);
|
||||||
|
|
||||||
|
float fx = fract(texcoord.x);
|
||||||
|
float fy = fract(texcoord.y);
|
||||||
|
texcoord.x -= fx;
|
||||||
|
texcoord.y -= fy;
|
||||||
|
|
||||||
|
vec4 xcubic = cubic(fx);
|
||||||
|
vec4 ycubic = cubic(fy);
|
||||||
|
|
||||||
|
vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y - 0.5, texcoord.y + 1.5);
|
||||||
|
vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x + ycubic.y, ycubic.z + ycubic.w);
|
||||||
|
vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) / s;
|
||||||
|
|
||||||
|
vec4 sample0 = texture2D(texture, vec2(offset.x, offset.z) * texscale);
|
||||||
|
vec4 sample1 = texture2D(texture, vec2(offset.y, offset.z) * texscale);
|
||||||
|
vec4 sample2 = texture2D(texture, vec2(offset.x, offset.w) * texscale);
|
||||||
|
vec4 sample3 = texture2D(texture, vec2(offset.y, offset.w) * texscale);
|
||||||
|
|
||||||
|
float sx = s.x / (s.x + s.y);
|
||||||
|
float sy = s.z / (s.z + s.w);
|
||||||
|
|
||||||
|
return mix(
|
||||||
|
mix(sample3, sample2, sx),
|
||||||
|
mix(sample1, sample0, sx), sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 texColor;
|
||||||
|
if (fragmentTextureIndex > 2.9) {
|
||||||
|
texColor = texture2D(texture3, fragmentTextureCoordinate);
|
||||||
|
} else if (fragmentTextureIndex > 1.9) {
|
||||||
|
texColor = texture2D(texture2, fragmentTextureCoordinate);
|
||||||
|
} else if (fragmentTextureIndex > 0.9) {
|
||||||
|
texColor = texture2D(texture1, fragmentTextureCoordinate);
|
||||||
|
} else {
|
||||||
|
texColor = texture2D(texture0, fragmentTextureCoordinate);
|
||||||
|
}
|
||||||
|
if (texColor.a <= 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
vec4 finalColor = texColor * fragmentColor;
|
||||||
|
float finalLightMapMultiplier = fragmentLightMapMultiplier * lightMapMultiplier;
|
||||||
|
if (lightMapEnabled && finalLightMapMultiplier > 0.0)
|
||||||
|
finalColor.rgb *= bicubicSample(lightMap, fragmentLightMapCoordinate, 1.0 / lightMapSize).rgb * finalLightMapMultiplier;
|
||||||
|
gl_FragColor = finalColor;
|
||||||
|
}
|
41
assets/opensb/rendering/opengl20.vert
Normal file
41
assets/opensb/rendering/opengl20.vert
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform vec2 textureSize0;
|
||||||
|
uniform vec2 textureSize1;
|
||||||
|
uniform vec2 textureSize2;
|
||||||
|
uniform vec2 textureSize3;
|
||||||
|
uniform vec2 screenSize;
|
||||||
|
uniform mat3 vertexTransform;
|
||||||
|
uniform vec2 lightMapSize;
|
||||||
|
uniform vec2 lightMapScale;
|
||||||
|
uniform vec2 lightMapOffset;
|
||||||
|
|
||||||
|
attribute vec2 vertexPosition;
|
||||||
|
attribute vec2 vertexTextureCoordinate;
|
||||||
|
attribute float vertexTextureIndex;
|
||||||
|
attribute vec4 vertexColor;
|
||||||
|
attribute float vertexParam1;
|
||||||
|
|
||||||
|
varying vec2 fragmentTextureCoordinate;
|
||||||
|
varying float fragmentTextureIndex;
|
||||||
|
varying vec4 fragmentColor;
|
||||||
|
varying float fragmentLightMapMultiplier;
|
||||||
|
varying vec2 fragmentLightMapCoordinate;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 screenPosition = (vertexTransform * vec3(vertexPosition, 1.0)).xy;
|
||||||
|
fragmentLightMapMultiplier = vertexParam1;
|
||||||
|
fragmentLightMapCoordinate = (screenPosition / lightMapScale) - lightMapOffset * lightMapSize / screenSize;
|
||||||
|
if (vertexTextureIndex > 2.9) {
|
||||||
|
fragmentTextureCoordinate = vertexTextureCoordinate / textureSize3;
|
||||||
|
} else if (vertexTextureIndex > 1.9) {
|
||||||
|
fragmentTextureCoordinate = vertexTextureCoordinate / textureSize2;
|
||||||
|
} else if (vertexTextureIndex > 0.9) {
|
||||||
|
fragmentTextureCoordinate = vertexTextureCoordinate / textureSize1;
|
||||||
|
} else {
|
||||||
|
fragmentTextureCoordinate = vertexTextureCoordinate / textureSize0;
|
||||||
|
}
|
||||||
|
fragmentTextureIndex = vertexTextureIndex;
|
||||||
|
fragmentColor = vertexColor;
|
||||||
|
gl_Position = vec4(screenPosition / screenSize * 2.0 - 1.0, 0.0, 1.0);
|
||||||
|
}
|
@ -117,7 +117,7 @@ public:
|
|||||||
// specific to each type of renderer, so it will be necessary to key the
|
// specific to each type of renderer, so it will be necessary to key the
|
||||||
// configuration off of the renderId string. This should not be called every
|
// configuration off of the renderId string. This should not be called every
|
||||||
// frame, because it will result in a recompile of the underlying shader set.
|
// frame, because it will result in a recompile of the underlying shader set.
|
||||||
virtual void setEffectConfig(Json const& effectConfig) = 0;
|
virtual void setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) = 0;
|
||||||
|
|
||||||
// The effect config will specify named parameters and textures which can be
|
// The effect config will specify named parameters and textures which can be
|
||||||
// set here.
|
// set here.
|
||||||
|
@ -7,29 +7,27 @@ namespace Star {
|
|||||||
|
|
||||||
size_t const MultiTextureCount = 4;
|
size_t const MultiTextureCount = 4;
|
||||||
|
|
||||||
char const* DefaultEffectConfig = R"JSON(
|
char const* DefaultVertexShader = R"SHADER(
|
||||||
{
|
#version 110
|
||||||
"vertexShader" : "
|
|
||||||
#version 110
|
|
||||||
|
|
||||||
uniform vec2 textureSize0;
|
uniform vec2 textureSize0;
|
||||||
uniform vec2 textureSize1;
|
uniform vec2 textureSize1;
|
||||||
uniform vec2 textureSize2;
|
uniform vec2 textureSize2;
|
||||||
uniform vec2 textureSize3;
|
uniform vec2 textureSize3;
|
||||||
uniform vec2 screenSize;
|
uniform vec2 screenSize;
|
||||||
uniform mat3 vertexTransform;
|
uniform mat3 vertexTransform;
|
||||||
|
|
||||||
attribute vec2 vertexPosition;
|
attribute vec2 vertexPosition;
|
||||||
attribute vec2 vertexTextureCoordinate;
|
attribute vec2 vertexTextureCoordinate;
|
||||||
attribute float vertexTextureIndex;
|
attribute float vertexTextureIndex;
|
||||||
attribute vec4 vertexColor;
|
attribute vec4 vertexColor;
|
||||||
attribute float vertexParam1;
|
attribute float vertexParam1;
|
||||||
|
|
||||||
varying vec2 fragmentTextureCoordinate;
|
varying vec2 fragmentTextureCoordinate;
|
||||||
varying float fragmentTextureIndex;
|
varying float fragmentTextureIndex;
|
||||||
varying vec4 fragmentColor;
|
varying vec4 fragmentColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 screenPosition = (vertexTransform * vec3(vertexPosition, 1.0)).xy;
|
vec2 screenPosition = (vertexTransform * vec3(vertexPosition, 1.0)).xy;
|
||||||
gl_Position = vec4(screenPosition / screenSize * 2.0 - 1.0, 0.0, 1.0);
|
gl_Position = vec4(screenPosition / screenSize * 2.0 - 1.0, 0.0, 1.0);
|
||||||
if (vertexTextureIndex > 2.9) {
|
if (vertexTextureIndex > 2.9) {
|
||||||
@ -43,22 +41,22 @@ char const* DefaultEffectConfig = R"JSON(
|
|||||||
}
|
}
|
||||||
fragmentTextureIndex = vertexTextureIndex;
|
fragmentTextureIndex = vertexTextureIndex;
|
||||||
fragmentColor = vertexColor;
|
fragmentColor = vertexColor;
|
||||||
}
|
}
|
||||||
",
|
)SHADER";
|
||||||
|
|
||||||
"fragmentShader" : "
|
char const* DefaultFragmentShader = R"SHADER(
|
||||||
#version 110
|
#version 110
|
||||||
|
|
||||||
uniform sampler2D texture0;
|
uniform sampler2D texture0;
|
||||||
uniform sampler2D texture1;
|
uniform sampler2D texture1;
|
||||||
uniform sampler2D texture2;
|
uniform sampler2D texture2;
|
||||||
uniform sampler2D texture3;
|
uniform sampler2D texture3;
|
||||||
|
|
||||||
varying vec2 fragmentTextureCoordinate;
|
varying vec2 fragmentTextureCoordinate;
|
||||||
varying float fragmentTextureIndex;
|
varying float fragmentTextureIndex;
|
||||||
varying vec4 fragmentColor;
|
varying vec4 fragmentColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (fragmentTextureIndex > 2.9) {
|
if (fragmentTextureIndex > 2.9) {
|
||||||
gl_FragColor = texture2D(texture3, fragmentTextureCoordinate) * fragmentColor;
|
gl_FragColor = texture2D(texture3, fragmentTextureCoordinate) * fragmentColor;
|
||||||
} else if (fragmentTextureIndex > 1.9) {
|
} else if (fragmentTextureIndex > 1.9) {
|
||||||
@ -68,10 +66,8 @@ char const* DefaultEffectConfig = R"JSON(
|
|||||||
} else {
|
} else {
|
||||||
gl_FragColor = texture2D(texture0, fragmentTextureCoordinate) * fragmentColor;
|
gl_FragColor = texture2D(texture0, fragmentTextureCoordinate) * fragmentColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"
|
)SHADER";
|
||||||
}
|
|
||||||
)JSON";
|
|
||||||
|
|
||||||
OpenGl20Renderer::OpenGl20Renderer() {
|
OpenGl20Renderer::OpenGl20Renderer() {
|
||||||
if (glewInit() != GLEW_OK)
|
if (glewInit() != GLEW_OK)
|
||||||
@ -97,7 +93,7 @@ OpenGl20Renderer::OpenGl20Renderer() {
|
|||||||
TextureFiltering::Nearest);
|
TextureFiltering::Nearest);
|
||||||
m_immediateRenderBuffer = createGlRenderBuffer();
|
m_immediateRenderBuffer = createGlRenderBuffer();
|
||||||
|
|
||||||
setEffectConfig(Json::parse(DefaultEffectConfig));
|
setEffectConfig(JsonObject(), {{"vertex", DefaultVertexShader}, {"fragment", DefaultFragmentShader}});
|
||||||
|
|
||||||
m_limitTextureGroupSize = false;
|
m_limitTextureGroupSize = false;
|
||||||
m_useMultiTexturing = true;
|
m_useMultiTexturing = true;
|
||||||
@ -119,43 +115,43 @@ Vec2U OpenGl20Renderer::screenSize() const {
|
|||||||
return m_screenSize;
|
return m_screenSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGl20Renderer::setEffectConfig(Json const& effectConfig) {
|
void OpenGl20Renderer::setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) {
|
||||||
flushImmediatePrimitives();
|
flushImmediatePrimitives();
|
||||||
|
|
||||||
GLint status = 0;
|
GLint status = 0;
|
||||||
char logBuffer[1024];
|
char logBuffer[1024];
|
||||||
|
|
||||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
auto compileShader = [&](GLenum type, String const& name) -> GLuint {
|
||||||
String vertexSource = effectConfig.getString("vertexShader");
|
GLuint shader = glCreateShader(type);
|
||||||
char const* vertexSourcePtr = vertexSource.utf8Ptr();
|
auto* source = shaders.ptr(name);
|
||||||
glShaderSource(vertexShader, 1, &vertexSourcePtr, NULL);
|
if (!source)
|
||||||
glCompileShader(vertexShader);
|
return 0;
|
||||||
|
char const* sourcePtr = source->utf8Ptr();
|
||||||
|
glShaderSource(shader, 1, &sourcePtr, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
glGetShaderInfoLog(vertexShader, sizeof(logBuffer), NULL, logBuffer);
|
glGetShaderInfoLog(shader, sizeof(logBuffer), NULL, logBuffer);
|
||||||
throw RendererException(strf("Failed to compile vertex shader: %s\n", logBuffer));
|
throw RendererException(strf("Failed to compile %s shader: %s\n", name, logBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
return shader;
|
||||||
String fragmentSource = effectConfig.getString("fragmentShader");
|
};
|
||||||
char const* fragmentSourcePtr = fragmentSource.utf8Ptr();
|
|
||||||
glShaderSource(fragmentShader, 1, &fragmentSourcePtr, NULL);
|
|
||||||
glCompileShader(fragmentShader);
|
|
||||||
|
|
||||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
|
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, "vertex");
|
||||||
if (!status) {
|
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, "fragment");
|
||||||
glGetShaderInfoLog(fragmentShader, sizeof(logBuffer), NULL, logBuffer);
|
|
||||||
throw RendererException(strf("Failed to compile fragment shader: %s\n", logBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint program = glCreateProgram();
|
GLuint program = glCreateProgram();
|
||||||
|
|
||||||
|
if (vertexShader)
|
||||||
glAttachShader(program, vertexShader);
|
glAttachShader(program, vertexShader);
|
||||||
|
if (fragmentShader)
|
||||||
glAttachShader(program, fragmentShader);
|
glAttachShader(program, fragmentShader);
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
if (vertexShader)
|
||||||
glDeleteShader(vertexShader);
|
glDeleteShader(vertexShader);
|
||||||
|
if (fragmentShader)
|
||||||
glDeleteShader(fragmentShader);
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
String rendererId() const override;
|
String rendererId() const override;
|
||||||
Vec2U screenSize() const override;
|
Vec2U screenSize() const override;
|
||||||
|
|
||||||
void setEffectConfig(Json const& effectConfig) override;
|
void setEffectConfig(Json const& effectConfig, StringMap<String> const& shaders) override;
|
||||||
void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override;
|
void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override;
|
||||||
void setEffectTexture(String const& textureName, Image const& image) override;
|
void setEffectTexture(String const& textureName, Image const& image) override;
|
||||||
|
|
||||||
|
@ -196,10 +196,25 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
|
|||||||
|
|
||||||
void ClientApplication::renderInit(RendererPtr renderer) {
|
void ClientApplication::renderInit(RendererPtr renderer) {
|
||||||
Application::renderInit(renderer);
|
Application::renderInit(renderer);
|
||||||
|
auto assets = m_root->assets();
|
||||||
|
|
||||||
String rendererConfig = strf("/rendering/%s.config", renderer->rendererId());
|
String rendererConfig = strf("/rendering/%s.config", renderer->rendererId());
|
||||||
if (m_root->assets()->assetExists(rendererConfig))
|
if (assets->assetExists(rendererConfig)) {
|
||||||
renderer->setEffectConfig(m_root->assets()->json(rendererConfig));
|
StringMap<String> shaders;
|
||||||
|
auto config = assets->json(rendererConfig);
|
||||||
|
auto shaderConfig = config.getObject("effectShaders");
|
||||||
|
for (auto& entry : shaderConfig) {
|
||||||
|
if (entry.second.isType(Json::Type::String)) {
|
||||||
|
String shader = entry.second.toString();
|
||||||
|
if (!shader.hasChar('\n')) {
|
||||||
|
auto shaderBytes = assets->bytes(AssetPath::relativeTo(rendererConfig, shader));
|
||||||
|
shader = std::string(shaderBytes->ptr(), shaderBytes->size());
|
||||||
|
}
|
||||||
|
shaders[entry.first] = shader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderer->setEffectConfig(config, shaders);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Logger::warn("No rendering config found for renderer with id '%s'", renderer->rendererId());
|
Logger::warn("No rendering config found for renderer with id '%s'", renderer->rendererId());
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ SET (star_game_HEADERS
|
|||||||
StarDamageManager.hpp
|
StarDamageManager.hpp
|
||||||
StarDamageTypes.hpp
|
StarDamageTypes.hpp
|
||||||
StarDanceDatabase.hpp
|
StarDanceDatabase.hpp
|
||||||
|
StarDirectives.hpp
|
||||||
StarDrawable.hpp
|
StarDrawable.hpp
|
||||||
StarDungeonGenerator.hpp
|
StarDungeonGenerator.hpp
|
||||||
StarDungeonImagePart.hpp
|
StarDungeonImagePart.hpp
|
||||||
@ -296,6 +297,7 @@ SET (star_game_SOURCES
|
|||||||
StarDamageManager.cpp
|
StarDamageManager.cpp
|
||||||
StarDamageTypes.cpp
|
StarDamageTypes.cpp
|
||||||
StarDanceDatabase.cpp
|
StarDanceDatabase.cpp
|
||||||
|
StarDirectives.cpp
|
||||||
StarDrawable.cpp
|
StarDrawable.cpp
|
||||||
StarDungeonGenerator.cpp
|
StarDungeonGenerator.cpp
|
||||||
StarDungeonImagePart.cpp
|
StarDungeonImagePart.cpp
|
||||||
|
51
source/game/StarDirectives.cpp
Normal file
51
source/game/StarDirectives.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "StarImage.hpp"
|
||||||
|
#include "StarImageProcessing.hpp"
|
||||||
|
#include "StarDirectives.hpp"
|
||||||
|
|
||||||
|
namespace Star {
|
||||||
|
|
||||||
|
NestedDirectives::NestedDirectives() {}
|
||||||
|
NestedDirectives::NestedDirectives(String const& string) : m_root{ Leaf{ parseImageOperations(string), string} } {}
|
||||||
|
|
||||||
|
void NestedDirectives::addBranch(const Branch& newBranch) {
|
||||||
|
convertToBranches();
|
||||||
|
|
||||||
|
m_root.value.get<Branches>().emplace_back(newBranch);
|
||||||
|
}
|
||||||
|
|
||||||
|
String NestedDirectives::toString() const {
|
||||||
|
String string;
|
||||||
|
buildString(string, m_root);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedDirectives::forEach() const {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Image NestedDirectives::apply(Image& image) const {
|
||||||
|
Image current = image;
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedDirectives::buildString(String& string, const Cell& cell) const {
|
||||||
|
if (auto leaf = cell.value.ptr<Leaf>())
|
||||||
|
string += leaf->string;
|
||||||
|
else {
|
||||||
|
for (auto& branch : cell.value.get<Branches>())
|
||||||
|
buildString(string, *branch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NestedDirectives::convertToBranches() {
|
||||||
|
if (m_root.value.is<Branches>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Leaf& leaf = m_root.value.get<Leaf>();
|
||||||
|
Branches newBranches;
|
||||||
|
newBranches.emplace_back(std::make_shared<Cell const>(move(leaf)));
|
||||||
|
m_root.value = move(newBranches);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
source/game/StarDirectives.hpp
Normal file
50
source/game/StarDirectives.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef STAR_DIRECTIVES_HPP
|
||||||
|
#define STAR_DIRECTIVES_HPP
|
||||||
|
|
||||||
|
#include "StarImageProcessing.hpp"
|
||||||
|
|
||||||
|
namespace Star {
|
||||||
|
|
||||||
|
STAR_CLASS(NestedDirectives);
|
||||||
|
|
||||||
|
// Attempt at reducing memory allocation and per-frame string parsing for extremely long directives
|
||||||
|
class NestedDirectives {
|
||||||
|
public:
|
||||||
|
struct Leaf {
|
||||||
|
List<ImageOperation> operations;
|
||||||
|
String string;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cell;
|
||||||
|
typedef std::shared_ptr<Cell const> Branch;
|
||||||
|
typedef List<Branch> Branches;
|
||||||
|
|
||||||
|
struct Cell {
|
||||||
|
Variant<Leaf, Branches> value;
|
||||||
|
|
||||||
|
Cell() : value(Leaf()) {};
|
||||||
|
Cell(Leaf&& leaf) : value(move(leaf)) {};
|
||||||
|
Cell(Branches&& branches) : value(move(branches)) {};
|
||||||
|
Cell(const Leaf& leaf) : value(leaf) {};
|
||||||
|
Cell(const Branches& branches) : value(branches) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
NestedDirectives();
|
||||||
|
NestedDirectives(String const& string);
|
||||||
|
|
||||||
|
void addBranch(const Branch& newBranch);
|
||||||
|
const Branch& branch() const;
|
||||||
|
String toString() const;
|
||||||
|
void forEach() const;
|
||||||
|
Image apply(Image& image) const;
|
||||||
|
private:
|
||||||
|
void buildString(String& string, const Cell& cell) const;
|
||||||
|
void convertToBranches();
|
||||||
|
|
||||||
|
Cell m_root;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -787,6 +787,10 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
|||||||
m_outgoingPackets.append(make_shared<EntityMessageResponsePacket>(makeLeft("Entity delivery error"), entityMessagePacket->uuid));
|
m_outgoingPackets.append(make_shared<EntityMessageResponsePacket>(makeLeft("Entity delivery error"), entityMessagePacket->uuid));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
ConnectionId fromConnection = entityMessagePacket->fromConnection;
|
||||||
|
if (fromConnection == *m_clientId) // Kae: The server should not be able to forge entity messages that appear as if they're from us
|
||||||
|
fromConnection = ServerConnectionId;
|
||||||
|
|
||||||
auto response = entity->receiveMessage(entityMessagePacket->fromConnection, entityMessagePacket->message, entityMessagePacket->args);
|
auto response = entity->receiveMessage(entityMessagePacket->fromConnection, entityMessagePacket->message, entityMessagePacket->args);
|
||||||
if (response)
|
if (response)
|
||||||
m_outgoingPackets.append(make_shared<EntityMessageResponsePacket>(makeRight(response.take()), entityMessagePacket->uuid));
|
m_outgoingPackets.append(make_shared<EntityMessageResponsePacket>(makeRight(response.take()), entityMessagePacket->uuid));
|
||||||
@ -805,7 +809,13 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
|||||||
response.fail(entityMessageResponsePacket->response.left());
|
response.fail(entityMessageResponsePacket->response.left());
|
||||||
|
|
||||||
} else if (auto updateWorldProperties = as<UpdateWorldPropertiesPacket>(packet)) {
|
} else if (auto updateWorldProperties = as<UpdateWorldPropertiesPacket>(packet)) {
|
||||||
m_worldProperties.merge(updateWorldProperties->updatedProperties, true);
|
// Kae: Properties set to null (nil from Lua) should be erased instead of lingering around
|
||||||
|
for (auto& pair : updateWorldProperties->updatedProperties) {
|
||||||
|
if (pair.second.isNull())
|
||||||
|
m_worldProperties.erase(pair.first);
|
||||||
|
else
|
||||||
|
m_worldProperties[pair.first] = pair.second;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (auto updateTileProtection = as<UpdateTileProtectionPacket>(packet)) {
|
} else if (auto updateTileProtection = as<UpdateTileProtectionPacket>(packet)) {
|
||||||
setTileProtection(updateTileProtection->dungeonId, updateTileProtection->isProtected);
|
setTileProtection(updateTileProtection->dungeonId, updateTileProtection->isProtected);
|
||||||
|
Loading…
Reference in New Issue
Block a user