| @@ -0,0 +1,248 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #include "uiwidget.h" | |
| 24 | + | #include <framework/graphics/painter.h> | |
| 25 | + | #include <framework/graphics/image.h> | |
| 26 | + | #include <framework/graphics/texture.h> | |
| 27 | + | #include <framework/graphics/texturemanager.h> | |
| 28 | + | #include <framework/graphics/graphics.h> | |
| 29 | + | #include <framework/util/crypt.h> | |
| 30 | + | ||
| 31 | + | void UIWidget::initImage() | |
| 32 | + | { | |
| 33 | + | } | |
| 34 | + | ||
| 35 | + | void UIWidget::parseImageStyle(const OTMLNodePtr& styleNode) | |
| 36 | + | { | |
| 37 | + | for(const OTMLNodePtr& node : styleNode->children()) { | |
| 38 | + | if (node->tag() == "qr" || node->tag() == "qr-code") | |
| 39 | + | setQRCode(node->value(), 1); | |
| 40 | + | else if(node->tag() == "image-source") | |
| 41 | + | setImageSource(stdext::resolve_path(node->value(), node->source())); | |
| 42 | + | else if(node->tag() == "image-source-base64") | |
| 43 | + | setImageSourceBase64(node->value()); | |
| 44 | + | else if(node->tag() == "image-offset-x") | |
| 45 | + | setImageOffsetX(node->value<int>()); | |
| 46 | + | else if(node->tag() == "image-offset-y") | |
| 47 | + | setImageOffsetY(node->value<int>()); | |
| 48 | + | else if(node->tag() == "image-offset") | |
| 49 | + | setImageOffset(node->value<Point>()); | |
| 50 | + | else if(node->tag() == "image-width") | |
| 51 | + | setImageWidth(node->value<int>()); | |
| 52 | + | else if(node->tag() == "image-height") | |
| 53 | + | setImageHeight(node->value<int>()); | |
| 54 | + | else if(node->tag() == "image-size") | |
| 55 | + | setImageSize(node->value<Size>()); | |
| 56 | + | else if(node->tag() == "image-rect") | |
| 57 | + | setImageRect(node->value<Rect>()); | |
| 58 | + | else if(node->tag() == "image-clip") | |
| 59 | + | setImageClip(node->value<Rect>()); | |
| 60 | + | else if(node->tag() == "image-fixed-ratio") | |
| 61 | + | setImageFixedRatio(node->value<bool>()); | |
| 62 | + | else if(node->tag() == "image-repeated") | |
| 63 | + | setImageRepeated(node->value<bool>()); | |
| 64 | + | else if(node->tag() == "image-smooth") | |
| 65 | + | setImageSmooth(node->value<bool>()); | |
| 66 | + | else if(node->tag() == "image-color") | |
| 67 | + | setImageColor(node->value<Color>()); | |
| 68 | + | else if(node->tag() == "image-border-top") | |
| 69 | + | setImageBorderTop(node->value<int>()); | |
| 70 | + | else if(node->tag() == "image-border-right") | |
| 71 | + | setImageBorderRight(node->value<int>()); | |
| 72 | + | else if(node->tag() == "image-border-bottom") | |
| 73 | + | setImageBorderBottom(node->value<int>()); | |
| 74 | + | else if(node->tag() == "image-border-left") | |
| 75 | + | setImageBorderLeft(node->value<int>()); | |
| 76 | + | else if(node->tag() == "image-border") | |
| 77 | + | setImageBorder(node->value<int>()); | |
| 78 | + | else if(node->tag() == "image-auto-resize") | |
| 79 | + | setImageAutoResize(node->value<bool>()); | |
| 80 | + | else if(node->tag() == "image-shader") | |
| 81 | + | setImageShader(node->value()); | |
| 82 | + | } | |
| 83 | + | } | |
| 84 | + | ||
| 85 | + | void UIWidget::drawImage(const Rect& screenCoords) | |
| 86 | + | { | |
| 87 | + | if(!m_imageTexture || !screenCoords.isValid()) | |
| 88 | + | return; | |
| 89 | + | ||
| 90 | + | // cache vertex buffers | |
| 91 | + | if(m_imageCachedScreenCoords != screenCoords || m_imageMustRecache) { | |
| 92 | + | m_imageCoordsBuffer.clear(); | |
| 93 | + | m_imageCachedScreenCoords = screenCoords; | |
| 94 | + | m_imageMustRecache = false; | |
| 95 | + | ||
| 96 | + | Rect drawRect = screenCoords; | |
| 97 | + | drawRect.translate(m_imageRect.topLeft()); | |
| 98 | + | if(m_imageRect.isValid()) | |
| 99 | + | drawRect.resize(m_imageRect.size()); | |
| 100 | + | ||
| 101 | + | Rect clipRect = m_imageClipRect.isValid() ? m_imageClipRect : Rect(0, 0, m_imageTexture->getSize()); | |
| 102 | + | ||
| 103 | + | if(!m_imageBordered) { | |
| 104 | + | if(m_imageFixedRatio) { | |
| 105 | + | Size textureSize = m_imageTexture->getSize(); | |
| 106 | + | ||
| 107 | + | Size textureClipSize = drawRect.size(); | |
| 108 | + | textureClipSize.scale(textureSize, Fw::KeepAspectRatio); | |
| 109 | + | ||
| 110 | + | Point texCoordsOffset; | |
| 111 | + | if(textureSize.height() > textureClipSize.height()) | |
| 112 | + | texCoordsOffset.y = (textureSize.height() - textureClipSize.height())/2; | |
| 113 | + | else if(textureSize.width() > textureClipSize.width()) | |
| 114 | + | texCoordsOffset.x = (textureSize.width() - textureClipSize.width())/2; | |
| 115 | + | ||
| 116 | + | Rect textureClipRect(texCoordsOffset, textureClipSize); | |
| 117 | + | ||
| 118 | + | m_imageCoordsBuffer.addRect(drawRect, textureClipRect); | |
| 119 | + | } else { | |
| 120 | + | if(m_imageRepeated) | |
| 121 | + | m_imageCoordsBuffer.addRepeatedRects(drawRect, clipRect); | |
| 122 | + | else | |
| 123 | + | m_imageCoordsBuffer.addRect(drawRect, clipRect); | |
| 124 | + | } | |
| 125 | + | } else { | |
| 126 | + | int top = m_imageBorder.top; | |
| 127 | + | int bottom = m_imageBorder.bottom; | |
| 128 | + | int left = m_imageBorder.left; | |
| 129 | + | int right = m_imageBorder.right; | |
| 130 | + | ||
| 131 | + | // calculates border coords | |
| 132 | + | const Rect clip = clipRect; | |
| 133 | + | Rect leftBorder(clip.left(), clip.top() + top, left, clip.height() - top - bottom); | |
| 134 | + | Rect rightBorder(clip.right() - right + 1, clip.top() + top, right, clip.height() - top - bottom); | |
| 135 | + | Rect topBorder(clip.left() + left, clip.top(), clip.width() - right - left, top); | |
| 136 | + | Rect bottomBorder(clip.left() + left, clip.bottom() - bottom + 1, clip.width() - right - left, bottom); | |
| 137 | + | Rect topLeftCorner(clip.left(), clip.top(), left, top); | |
| 138 | + | Rect topRightCorner(clip.right() - right + 1, clip.top(), right, top); | |
| 139 | + | Rect bottomLeftCorner(clip.left(), clip.bottom() - bottom + 1, left, bottom); | |
| 140 | + | Rect bottomRightCorner(clip.right() - right + 1, clip.bottom() - bottom + 1, right, bottom); | |
| 141 | + | Rect center(clip.left() + left, clip.top() + top, clip.width() - right - left, clip.height() - top - bottom); | |
| 142 | + | Size bordersSize(leftBorder.width() + rightBorder.width(), topBorder.height() + bottomBorder.height()); | |
| 143 | + | Size centerSize = drawRect.size() - bordersSize; | |
| 144 | + | Rect rectCoords; | |
| 145 | + | ||
| 146 | + | // first the center | |
| 147 | + | if(centerSize.area() > 0) { | |
| 148 | + | rectCoords = Rect(drawRect.left() + leftBorder.width(), drawRect.top() + topBorder.height(), centerSize); | |
| 149 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, center); | |
| 150 | + | } | |
| 151 | + | // top left corner | |
| 152 | + | rectCoords = Rect(drawRect.topLeft(), topLeftCorner.size()); | |
| 153 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, topLeftCorner); | |
| 154 | + | // top | |
| 155 | + | rectCoords = Rect(drawRect.left() + topLeftCorner.width(), drawRect.topLeft().y, centerSize.width(), topBorder.height()); | |
| 156 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, topBorder); | |
| 157 | + | // top right corner | |
| 158 | + | rectCoords = Rect(drawRect.left() + topLeftCorner.width() + centerSize.width(), drawRect.top(), topRightCorner.size()); | |
| 159 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, topRightCorner); | |
| 160 | + | // left | |
| 161 | + | rectCoords = Rect(drawRect.left(), drawRect.top() + topLeftCorner.height(), leftBorder.width(), centerSize.height()); | |
| 162 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, leftBorder); | |
| 163 | + | // right | |
| 164 | + | rectCoords = Rect(drawRect.left() + leftBorder.width() + centerSize.width(), drawRect.top() + topRightCorner.height(), rightBorder.width(), centerSize.height()); | |
| 165 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, rightBorder); | |
| 166 | + | // bottom left corner | |
| 167 | + | rectCoords = Rect(drawRect.left(), drawRect.top() + topLeftCorner.height() + centerSize.height(), bottomLeftCorner.size()); | |
| 168 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, bottomLeftCorner); | |
| 169 | + | // bottom | |
| 170 | + | rectCoords = Rect(drawRect.left() + bottomLeftCorner.width(), drawRect.top() + topBorder.height() + centerSize.height(), centerSize.width(), bottomBorder.height()); | |
| 171 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, bottomBorder); | |
| 172 | + | // bottom right corner | |
| 173 | + | rectCoords = Rect(drawRect.left() + bottomLeftCorner.width() + centerSize.width(), drawRect.top() + topRightCorner.height() + centerSize.height(), bottomRightCorner.size()); | |
| 174 | + | m_imageCoordsBuffer.addRepeatedRects(rectCoords, bottomRightCorner); | |
| 175 | + | } | |
| 176 | + | } | |
| 177 | + | ||
| 178 | + | m_imageTexture->setSmooth(m_imageSmooth); | |
| 179 | + | if (!m_shader.empty()) { | |
| 180 | + | DrawQueueItemTextureCoords* thing = new DrawQueueItemImageWithShader(m_imageCoordsBuffer, m_imageTexture, m_imageColor, m_shader); | |
| 181 | + | g_drawQueue->add(thing); | |
| 182 | + | } | |
| 183 | + | else { | |
| 184 | + | g_drawQueue->addTextureCoords(m_imageCoordsBuffer, m_imageTexture, m_imageColor); | |
| 185 | + | } | |
| 186 | + | } | |
| 187 | + | ||
| 188 | + | void UIWidget::setQRCode(const std::string& code, int border) | |
| 189 | + | { | |
| 190 | + | m_imageTexture = TexturePtr(new Texture(Image::fromQRCode(code, border))); | |
| 191 | + | m_imageTexture->setCanCache(false); | |
| 192 | + | ||
| 193 | + | if (m_imageTexture && (!m_rect.isValid() || m_imageAutoResize)) { | |
| 194 | + | Size size = getSize(); | |
| 195 | + | Size imageSize = m_imageTexture->getSize(); | |
| 196 | + | if (size.width() <= 0 || m_imageAutoResize) | |
| 197 | + | size.setWidth(imageSize.width()); | |
| 198 | + | if (size.height() <= 0 || m_imageAutoResize) | |
| 199 | + | size.setHeight(imageSize.height()); | |
| 200 | + | setSize(size); | |
| 201 | + | } | |
| 202 | + | ||
| 203 | + | m_imageMustRecache = true; | |
| 204 | + | } | |
| 205 | + | ||
| 206 | + | void UIWidget::setImageSource(const std::string& source) | |
| 207 | + | { | |
| 208 | + | if(source.empty()) | |
| 209 | + | m_imageTexture = nullptr; | |
| 210 | + | else | |
| 211 | + | m_imageTexture = g_textures.getTexture(source); | |
| 212 | + | ||
| 213 | + | if(m_imageTexture && (!m_rect.isValid() || m_imageAutoResize)) { | |
| 214 | + | Size size = getSize(); | |
| 215 | + | Size imageSize = m_imageTexture->getSize(); | |
| 216 | + | if(size.width() <= 0 || m_imageAutoResize) | |
| 217 | + | size.setWidth(imageSize.width()); | |
| 218 | + | if(size.height() <= 0 || m_imageAutoResize) | |
| 219 | + | size.setHeight(imageSize.height()); | |
| 220 | + | setSize(size); | |
| 221 | + | } | |
| 222 | + | ||
| 223 | + | m_imageMustRecache = true; | |
| 224 | + | } | |
| 225 | + | ||
| 226 | + | void UIWidget::setImageSourceBase64(const std::string& data) { | |
| 227 | + | if (data.size() % 4 != 0 || data.empty()) { | |
| 228 | + | m_imageTexture = nullptr; | |
| 229 | + | m_imageMustRecache = true; | |
| 230 | + | return; | |
| 231 | + | } | |
| 232 | + | ||
| 233 | + | std::stringstream stream; | |
| 234 | + | std::string decoded = g_crypt.base64Decode(data); | |
| 235 | + | stream.write(decoded.c_str(), decoded.size()); | |
| 236 | + | m_imageTexture = g_textures.loadTexture(stream, "base64"); | |
| 237 | + | if(m_imageTexture && (!m_rect.isValid() || m_imageAutoResize)) { | |
| 238 | + | Size size = getSize(); | |
| 239 | + | Size imageSize = m_imageTexture->getSize(); | |
| 240 | + | if(size.width() <= 0 || m_imageAutoResize) | |
| 241 | + | size.setWidth(imageSize.width()); | |
| 242 | + | if(size.height() <= 0 || m_imageAutoResize) | |
| 243 | + | size.setHeight(imageSize.height()); | |
| 244 | + | setSize(size); | |
| 245 | + | } | |
| 246 | + | ||
| 247 | + | m_imageMustRecache = true; | |
| 248 | + | } |
| @@ -0,0 +1,168 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #include "uiwidget.h" | |
| 24 | + | #include "uitranslator.h" | |
| 25 | + | #include <framework/graphics/fontmanager.h> | |
| 26 | + | #include <framework/graphics/painter.h> | |
| 27 | + | #include <framework/core/application.h> | |
| 28 | + | ||
| 29 | + | void UIWidget::initText() | |
| 30 | + | { | |
| 31 | + | m_font = g_fonts.getDefaultFont(); | |
| 32 | + | m_textAlign = Fw::AlignCenter; | |
| 33 | + | } | |
| 34 | + | ||
| 35 | + | void UIWidget::updateText() | |
| 36 | + | { | |
| 37 | + | if (m_textWrap && m_rect.isValid()) { | |
| 38 | + | m_drawTextColors = m_textColors; | |
| 39 | + | m_drawText = m_font->wrapText(m_text, getWidth() - m_textOffset.x, &m_drawTextColors); | |
| 40 | + | } else { | |
| 41 | + | m_drawText = m_text; | |
| 42 | + | m_drawTextColors = m_textColors; | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | // update rect size | |
| 46 | + | if(!m_rect.isValid() || m_textHorizontalAutoResize || m_textVerticalAutoResize) { | |
| 47 | + | Size textBoxSize = getTextSize(); | |
| 48 | + | textBoxSize += Size(m_padding.left + m_padding.right, m_padding.top + m_padding.bottom) + m_textOffset.toSize(); | |
| 49 | + | Size size = getSize(); | |
| 50 | + | if(size.width() <= 0 || (m_textHorizontalAutoResize && !m_textWrap)) | |
| 51 | + | size.setWidth(textBoxSize.width()); | |
| 52 | + | if(size.height() <= 0 || m_textVerticalAutoResize) | |
| 53 | + | size.setHeight(textBoxSize.height()); | |
| 54 | + | setSize(size); | |
| 55 | + | } | |
| 56 | + | ||
| 57 | + | m_textMustRecache = true; | |
| 58 | + | } | |
| 59 | + | ||
| 60 | + | void UIWidget::parseTextStyle(const OTMLNodePtr& styleNode) | |
| 61 | + | { | |
| 62 | + | for(const OTMLNodePtr& node : styleNode->children()) { | |
| 63 | + | if(node->tag() == "text") | |
| 64 | + | setText(node->value()); | |
| 65 | + | else if(node->tag() == "text-align") | |
| 66 | + | setTextAlign(Fw::translateAlignment(node->value())); | |
| 67 | + | else if(node->tag() == "text-offset") | |
| 68 | + | setTextOffset(node->value<Point>()); | |
| 69 | + | else if(node->tag() == "text-wrap") | |
| 70 | + | setTextWrap(node->value<bool>()); | |
| 71 | + | else if(node->tag() == "text-auto-resize") | |
| 72 | + | setTextAutoResize(node->value<bool>()); | |
| 73 | + | else if(node->tag() == "text-horizontal-auto-resize") | |
| 74 | + | setTextHorizontalAutoResize(node->value<bool>()); | |
| 75 | + | else if(node->tag() == "text-vertical-auto-resize") | |
| 76 | + | setTextVerticalAutoResize(node->value<bool>()); | |
| 77 | + | else if(node->tag() == "text-only-upper-case") | |
| 78 | + | setTextOnlyUpperCase(node->value<bool>()); | |
| 79 | + | else if(node->tag() == "font") | |
| 80 | + | setFont(node->value()); | |
| 81 | + | else if (node->tag() == "shadow") | |
| 82 | + | setShadow(node->value<bool>()); | |
| 83 | + | } | |
| 84 | + | } | |
| 85 | + | ||
| 86 | + | void UIWidget::drawText(const Rect& screenCoords) | |
| 87 | + | { | |
| 88 | + | if(m_drawText.length() == 0 || m_color.aF() == 0.0f) | |
| 89 | + | return; | |
| 90 | + | ||
| 91 | + | if(screenCoords != m_textCachedScreenCoords || m_textMustRecache) { | |
| 92 | + | Rect coords = Rect(screenCoords.topLeft() + m_textOffset, screenCoords.bottomRight()); | |
| 93 | + | m_textMustRecache = false; | |
| 94 | + | m_textCachedScreenCoords = coords; | |
| 95 | + | } | |
| 96 | + | ||
| 97 | + | if (!m_drawTextColors.empty()) { | |
| 98 | + | m_font->drawColoredText(m_drawText, m_textCachedScreenCoords, m_textAlign, m_drawTextColors, m_shadow); | |
| 99 | + | } else { | |
| 100 | + | m_font->drawText(m_drawText, m_textCachedScreenCoords, m_textAlign, m_color, m_shadow); | |
| 101 | + | } | |
| 102 | + | } | |
| 103 | + | ||
| 104 | + | void UIWidget::onTextChange(const std::string& text, const std::string& oldText) | |
| 105 | + | { | |
| 106 | + | callLuaField("onTextChange", text, oldText); | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | void UIWidget::onFontChange(const std::string& font) | |
| 110 | + | { | |
| 111 | + | callLuaField("onFontChange", font); | |
| 112 | + | } | |
| 113 | + | ||
| 114 | + | void UIWidget::setText(std::string text, bool dontFireLuaCall) | |
| 115 | + | { | |
| 116 | + | if(m_textOnlyUpperCase) | |
| 117 | + | stdext::toupper(text); | |
| 118 | + | ||
| 119 | + | m_textColors.clear(); | |
| 120 | + | m_drawTextColors.clear(); | |
| 121 | + | ||
| 122 | + | if(m_text == text) | |
| 123 | + | return; | |
| 124 | + | ||
| 125 | + | std::string oldText = m_text; | |
| 126 | + | m_text = text; | |
| 127 | + | updateText(); | |
| 128 | + | ||
| 129 | + | if(!dontFireLuaCall) { | |
| 130 | + | onTextChange(text, oldText); | |
| 131 | + | } | |
| 132 | + | } | |
| 133 | + | ||
| 134 | + | void UIWidget::setColoredText(const std::vector<std::string>& texts, bool dontFireLuaCall) | |
| 135 | + | { | |
| 136 | + | m_textColors.clear(); | |
| 137 | + | m_drawTextColors.clear(); | |
| 138 | + | ||
| 139 | + | std::string text = ""; | |
| 140 | + | for(size_t i = 0, p = 0; i < texts.size() - 1; i += 2) { | |
| 141 | + | Color c(Color::white); | |
| 142 | + | stdext::cast<Color>(texts[i + 1], c); | |
| 143 | + | text += texts[i]; | |
| 144 | + | for (auto& c : texts[i]) { | |
| 145 | + | if ((uint8)c >= 32) | |
| 146 | + | p += 1; | |
| 147 | + | } | |
| 148 | + | m_textColors.push_back(std::make_pair(p, c)); | |
| 149 | + | } | |
| 150 | + | ||
| 151 | + | if (m_textOnlyUpperCase) | |
| 152 | + | stdext::toupper(text); | |
| 153 | + | ||
| 154 | + | std::string oldText = m_text; | |
| 155 | + | m_text = text; | |
| 156 | + | updateText(); | |
| 157 | + | ||
| 158 | + | if (!dontFireLuaCall) { | |
| 159 | + | onTextChange(text, oldText); | |
| 160 | + | } | |
| 161 | + | } | |
| 162 | + | ||
| 163 | + | void UIWidget::setFont(const std::string& fontName) | |
| 164 | + | { | |
| 165 | + | m_font = g_fonts.getFont(fontName); | |
| 166 | + | updateText(); | |
| 167 | + | onFontChange(fontName); | |
| 168 | + | } |
| @@ -0,0 +1,145 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #include "color.h" | |
| 24 | + | ||
| 25 | + | // NOTE: AABBGGRR order | |
| 26 | + | const Color Color::alpha = 0x00000000U; | |
| 27 | + | const Color Color::white = 0xffffffff; | |
| 28 | + | const Color Color::black = 0xff000000; | |
| 29 | + | const Color Color::red = 0xff0000ff; | |
| 30 | + | const Color Color::darkRed = 0xff000080; | |
| 31 | + | const Color Color::green = 0xff00ff00; | |
| 32 | + | const Color Color::darkGreen = 0xff008000; | |
| 33 | + | const Color Color::blue = 0xffff0000; | |
| 34 | + | const Color Color::darkBlue = 0xff800000; | |
| 35 | + | const Color Color::pink = 0xffff00ff; | |
| 36 | + | const Color Color::darkPink = 0xff800080; | |
| 37 | + | const Color Color::yellow = 0xff00ffff; | |
| 38 | + | const Color Color::darkYellow = 0xff008080; | |
| 39 | + | const Color Color::teal = 0xffffff00; | |
| 40 | + | const Color Color::darkTeal = 0xff808000; | |
| 41 | + | const Color Color::gray = 0xffa0a0a0; | |
| 42 | + | const Color Color::darkGray = 0xff808080; | |
| 43 | + | const Color Color::lightGray = 0xffc0c0c0; | |
| 44 | + | const Color Color::orange = 0xff008cff; | |
| 45 | + | ||
| 46 | + | Color::Color(const std::string& coltext) | |
| 47 | + | { | |
| 48 | + | std::stringstream ss(coltext); | |
| 49 | + | ss >> *this; | |
| 50 | + | } | |
| 51 | + | ||
| 52 | + | Color Color::getOutfitColor(int color) | |
| 53 | + | { | |
| 54 | + | static const int HSI_SI_VALUES = 7; | |
| 55 | + | static const int HSI_H_STEPS = 19; | |
| 56 | + | ||
| 57 | + | if (color >= HSI_H_STEPS * HSI_SI_VALUES) | |
| 58 | + | color = 0; | |
| 59 | + | ||
| 60 | + | float loc1 = 0, loc2 = 0, loc3 = 0; | |
| 61 | + | if (color % HSI_H_STEPS != 0) { | |
| 62 | + | loc1 = color % HSI_H_STEPS * 1.0 / 18.0; | |
| 63 | + | loc2 = 1; | |
| 64 | + | loc3 = 1; | |
| 65 | + | ||
| 66 | + | switch (int(color / HSI_H_STEPS)) { | |
| 67 | + | case 0: | |
| 68 | + | loc2 = 0.25; | |
| 69 | + | loc3 = 1.00; | |
| 70 | + | break; | |
| 71 | + | case 1: | |
| 72 | + | loc2 = 0.25; | |
| 73 | + | loc3 = 0.75; | |
| 74 | + | break; | |
| 75 | + | case 2: | |
| 76 | + | loc2 = 0.50; | |
| 77 | + | loc3 = 0.75; | |
| 78 | + | break; | |
| 79 | + | case 3: | |
| 80 | + | loc2 = 0.667; | |
| 81 | + | loc3 = 0.75; | |
| 82 | + | break; | |
| 83 | + | case 4: | |
| 84 | + | loc2 = 1.00; | |
| 85 | + | loc3 = 1.00; | |
| 86 | + | break; | |
| 87 | + | case 5: | |
| 88 | + | loc2 = 1.00; | |
| 89 | + | loc3 = 0.75; | |
| 90 | + | break; | |
| 91 | + | case 6: | |
| 92 | + | loc2 = 1.00; | |
| 93 | + | loc3 = 0.50; | |
| 94 | + | break; | |
| 95 | + | } | |
| 96 | + | } else { | |
| 97 | + | loc1 = 0; | |
| 98 | + | loc2 = 0; | |
| 99 | + | loc3 = 1 - (float)color / HSI_H_STEPS / (float)HSI_SI_VALUES; | |
| 100 | + | } | |
| 101 | + | ||
| 102 | + | if (loc3 == 0) | |
| 103 | + | return Color(0, 0, 0); | |
| 104 | + | ||
| 105 | + | if (loc2 == 0) { | |
| 106 | + | int loc7 = int(loc3 * 255); | |
| 107 | + | return Color(loc7, loc7, loc7); | |
| 108 | + | } | |
| 109 | + | ||
| 110 | + | float red = 0, green = 0, blue = 0; | |
| 111 | + | ||
| 112 | + | if (loc1 < 1.0 / 6.0) { | |
| 113 | + | red = loc3; | |
| 114 | + | blue = loc3 * (1 - loc2); | |
| 115 | + | green = blue + (loc3 - blue) * 6 * loc1; | |
| 116 | + | } else if (loc1 < 2.0 / 6.0) { | |
| 117 | + | green = loc3; | |
| 118 | + | blue = loc3 * (1 - loc2); | |
| 119 | + | red = green - (loc3 - blue) * (6 * loc1 - 1); | |
| 120 | + | } else if (loc1 < 3.0 / 6.0) { | |
| 121 | + | green = loc3; | |
| 122 | + | red = loc3 * (1 - loc2); | |
| 123 | + | blue = red + (loc3 - red) * (6 * loc1 - 2); | |
| 124 | + | } else if (loc1 < 4.0 / 6.0) { | |
| 125 | + | blue = loc3; | |
| 126 | + | red = loc3 * (1 - loc2); | |
| 127 | + | green = blue - (loc3 - red) * (6 * loc1 - 3); | |
| 128 | + | } else if (loc1 < 5.0 / 6.0) { | |
| 129 | + | blue = loc3; | |
| 130 | + | green = loc3 * (1 - loc2); | |
| 131 | + | red = green + (loc3 - green) * (6 * loc1 - 4); | |
| 132 | + | } else { | |
| 133 | + | red = loc3; | |
| 134 | + | green = loc3 * (1 - loc2); | |
| 135 | + | blue = red - (loc3 - green) * (6 * loc1 - 5); | |
| 136 | + | } | |
| 137 | + | return Color(int(red * 255), int(green * 255), int(blue * 255)); | |
| 138 | + | } | |
| 139 | + | ||
| 140 | + | std::string Color::toHex() | |
| 141 | + | { | |
| 142 | + | std::stringstream ss; | |
| 143 | + | ss << *this; | |
| 144 | + | return ss.str(); | |
| 145 | + | } |
| @@ -0,0 +1,222 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #ifndef COLOR_H | |
| 24 | + | #define COLOR_H | |
| 25 | + | ||
| 26 | + | #include "../stdext/types.h" | |
| 27 | + | #include "../stdext/cast.h" | |
| 28 | + | #include "../stdext/string.h" | |
| 29 | + | #include "../const.h" | |
| 30 | + | #include <iomanip> | |
| 31 | + | #include <algorithm> | |
| 32 | + | #include <sstream> | |
| 33 | + | ||
| 34 | + | class Color | |
| 35 | + | { | |
| 36 | + | public: | |
| 37 | + | Color() : m_r(1.0f), m_g(1.0f), m_b(1.0f), m_a(1.0f) { } | |
| 38 | + | Color(uint32 rgba) { setRGBA(rgba); } | |
| 39 | + | Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : m_r(r/255.0f), m_g(g/255.0f), m_b(b/255.0f), m_a(a/255.0f) { } | |
| 40 | + | Color(int r, int g, int b, int a = 0xFF) : m_r(r/255.0f), m_g(g/255.0f), m_b(b/255.0f), m_a(a/255.0f) { } | |
| 41 | + | Color(float r, float g, float b, float a = 1.0f) : m_r(r), m_g(g), m_b(b), m_a(a) { } | |
| 42 | + | Color(const std::string& coltext); | |
| 43 | + | ||
| 44 | + | uint8 a() const { return 255.0f * m_a; } | |
| 45 | + | uint8 b() const { return 255.0f * m_b; } | |
| 46 | + | uint8 g() const { return 255.0f * m_g; } | |
| 47 | + | uint8 r() const { return 255.0f * m_r; } | |
| 48 | + | ||
| 49 | + | float aF() const { return m_a; } | |
| 50 | + | float bF() const { return m_b; } | |
| 51 | + | float gF() const { return m_g; } | |
| 52 | + | float rF() const { return m_r; } | |
| 53 | + | ||
| 54 | + | void setRed(int r) { m_r = 0.003921f * r; } | |
| 55 | + | void setGreen(int g) { m_g = 0.003921f * g; } | |
| 56 | + | void setBlue(int b) { m_b = 0.003921f * b; } | |
| 57 | + | void setAlpha(int a) { m_a = 0.003921f * a; } | |
| 58 | + | ||
| 59 | + | void setRed(float r) { m_r = r; } | |
| 60 | + | void setGreen(float g) { m_g = g; } | |
| 61 | + | void setBlue(float b) { m_b = b; } | |
| 62 | + | void setAlpha(float a) { m_a = a; } | |
| 63 | + | ||
| 64 | + | void setRGBA(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) { m_r = r/255.0f; m_g = g/255.0f; m_b = b/255.0f; m_a = a/255.0f; } | |
| 65 | + | void setRGBA(uint32 rgba) { setRGBA((rgba >> 0) & 0xff, (rgba >> 8) & 0xff, (rgba >> 16) & 0xff, (rgba >> 24) & 0xff); } | |
| 66 | + | ||
| 67 | + | Color opacity(float opacity) const { | |
| 68 | + | return Color(m_r, m_g, m_b, m_a * opacity); | |
| 69 | + | } | |
| 70 | + | ||
| 71 | + | Color operator+(const Color& other) const { return Color(m_r + other.m_r, m_g + other.m_g, m_b + other.m_b, m_a + other.m_a); } | |
| 72 | + | Color operator-(const Color& other) const { return Color(m_r - other.m_r, m_g - other.m_g, m_b - other.m_b, m_a - other.m_a); } | |
| 73 | + | ||
| 74 | + | Color operator*(float v) const { return Color(m_r*v, m_g*v, m_b*v, m_a*v); } | |
| 75 | + | Color operator/(float v) const { return Color(m_r/v, m_g/v, m_b/v, m_a/v); } | |
| 76 | + | ||
| 77 | + | Color& operator=(uint32_t rgba) { setRGBA(rgba); return *this; } | |
| 78 | + | ||
| 79 | + | Color operator+=(const Color& other) const { | |
| 80 | + | return Color(std::min<float>(1.0f, m_r + other.m_r), std::min<float>(1.0f, m_g + other.m_g), | |
| 81 | + | std::min<float>(1.0f, m_b + other.m_b), std::min<float>(1.0f, m_a + other.m_a)); | |
| 82 | + | } | |
| 83 | + | ||
| 84 | + | Color& operator=(const Color& other) { m_r = other.m_r; m_g = other.m_g; m_b = other.m_b; m_a = other.m_a; return *this; } | |
| 85 | + | bool operator==(const Color& other) const { | |
| 86 | + | if (std::abs(other.m_r - m_r) > 0.001) return false; | |
| 87 | + | if (std::abs(other.m_g - m_g) > 0.001) return false; | |
| 88 | + | if (std::abs(other.m_b - m_b) > 0.001) return false; | |
| 89 | + | if (std::abs(other.m_a - m_a) > 0.001) return false; | |
| 90 | + | return true; | |
| 91 | + | } | |
| 92 | + | bool operator!=(const Color& other) const { return !(other == *this); } | |
| 93 | + | ||
| 94 | + | std::string toHex(); | |
| 95 | + | ||
| 96 | + | static uint8 to8bit(const Color& color) { | |
| 97 | + | uint8 c = 0; | |
| 98 | + | c += (color.r() / 51) * 36; | |
| 99 | + | c += (color.g() / 51) * 6; | |
| 100 | + | c += (color.b() / 51); | |
| 101 | + | return c; | |
| 102 | + | } | |
| 103 | + | ||
| 104 | + | static Color from8bit(int color) { | |
| 105 | + | if(color >= 216 || color <= 0) | |
| 106 | + | return Color(0, 0, 0); | |
| 107 | + | ||
| 108 | + | int r = int(color / 36) % 6 * 51; | |
| 109 | + | int g = int(color / 6) % 6 * 51; | |
| 110 | + | int b = color % 6 * 51; | |
| 111 | + | return Color(r, g, b); | |
| 112 | + | } | |
| 113 | + | ||
| 114 | + | static Color getOutfitColor(int color); | |
| 115 | + | ||
| 116 | + | static const Color alpha; | |
| 117 | + | static const Color white; | |
| 118 | + | static const Color black; | |
| 119 | + | static const Color red; | |
| 120 | + | static const Color darkRed; | |
| 121 | + | static const Color green; | |
| 122 | + | static const Color darkGreen; | |
| 123 | + | static const Color blue; | |
| 124 | + | static const Color darkBlue; | |
| 125 | + | static const Color pink; | |
| 126 | + | static const Color darkPink; | |
| 127 | + | static const Color yellow; | |
| 128 | + | static const Color darkYellow; | |
| 129 | + | static const Color teal; | |
| 130 | + | static const Color darkTeal; | |
| 131 | + | static const Color gray; | |
| 132 | + | static const Color darkGray; | |
| 133 | + | static const Color lightGray; | |
| 134 | + | static const Color orange; | |
| 135 | + | ||
| 136 | + | private: | |
| 137 | + | float m_r; | |
| 138 | + | float m_g; | |
| 139 | + | float m_b; | |
| 140 | + | float m_a; | |
| 141 | + | }; | |
| 142 | + | ||
| 143 | + | inline std::ostream& operator<<(std::ostream& out, const Color& color) | |
| 144 | + | { | |
| 145 | + | using namespace std; | |
| 146 | + | out << "#" << hex << setfill('0') | |
| 147 | + | << setw(2) << (int)color.r() | |
| 148 | + | << setw(2) << (int)color.g() | |
| 149 | + | << setw(2) << (int)color.b() | |
| 150 | + | << setw(2) << (int)color.a(); | |
| 151 | + | out << dec << setfill(' '); | |
| 152 | + | return out; | |
| 153 | + | } | |
| 154 | + | ||
| 155 | + | inline std::istream& operator>>(std::istream& in, Color& color) | |
| 156 | + | { | |
| 157 | + | using namespace std; | |
| 158 | + | std::string tmp; | |
| 159 | + | ||
| 160 | + | if(in.get() == '#') { | |
| 161 | + | in >> tmp; | |
| 162 | + | ||
| 163 | + | if(tmp.length() == 6 || tmp.length() == 8) { | |
| 164 | + | color.setRed((uint8)stdext::hex_to_dec(tmp.substr(0, 2))); | |
| 165 | + | color.setGreen((uint8)stdext::hex_to_dec(tmp.substr(2, 2))); | |
| 166 | + | color.setBlue((uint8)stdext::hex_to_dec(tmp.substr(4, 2))); | |
| 167 | + | if(tmp.length() == 8) | |
| 168 | + | color.setAlpha((uint8)stdext::hex_to_dec(tmp.substr(6, 2))); | |
| 169 | + | else | |
| 170 | + | color.setAlpha(255); | |
| 171 | + | } else | |
| 172 | + | in.seekg(-(std::streampos)tmp.length()-1, ios_base::cur); | |
| 173 | + | } else { | |
| 174 | + | in.unget(); | |
| 175 | + | in >> tmp; | |
| 176 | + | ||
| 177 | + | if(tmp == "alpha") { | |
| 178 | + | color = Color::alpha; | |
| 179 | + | } else if(tmp == "black") { | |
| 180 | + | color = Color::black; | |
| 181 | + | } else if(tmp == "white") { | |
| 182 | + | color = Color::white; | |
| 183 | + | } else if(tmp == "red") { | |
| 184 | + | color = Color::red; | |
| 185 | + | } else if(tmp == "darkRed") { | |
| 186 | + | color = Color::darkRed; | |
| 187 | + | } else if(tmp == "green") { | |
| 188 | + | color = Color::green; | |
| 189 | + | } else if(tmp == "darkGreen") { | |
| 190 | + | color = Color::darkGreen; | |
| 191 | + | } else if(tmp == "blue") { | |
| 192 | + | color = Color::blue; | |
| 193 | + | } else if(tmp == "darkBlue") { | |
| 194 | + | color = Color::darkBlue; | |
| 195 | + | } else if(tmp == "pink") { | |
| 196 | + | color = Color::pink; | |
| 197 | + | } else if(tmp == "darkPink") { | |
| 198 | + | color = Color::darkPink; | |
| 199 | + | } else if(tmp == "yellow") { | |
| 200 | + | color = Color::yellow; | |
| 201 | + | } else if(tmp == "darkYellow") { | |
| 202 | + | color = Color::darkYellow; | |
| 203 | + | } else if(tmp == "teal") { | |
| 204 | + | color = Color::teal; | |
| 205 | + | } else if(tmp == "darkTeal") { | |
| 206 | + | color = Color::darkTeal; | |
| 207 | + | } else if(tmp == "gray") { | |
| 208 | + | color = Color::gray; | |
| 209 | + | } else if(tmp == "darkGray") { | |
| 210 | + | color = Color::darkGray; | |
| 211 | + | } else if(tmp == "lightGray") { | |
| 212 | + | color = Color::lightGray; | |
| 213 | + | } else if(tmp == "orange") { | |
| 214 | + | color = Color::orange; | |
| 215 | + | } else { | |
| 216 | + | in.seekg(-tmp.length(), ios_base::cur); | |
| 217 | + | } | |
| 218 | + | } | |
| 219 | + | return in; | |
| 220 | + | } | |
| 221 | + | ||
| 222 | + | #endif |
| @@ -0,0 +1,526 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #include "crypt.h" | |
| 24 | + | #include <framework/stdext/math.h> | |
| 25 | + | #include <framework/core/logger.h> | |
| 26 | + | #include <framework/core/resourcemanager.h> | |
| 27 | + | #include <framework/platform/platform.h> | |
| 28 | + | #include <framework/core/application.h> | |
| 29 | + | ||
| 30 | + | #include <boost/uuid/uuid_generators.hpp> | |
| 31 | + | #include <boost/uuid/uuid_io.hpp> | |
| 32 | + | #include <boost/functional/hash.hpp> | |
| 33 | + | ||
| 34 | + | #ifndef __EMSCRIPTEN__ | |
| 35 | + | #include <openssl/rsa.h> | |
| 36 | + | #include <openssl/sha.h> | |
| 37 | + | #include <openssl/md5.h> | |
| 38 | + | #include <openssl/bn.h> | |
| 39 | + | #include <openssl/err.h> | |
| 40 | + | #endif | |
| 41 | + | #include <zlib.h> | |
| 42 | + | ||
| 43 | + | static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 44 | + | static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } | |
| 45 | + | ||
| 46 | + | Crypt g_crypt; | |
| 47 | + | ||
| 48 | + | Crypt::Crypt() | |
| 49 | + | { | |
| 50 | + | #ifndef __EMSCRIPTEN__ | |
| 51 | + | m_rsa = RSA_new(); | |
| 52 | + | #endif | |
| 53 | + | } | |
| 54 | + | ||
| 55 | + | Crypt::~Crypt() | |
| 56 | + | { | |
| 57 | + | #ifndef __EMSCRIPTEN__ | |
| 58 | + | RSA_free(m_rsa); | |
| 59 | + | #endif | |
| 60 | + | } | |
| 61 | + | ||
| 62 | + | std::string Crypt::base64Encode(const std::string& decoded_string) | |
| 63 | + | { | |
| 64 | + | std::string ret; | |
| 65 | + | int i = 0; | |
| 66 | + | int j = 0; | |
| 67 | + | uint8 char_array_3[3]; | |
| 68 | + | uint8 char_array_4[4]; | |
| 69 | + | int pos = 0; | |
| 70 | + | int len = decoded_string.size(); | |
| 71 | + | ||
| 72 | + | while(len--) { | |
| 73 | + | char_array_3[i++] = decoded_string[pos++]; | |
| 74 | + | if(i == 3) { | |
| 75 | + | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | |
| 76 | + | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | |
| 77 | + | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | |
| 78 | + | char_array_4[3] = char_array_3[2] & 0x3f; | |
| 79 | + | ||
| 80 | + | for(i = 0; (i <4) ; i++) | |
| 81 | + | ret += base64_chars[char_array_4[i]]; | |
| 82 | + | i = 0; | |
| 83 | + | } | |
| 84 | + | } | |
| 85 | + | ||
| 86 | + | if(i) { | |
| 87 | + | for(j = i; j < 3; j++) | |
| 88 | + | char_array_3[j] = '\0'; | |
| 89 | + | ||
| 90 | + | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | |
| 91 | + | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | |
| 92 | + | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | |
| 93 | + | char_array_4[3] = char_array_3[2] & 0x3f; | |
| 94 | + | ||
| 95 | + | for(j = 0; (j < i + 1); j++) | |
| 96 | + | ret += base64_chars[char_array_4[j]]; | |
| 97 | + | ||
| 98 | + | while((i++ < 3)) | |
| 99 | + | ret += '='; | |
| 100 | + | } | |
| 101 | + | ||
| 102 | + | return ret; | |
| 103 | + | } | |
| 104 | + | ||
| 105 | + | std::string Crypt::base64Decode(const std::string& encoded_string) | |
| 106 | + | { | |
| 107 | + | int len = encoded_string.size(); | |
| 108 | + | int i = 0; | |
| 109 | + | int j = 0; | |
| 110 | + | int in_ = 0; | |
| 111 | + | uint8 char_array_4[4], char_array_3[3]; | |
| 112 | + | std::string ret; | |
| 113 | + | ||
| 114 | + | while(len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { | |
| 115 | + | char_array_4[i++] = encoded_string[in_]; in_++; | |
| 116 | + | if(i ==4) { | |
| 117 | + | for(i = 0; i <4; i++) | |
| 118 | + | char_array_4[i] = base64_chars.find(char_array_4[i]); | |
| 119 | + | ||
| 120 | + | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | |
| 121 | + | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | |
| 122 | + | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | |
| 123 | + | ||
| 124 | + | for(i = 0; (i < 3); i++) | |
| 125 | + | ret += char_array_3[i]; | |
| 126 | + | i = 0; | |
| 127 | + | } | |
| 128 | + | } | |
| 129 | + | ||
| 130 | + | if(i) { | |
| 131 | + | for(j = i; j <4; j++) | |
| 132 | + | char_array_4[j] = 0; | |
| 133 | + | ||
| 134 | + | for(j = 0; j <4; j++) | |
| 135 | + | char_array_4[j] = base64_chars.find(char_array_4[j]); | |
| 136 | + | ||
| 137 | + | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | |
| 138 | + | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | |
| 139 | + | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | |
| 140 | + | ||
| 141 | + | for(j = 0; (j < i - 1); j++) | |
| 142 | + | ret += char_array_3[j]; | |
| 143 | + | } | |
| 144 | + | ||
| 145 | + | return ret; | |
| 146 | + | } | |
| 147 | + | ||
| 148 | + | std::string Crypt::xorCrypt(const std::string& buffer, const std::string& key) | |
| 149 | + | { | |
| 150 | + | std::string out; | |
| 151 | + | out.resize(buffer.size()); | |
| 152 | + | size_t i, j=0; | |
| 153 | + | for(i=0;i<buffer.size();++i) { | |
| 154 | + | out[i] = buffer[i] ^ key[j++]; | |
| 155 | + | if(j >= key.size()) | |
| 156 | + | j = 0; | |
| 157 | + | } | |
| 158 | + | return out; | |
| 159 | + | } | |
| 160 | + | ||
| 161 | + | std::string Crypt::genUUID() | |
| 162 | + | { | |
| 163 | + | boost::uuids::random_generator gen; | |
| 164 | + | boost::uuids::uuid u = gen(); | |
| 165 | + | return boost::uuids::to_string(u); | |
| 166 | + | } | |
| 167 | + | ||
| 168 | + | bool Crypt::setMachineUUID(std::string uuidstr) | |
| 169 | + | { | |
| 170 | + | if(uuidstr.empty()) | |
| 171 | + | return false; | |
| 172 | + | uuidstr = _decrypt(uuidstr, false); | |
| 173 | + | if(uuidstr.length() != 16) | |
| 174 | + | return false; | |
| 175 | + | std::copy(uuidstr.begin(), uuidstr.end(), m_machineUUID.begin()); | |
| 176 | + | return true; | |
| 177 | + | } | |
| 178 | + | ||
| 179 | + | std::string Crypt::getMachineUUID() | |
| 180 | + | { | |
| 181 | + | if(m_machineUUID.is_nil()) { | |
| 182 | + | boost::uuids::random_generator gen; | |
| 183 | + | m_machineUUID = gen(); | |
| 184 | + | } | |
| 185 | + | return _encrypt(std::string(m_machineUUID.begin(), m_machineUUID.end()), false); | |
| 186 | + | } | |
| 187 | + | ||
| 188 | + | std::string Crypt::getCryptKey(bool useMachineUUID) | |
| 189 | + | { | |
| 190 | + | boost::hash<boost::uuids::uuid> uuid_hasher; | |
| 191 | + | boost::uuids::uuid uuid; | |
| 192 | + | if(useMachineUUID) { | |
| 193 | + | uuid = m_machineUUID; | |
| 194 | + | } else { | |
| 195 | + | boost::uuids::nil_generator nilgen; | |
| 196 | + | uuid = nilgen(); | |
| 197 | + | } | |
| 198 | + | boost::uuids::name_generator namegen(uuid); | |
| 199 | + | boost::uuids::uuid u = namegen(g_app.getCompactName() + g_platform.getCPUName() + g_platform.getOSName()); | |
| 200 | + | std::size_t hash = uuid_hasher(u); | |
| 201 | + | std::string key; | |
| 202 | + | key.assign((const char *)&hash, sizeof(hash)); | |
| 203 | + | return key; | |
| 204 | + | } | |
| 205 | + | ||
| 206 | + | std::string Crypt::_encrypt(const std::string& decrypted_string, bool useMachineUUID) | |
| 207 | + | { | |
| 208 | + | std::string tmp = std::string("0000") + decrypted_string; | |
| 209 | + | uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size()); | |
| 210 | + | stdext::writeULE32((uint8*)&tmp[0], sum); | |
| 211 | + | std::string encrypted = base64Encode(xorCrypt(tmp, getCryptKey(useMachineUUID))); | |
| 212 | + | return encrypted; | |
| 213 | + | } | |
| 214 | + | ||
| 215 | + | std::string Crypt::_decrypt(const std::string& encrypted_string, bool useMachineUUID) | |
| 216 | + | { | |
| 217 | + | std::string decoded = base64Decode(encrypted_string); | |
| 218 | + | std::string tmp = xorCrypt(decoded, getCryptKey(useMachineUUID)); | |
| 219 | + | if(tmp.length() >= 4) { | |
| 220 | + | uint32 readsum = stdext::readULE32((const uint8*)tmp.c_str()); | |
| 221 | + | std::string decrypted_string = tmp.substr(4); | |
| 222 | + | uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size()); | |
| 223 | + | if(readsum == sum) | |
| 224 | + | return decrypted_string; | |
| 225 | + | } | |
| 226 | + | return std::string(); | |
| 227 | + | } | |
| 228 | + | ||
| 229 | + | std::string Crypt::md5Encode(const std::string& decoded_string, bool upperCase) | |
| 230 | + | { | |
| 231 | + | #ifndef __EMSCRIPTEN__ | |
| 232 | + | MD5_CTX c; | |
| 233 | + | MD5_Init(&c); | |
| 234 | + | MD5_Update(&c, decoded_string.c_str(), decoded_string.length()); | |
| 235 | + | ||
| 236 | + | uint8_t md[MD5_DIGEST_LENGTH]; | |
| 237 | + | MD5_Final(md, &c); | |
| 238 | + | ||
| 239 | + | char output[(MD5_DIGEST_LENGTH << 1) + 1]; | |
| 240 | + | for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) | |
| 241 | + | sprintf(output + (i << 1), "%.2X", md[i]); | |
| 242 | + | ||
| 243 | + | std::string result = output; | |
| 244 | + | if(upperCase) | |
| 245 | + | return result; | |
| 246 | + | ||
| 247 | + | std::transform(result.begin(), result.end(), result.begin(), tolower); | |
| 248 | + | return result; | |
| 249 | + | #else | |
| 250 | + | return ""; | |
| 251 | + | #endif | |
| 252 | + | } | |
| 253 | + | ||
| 254 | + | std::string Crypt::sha1Encode(const std::string& decoded_string, bool upperCase) | |
| 255 | + | { | |
| 256 | + | #ifndef __EMSCRIPTEN__ | |
| 257 | + | SHA_CTX c; | |
| 258 | + | SHA1_Init(&c); | |
| 259 | + | SHA1_Update(&c, decoded_string.c_str(), decoded_string.length()); | |
| 260 | + | ||
| 261 | + | uint8_t md[SHA_DIGEST_LENGTH]; | |
| 262 | + | SHA1_Final(md, &c); | |
| 263 | + | ||
| 264 | + | char output[(SHA_DIGEST_LENGTH << 1) + 1]; | |
| 265 | + | for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) | |
| 266 | + | sprintf(output + (i << 1), "%.2X", md[i]); | |
| 267 | + | ||
| 268 | + | std::string result = output; | |
| 269 | + | if(upperCase) | |
| 270 | + | return result; | |
| 271 | + | ||
| 272 | + | std::transform(result.begin(), result.end(), result.begin(), tolower); | |
| 273 | + | return result; | |
| 274 | + | #else | |
| 275 | + | return ""; | |
| 276 | + | #endif | |
| 277 | + | } | |
| 278 | + | ||
| 279 | + | std::string Crypt::sha256Encode(const std::string& decoded_string, bool upperCase) | |
| 280 | + | { | |
| 281 | + | #ifndef __EMSCRIPTEN__ | |
| 282 | + | SHA256_CTX c; | |
| 283 | + | SHA256_Init(&c); | |
| 284 | + | SHA256_Update(&c, decoded_string.c_str(), decoded_string.length()); | |
| 285 | + | ||
| 286 | + | uint8_t md[SHA256_DIGEST_LENGTH]; | |
| 287 | + | SHA256_Final(md, &c); | |
| 288 | + | ||
| 289 | + | char output[(SHA256_DIGEST_LENGTH << 1) + 1]; | |
| 290 | + | for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) | |
| 291 | + | sprintf(output + (i << 1), "%.2X", md[i]); | |
| 292 | + | ||
| 293 | + | std::string result = output; | |
| 294 | + | if(upperCase) | |
| 295 | + | return result; | |
| 296 | + | ||
| 297 | + | std::transform(result.begin(), result.end(), result.begin(), tolower); | |
| 298 | + | return result; | |
| 299 | + | #else | |
| 300 | + | return ""; | |
| 301 | + | #endif | |
| 302 | + | } | |
| 303 | + | ||
| 304 | + | std::string Crypt::sha512Encode(const std::string& decoded_string, bool upperCase) | |
| 305 | + | { | |
| 306 | + | #ifndef __EMSCRIPTEN__ | |
| 307 | + | SHA512_CTX c; | |
| 308 | + | SHA512_Init(&c); | |
| 309 | + | SHA512_Update(&c, decoded_string.c_str(), decoded_string.length()); | |
| 310 | + | ||
| 311 | + | uint8_t md[SHA512_DIGEST_LENGTH]; | |
| 312 | + | SHA512_Final(md, &c); | |
| 313 | + | ||
| 314 | + | char output[(SHA512_DIGEST_LENGTH << 1) + 1]; | |
| 315 | + | for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) | |
| 316 | + | sprintf(output + (i << 1), "%.2X", md[i]); | |
| 317 | + | ||
| 318 | + | std::string result = output; | |
| 319 | + | if(upperCase) | |
| 320 | + | return result; | |
| 321 | + | ||
| 322 | + | std::transform(result.begin(), result.end(), result.begin(), tolower); | |
| 323 | + | return result; | |
| 324 | + | #else | |
| 325 | + | return ""; | |
| 326 | + | #endif | |
| 327 | + | } | |
| 328 | + | ||
| 329 | + | std::string Crypt::crc32(const std::string& decoded_string, bool upperCase) | |
| 330 | + | { | |
| 331 | + | uint32_t crc = ::crc32(0, Z_NULL, 0); | |
| 332 | + | crc = ::crc32(crc, (const Bytef*)decoded_string.c_str(), decoded_string.size()); | |
| 333 | + | std::string result = stdext::dec_to_hex(crc); | |
| 334 | + | if (upperCase) | |
| 335 | + | std::transform(result.begin(), result.end(), result.begin(), toupper); | |
| 336 | + | else | |
| 337 | + | std::transform(result.begin(), result.end(), result.begin(), tolower); | |
| 338 | + | return result; | |
| 339 | + | } | |
| 340 | + | ||
| 341 | + | ||
| 342 | + | void Crypt::rsaGenerateKey(int bits, int e) | |
| 343 | + | { | |
| 344 | + | // disabled because new OpenSSL changes broke | |
| 345 | + | /* | |
| 346 | + | RSA *rsa = RSA_new(); | |
| 347 | + | BIGNUM *ebn = BN_new(); | |
| 348 | + | BN_set_word(ebn, e); | |
| 349 | + | RSA_generate_key_ex(rsa, bits, ebn, nullptr); | |
| 350 | + | g_logger.info(stdext::format("%d bits (%d bytes) RSA key generated", bits, bits / 8)); | |
| 351 | + | g_logger.info(std::string("p = ") + BN_bn2dec(m_rsa->p)); | |
| 352 | + | g_logger.info(std::string("q = ") + BN_bn2dec(m_rsa->q)); | |
| 353 | + | g_logger.info(std::string("d = ") + BN_bn2dec(m_rsa->d)); | |
| 354 | + | g_logger.info(std::string("n = ") + BN_bn2dec(m_rsa->n)); | |
| 355 | + | g_logger.info(std::string("e = ") + BN_bn2dec(m_rsa->e)); | |
| 356 | + | BN_clear_free(ebn); | |
| 357 | + | RSA_free(rsa); | |
| 358 | + | */ | |
| 359 | + | } | |
| 360 | + | ||
| 361 | + | void Crypt::rsaSetPublicKey(const std::string& n, const std::string& e) | |
| 362 | + | { | |
| 363 | + | #ifndef __EMSCRIPTEN__ | |
| 364 | + | #if OPENSSL_VERSION_NUMBER < 0x10100005L | |
| 365 | + | BN_dec2bn(&m_rsa->n, n.c_str()); | |
| 366 | + | BN_dec2bn(&m_rsa->e, e.c_str()); | |
| 367 | + | // clear rsa cache | |
| 368 | + | if(m_rsa->_method_mod_n) { | |
| 369 | + | BN_MONT_CTX_free(m_rsa->_method_mod_n); | |
| 370 | + | m_rsa->_method_mod_n = nullptr; | |
| 371 | + | } | |
| 372 | + | #else | |
| 373 | + | BIGNUM *bn = nullptr, *be = nullptr; | |
| 374 | + | BN_dec2bn(&bn, n.c_str()); | |
| 375 | + | BN_dec2bn(&be, e.c_str()); | |
| 376 | + | RSA_set0_key(m_rsa, bn, be, nullptr); | |
| 377 | + | #endif | |
| 378 | + | #endif | |
| 379 | + | } | |
| 380 | + | ||
| 381 | + | void Crypt::rsaSetPrivateKey(const std::string& p, const std::string& q, const std::string& d) | |
| 382 | + | { | |
| 383 | + | #ifndef __EMSCRIPTEN__ | |
| 384 | + | #if OPENSSL_VERSION_NUMBER < 0x10100005L | |
| 385 | + | BN_dec2bn(&m_rsa->p, p.c_str()); | |
| 386 | + | BN_dec2bn(&m_rsa->q, q.c_str()); | |
| 387 | + | BN_dec2bn(&m_rsa->d, d.c_str()); | |
| 388 | + | // clear rsa cache | |
| 389 | + | if(m_rsa->_method_mod_p) { | |
| 390 | + | BN_MONT_CTX_free(m_rsa->_method_mod_p); | |
| 391 | + | m_rsa->_method_mod_p = nullptr; | |
| 392 | + | } | |
| 393 | + | if(m_rsa->_method_mod_q) { | |
| 394 | + | BN_MONT_CTX_free(m_rsa->_method_mod_q); | |
| 395 | + | m_rsa->_method_mod_q = nullptr; | |
| 396 | + | } | |
| 397 | + | #else | |
| 398 | + | BIGNUM *bp = nullptr, *bq = nullptr, *bd = nullptr; | |
| 399 | + | BN_dec2bn(&bp, p.c_str()); | |
| 400 | + | BN_dec2bn(&bq, q.c_str()); | |
| 401 | + | BN_dec2bn(&bd, d.c_str()); | |
| 402 | + | RSA_set0_key(m_rsa, nullptr, nullptr, bd); | |
| 403 | + | RSA_set0_factors(m_rsa, bp, bq); | |
| 404 | + | #endif | |
| 405 | + | #endif | |
| 406 | + | } | |
| 407 | + | ||
| 408 | + | bool Crypt::rsaCheckKey() | |
| 409 | + | { | |
| 410 | + | #ifndef __EMSCRIPTEN__ | |
| 411 | + | // only used by server, that sets both public and private | |
| 412 | + | if(RSA_check_key(m_rsa)) { | |
| 413 | + | BN_CTX *ctx = BN_CTX_new(); | |
| 414 | + | BN_CTX_start(ctx); | |
| 415 | + | ||
| 416 | + | BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx); | |
| 417 | + | #if OPENSSL_VERSION_NUMBER < 0x10100005L | |
| 418 | + | BN_mod(m_rsa->dmp1, m_rsa->d, r1, ctx); | |
| 419 | + | BN_mod(m_rsa->dmq1, m_rsa->d, r2, ctx); | |
| 420 | + | BN_mod_inverse(m_rsa->iqmp, m_rsa->q, m_rsa->p, ctx); | |
| 421 | + | #else | |
| 422 | + | const BIGNUM *dmp1_c = nullptr, *d = nullptr, *dmq1_c = nullptr, *iqmp_c = nullptr, *q = nullptr, *p = nullptr; | |
| 423 | + | ||
| 424 | + | RSA_get0_key(m_rsa, nullptr, nullptr, &d); | |
| 425 | + | RSA_get0_factors(m_rsa, &p, &q); | |
| 426 | + | RSA_get0_crt_params(m_rsa, &dmp1_c, &dmq1_c, &iqmp_c); | |
| 427 | + | ||
| 428 | + | BIGNUM *dmp1 = BN_dup(dmp1_c), *dmq1 = BN_dup(dmq1_c), *iqmp = BN_dup(iqmp_c); | |
| 429 | + | ||
| 430 | + | BN_mod(dmp1, d, r1, ctx); | |
| 431 | + | BN_mod(dmq1, d, r2, ctx); | |
| 432 | + | BN_mod_inverse(iqmp, q, p, ctx); | |
| 433 | + | RSA_set0_crt_params(m_rsa, dmp1, dmq1, iqmp); | |
| 434 | + | #endif | |
| 435 | + | return true; | |
| 436 | + | } | |
| 437 | + | else { | |
| 438 | + | ERR_load_crypto_strings(); | |
| 439 | + | g_logger.error(stdext::format("RSA check failed - %s", ERR_error_string(ERR_get_error(), nullptr))); | |
| 440 | + | return false; | |
| 441 | + | } | |
| 442 | + | #else | |
| 443 | + | return false; | |
| 444 | + | #endif | |
| 445 | + | } | |
| 446 | + | ||
| 447 | + | bool Crypt::rsaEncrypt(unsigned char *msg, int size) | |
| 448 | + | { | |
| 449 | + | #ifndef __EMSCRIPTEN__ | |
| 450 | + | if(size != RSA_size(m_rsa)) | |
| 451 | + | return false; | |
| 452 | + | return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; | |
| 453 | + | #else | |
| 454 | + | return false; | |
| 455 | + | #endif | |
| 456 | + | } | |
| 457 | + | ||
| 458 | + | bool Crypt::rsaDecrypt(unsigned char *msg, int size) | |
| 459 | + | { | |
| 460 | + | #ifndef __EMSCRIPTEN__ | |
| 461 | + | if(size != RSA_size(m_rsa)) | |
| 462 | + | return false; | |
| 463 | + | return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1; | |
| 464 | + | #else | |
| 465 | + | return false; | |
| 466 | + | #endif | |
| 467 | + | } | |
| 468 | + | ||
| 469 | + | int Crypt::rsaGetSize() | |
| 470 | + | { | |
| 471 | + | #ifndef __EMSCRIPTEN__ | |
| 472 | + | return RSA_size(m_rsa); | |
| 473 | + | #else | |
| 474 | + | return 0; | |
| 475 | + | #endif | |
| 476 | + | } | |
| 477 | + | ||
| 478 | + | #define DELTA 0x9e3779b9 | |
| 479 | + | #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) | |
| 480 | + | #ifdef WITH_ENCRYPTION | |
| 481 | + | void Crypt::bencrypt(uint8_t* buffer, int len, uint64_t k) { | |
| 482 | + | uint32_t const key[4] = { (uint32_t)(k >> 32), (uint32_t)(k & 0xFFFFFFFF), 0xDEADDEAD, 0xB00BEEEF }; | |
| 483 | + | uint32_t y, z, sum; | |
| 484 | + | uint32_t *v = (uint32_t*)buffer; | |
| 485 | + | unsigned rounds, e; | |
| 486 | + | int p, n = (len - len % 4) / 4; | |
| 487 | + | if (n < 2) | |
| 488 | + | return; | |
| 489 | + | rounds = 6 + 52 / n; | |
| 490 | + | sum = 0; | |
| 491 | + | z = v[n - 1]; | |
| 492 | + | do { | |
| 493 | + | sum += DELTA; | |
| 494 | + | e = (sum >> 2) & 3; | |
| 495 | + | for (p = 0; p < n - 1; p++) { | |
| 496 | + | y = v[p + 1]; | |
| 497 | + | z = v[p] += MX; | |
| 498 | + | } | |
| 499 | + | y = v[0]; | |
| 500 | + | z = v[n - 1] += MX; | |
| 501 | + | } while (--rounds); | |
| 502 | + | } | |
| 503 | + | #endif | |
| 504 | + | ||
| 505 | + | void Crypt::bdecrypt(uint8_t* buffer, int len, uint64_t k) { | |
| 506 | + | uint32_t const key[4] = { (uint32_t)(k >> 32), (uint32_t)(k & 0xFFFFFFFF), 0xDEADDEAD, 0xB00BEEEF }; | |
| 507 | + | uint32_t y, z, sum; | |
| 508 | + | uint32_t *v = (uint32_t*)buffer; | |
| 509 | + | unsigned p, rounds, e; | |
| 510 | + | int n = (len - len % 4) / 4; | |
| 511 | + | if (n < 2) | |
| 512 | + | return; | |
| 513 | + | rounds = 6 + 52 / n; | |
| 514 | + | sum = rounds * DELTA; | |
| 515 | + | y = v[0]; | |
| 516 | + | do { | |
| 517 | + | e = (sum >> 2) & 3; | |
| 518 | + | for (p = n - 1; p > 0; p--) { | |
| 519 | + | z = v[p - 1]; | |
| 520 | + | y = v[p] -= MX; | |
| 521 | + | } | |
| 522 | + | z = v[n - 1]; | |
| 523 | + | y = v[0] -= MX; | |
| 524 | + | sum -= DELTA; | |
| 525 | + | } while (--rounds); | |
| 526 | + | } |
| @@ -0,0 +1,79 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #ifndef CRYPT_H | |
| 24 | + | #define CRYPT_H | |
| 25 | + | ||
| 26 | + | #include "../stdext/types.h" | |
| 27 | + | #include <string> | |
| 28 | + | ||
| 29 | + | #include <boost/uuid/uuid.hpp> | |
| 30 | + | ||
| 31 | + | #ifndef __EMSCRIPTEN__ | |
| 32 | + | typedef struct rsa_st RSA; | |
| 33 | + | #endif | |
| 34 | + | ||
| 35 | + | class Crypt | |
| 36 | + | { | |
| 37 | + | public: | |
| 38 | + | Crypt(); | |
| 39 | + | ~Crypt(); | |
| 40 | + | ||
| 41 | + | std::string base64Encode(const std::string& decoded_string); | |
| 42 | + | std::string base64Decode(const std::string& encoded_string); | |
| 43 | + | std::string xorCrypt(const std::string& buffer, const std::string& key); | |
| 44 | + | std::string encrypt(const std::string& decrypted_string) { return _encrypt(decrypted_string, true); } | |
| 45 | + | std::string decrypt(const std::string& encrypted_string) { return _decrypt(encrypted_string, true); } | |
| 46 | + | std::string genUUID(); | |
| 47 | + | bool setMachineUUID(std::string uuidstr); | |
| 48 | + | std::string getMachineUUID(); | |
| 49 | + | std::string md5Encode(const std::string& decoded_string, bool upperCase); | |
| 50 | + | std::string sha1Encode(const std::string& decoded_string, bool upperCase); | |
| 51 | + | std::string sha256Encode(const std::string& decoded_string, bool upperCase); | |
| 52 | + | std::string sha512Encode(const std::string& decoded_string, bool upperCase); | |
| 53 | + | std::string crc32(const std::string& decoded_string, bool upperCase); | |
| 54 | + | ||
| 55 | + | void rsaGenerateKey(int bits, int e); | |
| 56 | + | void rsaSetPublicKey(const std::string& n, const std::string& e); | |
| 57 | + | void rsaSetPrivateKey(const std::string &p, const std::string &q, const std::string &d); | |
| 58 | + | bool rsaCheckKey(); | |
| 59 | + | bool rsaEncrypt(unsigned char *msg, int size); | |
| 60 | + | bool rsaDecrypt(unsigned char *msg, int size); | |
| 61 | + | int rsaGetSize(); | |
| 62 | + | #ifdef WITH_ENCRYPTION | |
| 63 | + | void bencrypt(uint8_t * buffer, int len, uint64_t k); | |
| 64 | + | #endif | |
| 65 | + | void bdecrypt(uint8_t * buffer, int len, uint64_t k); | |
| 66 | + | ||
| 67 | + | private: | |
| 68 | + | std::string _encrypt(const std::string& decrypted_string, bool useMachineUUID); | |
| 69 | + | std::string _decrypt(const std::string& encrypted_string, bool useMachineUUID); | |
| 70 | + | std::string getCryptKey(bool useMachineUUID); | |
| 71 | + | boost::uuids::uuid m_machineUUID; | |
| 72 | + | #ifndef __EMSCRIPTEN__ | |
| 73 | + | RSA *m_rsa; | |
| 74 | + | #endif | |
| 75 | + | }; | |
| 76 | + | ||
| 77 | + | extern Crypt g_crypt; | |
| 78 | + | ||
| 79 | + | #endif |
| @@ -0,0 +1,114 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #ifndef DATABUFFER_H | |
| 24 | + | #define DATABUFFER_H | |
| 25 | + | ||
| 26 | + | template<class T> | |
| 27 | + | class DataBuffer | |
| 28 | + | { | |
| 29 | + | public: | |
| 30 | + | DataBuffer(uint res = 64) : | |
| 31 | + | m_size(0), | |
| 32 | + | m_capacity(res), | |
| 33 | + | m_buffer(new T[m_capacity]) { } | |
| 34 | + | ~DataBuffer() { | |
| 35 | + | if(m_buffer) | |
| 36 | + | delete[] m_buffer; | |
| 37 | + | } | |
| 38 | + | ||
| 39 | + | DataBuffer(const DataBuffer<T>& d) | |
| 40 | + | { | |
| 41 | + | m_size = d.m_size; | |
| 42 | + | m_capacity = std::max<uint>(64, d.m_size * 2); | |
| 43 | + | m_buffer = new T[m_capacity]; | |
| 44 | + | memcpy(m_buffer, d.m_buffer, sizeof(T) * m_size); | |
| 45 | + | } | |
| 46 | + | DataBuffer& operator=(const DataBuffer<T>& d) = delete; | |
| 47 | + | ||
| 48 | + | inline void reset() { m_size = 0; } | |
| 49 | + | inline void clear() { | |
| 50 | + | m_size = 0; | |
| 51 | + | m_capacity = 0; | |
| 52 | + | delete[] m_buffer; | |
| 53 | + | m_buffer = nullptr; | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | inline bool empty() const { return m_size == 0; } | |
| 57 | + | inline uint size() const { return m_size; } | |
| 58 | + | inline T *data() const { return m_buffer; } | |
| 59 | + | ||
| 60 | + | inline const T& at(uint i) const { return m_buffer[i]; } | |
| 61 | + | inline const T& last() const { return m_buffer[m_size-1]; } | |
| 62 | + | inline const T& first() const { return m_buffer[0]; } | |
| 63 | + | inline const T& operator[](uint i) const { return m_buffer[i]; } | |
| 64 | + | inline T& operator[](uint i) { return m_buffer[i]; } | |
| 65 | + | ||
| 66 | + | inline void reserve(uint n) { | |
| 67 | + | if(n > m_capacity) { | |
| 68 | + | T *buffer = new T[n]; | |
| 69 | + | memcpy(buffer, m_buffer, m_size * sizeof(T)); | |
| 70 | + | if(m_buffer) | |
| 71 | + | delete[] m_buffer; | |
| 72 | + | m_buffer = buffer; | |
| 73 | + | m_capacity = n; | |
| 74 | + | } | |
| 75 | + | } | |
| 76 | + | ||
| 77 | + | inline void resize(uint n, T def = T()) { | |
| 78 | + | if(n == m_size) | |
| 79 | + | return; | |
| 80 | + | reserve(n); | |
| 81 | + | for(uint i=m_size;i<n;++i) | |
| 82 | + | m_buffer[i] = def; | |
| 83 | + | m_size = n; | |
| 84 | + | } | |
| 85 | + | ||
| 86 | + | inline void grow(uint n, bool precise = false) { | |
| 87 | + | if(n <= m_size) | |
| 88 | + | return; | |
| 89 | + | if(n > m_capacity) { | |
| 90 | + | uint newcapacity = m_capacity; | |
| 91 | + | if (precise) { | |
| 92 | + | newcapacity = n; | |
| 93 | + | } else { | |
| 94 | + | do { newcapacity *= 4; } while (newcapacity < n); | |
| 95 | + | } | |
| 96 | + | reserve(newcapacity); | |
| 97 | + | } | |
| 98 | + | m_size = n; | |
| 99 | + | } | |
| 100 | + | ||
| 101 | + | inline void add(const T& v) { | |
| 102 | + | grow(m_size + 1); | |
| 103 | + | m_buffer[m_size-1] = v; | |
| 104 | + | } | |
| 105 | + | ||
| 106 | + | inline DataBuffer &operator<<(const T &t) { add(t); return *this; } | |
| 107 | + | ||
| 108 | + | private: | |
| 109 | + | uint m_size; | |
| 110 | + | uint m_capacity; | |
| 111 | + | T *m_buffer; | |
| 112 | + | }; | |
| 113 | + | ||
| 114 | + | #endif |
| @@ -0,0 +1,6 @@ | |||
| 1 | + | #include "extras.h" | |
| 2 | + | #include <numeric> | |
| 3 | + | #include <algorithm> | |
| 4 | + | #include <sstream> | |
| 5 | + | ||
| 6 | + | Extras g_extras; |
| @@ -0,0 +1,86 @@ | |||
| 1 | + | #ifndef EXTRAS_H | |
| 2 | + | #define EXTRAS_H | |
| 3 | + | ||
| 4 | + | #include <string> | |
| 5 | + | #include <map> | |
| 6 | + | #include <framework/core/logger.h> | |
| 7 | + | #include <deque> | |
| 8 | + | ||
| 9 | + | constexpr bool default_value = true; | |
| 10 | + | ||
| 11 | + | #define DEFINE_OPTION(option, description) { m_options[ #option ] = std::make_pair(description, &(this -> option )); } | |
| 12 | + | ||
| 13 | + | class Extras { | |
| 14 | + | public: | |
| 15 | + | Extras() { | |
| 16 | + | DEFINE_OPTION(limitedPolling, "Limited polling"); | |
| 17 | + | ||
| 18 | + | DEFINE_OPTION(debugWalking, "Debug walking"); | |
| 19 | + | DEFINE_OPTION(debugPredictiveWalking, "Debug predictive walking"); | |
| 20 | + | DEFINE_OPTION(debugPathfinding, "Debug path finding"); | |
| 21 | + | DEFINE_OPTION(debugRender, "Debug render"); | |
| 22 | + | DEFINE_OPTION(debugProxy, "Debug proxy"); | |
| 23 | + | DEFINE_OPTION(showPredictions, "Show predictions"); | |
| 24 | + | DEFINE_OPTION(debugWidgets, "Debug widgets"); | |
| 25 | + | ||
| 26 | + | DEFINE_OPTION(disablePredictiveWalking, "Disable predictive walking"); | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | bool botDetection = default_value; | |
| 30 | + | ||
| 31 | + | bool newMapViewRendering = default_value; | |
| 32 | + | bool limitedPolling = default_value; | |
| 33 | + | ||
| 34 | + | bool debugWalking = false; | |
| 35 | + | bool debugPredictiveWalking = false; | |
| 36 | + | bool debugPathfinding = false; | |
| 37 | + | bool debugRender = false; | |
| 38 | + | bool debugProxy = false; | |
| 39 | + | bool disablePredictiveWalking = false; | |
| 40 | + | bool showPredictions = false; | |
| 41 | + | bool debugWidgets = false; | |
| 42 | + | ||
| 43 | + | int testMode = 0; | |
| 44 | + | ||
| 45 | + | void set(const std::string& key, bool value) { | |
| 46 | + | auto it = m_options.find(key); | |
| 47 | + | if (it == m_options.end()) { | |
| 48 | + | g_logger.fatal(std::string("Invalid extraOptions key:") + key); | |
| 49 | + | return; | |
| 50 | + | } | |
| 51 | + | *(it->second.second) = value; | |
| 52 | + | } | |
| 53 | + | ||
| 54 | + | bool get(const std::string& key) { | |
| 55 | + | auto it = m_options.find(key); | |
| 56 | + | if (it == m_options.end()) { | |
| 57 | + | g_logger.fatal(std::string("Invalid extraOptions key:") + key); | |
| 58 | + | return false; | |
| 59 | + | } | |
| 60 | + | return *(it->second.second); | |
| 61 | + | } | |
| 62 | + | ||
| 63 | + | std::string getDescription(const std::string& key) { | |
| 64 | + | auto it = m_options.find(key); | |
| 65 | + | if (it == m_options.end()) { | |
| 66 | + | g_logger.fatal(std::string("Invalid extraOptions key:") + key); | |
| 67 | + | return ""; | |
| 68 | + | } | |
| 69 | + | return it->second.first; | |
| 70 | + | } | |
| 71 | + | ||
| 72 | + | std::vector<std::string> getAll() { | |
| 73 | + | std::vector<std::string> ret; | |
| 74 | + | for (auto& it : m_options) | |
| 75 | + | ret.push_back(it.first); | |
| 76 | + | return ret; | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | private: | |
| 80 | + | std::map<std::string, std::pair<std::string, bool*>> m_options; | |
| 81 | + | std::deque<ticks_t> framerRenderTimes; | |
| 82 | + | }; | |
| 83 | + | ||
| 84 | + | extern Extras g_extras; | |
| 85 | + | ||
| 86 | + | #endif |
| @@ -0,0 +1,26 @@ | |||
| 1 | + | #include <atomic> | |
| 2 | + | #include <list> | |
| 3 | + | #include "../stdext/time.h" | |
| 4 | + | ||
| 5 | + | class FrameCounter { | |
| 6 | + | public: | |
| 7 | + | void addFrame() // not thread-safe | |
| 8 | + | { | |
| 9 | + | ticks_t now = stdext::millis(); | |
| 10 | + | m_framesList.push_back(now); | |
| 11 | + | m_frames += 1; | |
| 12 | + | while (m_framesList.front() + 1000 < now) { | |
| 13 | + | m_framesList.pop_front(); | |
| 14 | + | m_frames -= 1; | |
| 15 | + | } | |
| 16 | + | } | |
| 17 | + | ||
| 18 | + | int getFps() // thread safe | |
| 19 | + | { | |
| 20 | + | return m_frames.load(); | |
| 21 | + | } | |
| 22 | + | ||
| 23 | + | private: | |
| 24 | + | std::list<ticks_t> m_framesList; | |
| 25 | + | std::atomic_int m_frames; | |
| 26 | + | }; |
| @@ -0,0 +1,246 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #ifndef MATRIX_H | |
| 24 | + | #define MATRIX_H | |
| 25 | + | ||
| 26 | + | #include <array> | |
| 27 | + | #include <cstring> | |
| 28 | + | #include <initializer_list> | |
| 29 | + | #include <sstream> | |
| 30 | + | ||
| 31 | + | template<int N, int M, typename T = float> | |
| 32 | + | class Matrix | |
| 33 | + | { | |
| 34 | + | public: | |
| 35 | + | Matrix() { setIdentity(); } | |
| 36 | + | Matrix(int) {} // construct without initializing identity matrix | |
| 37 | + | Matrix(const Matrix<N,M,T>& other) = default; | |
| 38 | + | template<typename U> | |
| 39 | + | Matrix(const std::initializer_list<U>& values) { *this = values; } | |
| 40 | + | template<typename U> | |
| 41 | + | Matrix(const U *values) { *this = values; } | |
| 42 | + | ||
| 43 | + | void setIdentity(); | |
| 44 | + | bool isIdentity() const; | |
| 45 | + | void fill(T value); | |
| 46 | + | ||
| 47 | + | Matrix<M,N,T> transposed() const; | |
| 48 | + | typename std::enable_if<N==M>::type transpose() { *this = transposed(); } | |
| 49 | + | ||
| 50 | + | T *data() { return m[0]; } | |
| 51 | + | const T *data() const { return m[0]; } | |
| 52 | + | ||
| 53 | + | T& operator()(int row, int column) { return m[row-1][column-1]; } | |
| 54 | + | T operator()(int row, int column) const { return m[row-1][column-1]; } | |
| 55 | + | ||
| 56 | + | Matrix<N,M,T>& operator=(const Matrix<N,M,T>& other) = default; | |
| 57 | + | template<typename U> | |
| 58 | + | Matrix<N,M,T>& operator=(const std::initializer_list<U>& values); | |
| 59 | + | template<typename U> | |
| 60 | + | Matrix<N,M,T>& operator=(const U *values); | |
| 61 | + | Matrix<N,M,T>& operator+=(const Matrix<N,M,T>& other); | |
| 62 | + | Matrix<N,M,T>& operator-=(const Matrix<N,M,T>& other); | |
| 63 | + | Matrix<N,M,T>& operator*=(T factor); | |
| 64 | + | Matrix<N,M,T>& operator/=(T divisor); | |
| 65 | + | bool operator==(const Matrix<N,M,T>& other) const; | |
| 66 | + | bool operator!=(const Matrix<N,M,T>& other) const; | |
| 67 | + | ||
| 68 | + | private: | |
| 69 | + | T m[N][M]; | |
| 70 | + | }; | |
| 71 | + | ||
| 72 | + | template<int N, int M, typename T> | |
| 73 | + | void Matrix<N,M,T>::setIdentity() { | |
| 74 | + | for(int i=0;i<N;++i) { | |
| 75 | + | for(int j=0;j<M;++j) { | |
| 76 | + | if(i==j) | |
| 77 | + | m[i][j] = 1.0f; | |
| 78 | + | else | |
| 79 | + | m[i][j] = 0.0f; | |
| 80 | + | } | |
| 81 | + | } | |
| 82 | + | } | |
| 83 | + | ||
| 84 | + | template<int N, int M, typename T> | |
| 85 | + | bool Matrix<N,M,T>::isIdentity() const { | |
| 86 | + | for(int i=0;i<N;++i) | |
| 87 | + | for(int j=0;j<M;++j) | |
| 88 | + | if((i==j && m[i][j] != 1.0f) || (i!=j && m[i][j] != 0.0f)) | |
| 89 | + | return false; | |
| 90 | + | return true; | |
| 91 | + | } | |
| 92 | + | ||
| 93 | + | template<int N, int M, typename T> | |
| 94 | + | void Matrix<N,M,T>::fill(T value) { | |
| 95 | + | for(int i=0;i<N;++i) | |
| 96 | + | for(int j=0;j<M;++j) | |
| 97 | + | m[i][j] = value; | |
| 98 | + | } | |
| 99 | + | ||
| 100 | + | template<int N, int M, typename T> | |
| 101 | + | Matrix<M,N,T> Matrix<N,M,T>::transposed() const { | |
| 102 | + | Matrix<M,N,T> result(1); | |
| 103 | + | for(int i=0;i<N;++i) | |
| 104 | + | for(int j=0;j<M;++j) | |
| 105 | + | result.m[j][i] = m[i][j]; | |
| 106 | + | return result; | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | template<int N, int M, typename T> | |
| 110 | + | template<typename U> | |
| 111 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator=(const std::initializer_list<U>& values) { | |
| 112 | + | auto it = values.begin(); | |
| 113 | + | for(int i=0;i<N;++i) | |
| 114 | + | for(int j=0;j<M;++j) | |
| 115 | + | m[i][j] = *(it++); | |
| 116 | + | return *this; | |
| 117 | + | } | |
| 118 | + | ||
| 119 | + | template<int N, int M, typename T> | |
| 120 | + | template<typename U> | |
| 121 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator=(const U *values) { | |
| 122 | + | for(int i=0;i<N;++i) | |
| 123 | + | for(int j=0;j<M;++j) | |
| 124 | + | m[i][j] = values[i*N + j]; | |
| 125 | + | return *this; | |
| 126 | + | } | |
| 127 | + | ||
| 128 | + | template<int N, int M, typename T> | |
| 129 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator+=(const Matrix<N,M,T>& other) { | |
| 130 | + | for(int i=0;i<N;++i) | |
| 131 | + | for(int j=0;j<M;++j) | |
| 132 | + | m[i][j] += other.m[i][j]; | |
| 133 | + | return *this; | |
| 134 | + | } | |
| 135 | + | ||
| 136 | + | template<int N, int M, typename T> | |
| 137 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator-=(const Matrix<N,M,T>& other) { | |
| 138 | + | for(int i=0;i<N;++i) | |
| 139 | + | for(int j=0;j<M;++j) | |
| 140 | + | m[i][j] -= other.m[i][j]; | |
| 141 | + | return *this; | |
| 142 | + | } | |
| 143 | + | ||
| 144 | + | template<int N, int M, typename T> | |
| 145 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator*=(T factor) { | |
| 146 | + | for(int i=0;i<N;++i) | |
| 147 | + | for(int j=0;j<M;++j) | |
| 148 | + | m[i][j] *= factor; | |
| 149 | + | return *this; | |
| 150 | + | } | |
| 151 | + | ||
| 152 | + | template<int N, int M, typename T> | |
| 153 | + | Matrix<N,M,T>& Matrix<N,M,T>::operator/=(T divisor) { | |
| 154 | + | for(int i=0;i<N;++i) | |
| 155 | + | for(int j=0;j<M;++j) | |
| 156 | + | m[i][j] /= divisor; | |
| 157 | + | return *this; | |
| 158 | + | } | |
| 159 | + | ||
| 160 | + | template<int N, int M, typename T> | |
| 161 | + | bool Matrix<N,M,T>::operator==(const Matrix<N,M,T>& other) const | |
| 162 | + | { | |
| 163 | + | for(int i=0;i<N;++i) | |
| 164 | + | for(int j=0;j<M;++j) | |
| 165 | + | if(m[i][j] != other.m[i][j]) | |
| 166 | + | return false; | |
| 167 | + | return true; | |
| 168 | + | } | |
| 169 | + | ||
| 170 | + | template<int N, int M, typename T> | |
| 171 | + | bool Matrix<N,M,T>::operator!=(const Matrix<N,M,T>& other) const | |
| 172 | + | { | |
| 173 | + | return !(*this == other); | |
| 174 | + | } | |
| 175 | + | ||
| 176 | + | template<int N, int M, typename T> | |
| 177 | + | std::ostream& operator<<(std::ostream& out, const Matrix<N,M,T>& mat) | |
| 178 | + | { | |
| 179 | + | for(int i=1;i<=N;++i) { | |
| 180 | + | for(int j=1;j<=M;++j) { | |
| 181 | + | out << mat(i,j); | |
| 182 | + | if(j != M) | |
| 183 | + | out << " "; | |
| 184 | + | } | |
| 185 | + | out << "\n"; | |
| 186 | + | } | |
| 187 | + | return out; | |
| 188 | + | } | |
| 189 | + | ||
| 190 | + | template<int N, int M, typename T> | |
| 191 | + | std::istream& operator>>(std::istream& in, Matrix<N,M,T>& mat) | |
| 192 | + | { | |
| 193 | + | for(int i=0;i<N;++i) | |
| 194 | + | for(int j=0;j<M;++j) | |
| 195 | + | in >> mat(i,j); | |
| 196 | + | return in; | |
| 197 | + | } | |
| 198 | + | ||
| 199 | + | // faster comparing for 3x3 matrixes | |
| 200 | + | template<> | |
| 201 | + | inline bool Matrix<3,3,float>::operator==(const Matrix<3,3,float>& other) const | |
| 202 | + | { | |
| 203 | + | return m[0][0] == other.m[0][0] && m[1][1] == other.m[1][1] && | |
| 204 | + | m[2][1] == other.m[2][1] && m[2][0] == other.m[2][0] && | |
| 205 | + | m[1][2] == other.m[1][2] && m[0][2] == other.m[0][2] && | |
| 206 | + | m[1][0] == other.m[1][0] && m[0][1] == other.m[0][1] && | |
| 207 | + | m[2][2] == other.m[2][2]; | |
| 208 | + | } | |
| 209 | + | ||
| 210 | + | template<int M, int N, int P, int Q, typename T> | |
| 211 | + | Matrix<M, Q, T> operator*(const Matrix<M,N,T>& a, const Matrix<P,Q,T>& b) | |
| 212 | + | { | |
| 213 | + | static_assert(N==P, "N==P"); | |
| 214 | + | Matrix<M,Q,T> c(1); | |
| 215 | + | for(int i=1;i<=M;++i) { | |
| 216 | + | for(int j=1;j<=Q;++j) { | |
| 217 | + | T sum = 0; | |
| 218 | + | for(int k=1;k<=N;++k) | |
| 219 | + | sum += a(i,k) * b(k,j); | |
| 220 | + | c(i,j) = sum; | |
| 221 | + | } | |
| 222 | + | } | |
| 223 | + | return c; | |
| 224 | + | } | |
| 225 | + | ||
| 226 | + | template<int M, int N, typename T> | |
| 227 | + | Matrix<M, N, T> operator+(const Matrix<M,N,T>& a, const Matrix<M,N,T>& b) { Matrix<M,N,T> c(a); c += b; return c; } | |
| 228 | + | ||
| 229 | + | template<int M, int N, typename T> | |
| 230 | + | Matrix<M, N, T> operator-(const Matrix<M,N,T>& a, const Matrix<M,N,T>& b) { Matrix<M,N,T> c(a); c -= b; return c; } | |
| 231 | + | ||
| 232 | + | template<int M, int N, typename T> | |
| 233 | + | Matrix<M, N, T> operator*(const Matrix<M,N,T>& a, float b) { Matrix<M,N,T> c(a); c *= b; return c; } | |
| 234 | + | ||
| 235 | + | template<int M, int N, typename T> | |
| 236 | + | Matrix<M, N, T> operator/(const Matrix<M,N,T>& a, float b) { Matrix<M,N,T> c = a; c /= b; return c; } | |
| 237 | + | ||
| 238 | + | typedef Matrix<4,4> Matrix4x4; | |
| 239 | + | typedef Matrix<3,3> Matrix3x3; | |
| 240 | + | typedef Matrix<2,2> Matrix2x2; | |
| 241 | + | ||
| 242 | + | typedef Matrix4x4 Matrix4; | |
| 243 | + | typedef Matrix3x3 Matrix3; | |
| 244 | + | typedef Matrix2x2 Matrix2; | |
| 245 | + | ||
| 246 | + | #endif |
| @@ -0,0 +1,32 @@ | |||
| 1 | + | #include "pngunpacker.h" | |
| 2 | + | ||
| 3 | + | FileMetadata::FileMetadata(const FileStreamPtr& file) | |
| 4 | + | { | |
| 5 | + | offset = file->getU32(); | |
| 6 | + | fileSize = file->getU32(); | |
| 7 | + | fileName = file->getString(); | |
| 8 | + | } | |
| 9 | + | ||
| 10 | + | std::unordered_map<uint32_t, std::string> PngUnpacker::unpack(const FileStreamPtr& file) | |
| 11 | + | { | |
| 12 | + | std::unordered_map<uint32_t, std::string> data; | |
| 13 | + | ||
| 14 | + | uint32_t entries = file->getU32(); | |
| 15 | + | std::vector<FileMetadata> metadata; | |
| 16 | + | metadata.reserve(entries); | |
| 17 | + | for (uint32_t i = 0; i < entries; ++i) { | |
| 18 | + | metadata.emplace_back(file); | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | uint pos = file->tell(); | |
| 22 | + | for (const auto& fileMetadata : metadata) { | |
| 23 | + | uint32_t imageID = std::stoi(fileMetadata.getFileName()); | |
| 24 | + | auto it = data.emplace(imageID, std::string(fileMetadata.getFileSize(), '\0')); | |
| 25 | + | if (!it.second) | |
| 26 | + | continue; // duplicated | |
| 27 | + | file->seek(pos + fileMetadata.getOffset()); | |
| 28 | + | file->read(it.first->second.data(), fileMetadata.getFileSize()); | |
| 29 | + | } | |
| 30 | + | return data; | |
| 31 | + | } | |
| 32 | + |
| @@ -0,0 +1,29 @@ | |||
| 1 | + | #ifndef __PNG_UNPACKER_H | |
| 2 | + | #define __PNG_UNPACKER_H | |
| 3 | + | ||
| 4 | + | #include <framework/core/declarations.h> | |
| 5 | + | #include <framework/core/filestream.h> | |
| 6 | + | #include <framework/graphics/declarations.h> | |
| 7 | + | ||
| 8 | + | /* File unpacking related */ | |
| 9 | + | class FileMetadata | |
| 10 | + | { | |
| 11 | + | public: | |
| 12 | + | FileMetadata(const FileStreamPtr& file); | |
| 13 | + | ||
| 14 | + | const std::string& getFileName() const { return fileName; } | |
| 15 | + | uint32_t getOffset() const { return offset; } | |
| 16 | + | uint32_t getFileSize() const { return fileSize; } | |
| 17 | + | private: | |
| 18 | + | std::string fileName; | |
| 19 | + | uint32_t offset = 0; | |
| 20 | + | uint32_t fileSize = 0; | |
| 21 | + | }; | |
| 22 | + | ||
| 23 | + | class PngUnpacker | |
| 24 | + | { | |
| 25 | + | public: | |
| 26 | + | static std::unordered_map<uint32_t, std::string> unpack(const FileStreamPtr& file); | |
| 27 | + | }; | |
| 28 | + | ||
| 29 | + | #endif |
| @@ -0,0 +1,104 @@ | |||
| 1 | + | /* | |
| 2 | + | * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient> | |
| 3 | + | * | |
| 4 | + | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 5 | + | * of this software and associated documentation files (the "Software"), to deal | |
| 6 | + | * in the Software without restriction, including without limitation the rights | |
| 7 | + | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 8 | + | * copies of the Software, and to permit persons to whom the Software is | |
| 9 | + | * furnished to do so, subject to the following conditions: | |
| 10 | + | * | |
| 11 | + | * The above copyright notice and this permission notice shall be included in | |
| 12 | + | * all copies or substantial portions of the Software. | |
| 13 | + | * | |
| 14 | + | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 15 | + | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 16 | + | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 17 | + | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 18 | + | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 | + | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 20 | + | * THE SOFTWARE. | |
| 21 | + | */ | |
| 22 | + | ||
| 23 | + | #ifndef POINT_H | |
| 24 | + | #define POINT_H | |
| 25 | + | ||
| 26 | + | #include "../stdext/types.h" | |
| 27 | + | #include <sstream> | |
| 28 | + | #include <cmath> | |
| 29 | + | ||
| 30 | + | template<class T> | |
| 31 | + | class TSize; | |
| 32 | + | ||
| 33 | + | template<class T> | |
| 34 | + | class TPoint | |
| 35 | + | { | |
| 36 | + | public: | |
| 37 | + | TPoint() : x(0), y(0) {} | |
| 38 | + | TPoint(T x, T y) : x(x), y(y) { } | |
| 39 | + | TPoint(const TPoint<T>& other) : x(other.x), y(other.y) { } | |
| 40 | + | ||
| 41 | + | bool isNull() const { return x==0 && y==0; } | |
| 42 | + | TSize<T> toSize() const { return TSize<T>(x, y); } | |
| 43 | + | ||
| 44 | + | TPoint<T> operator-() const { return TPoint<T>(-x, -y); } | |
| 45 | + | ||
| 46 | + | TPoint<T> operator+(const TPoint<T>& other) const { return TPoint<T>(x + other.x, y + other.y); } | |
| 47 | + | TPoint<T>& operator+=(const TPoint<T>& other) { x+=other.x; y+=other.y; return *this; } | |
| 48 | + | TPoint<T> operator-(const TPoint<T>& other) const { return TPoint<T>(x - other.x, y - other.y); } | |
| 49 | + | TPoint<T>& operator-=(const TPoint<T>& other) { x-=other.x; y-=other.y; return *this; } | |
| 50 | + | TPoint<T> operator*(const TPoint<T>& other) const { return TPoint<T>(x * other.x, y * other.y); } | |
| 51 | + | TPoint<T>& operator*=(const TPoint<T>& other) { x*=other.x; y*=other.y; return *this; } | |
| 52 | + | TPoint<T> operator/(const TPoint<T>& other) const { return TPoint<T>(x/other.x, y/other.y); } | |
| 53 | + | TPoint<T>& operator/=(const TPoint<T>& other) { x/=other.x; y/=other.y; return *this; } | |
| 54 | + | ||
| 55 | + | TPoint<T> operator+(T other) const { return TPoint<T>(x + other, y + other); } | |
| 56 | + | TPoint<T>& operator+=(T other) { x+=other; y+=other; return *this; } | |
| 57 | + | TPoint<T> operator-(T other) const { return TPoint<T>(x - other, y - other); } | |
| 58 | + | TPoint<T>& operator-=(T other) { x-=other; y-=other; return *this; } | |
| 59 | + | TPoint<T> operator*(float v) const { return TPoint<T>(x*v, y*v); } | |
| 60 | + | TPoint<T>& operator*=(float v) { x*=v; y*=v; return *this; } | |
| 61 | + | TPoint<T> operator/(float v) const { return TPoint<T>(x/v, y/v); } | |
| 62 | + | TPoint<T>& operator/=(float v) { x/=v; y/=v; return *this; } | |
| 63 | + | ||
| 64 | + | TPoint<T> operator&(int a) { return TPoint<T>(x & a, y & a); } | |
| 65 | + | TPoint<T>& operator&=(int a) { x &= a; y &= a; return *this; } | |
| 66 | + | ||
| 67 | + | bool operator<=(const TPoint<T>&other) const { return x<=other.x || (x==other.x && y<=other.y); } | |
| 68 | + | bool operator>=(const TPoint<T>&other) const { return x>=other.x || (x==other.x && y>=other.y); } | |
| 69 | + | bool operator<(const TPoint<T>&other) const { return x<other.x || (x==other.x && y<other.y); } | |
| 70 | + | bool operator>(const TPoint<T>&other) const { return x>other.x || (x==other.x && y>other.y); } | |
| 71 | + | ||
| 72 | + | TPoint<T>& operator=(const TPoint<T>& other) { x = other.x; y = other.y; return *this; } | |
| 73 | + | bool operator==(const TPoint<T>& other) const { return other.x==x && other.y==y; } | |
| 74 | + | bool operator!=(const TPoint<T>& other) const { return other.x!=x || other.y!=y; } | |
| 75 | + | ||
| 76 | + | float length() const { return sqrt((float)(x*x + y*y)); } | |
| 77 | + | T manhattanLength() const { return std::abs(x) + std::abs(y); } | |
| 78 | + | ||
| 79 | + | float distanceFrom(const TPoint<T>& other) const { | |
| 80 | + | return TPoint<T>(x - other.x, y - other.y).getLength(); | |
| 81 | + | } | |
| 82 | + | ||
| 83 | + | T x, y; | |
| 84 | + | }; | |
| 85 | + | ||
| 86 | + | typedef TPoint<int> Point; | |
| 87 | + | typedef TPoint<float> PointF; | |
| 88 | + | ||
| 89 | + | template<class T> | |
| 90 | + | std::ostream& operator<<(std::ostream& out, const TPoint<T>& point) | |
| 91 | + | { | |
| 92 | + | out << point.x << " " << point.y; | |
| 93 | + | return out; | |
| 94 | + | } | |
| 95 | + | ||
| 96 | + | template<class T> | |
| 97 | + | std::istream& operator>>(std::istream& in, TPoint<T>& point) | |
| 98 | + | { | |
| 99 | + | in >> point.x; | |
| 100 | + | in >> point.y; | |
| 101 | + | return in; | |
| 102 | + | } | |
| 103 | + | ||
| 104 | + | #endif |