Add files via upload
|
@ -0,0 +1,25 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(dragonblocks)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
||||||
|
add_executable(dragonblocks
|
||||||
|
src/game.cpp
|
||||||
|
src/graphics.cpp
|
||||||
|
src/inventory.cpp
|
||||||
|
src/main.cpp
|
||||||
|
src/map.cpp
|
||||||
|
src/mapgen.cpp
|
||||||
|
src/mods.cpp
|
||||||
|
src/node.cpp
|
||||||
|
src/texture.cpp
|
||||||
|
src/threads.cpp
|
||||||
|
src/util.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(dragonblocks
|
||||||
|
GL
|
||||||
|
freeglut
|
||||||
|
lua5.3
|
||||||
|
pthread
|
||||||
|
png16
|
||||||
|
m
|
||||||
|
)
|
|
@ -0,0 +1,82 @@
|
||||||
|
DRAGONBLOCKS BEDROCK EDITION
|
||||||
|
Written in C++
|
||||||
|
An Open Source Project by Elias Fleckenstein
|
||||||
|
|
||||||
|
1. General
|
||||||
|
1.1. What this is about
|
||||||
|
Dragonblocks originaly was a Browsergame I made that should be some kind of 2D Minetest (Minetest (www.minetest.net) is a game similar to
|
||||||
|
Minecraft, except Minetest is free & open source and is meant to be modded). The JavaScript Edition is hosted at www.dragonblocks.tk and
|
||||||
|
further developed then this C++ Version, through the C++ Version has advantages like map saving and lot larger map. I decided to call the
|
||||||
|
C++ Version "Bedrock Edition" as a joke for the Minecraft C++ Version is Called Bedrock or Pocket Edition.
|
||||||
|
1.2. Version
|
||||||
|
This is the Dragonblocks Bedrock Edition 3.0.
|
||||||
|
1.4. Bugs
|
||||||
|
Please Report Bugs to eliasfleckenstein@web.de.
|
||||||
|
1.5. License
|
||||||
|
Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
|
||||||
|
|
||||||
|
This program 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 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA.
|
||||||
|
|
||||||
|
2. Starting the Game
|
||||||
|
2.1. Platform Compability
|
||||||
|
This Game was developed on linux, therefore following instructions are only for linux users, basically because I have no idea how to
|
||||||
|
port the game to other platforms. Feel free to add building instructions for other systems over github.
|
||||||
|
2.3. Download
|
||||||
|
You can download the game using git:
|
||||||
|
$ git clone https://
|
||||||
|
2.2. Dependencies:
|
||||||
|
You need Freeglut, OpenGl, Cmake, Liblua and Libpng.
|
||||||
|
If you are on Debian/Ubuntu You can install them over apt:
|
||||||
|
$ sudo apt install liblua5.3-dev freeglut3-dev libgl1-mesa-dev cmake libpng-dev
|
||||||
|
2.3. Building
|
||||||
|
to Build dragonblocks run:
|
||||||
|
$ cd dragonblocks
|
||||||
|
$ cmake .
|
||||||
|
$ make
|
||||||
|
2.4. Exectute
|
||||||
|
2.4.1. Run-In-Place
|
||||||
|
Invoke dragonblocks by typing:
|
||||||
|
$ cd dragonblocks
|
||||||
|
$ bin/dragonblocks --worldname <your_worldname>
|
||||||
|
To see a list of worlds do:
|
||||||
|
$ bin/dragonblocks --worldlist
|
||||||
|
You can select a world from this list or create a new one.
|
||||||
|
For more info run:
|
||||||
|
$ bin/dragonblocks --help
|
||||||
|
2.4.2. Installation
|
||||||
|
You can install dragonblocks by doing:
|
||||||
|
$ sudo ./install.sh
|
||||||
|
It will copy the dragonblocks directory to /usr/share/dragonblocks and place a script in
|
||||||
|
/usr/bin/dragonblocks that starts dragonblocks.
|
||||||
|
|
||||||
|
3. Developing
|
||||||
|
3.1. The Lua Modding API
|
||||||
|
If you want to add a lua file to the game, place it in the game folder and add a dofile() in game/init.lua
|
||||||
|
Note: The lua api currently consists of only two functions. If you want to add something I'm open to ideas or code.
|
||||||
|
dragonblocks.register_node(obj)
|
||||||
|
Register a new node
|
||||||
|
obj has to contain:
|
||||||
|
name: string - the itemstring. It should follow the convention "modulename:nodename"
|
||||||
|
texture: string - the texture path. Textures should be placed in the textures folder and have to be 16 x 16 px.
|
||||||
|
obj can contain:
|
||||||
|
stable: boolean - Nodes like water or air are unstable. [default = true]
|
||||||
|
hidden: boolean - The Node will be hidden in the invenotry. [default = false]
|
||||||
|
translucent: boolean - Whether the node's texture should be transparent. [default = false]
|
||||||
|
dragonblocks.log(text)
|
||||||
|
Log something.
|
||||||
|
3.2. The C++ API
|
||||||
|
The C++ API is probably to big to explain here, but if you do C++ you should understand it. In case you have questions, feel free to
|
||||||
|
ask them on github. You can also contribute code if you want.
|
|
@ -0,0 +1,5 @@
|
||||||
|
local cpp_last_node = 0
|
||||||
|
function cpp_get_next_node()
|
||||||
|
cpp_last_node = cpp_last_node + 1
|
||||||
|
return core.nodes[cpp_last_node]
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
dragonblocks.log = function(text)
|
||||||
|
print("[LUA] "..text)
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
core = {}
|
||||||
|
dragonblocks = {}
|
||||||
|
dragonblocks.settings = {}
|
||||||
|
|
||||||
|
dofile("builtin/register.lua")
|
||||||
|
dofile("builtin/functions.lua")
|
||||||
|
dofile("builtin/cpp.lua")
|
||||||
|
|
||||||
|
--local popenfile = io.popen("ls game")
|
||||||
|
--for filename in popenfile:lines() do
|
||||||
|
-- dofile("game/"..filename.."/init.lua")
|
||||||
|
--end
|
||||||
|
--popenfile:close()
|
||||||
|
|
||||||
|
dofile("game/init.lua")
|
|
@ -0,0 +1,20 @@
|
||||||
|
core.nodes = {}
|
||||||
|
dragonblocks.register_node = function(obj)
|
||||||
|
if obj and obj.name and obj.texture then
|
||||||
|
core.nodes[#core.nodes+1] = {}
|
||||||
|
core.nodes[#core.nodes].name = obj.name
|
||||||
|
core.nodes[#core.nodes].texture = obj.texture
|
||||||
|
core.nodes[#core.nodes].stable = false
|
||||||
|
if obj.stable == nil or obj.stable == true then
|
||||||
|
core.nodes[#core.nodes].stable = true
|
||||||
|
end
|
||||||
|
core.nodes[#core.nodes].hidden = false
|
||||||
|
if obj.hidden then
|
||||||
|
core.nodes[#core.nodes].hidden = true
|
||||||
|
end
|
||||||
|
core.nodes[#core.nodes].translucent = false
|
||||||
|
if obj.translucent then
|
||||||
|
core.nodes[#core.nodes].translucent = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
dragonblocks.log(" ____ _ _ _ ")
|
||||||
|
dragonblocks.log("| _ \\ _ __ __ _ __ _ ___ _ __ | |__ | | ___ ___| | _____ ")
|
||||||
|
dragonblocks.log("| | | | '__/ _` |/ _` |/ _ \\| '_ \\| '_ \\| |/ _ \\ / __| |/ / __| ")
|
||||||
|
dragonblocks.log("| |_| | | | (_| | (_| | (_) | | | | |_) | | (_) | (__| <\\__ \\ ")
|
||||||
|
dragonblocks.log("|____/|_| \\__,_|\\__, |\\___/|_| |_|_.__/|_|\\___/ \\___|_|\\_\\___/ ")
|
||||||
|
dragonblocks.log(" |___/ ")
|
||||||
|
dofile("game/nodes.lua")
|
|
@ -0,0 +1,50 @@
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:air",
|
||||||
|
texture = "textures/air.png",
|
||||||
|
stable = false,
|
||||||
|
hidden = true,
|
||||||
|
translucent = true,
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:stone",
|
||||||
|
texture = "textures/stone.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:dirt",
|
||||||
|
texture = "textures/dirt.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:grass",
|
||||||
|
texture = "textures/grass.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:wood",
|
||||||
|
texture = "textures/wood.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:water",
|
||||||
|
texture = "textures/water.png",
|
||||||
|
stable = false,
|
||||||
|
translucent = true,
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:leaves",
|
||||||
|
texture = "textures/leaves.png",
|
||||||
|
translucent = true,
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:bedrock",
|
||||||
|
texture = "textures/bedrock.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:mese",
|
||||||
|
texture = "textures/mese.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:sand",
|
||||||
|
texture = "textures/sand.png"
|
||||||
|
})
|
||||||
|
dragonblocks.register_node({
|
||||||
|
name = "dragonblocks:cobble",
|
||||||
|
texture = "textures/cobble.png"
|
||||||
|
})
|
|
@ -0,0 +1,7 @@
|
||||||
|
#! /bin/bash
|
||||||
|
cp . /usr/share/dragonblocks -R
|
||||||
|
echo "
|
||||||
|
cd /usr/share/dragonblocks
|
||||||
|
bin/dragonblocks \$*
|
||||||
|
" > /usr/bin/dragonblocks
|
||||||
|
chmod +x /usr/bin/dragonblocks
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "mods.h"
|
||||||
|
#include "game.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void Game::log(string text, int level){
|
||||||
|
string prefix;
|
||||||
|
int color;
|
||||||
|
switch(level){
|
||||||
|
case WARNING:
|
||||||
|
color = ORANGE;
|
||||||
|
prefix = "WARNING";
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
color = RED;
|
||||||
|
prefix = "ERROR";
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
color = LIGHTBLUE;
|
||||||
|
prefix = "INFO";
|
||||||
|
break;
|
||||||
|
case LOG:
|
||||||
|
color = BLUE;
|
||||||
|
prefix = "LOG";
|
||||||
|
break;
|
||||||
|
case EASTEREGG:
|
||||||
|
color = VIOLET;
|
||||||
|
prefix = "EASTEREGG";
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
cout << "\e[3" << color << "m" << "[" << prefix << "] \e[0m" << text << endl;
|
||||||
|
if(logfile_fd)
|
||||||
|
fprintf(logfile_fd, "[%s] %s\n", prefix.c_str(), text.c_str());
|
||||||
|
}
|
||||||
|
void Game::log(string text){
|
||||||
|
log(text, LOG);
|
||||||
|
}
|
||||||
|
void Game::help(){
|
||||||
|
cout << "Usage: " << argv[0] << "[OPTIONS]" << endl;
|
||||||
|
cout << "Options:" << endl;
|
||||||
|
cout << "\t" << "-h" << "\t" << "--help" << "\t\t\t" << "Display this help and exit." << endl;
|
||||||
|
cout << "\t" << "-v" << "\t" << "--version" << "\t\t" << "Display version info." << endl;
|
||||||
|
cout << "\t" << "-p" << "\t" << "--worldpath [PATH]" << "\t" << "Set world path." << endl;
|
||||||
|
cout << "\t" << "-w" << "\t" << "--worldname [PATH]" << "\t" << "Select world by name (Worlds are placed in ~/.dragonblocks/worlds/)." << endl;
|
||||||
|
cout << "\t" << "-r" << "\t" << "--worldlist" << "\t\t" << "Show a list of your worlds." << endl;
|
||||||
|
cout << "\t" << "-s" << "\t" << "--seed [NUMBER]" << "\t\t" << "Set seed." << endl;
|
||||||
|
cout << "\t" << "-l" << "\t" << "--logfile [PATH]" << "\t" << "Set logfile." << endl;
|
||||||
|
}
|
||||||
|
void Game::version(){
|
||||||
|
cout << "DRAGONBLOCKS BEDROCK EDITION" << endl;
|
||||||
|
cout << "Written in C++" << endl;
|
||||||
|
cout << "An Open Source Project by Elias Fleckenstein" << endl;
|
||||||
|
cout << "Dragonblocks " << VERSION << endl;
|
||||||
|
}
|
||||||
|
void Game::worldlist(){
|
||||||
|
log("Your worlds:");
|
||||||
|
DIR *folder;
|
||||||
|
struct dirent *entry;
|
||||||
|
int files = 0;
|
||||||
|
|
||||||
|
folder = opendir(((string)getenv("HOME")+"/.dragonblocks/worlds/").c_str());
|
||||||
|
if(!folder){
|
||||||
|
Game::log("Cant Open World Directory", ERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
while(entry = readdir(folder))
|
||||||
|
{
|
||||||
|
files++;
|
||||||
|
if(files > 2)
|
||||||
|
cout << "\t" << entry->d_name;
|
||||||
|
}
|
||||||
|
if(files <= 2)
|
||||||
|
cout << "\tYou have no Worlds yet.";
|
||||||
|
cout << endl;
|
||||||
|
closedir(folder);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef _GAME_H_
|
||||||
|
#define _GAME_H_
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
#define WARNING 1
|
||||||
|
#define ERROR 2
|
||||||
|
#define INFO -1
|
||||||
|
#define EASTEREGG 17
|
||||||
|
#define LOG 0
|
||||||
|
|
||||||
|
#define VERSION "3.0"
|
||||||
|
|
||||||
|
#define BLACK 0
|
||||||
|
#define RED 1
|
||||||
|
#define GREEN 2
|
||||||
|
#define ORANGE 3
|
||||||
|
#define BLUE 4
|
||||||
|
#define VIOLET 5
|
||||||
|
#define LIGHTBLUE 6
|
||||||
|
#define GREY 7
|
||||||
|
|
||||||
|
class Game{
|
||||||
|
public:
|
||||||
|
static int *argc;
|
||||||
|
static char **argv;
|
||||||
|
static int seed;
|
||||||
|
static std::string mapfile;
|
||||||
|
static std::string logfile;
|
||||||
|
static FILE *logfile_fd;
|
||||||
|
static Map *map;
|
||||||
|
static void log(std::string);
|
||||||
|
static void log(std::string, int);
|
||||||
|
static void help();
|
||||||
|
static void version();
|
||||||
|
static void worldlist();
|
||||||
|
static Inventory *inventory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,130 @@
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include "graphics.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "mapgen.h"
|
||||||
|
|
||||||
|
position Graphics::pointed;
|
||||||
|
position Graphics::pos = {MAPWIDTH/2 - DISPLAYWIDTH/2, MAPHEIGHT/2 - DISPLAYHEIGHT/2};
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
void Graphics::display(){
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
//sky
|
||||||
|
drawRectangle(0, 0, DISPLAYWIDTH*BLOCKWIDTH, DISPLAYHEIGHT*BLOCKWIDTH, "#87CEEB");
|
||||||
|
//map
|
||||||
|
for(int x = 0; x < DISPLAYWIDTH; x++){
|
||||||
|
for(int y = 0; y < DISPLAYHEIGHT; y++){
|
||||||
|
Game::map -> getNode(x+pos.x, y+pos.y) -> texture -> draw(x*BLOCKWIDTH, y*BLOCKWIDTH, BLOCKWIDTH, BLOCKWIDTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//pointed block
|
||||||
|
if(pointed.x < DISPLAYWIDTH){
|
||||||
|
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH, BLOCKWIDTH, 1, COLOR_BLACK);
|
||||||
|
drawRectangle(pointed.x * BLOCKWIDTH + BLOCKWIDTH - 1, pointed.y * BLOCKWIDTH, 1, BLOCKWIDTH, COLOR_BLACK);
|
||||||
|
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH + BLOCKWIDTH - 1, BLOCKWIDTH, 1, COLOR_BLACK);
|
||||||
|
drawRectangle(pointed.x * BLOCKWIDTH, pointed.y * BLOCKWIDTH, 1, BLOCKWIDTH, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
//inventory
|
||||||
|
|
||||||
|
drawRectangle(DISPLAYWIDTH*BLOCKWIDTH, 0, INVWIDTH, DISPLAYHEIGHT*BLOCKWIDTH, "#B4B4B4");
|
||||||
|
drawRectangle(DISPLAYWIDTH*BLOCKWIDTH, Game::inventory->selected * INVWIDTH, INVWIDTH, INVWIDTH, "#636363");
|
||||||
|
for(int i = 0; i < Game::inventory->count; i++)
|
||||||
|
Game::inventory -> getSlot(i) -> texture -> draw(BLOCKWIDTH*DISPLAYWIDTH + (INVWIDTH-INVBLOCKWIDTH)/2, i * INVWIDTH + (INVWIDTH-INVBLOCKWIDTH)/2, INVBLOCKWIDTH, INVBLOCKWIDTH);
|
||||||
|
//infotext
|
||||||
|
writeText(5, 5, (string)"Dragonblocks "+VERSION, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||||
|
string infotext = "pos: ("+to_string(pos.x)+", "+to_string(pos.y)+"), seed: "+to_string(Game::seed);
|
||||||
|
if(pointed.x < DISPLAYWIDTH)
|
||||||
|
infotext += ", pointed: "+ Game::map->getNode(pointed.x+pos.x, pointed.y+pos.y)->name + "("+to_string(pointed.x+pos.x)+", "+to_string(pointed.y+pos.y)+")";
|
||||||
|
writeText(5, 20, infotext, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||||
|
//writeText(5, 35, "world: "+Game::mapfile, GLUT_BITMAP_9_BY_15, COLOR_WHITE);
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
void Graphics::reshape(int width, int height){
|
||||||
|
glViewport(0, 0, width, height); /* Establish viewing area to cover entire window. */
|
||||||
|
glMatrixMode(GL_PROJECTION); /* Start modifying the projection matrix. */
|
||||||
|
glLoadIdentity(); /* Reset project matrix. */
|
||||||
|
glOrtho(0, width, 0, height, -1, 1); /* Map abstract coords directly to window coords. */
|
||||||
|
glScalef(1, -1, 1); /* Invert Y axis so increasing Y goes down. */
|
||||||
|
glTranslatef(0, -height, 0); /* Shift origin up to upper-pos.x corner. */
|
||||||
|
}
|
||||||
|
void Graphics::init(){
|
||||||
|
glutInit(Game::argc, Game::argv);
|
||||||
|
glutCreateWindow("Dragonblocks");
|
||||||
|
glutReshapeWindow(DISPLAYWIDTH*BLOCKWIDTH+INVWIDTH, DISPLAYHEIGHT*BLOCKWIDTH);
|
||||||
|
glutDisplayFunc(display);
|
||||||
|
glutReshapeFunc(reshape);
|
||||||
|
glutKeyboardFunc(keyboard);
|
||||||
|
glutSpecialFunc(special);
|
||||||
|
glutMouseFunc(mouse);
|
||||||
|
glutPassiveMotionFunc(motion);
|
||||||
|
glutMotionFunc(motion);
|
||||||
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
||||||
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||||
|
glutMainLoop();
|
||||||
|
}
|
||||||
|
void Graphics::keyboard(unsigned char key, int x, int y){
|
||||||
|
}
|
||||||
|
void Graphics::special(int key, int x, int y){
|
||||||
|
switch(key){
|
||||||
|
case GLUT_KEY_LEFT:
|
||||||
|
if(pos.x > 0)
|
||||||
|
pos.x--;
|
||||||
|
break;
|
||||||
|
case GLUT_KEY_UP:
|
||||||
|
if(pos.y > 0)
|
||||||
|
pos.y--;
|
||||||
|
break;
|
||||||
|
case GLUT_KEY_RIGHT:
|
||||||
|
if(pos.x < MAPWIDTH-DISPLAYWIDTH)
|
||||||
|
pos.x++;
|
||||||
|
break;
|
||||||
|
case GLUT_KEY_DOWN:
|
||||||
|
if(pos.y < MAPHEIGHT-DISPLAYHEIGHT)
|
||||||
|
pos.y++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Graphics::mouse(int key, int action, int x, int y){
|
||||||
|
if(action == 0){
|
||||||
|
if(x < BLOCKWIDTH*DISPLAYWIDTH){
|
||||||
|
switch(key){
|
||||||
|
case 0:
|
||||||
|
if(Game::map -> getNode(pointed.x+pos.x, pointed.y+pos.y)->stable)
|
||||||
|
Game::map -> setNode(pointed.x+pos.x, pointed.y+pos.y, MAPGEN_AIR);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(! Game::map -> getNode(pointed.x+pos.x, pointed.y+pos.y)->stable)
|
||||||
|
Game::map -> setNode(pointed.x+pos.x, pointed.y+pos.y, Game::inventory->getSelectedSlot());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Game::inventory->select(y/INVWIDTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Graphics::motion(int x, int y){
|
||||||
|
pointed.x = x / BLOCKWIDTH;
|
||||||
|
pointed.y = y / BLOCKWIDTH;
|
||||||
|
}
|
||||||
|
void Graphics::writeText(int x, int y, string text, void *font, color c){
|
||||||
|
glColor3f(c.red, c.green, c.blue);
|
||||||
|
glRasterPos2i(x, y+10);
|
||||||
|
char *s = strdup(text.c_str());
|
||||||
|
--s;
|
||||||
|
while(*++s)
|
||||||
|
glutBitmapCharacter(font, *s);
|
||||||
|
}
|
||||||
|
void Graphics::drawRectangle(int x, int y, int width, int height, color c){
|
||||||
|
glColor3f(c.red, c.green, c.blue);
|
||||||
|
glBegin(GL_POLYGON);
|
||||||
|
glVertex2i(x, y);
|
||||||
|
glVertex2i(x+width, y);
|
||||||
|
glVertex2i(x+width, y+height);
|
||||||
|
glVertex2i(x, y+height);
|
||||||
|
glEnd();
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef _GRAPHICS_H_
|
||||||
|
#define _GRAPHICS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "texture.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BLOCKWIDTH 32
|
||||||
|
#define DISPLAYWIDTH 25
|
||||||
|
#define DISPLAYHEIGHT 25
|
||||||
|
#define INVBLOCKWIDTH 64
|
||||||
|
#define INVWIDTH 80
|
||||||
|
|
||||||
|
#define COLOR_WHITE {1,1,1}
|
||||||
|
#define COLOR_BLACK {0,0,0}
|
||||||
|
|
||||||
|
|
||||||
|
class Graphics{
|
||||||
|
public:
|
||||||
|
static void init();
|
||||||
|
|
||||||
|
static position pointed;
|
||||||
|
static position pos;
|
||||||
|
|
||||||
|
//handlers
|
||||||
|
static void display();
|
||||||
|
static void keyboard(unsigned char, int, int);
|
||||||
|
static void mouse(int, int, int, int);
|
||||||
|
static void special(int, int, int);
|
||||||
|
static void reshape(int, int);
|
||||||
|
static void motion(int, int);
|
||||||
|
|
||||||
|
//functions
|
||||||
|
static void drawRectangle(int, int, int, int, color);
|
||||||
|
static void writeText(int, int, std::string, void*, color);
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "node.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
Inventory::Inventory(){
|
||||||
|
count = 0;
|
||||||
|
selected = 0;
|
||||||
|
for(int i = 0; i < Node::count; i++){
|
||||||
|
if(! Node::getNodeById(i) -> hidden){
|
||||||
|
list[count] = Node::getNodeById(i);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Node *Inventory::getSlot(int nr){
|
||||||
|
if(nr >= 0 && nr < count)
|
||||||
|
return list[nr];
|
||||||
|
return list[0];
|
||||||
|
}
|
||||||
|
void Inventory::select(int nr){
|
||||||
|
if(nr >= 0 && nr < count)
|
||||||
|
selected = nr;
|
||||||
|
}
|
||||||
|
Node *Inventory::getSelectedSlot(){
|
||||||
|
return list[selected];
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _INVENTORY_H_
|
||||||
|
#define _INVENTORY_H_
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
class Inventory{
|
||||||
|
public:
|
||||||
|
int count;
|
||||||
|
int selected;
|
||||||
|
Node *list[MAXNODES];
|
||||||
|
Node *getSlot(int);
|
||||||
|
void select(int);
|
||||||
|
Node *getSelectedSlot();
|
||||||
|
Inventory();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "graphics.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "mapgen.h"
|
||||||
|
#include "mods.h"
|
||||||
|
#include "threads.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Map *Game::map;
|
||||||
|
string Game::mapfile;
|
||||||
|
string Game::logfile;
|
||||||
|
int Game::seed;
|
||||||
|
char **Game::argv;
|
||||||
|
int *Game::argc;
|
||||||
|
FILE *Game::logfile_fd;
|
||||||
|
Inventory *Game::inventory;
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
if((string)argv[0] != "bin/dragonblocks"){
|
||||||
|
string command = "cd ..; bin/dragonblocks -w world ";
|
||||||
|
while(*++argv)
|
||||||
|
command += *argv;
|
||||||
|
exit(system(command.c_str()));
|
||||||
|
}
|
||||||
|
create_dir_if_not_exists((string)getenv("HOME")+"/.dragonblocks");
|
||||||
|
create_dir_if_not_exists((string)getenv("HOME")+"/.dragonblocks/worlds");
|
||||||
|
Game::argc = &argc;
|
||||||
|
Game::argv = argv;
|
||||||
|
Game::seed = time(0);
|
||||||
|
Game::logfile = (string)getenv("HOME")+"/.dragonblocks/dragonblocks.log";
|
||||||
|
const char *short_options = "hrvs:l:w:p:";
|
||||||
|
const struct option long_options[] = {
|
||||||
|
{"help", 0, NULL, 'h'},
|
||||||
|
{"version", 0, NULL, 'v'},
|
||||||
|
{"worldname", 1, NULL, 'w'},
|
||||||
|
{"worldpath", 1, NULL, 'p'},
|
||||||
|
{"worldlist", 0, NULL, 'r'},
|
||||||
|
{"seed", 1, NULL, 's'},
|
||||||
|
{"logfile", 1, NULL, 'l'},
|
||||||
|
{NULL, 0, NULL, 0},
|
||||||
|
};
|
||||||
|
int next_option;
|
||||||
|
while((next_option = getopt_long(argc, argv, short_options, long_options, NULL)) != -1){
|
||||||
|
switch(next_option){
|
||||||
|
case 'h':
|
||||||
|
Game::help();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
Game::version();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
Game::mapfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
Game::mapfile = (string)getenv("HOME")+"/.dragonblocks/worlds/"+optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
Game::seed = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
Game::logfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
Game::worldlist();
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
Game::log("Invalid Usage", ERROR);
|
||||||
|
Game::help();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if(Game::logfile_fd = fopen(Game::logfile.c_str(), "a"))
|
||||||
|
fprintf(Game::logfile_fd, "\n--------------------------------------------------\n");
|
||||||
|
else
|
||||||
|
Game::log((string)"Failed to open log file " + Game::logfile, WARNING);
|
||||||
|
Game::log((string)"Welcome to Dragonblocks "+VERSION);
|
||||||
|
srand(Game::seed);
|
||||||
|
new Node("unknown_node", "textures/unknown_node.png", true, true, false);
|
||||||
|
Mods::init();
|
||||||
|
Game::inventory = new Inventory();
|
||||||
|
Game::map = new Map();
|
||||||
|
if(Game::mapfile == ""){
|
||||||
|
Game::log("No World Specified", ERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if(fopen(Game::mapfile.c_str(), "r"))
|
||||||
|
Game::map->load();
|
||||||
|
else
|
||||||
|
Mapgen();
|
||||||
|
Threads::startMapBackupThread();
|
||||||
|
Threads::startGraphicUpdateThread();
|
||||||
|
Threads::addSignalHandlers();
|
||||||
|
Graphics::init();
|
||||||
|
Game::log("Closed Window, Exiting.");
|
||||||
|
Game::map -> save();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include "map.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "game.h"
|
||||||
|
using namespace std;
|
||||||
|
Node *Map::getNode(int x, int y){
|
||||||
|
if(x < MAPWIDTH && y < MAPHEIGHT && x > -1 && y > -1)
|
||||||
|
return content[x][y];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void Map::setNode(int x, int y, Node *n){
|
||||||
|
if(x < MAPWIDTH && y < MAPHEIGHT && x > -1 && y > -1)
|
||||||
|
content[x][y] = n;
|
||||||
|
}
|
||||||
|
void Map::setNode(int x, int y, string n){
|
||||||
|
setNode(x, y, Node::getNodeByName(n));
|
||||||
|
}
|
||||||
|
void Map::load(){
|
||||||
|
Game::log("Loading Map from " + Game::mapfile);
|
||||||
|
FILE *mapfile = fopen(Game::mapfile.c_str(), "r");
|
||||||
|
if(mapfile){
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++)
|
||||||
|
for(int y = 0; y < MAPHEIGHT; y++){
|
||||||
|
char buffer[512] = {0};
|
||||||
|
fscanf(mapfile, "%s", buffer);
|
||||||
|
setNode(x, y, buffer);
|
||||||
|
}
|
||||||
|
fclose(mapfile);
|
||||||
|
Game::log("Loaded Map");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Game::log("Could not Load Map.", ERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Map::save(){
|
||||||
|
Game::log("Saving Map to " + Game::mapfile);
|
||||||
|
FILE *mapfile = fopen(Game::mapfile.c_str(), "w");
|
||||||
|
if(mapfile){
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = 0; y < MAPHEIGHT; y++)
|
||||||
|
fprintf(mapfile,"%s ", getNode(x,y)->name.c_str());
|
||||||
|
fprintf(mapfile, "\n");
|
||||||
|
}
|
||||||
|
fclose(mapfile);
|
||||||
|
Game::log("Saved Map");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Game::log("Could not Save Map.", ERROR);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef _MAP_H_
|
||||||
|
#define _MAP_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
#define MAPWIDTH 500
|
||||||
|
#define MAPHEIGHT 100
|
||||||
|
|
||||||
|
class Map{
|
||||||
|
public:
|
||||||
|
Node *getNode(int, int);
|
||||||
|
void setNode(int, int, Node *);
|
||||||
|
void setNode(int, int, std::string);
|
||||||
|
void load();
|
||||||
|
void save();
|
||||||
|
private:
|
||||||
|
Node *content[MAPWIDTH][MAPHEIGHT];
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "mapgen.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
void Mapgen(){
|
||||||
|
Game::log("Generating Map");
|
||||||
|
//Air
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = 0; y < MAPHEIGHT; y++){
|
||||||
|
Game::map->setNode(x,y,MAPGEN_AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Seed 13 Easteregg
|
||||||
|
if(Game::seed == 13){
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = 0; y < MAPHEIGHT; y++){
|
||||||
|
Game::map->setNode(x,y,MAPGEN_BEDROCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Game::log("LOL Seed 13", EASTEREGG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Bottom
|
||||||
|
int bottom[MAPWIDTH];
|
||||||
|
bottom[0] = random(MAPHEIGHT/2 - MAPHEIGHT/10, MAPHEIGHT/2);
|
||||||
|
for(int x = 1; x < MAPWIDTH; x++){
|
||||||
|
bottom[x] = bottom[x-1] + random(-1,1);
|
||||||
|
}
|
||||||
|
//Smooth
|
||||||
|
for(int x = 1; x < MAPWIDTH-1; x++){
|
||||||
|
if(bottom[x] > bottom[x+1] && bottom[x] > bottom[x-1]) bottom[x]--;
|
||||||
|
else if(bottom[x] < bottom[x+1] && bottom[x] < bottom[x-1])bottom[x]++;
|
||||||
|
}
|
||||||
|
//Dirt with Grass
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
Game::map->setNode(x,bottom[x],MAPGEN_GRASS);
|
||||||
|
}
|
||||||
|
//Dirt
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = bottom[x]+1; y < bottom[x]+5; y++){
|
||||||
|
Game::map->setNode(x,y,MAPGEN_DIRT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Stone
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = bottom[x]+5; y < MAPHEIGHT; y++){
|
||||||
|
Game::map->setNode(x,y,MAPGEN_STONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Mese
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
for(int y = bottom[x]+10; y < MAPHEIGHT; y++){
|
||||||
|
if((rand() % 100) == 0) Game::map->setNode(x,y,MAPGEN_MESE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Bedrock
|
||||||
|
for(int x = 0; x < MAPWIDTH; x++){
|
||||||
|
Game::map->setNode(x,MAPHEIGHT-1,MAPGEN_BEDROCK);
|
||||||
|
if(random(0,1) == 0){
|
||||||
|
Game::map->setNode(x,MAPHEIGHT-2,MAPGEN_BEDROCK);
|
||||||
|
if(random(0,2) == 0){
|
||||||
|
Game::map->setNode(x,MAPHEIGHT-3,MAPGEN_BEDROCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Water
|
||||||
|
int flatcount = 0;
|
||||||
|
for(int x = 1; x < MAPWIDTH; x++){
|
||||||
|
if(bottom[x] == bottom[x-1]) flatcount++;
|
||||||
|
else if(flatcount > 7){
|
||||||
|
int leftborder = rand() % 2;
|
||||||
|
int rightborder = rand() % 2;
|
||||||
|
for(int mx = x-flatcount-3; mx < x+2; mx++){
|
||||||
|
for(int y = bottom[mx];y < bottom[mx]+5;y++){
|
||||||
|
if(Game::map->getNode(mx,y) == MAPGEN_STONE) break;
|
||||||
|
if(Game::map->getNode(mx,y) == MAPGEN_DIRT || Game::map->getNode(mx,y) == MAPGEN_GRASS) Game::map->setNode(mx,y,MAPGEN_SAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int mx = x-flatcount+leftborder;mx < x-1-rightborder;mx++) Game::map->setNode(mx,bottom[x-1],MAPGEN_WATER);
|
||||||
|
for(int mx = x-flatcount+1+leftborder;mx < x-2-rightborder;mx++) Game::map->setNode(mx,bottom[x-1]+1,MAPGEN_WATER);
|
||||||
|
for(int mx = x-flatcount+2+leftborder; mx < x-3-rightborder;mx++) Game::map->setNode(mx,bottom[x-1]+2,MAPGEN_WATER);
|
||||||
|
flatcount = 0;
|
||||||
|
}
|
||||||
|
else flatcount = 0;
|
||||||
|
}
|
||||||
|
//Tree
|
||||||
|
int treecount = rand() % MAPWIDTH/10;
|
||||||
|
int treepos[treecount];
|
||||||
|
for(int i = 0; i < treecount; i++){
|
||||||
|
while(true){
|
||||||
|
bool cont = true;
|
||||||
|
treepos[i] = rand() % MAPWIDTH;
|
||||||
|
for(int j = 0; j < i; j++){
|
||||||
|
if(abs(treepos[j]-treepos[i]) < 3) cont = false;
|
||||||
|
}
|
||||||
|
if(!(Game::map->getNode(treepos[i],bottom[treepos[i]]) == MAPGEN_GRASS)) cont = false;
|
||||||
|
if(cont) break;
|
||||||
|
}
|
||||||
|
int x = treepos[i];
|
||||||
|
int y = bottom[x] - 1;
|
||||||
|
Game::map->setNode(x,y,MAPGEN_WOOD);
|
||||||
|
Game::map->setNode(x,y-1,MAPGEN_WOOD);
|
||||||
|
Game::map->setNode(x,y-2,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x,y-3,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x,y-4,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x-1,y-2,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x-1,y-3,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x-1,y-4,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x+1,y-2,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x+1,y-3,MAPGEN_LEAVES);
|
||||||
|
Game::map->setNode(x+1,y-4,MAPGEN_LEAVES);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef _MAPGEN_H_
|
||||||
|
#define _MAPGEN_H_
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
#define MAPGEN_AIR Node::getNodeByName("dragonblocks:air")
|
||||||
|
#define MAPGEN_GRASS Node::getNodeByName("dragonblocks:grass")
|
||||||
|
#define MAPGEN_DIRT Node::getNodeByName("dragonblocks:dirt")
|
||||||
|
#define MAPGEN_STONE Node::getNodeByName("dragonblocks:stone")
|
||||||
|
#define MAPGEN_BEDROCK Node::getNodeByName("dragonblocks:bedrock")
|
||||||
|
#define MAPGEN_MESE Node::getNodeByName("dragonblocks:mese")
|
||||||
|
#define MAPGEN_LEAVES Node::getNodeByName("dragonblocks:leaves")
|
||||||
|
#define MAPGEN_WOOD Node::getNodeByName("dragonblocks:wood")
|
||||||
|
#define MAPGEN_WATER Node::getNodeByName("dragonblocks:water")
|
||||||
|
#define MAPGEN_SAND Node::getNodeByName("dragonblocks:sand")
|
||||||
|
|
||||||
|
void Mapgen();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,87 @@
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
#include "mods.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
lua_State *Mods::lua_vm;
|
||||||
|
|
||||||
|
void Mods::init(){
|
||||||
|
Game::log("Initializing Mods");
|
||||||
|
lua_vm = luaL_newstate();
|
||||||
|
luaL_openlibs(lua_vm);
|
||||||
|
if(! check_lua(luaL_dofile(lua_vm, "builtin/init.lua"))){
|
||||||
|
Game::log("Failed to load Builtin", ERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
lua_getglobal(lua_vm, "cpp_get_next_node");
|
||||||
|
if(!lua_isfunction(lua_vm, -1)){
|
||||||
|
Game::log("Lua is sick. What's Wrong with her?", EASTEREGG);
|
||||||
|
Game::log("No, seriously, something is wrong with the lua builtin (it is missing the function cpp_get_next_node)", ERROR);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
lua_pcall(lua_vm, 0, 1, 0);
|
||||||
|
if(! lua_istable(lua_vm, -1))
|
||||||
|
break;
|
||||||
|
|
||||||
|
lua_pushstring(lua_vm, "name");
|
||||||
|
lua_gettable(lua_vm, -2);
|
||||||
|
if(!lua_isstring(lua_vm,-1))
|
||||||
|
continue;
|
||||||
|
string name = lua_tostring(lua_vm,-1);
|
||||||
|
lua_pop(lua_vm, 1);
|
||||||
|
|
||||||
|
lua_pushstring(lua_vm, "texture");
|
||||||
|
lua_gettable(lua_vm, -2);
|
||||||
|
if(!lua_isstring(lua_vm,-1))
|
||||||
|
continue;
|
||||||
|
string texture = lua_tostring(lua_vm,-1);
|
||||||
|
lua_pop(lua_vm, 1);
|
||||||
|
|
||||||
|
lua_pushstring(lua_vm, "hidden");
|
||||||
|
lua_gettable(lua_vm, -2);
|
||||||
|
if(!lua_isboolean(lua_vm,-1))
|
||||||
|
continue;
|
||||||
|
bool hidden = lua_toboolean(lua_vm,-1);
|
||||||
|
lua_pop(lua_vm, 1);
|
||||||
|
|
||||||
|
lua_pushstring(lua_vm, "stable");
|
||||||
|
lua_gettable(lua_vm, -2);
|
||||||
|
if(!lua_isboolean(lua_vm,-1))
|
||||||
|
continue;
|
||||||
|
bool stable = lua_toboolean(lua_vm,-1);
|
||||||
|
lua_pop(lua_vm, 1);
|
||||||
|
|
||||||
|
lua_pushstring(lua_vm, "translucent");
|
||||||
|
lua_gettable(lua_vm, -2);
|
||||||
|
if(!lua_isboolean(lua_vm,-1))
|
||||||
|
continue;
|
||||||
|
bool translucent = lua_toboolean(lua_vm,-1);
|
||||||
|
lua_pop(lua_vm, 1);
|
||||||
|
|
||||||
|
new Node(name, texture, hidden, stable, translucent);
|
||||||
|
Game::log("Registered Node " + name, INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool Mods::check_lua(int code){
|
||||||
|
if(code == LUA_OK)
|
||||||
|
return true;
|
||||||
|
else{
|
||||||
|
error(lua_tostring(lua_vm, -1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Mods::error(string text){
|
||||||
|
Game::log("\e[34mlua: \e[0m" + text, ERROR);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _MODS_H_
|
||||||
|
#define _MODS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C"{
|
||||||
|
#include <lua5.3/lua.h>
|
||||||
|
#include <lua5.3/lauxlib.h>
|
||||||
|
#include <lua5.3/lualib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mods{
|
||||||
|
public:
|
||||||
|
static lua_State *lua_vm;
|
||||||
|
static bool check_lua(int);
|
||||||
|
static void init();
|
||||||
|
static void error(std::string);
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "node.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "texture.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int Node::count = 0;
|
||||||
|
Node *Node::list[MAXNODES];
|
||||||
|
|
||||||
|
Node::Node(string n, string t, bool h, bool s, bool tr){
|
||||||
|
if (Node::count >= MAXNODES)
|
||||||
|
Game::log("Too many registered Nodes", ERROR);
|
||||||
|
else{
|
||||||
|
name = n;
|
||||||
|
id = Node::count;
|
||||||
|
hidden = h;
|
||||||
|
stable = s;
|
||||||
|
Node::list[id] = this;
|
||||||
|
texture = new Texture(t,tr);
|
||||||
|
Node::count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Node *Node::getNodeById(int id){
|
||||||
|
if(id < count && id > -1)
|
||||||
|
return list[id];
|
||||||
|
return list[0];
|
||||||
|
}
|
||||||
|
Node *Node::getNodeByName(string name){
|
||||||
|
for(int i = 0; i < count; i++){
|
||||||
|
if(list[i]->name == name ){
|
||||||
|
return list[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Game::log("Node "+name+" not found", WARNING);
|
||||||
|
return list[0];
|
||||||
|
}
|
||||||
|
bool Node::operator==(Node *node){
|
||||||
|
return id == node->id;
|
||||||
|
}
|
||||||
|
bool Node::operator==(string n){
|
||||||
|
return name == n;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef _NODE_H_
|
||||||
|
#define _NODE_H_
|
||||||
|
#include <string>
|
||||||
|
#include "texture.h"
|
||||||
|
#define MAXNODES 1024
|
||||||
|
|
||||||
|
|
||||||
|
class Node{
|
||||||
|
public:
|
||||||
|
int id;
|
||||||
|
std::string name;
|
||||||
|
static Node *getNodeById(int);
|
||||||
|
static Node *getNodeByName(std::string);
|
||||||
|
static Node *list[MAXNODES];
|
||||||
|
static int count;
|
||||||
|
bool operator==(Node *);
|
||||||
|
bool operator==(std::string);
|
||||||
|
Texture *texture;
|
||||||
|
bool hidden;
|
||||||
|
bool stable;
|
||||||
|
bool translucent;
|
||||||
|
Node(std::string, std::string, bool, bool, bool);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <png.h>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
Texture::Texture(string filename, bool t){
|
||||||
|
translucent = t;
|
||||||
|
dummyimage = false;
|
||||||
|
FILE *file = fopen(filename.c_str(), "rb");
|
||||||
|
if(!file){
|
||||||
|
Game::log("Failed to Load Image " + filename + ": File not found. Using a dummy Image.", WARNING);
|
||||||
|
dummyimage = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
assert(png);
|
||||||
|
png_infop info = png_create_info_struct(png);
|
||||||
|
assert(info);
|
||||||
|
png_init_io(png, file);
|
||||||
|
png_read_info(png, info);
|
||||||
|
width = png_get_image_width(png, info);
|
||||||
|
height = png_get_image_height(png, info);
|
||||||
|
color_type = png_get_color_type(png, info);
|
||||||
|
bit_depth = png_get_bit_depth(png, info);
|
||||||
|
if(bit_depth == 16)
|
||||||
|
png_set_strip_16(png);
|
||||||
|
if(color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_palette_to_rgb(png);
|
||||||
|
#ifndef _WIN32
|
||||||
|
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||||
|
png_set_expand_gray_1_2_4_to_8(png);
|
||||||
|
#endif
|
||||||
|
if(png_get_valid(png, info, PNG_INFO_tRNS))
|
||||||
|
png_set_tRNS_to_alpha(png);
|
||||||
|
if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||||
|
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
png_set_gray_to_rgb(png);
|
||||||
|
png_read_update_info(png, info);
|
||||||
|
row_pointers = (png_bytep*)malloc(sizeof(png_bytep) *height);
|
||||||
|
for(int y = 0; y < height; y++) {
|
||||||
|
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png,info));
|
||||||
|
}
|
||||||
|
png_read_image(png, row_pointers);
|
||||||
|
fclose(file);
|
||||||
|
png_destroy_read_struct(&png, &info, NULL);
|
||||||
|
}
|
||||||
|
void Texture::draw(int displayX, int displayY, int displayWidth, int displayHeight){
|
||||||
|
if(dummyimage){
|
||||||
|
Graphics::drawRectangle(displayX, displayY, displayWidth, displayHeight, {0, 0, 0});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int scaleX = (float)displayWidth/width;
|
||||||
|
int scaleY = (float)displayHeight/height;
|
||||||
|
for(int y = 0; y < height; y++) {
|
||||||
|
png_bytep row = row_pointers[y];
|
||||||
|
for(int x = 0; x < width; x++) {
|
||||||
|
png_bytep px = &(row[x * 4]);
|
||||||
|
if(!translucent || px[0] || px[1] || px[2])
|
||||||
|
Graphics::drawRectangle(x*scaleX + displayX, y*scaleY + displayY, scaleX, scaleY, {(float)px[0]/255, (float)px[1]/255, (float)px[2]/255});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef _TEXTURE_H_
|
||||||
|
#define _TEXTURE_H_
|
||||||
|
|
||||||
|
#include <png.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Texture{
|
||||||
|
public:
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
void draw(int, int, int, int);
|
||||||
|
Texture(std::string, bool);
|
||||||
|
private:
|
||||||
|
png_byte color_type;
|
||||||
|
png_byte bit_depth;
|
||||||
|
png_bytep *row_pointers;
|
||||||
|
bool dummyimage;
|
||||||
|
bool translucent;
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <GL/glut.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "threads.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void Threads::startMapBackupThread(){
|
||||||
|
Game::log("Starting Map Backup Thread");
|
||||||
|
pthread_t thread_id;
|
||||||
|
pthread_create(&thread_id, NULL, &mapBackupThread, NULL);
|
||||||
|
}
|
||||||
|
void *Threads::mapBackupThread(void *unused){
|
||||||
|
while(true){
|
||||||
|
sleep(MAP_BACKUP_INTERVAL);
|
||||||
|
Game::map -> save();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void Threads::startGraphicUpdateThread(){
|
||||||
|
Game::log("Starting Graphic Update Thread");
|
||||||
|
pthread_t thread_id;
|
||||||
|
pthread_create(&thread_id, NULL, &graphicUpdateThread, NULL);
|
||||||
|
}
|
||||||
|
void *Threads::graphicUpdateThread(void *unused){
|
||||||
|
while(true){
|
||||||
|
usleep(1);
|
||||||
|
if(glutGetWindow())
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void Threads::addSignalHandlers(){
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct sigaction sa_sigterm;
|
||||||
|
sa_sigterm.sa_handler = &signal_handler;
|
||||||
|
sigaction(SIGTERM, &sa_sigterm, NULL);
|
||||||
|
|
||||||
|
struct sigaction sa_sigint;
|
||||||
|
sa_sigint.sa_handler = &signal_handler;
|
||||||
|
sigaction(SIGINT, &sa_sigint, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void Threads::signal_handler(int signal_number){
|
||||||
|
#ifndef _WIN32
|
||||||
|
Game::log((string)"Got "+sys_siglist[signal_number]+" Signal, Exiting.");
|
||||||
|
Game::map -> save();
|
||||||
|
exit(0);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _THREADS_H_
|
||||||
|
#define _THREADS_H_
|
||||||
|
|
||||||
|
#define MAP_BACKUP_INTERVAL 15
|
||||||
|
|
||||||
|
class Threads{
|
||||||
|
public:
|
||||||
|
static void startMapBackupThread();
|
||||||
|
static void addSignalHandlers();
|
||||||
|
static void startGraphicUpdateThread();
|
||||||
|
private:
|
||||||
|
static void *mapBackupThread(void *);
|
||||||
|
static void *graphicUpdateThread(void *);
|
||||||
|
static void signal_handler(int);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
int random(int min, int max){
|
||||||
|
return min + rand() % (max - min + 1);
|
||||||
|
}
|
||||||
|
color::color(const char *htmlcolor){
|
||||||
|
unsigned int r, g, b;
|
||||||
|
sscanf(htmlcolor, "#%2x%2x%2x", &r, &g, &b);
|
||||||
|
red = (float) r / 255;
|
||||||
|
green = (float) g / 255;
|
||||||
|
blue = (float) b / 255;
|
||||||
|
}
|
||||||
|
color::color(float r, float g, float b){
|
||||||
|
red = r;
|
||||||
|
green = g;
|
||||||
|
blue = b;
|
||||||
|
}
|
||||||
|
void create_dir_if_not_exists(string d){
|
||||||
|
const char *dir = d.c_str();
|
||||||
|
struct stat dir_exists_st = {0};
|
||||||
|
if(stat(dir, &dir_exists_st) == -1){
|
||||||
|
Game::log((string)dir + " doesn't exist, creating", INFO);
|
||||||
|
#ifdef _WIN32
|
||||||
|
mkdir(dir);
|
||||||
|
#else
|
||||||
|
mkdir(dir, 0700);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef _UTIL_H_
|
||||||
|
#define _UTIL_H_
|
||||||
|
#include <string>
|
||||||
|
class color{
|
||||||
|
public:
|
||||||
|
float red;
|
||||||
|
float green;
|
||||||
|
float blue;
|
||||||
|
color(const char *);
|
||||||
|
color(float, float, float);
|
||||||
|
};
|
||||||
|
class position{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
int random(int, int);
|
||||||
|
void create_dir_if_not_exists(std::string d);
|
||||||
|
#endif
|
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 268 B |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 773 B |
After Width: | Height: | Size: 188 B |
After Width: | Height: | Size: 253 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 193 B |
After Width: | Height: | Size: 257 B |
After Width: | Height: | Size: 309 B |