Browse Source

Projektdateien hinzufügen.

Kolja Strohm 6 years ago
parent
commit
94625b3f84

+ 34 - 0
Minigame Server.sln

@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Minigame Server", "Minigame Server\Minigame Server.vcxproj", "{71F06ACF-40EA-4355-90E2-08672B6BD706}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|ARM = Release|ARM
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|ARM.ActiveCfg = Debug|ARM
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|ARM.Build.0 = Debug|ARM
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|x64.ActiveCfg = Debug|x64
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|x64.Build.0 = Debug|x64
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|x86.ActiveCfg = Debug|x86
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Debug|x86.Build.0 = Debug|x86
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|ARM.ActiveCfg = Release|ARM
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|ARM.Build.0 = Release|ARM
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|x64.ActiveCfg = Release|x64
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|x64.Build.0 = Release|x64
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|x86.ActiveCfg = Release|x86
+		{71F06ACF-40EA-4355-90E2-08672B6BD706}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 476 - 0
Minigame Server/Datenbank.cpp

@@ -0,0 +1,476 @@
+#include "Datenbank.h"
+#include <iostream>
+
+// Inhalt der LSDatenbank Klasse aus Datenbank.h
+// Konstruktor
+MSDatenbank::MSDatenbank( InitDatei *zIni )
+{
+    datenbank = new Datenbank( zIni->zWert( "DBBenutzer" )->getText(), zIni->zWert( "DBPasswort" )->getText(),
+                               zIni->zWert( "DBName" )->getText(), zIni->zWert( "DBIP" )->getText(),
+                               (unsigned short)TextZuInt( zIni->zWert( "DBPort" )->getText(), 10 ) );
+    if( !datenbank->istOk() )
+    {
+        std::cout << "MS: Die Verbindung zur Datenbank konnte nicht hergestellt werden.\nDas Programm wird beendet.";
+        exit( 1 );
+    }
+    InitializeCriticalSection( &cs );
+    ref = 1;
+    Text befehl = "SELECT port, admin_port  FROM server WHERE id = ";
+    befehl += zIni->zWert( "ServerId" )->getText();
+    lock();
+    datenbank->befehl( befehl );
+    Result res = datenbank->getResult();
+    unlock();
+    if( res.zeilenAnzahl == 1 )
+    {
+        zIni->addWert( "ServerPort", res.values[ 0 ] );
+        zIni->addWert( "AdminServerPort", res.values[ 1 ] );
+    }
+    res.destroy();
+}
+
+// Destruktor
+MSDatenbank::~MSDatenbank()
+{
+    datenbank->release();
+    DeleteCriticalSection( &cs );
+}
+
+// nicht constant
+void MSDatenbank::lock()
+{
+    EnterCriticalSection( &cs );
+}
+
+void MSDatenbank::unlock()
+{
+    LeaveCriticalSection( &cs );
+}
+
+int MSDatenbank::istAdministrator( const char *name, const char *passwort )
+{
+    Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
+    Text n( name );
+    n.ersetzen( "'", "''" );
+    befehl->append( (char*)n );
+    befehl->append( "' AND passwort = md5( '" );
+    Text p( passwort );
+    p.ersetzen( "'", "''" );
+    befehl->append( (char*)p );
+    befehl->append( "' )" );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    int ret = 0;
+    if( res.zeilenAnzahl > 0 )
+        ret = TextZuInt( res.values[ 0 ].getText(), 10 );
+    res.destroy();
+    return ret;
+}
+
+bool MSDatenbank::adminHatRecht( int id, int recht )
+{
+    Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
+    befehl->append( id );
+    befehl->append( " AND rechte_id = " );
+    befehl->append( recht );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    int ret = datenbank->getZeilenAnzahl();
+    unlock();
+    befehl->release();
+    return ret != 0;
+}
+
+bool MSDatenbank::proveKlient( int num, int sNum )
+{
+    Text *befehl = new Text( "SELECT * FROM server_client WHERE server_id = " );
+    befehl->append( sNum );
+    befehl->append( " AND client_id = " );
+    befehl->append( num );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    bool ret = 0;
+    if( res.zeilenAnzahl == 1 )
+        ret = 1;
+    res.destroy();
+    return ret;
+}
+
+Text *MSDatenbank::getKlientKey( int cId )
+{
+    lock();
+    if( !datenbank->befehl( Text( "SELECT schluessel FROM client WHERE id = " ) += cId ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    Text *ret = new Text( res.values[ 0 ].getText() );
+    res.destroy();
+    return ret;
+}
+
+void MSDatenbank::unregisterKlient( int num, int sNum )
+{
+    Text *befehl = new Text( "DELETE FROM server_client WHERE client_id = " );
+    befehl->append( num );
+    befehl->append( " AND server_id = " );
+    befehl->append( sNum );
+    lock();
+    datenbank->befehl( befehl->getText() );
+    int za = datenbank->getZeilenAnzahl();
+    unlock();
+    if( za == 1 )
+    {
+        befehl->setText( "UPDATE server SET tasks = tasks - 1 WHERE id = " );
+        befehl->append( sNum );
+        lock();
+        datenbank->befehl( befehl->getText() );
+        unlock();
+    }
+    befehl->release();
+}
+
+bool MSDatenbank::setServerStatus( int id, int status )
+{
+    Text *befehl = new Text( "UPDATE server SET server_status_id = " );
+    *befehl += status;
+    *befehl += "WHERE id = ";
+    *befehl += id;
+    lock();
+    if( !datenbank->befehl( befehl->getText() ) )
+    {
+        unlock();
+        befehl->release();
+        return 0;
+    }
+    bool ret = datenbank->getZeilenAnzahl() != 0;
+    unlock();
+    befehl->release();
+    return ret;
+}
+
+bool MSDatenbank::setMaxClients( int id, int maxC )
+{
+    Text *befehl = new Text( "UPDATE server SET max_tasks = " );
+    befehl->append( maxC );
+    befehl->append( " WHERE id = " );
+    befehl->append( id );
+    lock();
+    if( !datenbank->befehl( befehl->getText() ) )
+    {
+        unlock();
+        befehl->release();
+        return 0;
+    }
+    bool ret = datenbank->getZeilenAnzahl() > 0;
+    unlock();
+    befehl->release();
+    return ret;
+}
+
+bool MSDatenbank::serverIstNichtPausiert( int id )
+{
+    Text *befehl = new Text( "SELECT server_status_id FROM server WHERE id = " );
+    befehl->append( id );
+    lock();
+    if( !datenbank->befehl( befehl->getText() ) )
+    {
+        unlock();
+        befehl->release();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    befehl->release();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    bool ret = (int)res.values[ 0 ] == 3;
+    res.destroy();
+    return ret;
+}
+
+int MSDatenbank::getMinigameOptionList( char *minigame, RCArray< Text > *zOptionList )
+{
+    Text befehl = "SELECT a.options FROM minigame_option a, minigame b WHERE a.minigame_id = b.id AND b.name = '";
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    befehl += m;
+    befehl += "' ORDER BY a.options";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    int anz = res.zeilenAnzahl;
+    for( int i = 0; i < anz; i++ )
+        zOptionList->add( new Text( (char*)res.values[ i ] ) );
+    res.destroy();
+    return anz;
+}
+
+int MSDatenbank::getMinigameBestscore( char *options, char *minigame, Text *zPlayer )
+{
+    Text o( options );
+    o.ersetzen( "'", "''" );
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT b.score, a.ruf_name FROM account a, minigame_bestscore b, minigame_option o, minigame m "
+        "WHERE m.id = o.minigame_id AND o.id = b.minigame_options_id AND a.id = b.account_id AND m.name = '";
+    befehl += o;
+    befehl += "' AND o.options = '";
+    befehl += m;
+    befehl += "'";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    int ret = (int)res.values[ 0 ];
+    zPlayer->setText( res.values[ 1 ] );
+    res.destroy();
+    return ret;
+}
+
+int MSDatenbank::getMinigameBestscore( char *minigame, Array< int > *zScoreList, RCArray< Text > *zPlayerList, RCArray< Text > *zOptionList )
+{
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT b.score, a.ruf_name, o.options FROM account a, minigame_bestscore b, minigame_option o, minigame m "
+        "WHERE m.id = o.minigame_id AND o.id = b.minigame_options_id AND a.id = b.account_id AND m.name = '";
+    befehl += m;
+    befehl += "' ORDER BY o.options, b.score";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    int anz = res.zeilenAnzahl;
+    for( int i = 0; i < anz; i++ )
+    {
+        zScoreList->add( (int)res.values[ i * 3 ] );
+        zPlayerList->add( new Text( res.values[ i * 3 + 1 ] ) );
+        zOptionList->add( new Text( res.values[ i * 3 + 2 ] ) );
+    }
+    res.destroy();
+    return anz;
+}
+
+bool MSDatenbank::updateMinigameScore( int score, char *option, int cId, char *minigame, int sId, Text *zFileName )
+{
+    Text o( option );
+    o.ersetzen( "'", "''" );
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT a.id FROM minigame_option a, minigame b WHERE a.minigame_id = b.id AND b.name = '";
+    befehl += m;
+    befehl += "' AND a.options = '";
+    befehl += o;
+    befehl += "'";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    int optionId = res.values[ 0 ];
+    *zFileName = optionId;
+    *zFileName += ".mgc";
+    res.destroy();
+    befehl = "SELECT score FROM minigame_bestscore WHERE minigame_options_id = ";
+    befehl += optionId;
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    res = datenbank->getResult();
+    unlock();
+    int anz = res.zeilenAnzahl;
+    bool ret = !anz || (int)res.values[ 0 ] < score;
+    res.destroy();
+    if( ret )
+    {
+        if( anz )
+        {
+            befehl = "UPDATE minigame_bestscore b SET score = ";
+            befehl += score;
+            befehl += ", account_id = a.account_id, minigame_server_id = ";
+            befehl += sId;
+            befehl += " FROM account_client a WHERE a.client_id = ";
+            befehl += cId;
+            befehl += " AND b.minigame_options_id = ";
+            befehl += optionId;
+        }
+        else
+        {
+            befehl = "INSERT INTO minigame_bestscore( account_id, score, minigame_options_id, minigame_server_id ) SELECT a.account_id AS account_id, ";
+            befehl += score;
+            befehl += " AS score, ";
+            befehl += optionId;
+            befehl += " AS minigame_options_id, ";
+            befehl += sId;
+            befehl += " AS minigame_server_id FROM account_client a WHERE a.client_id = ";
+            befehl += cId;
+        }
+        lock();
+        if( !datenbank->befehl( befehl ) )
+        {
+            unlock();
+            return 0;
+        }
+        unlock();
+    }
+    return ret;
+}
+
+Text *MSDatenbank::getMinigameCaptureFileName( char *option, char *minigame )
+{
+    Text o( option );
+    o.ersetzen( "'", "''" );
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT a.id FROM minigame_option a, minigame b WHERE a.minigame_id = b.id AND b.name = '";
+    befehl += m;
+    befehl += "' AND a.options = '";
+    befehl += o;
+    befehl += "'";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( !res.zeilenAnzahl )
+    {
+        res.destroy();
+        return 0;
+    }
+    int optionId = res.values[ 0 ];
+    Text *fileName = new Text();
+    fileName->append( optionId );
+    fileName->append( ".mgc" );
+    res.destroy();
+    return fileName;
+}
+
+int MSDatenbank::getMinigameServer( char *minigame, char *option )
+{
+    Text o( option );
+    o.ersetzen( "'", "''" );
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT a.id FROM server a, minigame_bestscore b, minigame_option c, minigame d WHERE a.id = b.minigame_server_id AND d.id = c.minigame_id AND b.minigame_options_id = c.id AND c.options = '";
+    befehl += o;
+    befehl += "' AND d.name = '";
+    befehl += m;
+    befehl += "'";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    int ret = 0;
+    if( res.zeilenAnzahl )
+        ret = res.values[ 0 ];
+    res.destroy();
+    return ret;
+}
+
+bool MSDatenbank::getMinigameServer( char *minigame, char *option, Text *zIp, Text *zPort )
+{
+    Text o( option );
+    o.ersetzen( "'", "''" );
+    Text m( minigame );
+    m.ersetzen( "'", "''" );
+    Text befehl = "SELECT a.ip, a.port FROM server a, minigame_bestscore b, minigame_option c, minigame d WHERE a.id = b.minigame_server_id AND d.id = c.minigame_id AND b.minigame_options_id = c.id AND c.options = '";
+    befehl += o;
+    befehl += "' AND d.name = '";
+    befehl += m;
+    befehl += "'";
+    lock();
+    if( !datenbank->befehl( befehl ) )
+    {
+        unlock();
+        return 0;
+    }
+    Result res = datenbank->getResult();
+    unlock();
+    if( res.zeilenAnzahl )
+    {
+        zIp->setText( (char*)res.values[ 0 ] );
+        zPort->setText( (char*)res.values[ 1 ] );
+        res.destroy();
+        return 1;
+    }
+    res.destroy();
+    return 0;
+}
+
+// constant
+Text *MSDatenbank::getLetzterFehler() const
+{
+    return datenbank->getLetzterFehler();
+}
+
+// Reference Counting
+MSDatenbank *MSDatenbank::getThis()
+{
+    ref++;
+    return this;
+}
+
+MSDatenbank *MSDatenbank::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}

+ 54 - 0
Minigame Server/Datenbank.h

@@ -0,0 +1,54 @@
+#pragma once
+
+#include <sql.h>
+#include <Text.h>
+#include <InitDatei.h>
+#include <Array.h>
+
+using namespace Framework;
+using namespace sql;
+
+namespace Admin_Recht
+{
+    const int LSStarten = 12;
+    const int LSBeenden = 13;
+    const int LSPausieren = 14;
+    const int LSMCChange = 15;
+}
+
+class MSDatenbank
+{
+private:
+    Datenbank *datenbank;
+    CRITICAL_SECTION cs;
+    int ref;
+
+public:
+    // Konstruktor
+    MSDatenbank( InitDatei *zIni );
+    // Destruktor
+    ~MSDatenbank();
+    // nicht constant
+    void lock();
+    void unlock();
+    int istAdministrator( const char *name, const char *passwort );
+    bool adminHatRecht( int id, int recht );
+    bool proveKlient( int num, int sNum );
+    Text *getKlientKey( int cId );
+    void unregisterKlient( int num, int sNum );
+    bool setServerStatus( int id, int status );
+    bool setMaxClients( int id, int maxC );
+    bool serverIstNichtPausiert( int id );
+    int getMinigameOptionList( char *minigame, RCArray< Text > *zOptionList );
+    int getMinigameBestscore( char *options, char *minigame, Text *zPlayer );
+    int getMinigameBestscore( char *minigame, Array< int > *zScoreList, RCArray< Text > *zPlayerList, RCArray< Text > *zOptionList );
+    bool updateMinigameScore( int score, char *option, int cId, char *minigame, int sId, Text *zFileName );
+    Text *getMinigameCaptureFileName( char *option, char *minigame );
+    int getMinigameServer( char *minigame, char *option );
+    bool getMinigameServer( char *minigame, char *option, Text *zIp, Text *zPort );
+    // constant
+    Text *getLetzterFehler() const;
+    // Reference Counting
+    MSDatenbank *getThis();
+    MSDatenbank *release();
+};

+ 103 - 0
Minigame Server/Minigame Server.vcxproj

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|ARM">
+      <Configuration>Debug</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|ARM">
+      <Configuration>Release</Configuration>
+      <Platform>ARM</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x86">
+      <Configuration>Debug</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x86">
+      <Configuration>Release</Configuration>
+      <Platform>x86</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{71f06acf-40ea-4355-90e2-08672b6bd706}</ProjectGuid>
+    <Keyword>Linux</Keyword>
+    <RootNamespace>Minigame_Server</RootNamespace>
+    <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
+    <ApplicationType>Linux</ApplicationType>
+    <ApplicationTypeRevision>1.0</ApplicationTypeRevision>
+    <TargetLinuxPlatform>Generic</TargetLinuxPlatform>
+    <LinuxProjectType>{D51BCBC9-82E9-4017-911E-C93873C4EA2B}</LinuxProjectType>
+    <ProjectName>MinigameServer</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <RemoteRootDir>/home/kolja/projects</RemoteRootDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings" />
+  <ImportGroup Label="Shared" />
+  <ImportGroup Label="PropertySheets" />
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(ProjectDir)bin\$(Platform)\debug\</OutDir>
+    <IntDir>$(ProjectDir)obj\$(Platform)\debug\</IntDir>
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/debug</RemoteProjectDir>
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/debug;..\..\..\..\Allgemein\Network\Network;../../../Network/debug;..\..\..\..\Allgemein\sql\sql;../../../sql/debug;$(IncludePath)</IncludePath>
+    <TargetExt />
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(ProjectDir)bin\$(Platform)\release\</OutDir>
+    <IntDir>$(ProjectDir)obj\$(Platform)\release\</IntDir>
+    <RemoteProjectDir>$(RemoteRootDir)/Server/$(ProjectName)/release</RemoteProjectDir>
+    <IncludePath>..\..\..\..\Allgemein\Framework;../../../Framework/release;..\..\..\..\Allgemein\Network\Network;../../../Network/release;..\..\..\..\Allgemein\sql\sql;../../../sql/release;$(IncludePath)</IncludePath>
+    <TargetExt />
+  </PropertyGroup>
+  <ItemGroup>
+    <ClCompile Include="Datenbank.cpp" />
+    <ClCompile Include="main.cpp" />
+    <ClCompile Include="MinigameServer.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Datenbank.h" />
+    <ClInclude Include="MinigameServer.h" />
+  </ItemGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/debug/bin/x64/debug;$(RemoteRootDir)/Network/debug/bin/x64/debug;$(RemoteRootDir)/Framework/debug/bin/x64/debug;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>dbgFramework;dbgNetwork;dbgSQL;pq;pthread</LibraryDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Link>
+      <AdditionalLibraryDirectories>$(RemoteRootDir)/sql/release/bin/x64/release;$(RemoteRootDir)/Network/release/bin/x64/release;$(RemoteRootDir)/Framework/release/bin/x64/release;/usr/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <LibraryDependencies>Framework;Network;SQL;pq;pthread</LibraryDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets" />
+</Project>

+ 988 - 0
Minigame Server/MinigameServer.cpp

@@ -0,0 +1,988 @@
+#include "MinigameServer.h"
+#include <iostream>
+#include <Klient.h>
+#include <Globals.h>
+
+// Inhalt der LoginServer Klasse aus LoginServer.h
+// Konstruktor 
+MinigameServer::MinigameServer( InitDatei *zIni )
+    : Thread()
+{
+    Network::Start( 100 );
+    std::cout << "MS: Verbindung mit Datenbank wird hergestellt...\n";
+    db = new MSDatenbank( zIni );
+    klientAnzahl = 0;
+    klients = new RCArray< MSKlient >();
+    empfangen = 0;
+    gesendet = 0;
+    fehler = new Text();
+    ini = zIni->getThis();
+    id = *zIni->zWert( "ServerId" );
+    server = new Server();
+    aServer = new Server();
+    std::cout << "MS: Starten des Admin Servers...\n";
+    if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
+    {
+        std::cout << "MS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
+        exit( 1 );
+    }
+    db->setServerStatus( id, 2 );
+    end = 0;
+    nichtPausiert = 0;
+    InitializeCriticalSection( &cs );
+    ref = 1;
+    if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
+    {
+        serverStarten();
+        serverFortsetzen();
+    }
+}
+
+// Destruktor 
+MinigameServer::~MinigameServer()
+{
+    fehler->release();
+    server->trenne();
+    server->release();
+    aServer->trenne();
+    aServer->release();
+    if( klients )
+        klients->release();
+    ini->release();
+    db->release();
+    DeleteCriticalSection( &cs );
+}
+
+// nicht constant 
+void MinigameServer::runn()
+{
+    while( !end )
+    {
+        SKlient *klient;
+        klient = aServer->getKlient();
+        if( end && klient )
+        {
+            klient->trenne();
+            klient = klient->release();
+            Sleep( 1000 );
+            return;
+        }
+        if( !klient )
+            return;
+        MSAKlient *clHandle = new MSAKlient( klient, getThis() );
+        clHandle->start();
+    }
+}
+
+void MinigameServer::thread()
+{
+    while( 1 )
+    {
+        SKlient *klient;
+        klient = server->getKlient();
+        if( !klient )
+            break;
+        Framework::getThreadRegister()->cleanUpClosedThreads();
+        MSKlient *clHandle = new MSKlient( klient, getThis() );
+        EnterCriticalSection( &cs );
+        klients->set( clHandle, klientAnzahl );
+        klientAnzahl++;
+        LeaveCriticalSection( &cs );
+        clHandle->start();
+    }
+}
+
+void MinigameServer::close()
+{
+    db->setServerStatus( id, 1 );
+    server->trenne();
+#ifdef WIN32
+    warteAufThread( 1000 );
+#endif
+    EnterCriticalSection( &cs );
+    for( int i = 0; i < klientAnzahl; i++ )
+        klients->z( i )->absturz();
+    klients = klients->release();
+    klientAnzahl = 0;
+    LeaveCriticalSection( &cs );
+    ende();
+    run = 0;
+    end = 1;
+    Klient *klient = new Klient();
+    klient->verbinde( aServer->getPort(), "127.0.0.1" );
+    Sleep( 500 );
+    aServer->trenne();
+    klient->release();
+}
+
+bool MinigameServer::serverStarten()
+{
+    if( nichtPausiert )
+    {
+        fehler->setText( "Der Server konnte nicht gestartet werden: Der Server läuft bereits." );
+        return 0;
+    }
+    if( server )
+        server->release();
+    server = new Server();
+    if( server->verbinde( (unsigned short)TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 ), 10 ) )
+    {
+        nichtPausiert = 1;
+        start();
+        return 1;
+    }
+    else
+    {
+        serverBeenden();
+        fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." );
+        return 0;
+    }
+}
+
+bool MinigameServer::serverPause()
+{
+    if( !nichtPausiert )
+    {
+        fehler->setText( "Der Server konnte nicht pausiert werden: Der Server läuft nicht." );
+        return 0;
+    }
+    if( !db->setServerStatus( id, 2 ) )
+    {
+        fehler->setText( "Der Server konnte nicht pausiert werden: " );
+        fehler->append( db->getLetzterFehler() );
+        return 0;
+    }
+    return 1;
+}
+
+bool MinigameServer::serverFortsetzen()
+{
+    if( !nichtPausiert )
+    {
+        fehler->setText( "Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht." );
+        return 0;
+    }
+    if( !db->setServerStatus( id, 3 ) )
+    {
+        fehler->setText( "Der Server konnte nicht fortgesetzt werden: " );
+        fehler->append( db->getLetzterFehler() );
+        return 0;
+    }
+    return 1;
+}
+
+bool MinigameServer::serverBeenden()
+{
+    if( !nichtPausiert )
+    {
+        fehler->setText( "Der Server konnte nicht beendet werden: Der Server läuft nicht." );
+        return 0;
+    }
+    if( db->serverIstNichtPausiert( id ) )
+    {
+        fehler->setText( "Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden." );
+        return 0;
+    }
+    nichtPausiert = 0;
+    ende();
+    if( server )
+        server->trenne();
+    return 1;
+}
+
+bool MinigameServer::setMaxKlients( int mc )
+{
+    if( !db->setMaxClients( id, mc ) )
+    {
+        fehler->setText( "Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n" );
+        fehler->append( db->getLetzterFehler() );
+        return 0;
+    }
+    ini->setWert( "MaxClients", Text() += mc );
+    return 1;
+}
+
+bool MinigameServer::absturzKlient( int klientId )
+{
+    bool gefunden = 0;
+    EnterCriticalSection( &cs );
+    for( int i = 0; i < klientAnzahl; i++ )
+    {
+        if( klients->z( i ) && klients->z( i )->getKlientNummer() == klientId )
+        {
+            klients->z( i )->absturz();
+            klients->remove( i );
+            klientAnzahl--;
+            gefunden = 1;
+            break;
+        }
+    }
+    LeaveCriticalSection( &cs );
+    return gefunden;
+}
+
+bool MinigameServer::removeKlient( MSKlient *zKlient )
+{
+    bool gefunden = 0;
+    EnterCriticalSection( &cs );
+    for( int i = 0; i < klientAnzahl; i++ )
+    {
+        if( klients->z( i ) == zKlient )
+        {
+            klients->remove( i );
+            klientAnzahl--;
+            gefunden = 1;
+            break;
+        }
+    }
+    LeaveCriticalSection( &cs );
+    return gefunden;
+}
+
+void MinigameServer::addGesendet( int bytes )
+{
+    gesendet += bytes;
+}
+
+void MinigameServer::addEmpfangen( int bytes )
+{
+    empfangen += bytes;
+}
+
+// constant
+bool MinigameServer::istAn() const
+{
+    return db->serverIstNichtPausiert( id );
+}
+
+Server *MinigameServer::zServer() const
+{
+    return server;
+}
+
+MSDatenbank *MinigameServer::zDB() const
+{
+    return db;
+}
+
+bool MinigameServer::hatClients() const
+{
+    return klientAnzahl > 0;
+}
+
+int MinigameServer::getId() const
+{
+    return id;
+}
+
+char *MinigameServer::getLetzterFehler() const
+{
+    return fehler->getText();
+}
+
+InitDatei *MinigameServer::zInit() const
+{
+    return ini;
+}
+
+// Reference Counting
+MinigameServer *MinigameServer::getThis()
+{
+    ref++;
+    return this;
+}
+
+MinigameServer *MinigameServer::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}
+
+
+// Inhalt der LSAKlient Klasse aus LoginServer.h
+// Konstruktor 
+MSAKlient::MSAKlient( SKlient *klient, MinigameServer *ls )
+    : Thread()
+{
+    this->klient = klient;
+    unsigned char key[ 20 ] = { 168, 13, 57, 219, 1, 54, 176, 97, 163, 80, 63, 101, 137, 132, 45, 103, 204, 225, 53, 197 };
+    klient->setSendeKey( (char*)key, 20 );
+    klient->setEmpfangKey( (char*)key, 20 );
+    name = new Text( "" );
+    passwort = new Text( "" );
+    adminId = 0;
+    version = 0;
+    this->ms = ls;
+}
+
+// Destruktor 
+MSAKlient::~MSAKlient()
+{
+    klient->trenne();
+    klient->release();
+    ms->release();
+    name->release();
+    passwort->release();
+}
+
+// nicht constant 
+void MSAKlient::thread()
+{
+    while( 1 )
+    {
+        char c = 0;
+        if( !klient->getNachrichtEncrypted( &c, 1 ) )
+            break;
+        else
+        {
+            bool br = 0;
+            switch( c )
+            {
+            case 1: // Login
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char nLen = 0;
+                    klient->getNachrichtEncrypted( &nLen, 1 );
+                    char *n = new char[ nLen + 1 ];
+                    n[ (int)nLen ] = 0;
+                    if( nLen )
+                        klient->getNachrichtEncrypted( n, nLen );
+                    char pLen = 0;
+                    klient->getNachrichtEncrypted( &pLen, 1 );
+                    char *p = new char[ pLen + 1 ];
+                    p[ (int)pLen ] = 0;
+                    if( pLen )
+                        klient->getNachrichtEncrypted( p, pLen );
+                    int adminId = ms->zDB()->istAdministrator( n, p );
+                    if( adminId )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        name->setText( n );
+                        passwort->setText( p );
+                        this->adminId = adminId;
+                    }
+                    else
+                        errorZuKlient( "Falsche Kombination aus Name und Passwort." );
+                    delete[] n;
+                    delete[] p;
+                }
+                break;
+            case 2: // Logout
+                adminId = 0;
+                name->setText( "" );
+                passwort->setText( "" );
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 3: // Trennen
+                br = 1;
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 4: // Server starten
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSStarten ) )
+                    {
+                        if( !ms->serverStarten() )
+                        {
+                            Text *err = new Text();
+                            err->append( ms->getLetzterFehler() );
+                            errorZuKlient( err->getText() );
+                            err->release();
+                        }
+                        else
+                            klient->sendeEncrypted( "\1", 1 );
+                    }
+                    else
+                        errorZuKlient( "Du bist nicht berechtigt den Server zu starten." );
+                }
+                break;
+            case 5: // Server beenden
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
+                    {
+                        if( ms->serverBeenden() )
+                            klient->sendeEncrypted( "\1", 1 );
+                        else
+                        {
+                            Text *err = new Text();
+                            err->append( ms->getLetzterFehler() );
+                            errorZuKlient( err->getText() );
+                            err->release();
+                        }
+                    }
+                    else
+                        errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                }
+                break;
+            case 6: // Programm Schließen
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    bool ok = 0;
+                    if( ms->isRunning() )
+                    {
+                        if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
+                        {
+                            if( ms->serverBeenden() )
+                                ok = 1;
+                            else
+                            {
+                                Text *err = new Text();
+                                err->append( ms->getLetzterFehler() );
+                                errorZuKlient( err->getText() );
+                                err->release();
+                            }
+                        }
+                        else
+                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                    }
+                    else
+                        ok = 1;
+                    if( ok && ms->hatClients() )
+                    {
+                        errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
+                        break;
+                    }
+                    if( ok )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        std::cout << "MS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
+                        ms->close();
+                        br = 1;
+                    }
+                }
+                break;
+            case 7: // Progtamm abstürzen
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    bool ok = 0;
+                    if( ms->isRunning() )
+                    {
+                        if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSBeenden ) )
+                        {
+                            ms->serverBeenden();
+                            ok = 1;
+                        }
+                        else
+                            errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
+                    }
+                    else
+                        ok = 1;
+                    if( ok )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        std::cout << "MS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
+                        ms->close();
+                        br = 1;
+                    }
+                }
+                break;
+            case 8: // Status Frage
+                if( 1 )
+                {
+                    char status = 0;
+                    if( ms->isRunning() )
+                    {
+                        status = 1;
+                        if( ms->istAn() )
+                            status = 2;
+                    }
+                    klient->sendeEncrypted( "\1", 1 );
+                    klient->sendeEncrypted( &status, 1 );
+                }
+                break;
+            case 9: // Server pausieren
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    char pause = 0;
+                    klient->getNachrichtEncrypted( &pause, 1 );
+                    if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSPausieren ) )
+                    {
+                        bool ok = 0;
+                        if( pause )
+                            ok = ms->serverPause();
+                        else
+                            ok = ms->serverFortsetzen();
+                        if( ok )
+                            klient->sendeEncrypted( "\1", 1 );
+                        else
+                        {
+                            Text *err = new Text();
+                            err->append( ms->getLetzterFehler() );
+                            errorZuKlient( err->getText() );
+                            err->release();
+                        }
+                    }
+                    else
+                    {
+                        if( pause )
+                            errorZuKlient( "Du bist nicht berechtigt den Server zu pausieren." );
+                        else
+                            errorZuKlient( "Du bist nicht berechtigt den Server fortzusetzen." );
+                    }
+                }
+                break;
+            case 0xA: // maximale Anzahl der Clients setzen
+                if( !adminId )
+                    errorZuKlient( "Du musst dich einloggen." );
+                else
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int maxC = 0;
+                    klient->getNachrichtEncrypted( (char*)&maxC, 4 );
+                    if( ms->zDB()->adminHatRecht( adminId, Admin_Recht::LSMCChange ) )
+                    {
+                        if( ms->setMaxKlients( maxC ) )
+                            klient->sendeEncrypted( "\1", 1 );
+                        else
+                        {
+                            Text *err = new Text();
+                            err->append( ms->getLetzterFehler() );
+                            errorZuKlient( err->getText() );
+                            err->release();
+                        }
+                    }
+                    else
+                        errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern." );
+                }
+                break;
+            case 0xC: // klient absturtz
+                if( 1 )
+                {
+                    klient->sendeEncrypted( "\1", 1 );
+                    int klientId = 0;
+                    klient->getNachrichtEncrypted( (char*)&klientId, 4 );
+                    if( klientId && ms->absturzKlient( klientId ) )
+                        klient->sendeEncrypted( "\1", 1 );
+                    else
+                        klient->sendeEncrypted( "\0", 1 );
+                }
+                break;
+            default:
+                errorZuKlient( "Unbekannte Nachricht!" );
+                break;
+            }
+            if( br )
+                break;
+            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
+            ms->addGesendet( klient->getUploadBytes( 1 ) );
+        }
+    }
+    ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
+    ms->addGesendet( klient->getUploadBytes( 1 ) );
+    delete this;
+}
+
+void MSAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+    klient->sendeEncrypted( "\3", 1 );
+    char len = (char)textLength( nachricht );
+    klient->sendeEncrypted( &len, 1 );
+    klient->sendeEncrypted( nachricht, len );
+}
+
+
+// Inhalt der LSKlient aus LoginServer.h
+// Konstruktor
+MSKlient::MSKlient( SKlient *klient, MinigameServer *ls )
+    : Thread()
+{
+    this->klient = klient;
+    unsigned char key[ 20 ] = { 88, 103, 192, 232, 69, 54, 57, 3, 239, 138, 234, 172, 126, 72, 81, 55, 205, 97, 59, 255 };
+    klient->setSendeKey( (char*)key, 20 );
+    klient->setEmpfangKey( (char*)key, 20 );
+    klientNummer = 0;
+    this->ms = ls;
+    ref = 1;
+}
+
+// Destruktor 
+MSKlient::~MSKlient()
+{
+    klient->release();
+    ms->release();
+}
+
+// nicht constant 
+void MSKlient::absturz()
+{
+    ende();
+    klient->trenne();
+    ms->zDB()->unregisterKlient( klientNummer, ms->getId() );
+}
+
+void MSKlient::thread()
+{
+    while( 1 )
+    {
+        char c = 0;
+        if( !klient->getNachrichtEncrypted( &c, 1 ) )
+            break;
+        else
+        {
+            bool br = 0;
+            switch( c )
+            {
+            case 1: // Klient identifikation
+                klient->getNachrichtEncrypted( (char*)&klientNummer, 4 );
+                if( !ms->zDB()->proveKlient( klientNummer, ms->getId() ) )
+                {
+                    klientNummer = 0;
+                    errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
+                }
+                else
+                {
+                    Text *key = ms->zDB()->getKlientKey( klientNummer );
+                    if( !key )
+                        errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
+                    else
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        klient->setEmpfangKey( *key, key->getLength() );
+                        klient->setSendeKey( *key, key->getLength() );
+                        key->release();
+                    }
+                }
+                break;
+            case 2: // Main / Erhaltung Server message
+                if( 1 )
+                {
+                    char befehl = 0;
+                    klient->getNachrichtEncrypted( &befehl, 1 );
+                    switch( befehl )
+                    {
+                    case 2: // klient absturtz
+                        if( 1 )
+                        {
+                            int klientId = 0;
+                            klient->getNachrichtEncrypted( (char*)&klientId, 4 );
+                            if( klientId && ms->absturzKlient( klientId ) )
+                                klient->sendeEncrypted( "\1", 1 );
+                            else
+                                klient->sendeEncrypted( "\0", 1 );
+                        }
+                        break;
+                    default:
+                        errorZuKlient( "Befehl nicht bekannt!" );
+                        break;
+                    }
+                }
+                break;
+            case 3: // Verbindungsende
+                br = 1;
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 4: // unregister Klient
+                if( !klientNummer )
+                {
+                    errorZuKlient( "Du bist nicht Identifiziert." );
+                    break;
+                }
+                ms->zDB()->unregisterKlient( klientNummer, ms->getId() );
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 0x5: // ping
+                if( !klientNummer )
+                {
+                    errorZuKlient( "Du bist nicht Identifiziert." );
+                    break;
+                }
+                klient->sendeEncrypted( "\1", 1 );
+                break;
+            case 0x6: // Get Minigame Option List
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *mName = new char[ l ];
+                mName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( mName, l );
+                RCArray< Text > oList;
+                int anz = ms->zDB()->getMinigameOptionList( mName, &oList );
+                delete[] mName;
+                klient->sendeEncrypted( (char*)&anz, 4 );
+                for( auto t = oList.getArray(); t.set && t.var; t++ )
+                {
+                    l = (char)t.var->getLength();
+                    klient->sendeEncrypted( &l, 1 );
+                    klient->sendeEncrypted( t.var->getText(), l );
+                }
+                break;
+            }
+            case 0x7: // Get Minigame Bestscore List
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *mName = new char[ l ];
+                mName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( mName, l );
+                Array< int > sList;
+                RCArray< Text > pList;
+                RCArray< Text > oList;
+                int anz = ms->zDB()->getMinigameBestscore( mName, &sList, &pList, &oList );
+                delete[] mName;
+                klient->sendeEncrypted( (char*)&anz, 4 );
+                for( int i = 0; i < anz; i++ )
+                {
+                    int s = sList.get( i );
+                    klient->sendeEncrypted( (char*)&s, 4 );
+                    l = (char)pList.z( i )->getLength();
+                    klient->sendeEncrypted( &l, 1 );
+                    klient->sendeEncrypted( pList.z( i )->getText(), l );
+                    l = (char)oList.z( i )->getLength();
+                    klient->sendeEncrypted( &l, 1 );
+                    klient->sendeEncrypted( oList.z( i )->getText(), l );
+                }
+                break;
+            }
+            case 0x8: // Get Minigame Option Bestscore
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *mName = new char[ l ];
+                mName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( mName, l );
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *oName = new char[ l ];
+                oName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( oName, l );
+                Text player;
+                int score = ms->zDB()->getMinigameBestscore( oName, mName, &player );
+                delete[] mName;
+                delete[] oName;
+                klient->sendeEncrypted( (char*)&score, 4 );
+                if( score )
+                {
+                    l = (char)player.getLength();
+                    klient->sendeEncrypted( &l, 1 );
+                    klient->sendeEncrypted( player.getText(), l );
+                }
+                break;
+            }
+            case 0x9: // Report End of Game
+            {
+                if( !klientNummer )
+                {
+                    errorZuKlient( "Du bist nicht Identifiziert." );
+                    break;
+                }
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *mName = new char[ l ];
+                mName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( mName, l );
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *oName = new char[ l ];
+                oName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( oName, l );
+                int score;
+                klient->getNachrichtEncrypted( (char*)&score, 4 );
+                Text fName;
+                if( ms->zDB()->updateMinigameScore( score, oName, klientNummer, mName, ms->getId(), &fName ) )
+                {
+                    ms->zDB()->lock();
+                    Text path = ms->zInit()->zWert( "MGC_Pfad" )->getText();
+                    if( path.getText()[ path.getLength() - 1 ] != '/' )
+                        path += "/";
+                    path += (char*)fName;
+                    Datei d;
+                    d.setDatei( path );
+                    d.erstellen();
+                    if( d.open( Datei::Style::schreiben ) )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        int size;
+                        klient->getNachrichtEncrypted( (char*)&size, 4 );
+                        char *buffer = new char[ 2048 ];
+                        while( size > 0 )
+                        {
+                            int l = size > 2048 ? 2048 : size;
+                            klient->getNachrichtEncrypted( buffer, l );
+                            d.schreibe( buffer, l );
+                            size -= l;
+                        }
+                        delete[] buffer;
+                        d.close();
+                    }
+                    else
+                        errorZuKlient( "Fehler beim speichern des Spielverlaufs" );
+                    ms->zDB()->unlock();
+                }
+                else
+                    klient->sendeEncrypted( "\0", 1 );
+                delete[] mName;
+                delete[] oName;
+                break;
+            }
+            case 0xA: // Get Minigame Capture
+            {
+                klient->sendeEncrypted( "\1", 1 );
+                char l = 0;
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *mName = new char[ l ];
+                mName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( mName, l );
+                klient->getNachrichtEncrypted( &l, 1 );
+                char *oName = new char[ l ];
+                oName[ (int)l ] = 0;
+                klient->getNachrichtEncrypted( oName, l );
+                int serverId = ms->zDB()->getMinigameServer( mName, oName );
+                if( serverId && serverId == ms->getId() )
+                {
+                    ms->zDB()->lock();
+                    Text *fileName = ms->zDB()->getMinigameCaptureFileName( oName, mName );
+                    Text path = ms->zInit()->zWert( "MGC_Pfad" )->getText();
+                    if( path.getText()[ path.getLength() - 1 ] != '/' )
+                        path += "/";
+                    path += fileName->getText();
+                    fileName->release();
+                    Datei d;
+                    d.setDatei( path );
+                    if( d.open( Datei::Style::lesen ) )
+                    {
+                        klient->sendeEncrypted( "\1", 1 );
+                        int size = (int)d.getSize();
+                        klient->sendeEncrypted( (char*)&size, 4 );
+                        char *buffer = new char[ 2048 ];
+                        while( size > 0 )
+                        {
+                            int l = size > 2048 ? 2048 : size;
+                            d.lese( buffer, l );
+                            klient->sendeEncrypted( buffer, l );
+                            size -= l;
+                        }
+                        delete[] buffer;
+                        d.close();
+                    }
+                    errorZuKlient( "Aufzeichnung konnte nicht gelesen werden." );
+                    ms->zDB()->unlock();
+                }
+                else if( serverId )
+                {
+                    Text ip;
+                    Text port;
+                    if( ms->zDB()->getMinigameServer( mName, oName, &ip, &port ) )
+                    {
+                        Klient *k = new Klient();
+                        unsigned char key[ 20 ] = { 88, 103, 192, 232, 69, 54, 57, 3, 239, 138, 234, 172, 126, 72, 81, 55, 205, 97, 59, 255 };
+                        k->setSendeKey( (char*)key, 20 );
+                        k->setEmpfangKey( (char*)key, 20 );
+                        if( k->verbinde( (unsigned short)(int)port, (char*)ip ) )
+                        {
+                            k->sendeEncrypted( "\xA", 1 );
+                            char ret;
+                            k->getNachrichtEncrypted( &ret, 1 );
+                            if( ret == 1 )
+                            {
+                                l = (char)textLength( mName );
+                                k->sendeEncrypted( &l, 1 );
+                                k->sendeEncrypted( mName, l );
+                                l = (char)textLength( oName );
+                                k->sendeEncrypted( &l, 1 );
+                                k->sendeEncrypted( oName, l );
+                                k->getNachrichtEncrypted( &ret, 1 );
+                                if( ret == 1 )
+                                {
+                                    klient->sendeEncrypted( "\1", 1 );
+                                    int size;
+                                    k->getNachrichtEncrypted( (char*)&size, 4 );
+                                    klient->sendeEncrypted( (char*)&size, 4 );
+                                    char *buffer = new char[ 2048 ];
+                                    while( size > 0 )
+                                    {
+                                        int l = size > 2048 ? 2048 : size;
+                                        k->getNachrichtEncrypted( buffer, l );
+                                        klient->sendeEncrypted( buffer, l );
+                                        size -= l;
+                                    }
+                                    delete[] buffer;
+                                }
+                            }
+                            if( ret == 3 )
+                            {
+                                k->getNachrichtEncrypted( &l, 1 );
+                                char *error = new char[ l + 1 ];
+                                error[ (int)l ] = 0;
+                                k->getNachrichtEncrypted( error, l );
+                                errorZuKlient( error );
+                                delete[] error;
+                            }
+                            else if( ret != 1 )
+                                errorZuKlient( "Umbekannter Fehler während der Kommunikation mit dem Aufzeichnungs Server." );
+                            k->sendeEncrypted( "\3", 1 );
+                            k->getNachrichtEncrypted( &ret, 1 );
+                            k->trenne();
+                            k->release();
+                        }
+                        else
+                            errorZuKlient( "Aufzeichnungs Server konnte nicht kontaktiert werden." );
+                    }
+                    else
+                        errorZuKlient( "Aufzeichnungs Server wurde nicht gefunden." );
+                }
+                else
+                    errorZuKlient( "Aufzeichnung wurde nicht gefunden." );
+                delete[] mName;
+                delete[] oName;
+                break;
+            }
+            default:
+                errorZuKlient( "Unbekannte Nachricht!" );
+                break;
+            }
+            if( br )
+                break;
+            ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
+            ms->addGesendet( klient->getUploadBytes( 1 ) );
+        }
+    }
+    ms->addEmpfangen( klient->getDownloadBytes( 1 ) );
+    ms->addGesendet( klient->getUploadBytes( 1 ) );
+    ms->removeKlient( this ); // delete this
+}
+
+// constant
+void MSKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
+{
+    klient->sendeEncrypted( "\3", 1 );
+    char len = (char)textLength( nachricht );
+    klient->sendeEncrypted( &len, 1 );
+    klient->sendeEncrypted( nachricht, len );
+}
+
+int MSKlient::getKlientNummer() const // gibt die KlientId zurück
+{
+    return klientNummer;
+}
+
+// Reference Counting
+MSKlient *MSKlient::getThis()
+{
+    ref++;
+    return this;
+}
+
+MSKlient *MSKlient::release()
+{
+    ref--;
+    if( !ref )
+        delete this;
+    return 0;
+}

+ 106 - 0
Minigame Server/MinigameServer.h

@@ -0,0 +1,106 @@
+#pragma once
+
+#include <Server.h>
+#include <Thread.h>
+#include <Datei.h>
+#include <Text.h>
+#include <InitDatei.h>
+#include "Datenbank.h"
+
+using namespace Framework;
+using namespace Network;
+
+class MSKlient;
+
+class MinigameServer : public Thread
+{
+private:
+    Server *server;
+    Server *aServer;
+    InitDatei *ini;
+    MSDatenbank *db;
+    CRITICAL_SECTION cs;
+    RCArray< MSKlient > *klients;
+    Text *fehler;
+    int klientAnzahl;
+    int id;
+    bool nichtPausiert;
+    int empfangen;
+    int gesendet;
+    bool end;
+    int ref;
+
+public:
+    // Konstruktor 
+    MinigameServer( InitDatei *zIni );
+    // Destruktor 
+    virtual ~MinigameServer();
+    // nicht constant
+    void runn();
+    void thread();
+    void close();
+    bool serverStarten();
+    bool serverPause();
+    bool serverFortsetzen();
+    bool serverBeenden();
+    bool setMaxKlients( int mc );
+    bool absturzKlient( int klientId );
+    bool removeKlient( MSKlient *zKlient );
+    void addGesendet( int bytes );
+    void addEmpfangen( int bytes );
+    // conatant 
+    bool istAn() const;
+    Server *zServer() const;
+    MSDatenbank *zDB() const;
+    bool hatClients() const;
+    int getId() const;
+    char *getLetzterFehler() const;
+    InitDatei *zInit() const;
+    // Reference Counting
+    MinigameServer *getThis();
+    MinigameServer *release();
+};
+
+class MSAKlient : public Thread
+{
+private:
+    SKlient *klient;
+    Text *name;
+    Text *passwort;
+    int adminId;
+    MinigameServer *ms;
+    int version;
+
+public:
+    // Konstruktor 
+    MSAKlient( SKlient *klient, MinigameServer *ls );
+    // Destruktor 
+    virtual ~MSAKlient();
+    // nicht constant
+    void thread();
+    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum AKlient
+};
+
+class MSKlient : public Thread
+{
+private:
+    SKlient     *klient;
+    unsigned int klientNummer;
+    MinigameServer *ms;
+    int ref;
+
+public:
+    // Konstruktor 
+    MSKlient( SKlient *klient, MinigameServer *ls );
+    // Destruktor 
+    virtual ~MSKlient();
+    // nicht constant 
+    void absturz();
+    void thread();
+    // constant
+    void errorZuKlient( const char *nachricht ) const; // sendet eine Fehlernachricht zum Klient
+    int getKlientNummer() const;
+    // Reference Counting
+    MSKlient *getThis();
+    MSKlient *release();
+};

+ 54 - 0
Minigame Server/main.cpp

@@ -0,0 +1,54 @@
+#include "MinigameServer.h"
+#include <Zeit.h>
+#include <iostream>
+#include <fstream>
+#include <Globals.h>
+
+int main()
+{
+    Framework::initFramework();
+    Zeit *z = getZeit();
+    Text *pfad = new Text( "../log/login/" );
+    pfad->append( z->getZeit( "y-m-d h-i-s.log" ) );
+    z->release();
+    DateiPfadErstellen( pfad->getThis() );
+    std::ofstream file;
+    file.open( pfad->getText() );
+    std::streambuf* sbuf = std::cout.rdbuf();
+    std::cout.rdbuf( file.rdbuf() );
+    pfad->release();
+
+    std::cout << "MS: Startet...\n";
+    std::cout << "MS: Lese init Datei ../data/misInit.ini ...\n";
+    InitDatei *dat = new InitDatei( "../data/misInit.ini" );
+    if( !dat->laden() )
+    {
+        std::cout << "MS: error: Datei konnte nicht gelesen werden. Das Programm wird geschlossen.\n";
+        dat->release();
+        exit( 1 );
+    }
+    const char *wichtig[] = { "ServerId", "DBBenutzer", "DBPasswort", "DBName", "DBIP", "DBPort", "Aktiv", "MGC_Pfad" };
+    for( const char *w : wichtig )
+    {
+        if( !dat->wertExistiert( w ) )
+        {
+            std::cout << "MS: error: Der Wert '" << w << "' wurde nicht gefunden. Das Programm wird geschlossen.\n";
+            dat->release();
+            exit( 1 );
+        }
+    }
+
+    MinigameServer *lServer = new MinigameServer( dat );
+
+    std::cout << "MS: Der Admin Server läuft. Startforgang beendet.\n";
+    lServer->runn();
+
+    lServer->ende();
+    lServer->release();
+    dat->release();
+    std::cout << "MS: Der Server ist heruntergefahren.\n";
+    file.close();
+    std::cout.rdbuf( sbuf );
+    Framework::releaseFramework();
+    return 0;
+}

BIN
Minigame Server/readme/images/ArchOptions.gif


BIN
Minigame Server/readme/images/ChangeRemote.gif


BIN
Minigame Server/readme/images/ManageConnections.gif


BIN
Minigame Server/readme/images/OutputTypes.gif


BIN
Minigame Server/readme/images/debuggerexport.png


BIN
Minigame Server/readme/images/firstconnection.png


BIN
Minigame Server/readme/images/linker.png


BIN
Minigame Server/readme/images/postbuild.png


+ 77 - 0
Minigame Server/readme/readme.html

@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+
+    <link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen">
+
+    <title>Getting Started</title>
+  </head>
+
+<body>
+
+    <div class="container">
+        <div id="header">
+            <h1>Getting Started</h1>
+            <h2>Visual C++ for Linux Development</h2>
+        </div>
+    
+    <table>
+    <tr>    
+    <div id="main_content">
+        
+        <td>
+        <div id="lpanel">
+            <h1>Setting up your project for Linux Development</h1>
+
+            <p>With this workload you can author C++ code for Linux servers, desktops and devices. You can manage your connections to these machines from within VS. VS will automatically copy and remotely build your sources and can launch your application with the debugger. Our project system supports targeting specific architectures, including ARM.</p>
+            <img src="images\ArchOptions.gif"/>
+            
+            <h1>Connecting to Linux</h1>
+            <h2>Prerequisites</h2>
+            <p>Today we only support building remotely on the Linux target machine. We are not limited by specific Linux distros but we do have dependencies on the presence of some tools. Specifically, we need openssh-server, g++, gdb and gdbserver. Use your favorite package manager to install them, e.g. on Debian based systems: sudo apt-get install openssh-server g++ gdb gdbserver</p>
+            
+            <h2>First connection</h2>
+            <p>The first time you target a Linux machine you will be prompted for connection information.  This is triggered by building the project.</p>
+            <img src="images\firstconnection.png"/>
+                
+            <h2>Adding and removing connections</h2>
+            <p>To add a new connection, go to Tools > Options and search for Connection, Connection Manager will be under Cross Platform. From here you can add and remove connections.</p>
+            <img src="images\ManageConnections.gif"/>
+            
+            <p>To change which connection a project is using go to the project properties general settings and update the Remote Build Machine option.</p>
+            <img src="images\ChangeRemote.gif"/>
+            
+            <h1>Project Properties</h1>
+            <p>All of the options necessary to control C++ compilation are exposed on the project properies pages. We'll cover a few specific to how things work for Linux. First under general settings, you will see the remote root is set to ~/projects/ by default and that we are setting the remote project directory to match our project name in that location. </p>
+            <img src="images\OutputTypes.gif"/>
+            
+            <p>Looking at the General settings for the project, you can see how our output and intermediate directories were configured. Additionally, you’ll see that this project was configured as an application – thus our executable is under bin/x64/Debug/ as ConsoleApplication1.out. Notice that for configuration types we also support static and dynamic libraries.</p>
+            
+            <p>Add additional library dependencies on the Linker > Input property page.</p>
+            <img src="images\linker.png"/>
+            
+            <p>You can pass additional pre launch commands to the debugger to do things like launch graphical apps on the remote linux machine.</p>
+            <img src="images\debuggerexport.png"/>
+            
+            <p>You can also send post build events to control remote behavior, as in this example that exports a gpio pin for use without requiring the executable run as super user.</p>
+            <img src="images\postbuild.png"/>
+            
+        </div>
+        </td>
+        <td>
+        <div id="rpanel">
+
+            <h1>Resources</h1>
+
+            <p>Check out the <a href="http://aka.ms/vslinux">VC++ for Linux Development page</a> where we will keep updates posted and provider more in depth details on usage.</p>
+            <h1>Give us feedback</h1>
+            <p>Use the send feedback function in Visual Studio or contact us directly at <a href="mailto:vcpplinux-support@microsoft.com?subject=Linux%20Console%20App%20question">VC++ Linux Support</a></p>
+        </div>
+        </td>   
+    </div>
+    </tr>
+    </table>
+    </div>
+</body>
+</html>

+ 119 - 0
Minigame Server/readme/stylesheet.css

@@ -0,0 +1,119 @@
+body {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  color: #1E1E1E;
+  font-size: 13px;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1.45;
+  word-wrap: break-word;
+}
+
+/* General & 'Reset' Stuff */
+
+
+.container {
+  width: 1100px;
+  margin: 0 auto;
+}
+
+section {
+  display: block;
+  margin: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin: 0;
+}
+
+table, tr {
+    width: 1100px;
+    padding: 0px;
+    vertical-align: top;
+  }
+
+/* Header, <header>
+   header   - container
+   h1       - project name
+   h2       - project description
+*/
+
+#header {
+  color: #FFF;
+  background: #68217a;
+  position:relative;
+}
+h1, h2 {
+  font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif;
+  line-height: 1;
+  margin: 0 18px;;
+  padding: 0;
+}
+#header h1 {
+  font-size: 3.4em;
+  padding-top: 18px;
+  font-weight: normal;
+  margin-left: 15px;
+}
+
+#header h2 {
+  font-size: 1.5em;
+  margin-top: 10px;
+  padding-bottom: 18px;
+  font-weight: normal;
+}
+
+#main_content {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+  font-weight: bolder;
+}
+
+#main_content h1 {
+  font-size: 1.8em;
+  margin-top: 34px;
+}
+
+    #main_content h1:first-child {
+        margin-top: 30px;
+    }
+
+#main_content h2 {
+  font-size: 1.8em;
+}
+p, ul {
+    margin: 11px 18px;
+}
+
+#main_content a {
+    color: #06C;
+    text-decoration: none;
+}
+ul {
+        margin-top: 13px;
+    margin-left: 18px;
+    padding-left: 0;
+}
+    ul li {
+        margin-left: 18px;
+        padding-left: 0;
+    }
+#lpanel {
+    width: 870px;
+    float: left;
+}
+#rpanel ul {
+    list-style-type: none;
+}
+    #rpanel ul li {
+        line-height: 1.8em;
+    }
+#rpanel {
+    background: #e7e7e7;
+    width: 230px;
+}