/* Copyright (c) 2013 yvt This file is part of OpenSpades. OpenSpades is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenSpades is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenSpades. If not, see . */ #pragma once #include #include "../Core/Debug.h" #include "../Core/Math.h" #include "IGameMapListener.h" namespace spades{ class IStream; namespace client { class GameMap { public: // fixed for now enum { DefaultWidth = 512, DefaultHeight = 512, DefaultDepth = 64 // should be <= 64 }; GameMap(); ~GameMap(); static GameMap *Load(IStream *); int Width() { return DefaultWidth; } int Height() { return DefaultHeight; } int Depth() { return DefaultDepth; } inline bool IsSolid(int x, int y, int z) { SPAssert(x >= 0); SPAssert(x < Width()); SPAssert(y >= 0); SPAssert(y < Height()); SPAssert(z >= 0); SPAssert(z < Depth()); return ((solidMap[x][y] >> (uint64_t)z) & 1ULL) != 0; } /** @return 0xHHBBGGRR where HH is health (up to 100) */ inline uint32_t GetColor(int x, int y, int z){ SPAssert(x >= 0); SPAssert(x < Width()); SPAssert(y >= 0); SPAssert(y < Height()); SPAssert(z >= 0); SPAssert(z < Depth()); return colorMap[x][y][z]; } inline bool IsSolidWrapped(int x, int y, int z){ if(z < 0) return false; if(z >= Depth()) return true; return ((solidMap[x & (Width() - 1)][y & (Height() - 1)] >> (uint64_t)z) & 1ULL) != 0; } inline uint32_t GetColorWrapped(int x, int y, int z){ return colorMap[x & (Width() - 1)] [y & (Height() - 1)] [z & (Depth() - 1)]; } inline void Set(int x, int y, int z, bool solid, uint32_t color){ SPAssert(x >= 0); SPAssert(x < Width()); SPAssert(y >= 0); SPAssert(y < Height()); SPAssert(z >= 0); SPAssert(z < Depth()); uint64_t mask = 1ULL << z; uint64_t value = solidMap[x][y]; bool changed = false; if((value & mask) != (solid ? mask : 0ULL)){ changed = true; value &= ~mask; if(solid) value |= mask; solidMap[x][y] = value; } if(solid){ if(color != colorMap[x][y][z]){ changed = true; colorMap[x][y][z] = color; } } if(changed && listener){ listener->GameMapChanged(x, y, z, this); } } void SetListener(IGameMapListener *l) { listener = l; } IGameMapListener *GetListener() { return listener; } bool ClipBox(int x, int y, int z); bool ClipWorld(int x, int y, int z); bool ClipBox(float x, float y, float z); bool ClipWorld(float x, float y, float z); // vanila compat bool CastRay(Vector3 v0, Vector3 v1, float length, IntVector3& vOut); // accurate and slow ray casting struct RayCastResult { bool hit; bool startSolid; Vector3 hitPos; IntVector3 hitBlock; IntVector3 normal; }; RayCastResult CastRay2(Vector3 v0, Vector3 dir, int maxSteps); private: uint64_t solidMap[DefaultWidth][DefaultHeight]; uint32_t colorMap[DefaultWidth][DefaultHeight][DefaultDepth]; IGameMapListener *listener; }; } }