Skip to content

Commit

Permalink
Merge branch 'master' into v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
yvt committed May 5, 2019
2 parents 7e03e09 + ac6bc01 commit cb82969
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 128 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,23 @@ OpenSpades is a compatible client of Ace of Spades 0.75.
2. Or [open an issue](https://github.com/yvt/openspades/issues) if the problem persists

### On Linux

#### Snap package
On [snap enabled](https://snapcraft.io/docs/core/install) systems, the latest pre-built stable release of OpenSpades can be installed with:

```bash
sudo snap install openspades
```
Once installed, you'll be able to launch OpenSpades from inside the desktop menu or from your terminal with the `openspades`

#### Flatpak package
On [flatpak enabled](https://flatpak.org/setup/) systems, OpenSpades can be installed with:

```bash
flatpak install flathub jp.yvt.OpenSpades
```

Once installed, you'll be able to launch OpenSpades from inside the desktop menu or from your terminal with the `openspades` command.
Once installed, you'll be able to launch OpenSpades from inside the desktop menu or from your terminal with `flatpak run jp.yvt.OpenSpades`

#### Building and installing from source
GCC 4.9 / Clang 3.2 or later is recommended because OpenSpades relies on C++11 features heavily.
Expand Down
6 changes: 4 additions & 2 deletions Resources/Shaders/DynamicLight/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ varying vec3 lightNormal;
varying vec3 lightTexCoord;

vec3 EvaluateDynamicLightNoBump() {
if(lightTexCoord.z < 0.) discard;

if (lightTexCoord.z < 0. || any(lessThan(lightTexCoord.xy, vec2(0.0))) ||
any(greaterThan(lightTexCoord.xy, vec2(lightTexCoord.z))))
discard;

// diffuse lighting
float intensity = dot(normalize(lightPos), normalize(lightNormal));
if(intensity < 0.) discard;
Expand Down
31 changes: 25 additions & 6 deletions Sources/Client/ClientPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "ClientPlayer.h"
#include "GameMap.h"
#include "GunCasing.h"
#include "GunCasing.h"
#include "IAudioChunk.h"
#include "IAudioDevice.h"
#include "IImage.h"
Expand Down Expand Up @@ -199,6 +198,7 @@ namespace spades {
time = 0.f;
viewWeaponOffset = MakeVector3(0, 0, 0);
lastFront = MakeVector3(0, 0, 0);
flashlightOrientation = p->GetFront();

ScriptContextHandle ctx;
IRenderer *renderer = client->GetRenderer();
Expand Down Expand Up @@ -302,8 +302,6 @@ namespace spades {

PlayerInput actualInput = player->GetInput();
WeaponInput actualWeapInput = player->GetWeaponInput();
Vector3 vel = player->GetVelocty();
vel.z = 0.f;
if (actualInput.sprint && player->IsAlive()) {
sprintState += dt * 4.f;
if (sprintState > 1.f)
Expand Down Expand Up @@ -442,6 +440,19 @@ namespace spades {
}
}

{
// Smooth the flashlight's movement
Vector3 diff = player->GetFront() - flashlightOrientation;
float sq = diff.GetLength();
if (sq > 0.1) {
flashlightOrientation += diff.Normalize() * (sq - 0.1);
}

flashlightOrientation =
Mix(flashlightOrientation, player->GetFront(), 1.0f - powf(1.0e-6, dt))
.Normalize();
}

// FIXME: should do for non-active skins?
asIScriptObject *skin;
if (ShouldRenderInThirdPersonView()) {
Expand Down Expand Up @@ -594,6 +605,16 @@ namespace spades {
}
}

std::array<Vector3, 3> ClientPlayer::GetFlashlightAxes() {
std::array<Vector3, 3> axes;

axes[2] = flashlightOrientation;
axes[0] = Vector3::Cross(flashlightOrientation, player->GetUp()).Normalize();
axes[1] = Vector3::Cross(axes[0], axes[2]);

return axes;
}

void ClientPlayer::AddToSceneFirstPersonView() {
Player *p = player;
IRenderer *renderer = client->GetRenderer();
Expand All @@ -617,9 +638,7 @@ namespace spades {
light.radius = 40.f;
light.type = DynamicLightTypeSpotlight;
light.spotAngle = 30.f * M_PI / 180.f;
light.spotAxis[0] = p->GetRight();
light.spotAxis[1] = p->GetUp();
light.spotAxis[2] = p->GetFront();
light.spotAxis = GetFlashlightAxes();
light.image = renderer->RegisterImage("Gfx/Spotlight.png");
renderer->AddLight(light);

Expand Down
5 changes: 5 additions & 0 deletions Sources/Client/ClientPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#pragma once

#include <array>

#include "Player.h"
#include <Core/Math.h>
#include <Core/RefCountedObject.h>
Expand Down Expand Up @@ -60,6 +62,8 @@ namespace spades {

Vector3 lastFront;

Vector3 flashlightOrientation;

asIScriptObject *spadeSkin;
asIScriptObject *blockSkin;
asIScriptObject *weaponSkin;
Expand All @@ -72,6 +76,7 @@ namespace spades {

Handle<SandboxedRenderer> sandboxedRenderer;

std::array<Vector3, 3> GetFlashlightAxes();
void AddToSceneThirdPersonView();
void AddToSceneFirstPersonView();

Expand Down
4 changes: 3 additions & 1 deletion Sources/Client/IRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
#pragma once

#include <vector>
#include <array>

#include <Core/Math.h>
#include "IImage.h"
#include "IModel.h"
#include "SceneDefinition.h"
Expand Down Expand Up @@ -56,7 +58,7 @@ namespace spades {
float radius;
Vector3 color;

Vector3 spotAxis[3];
std::array<Vector3, 3> spotAxis;
IImage *image;
float spotAngle;

Expand Down
113 changes: 20 additions & 93 deletions Sources/Client/NetClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@ namespace spades {

status = NetClientStatusConnecting;
statusString = _Tr("NetClient", "Connecting to the server");
timeToTryMapLoad = 0;
}

void NetClient::Disconnect() {
Expand Down Expand Up @@ -529,8 +528,6 @@ namespace spades {
mapSize = reader.ReadInt();
status = NetClientStatusReceivingMap;
statusString = _Tr("NetClient", "Loading snapshot");
timeToTryMapLoad = 30;
tryMapLoadOnPacketType = true;
}
} else if (status == NetClientStatusReceivingMap) {
if (event.type == ENET_EVENT_TYPE_RECEIVE) {
Expand All @@ -541,60 +538,29 @@ namespace spades {
dt.erase(dt.begin());
mapData.insert(mapData.end(), dt.begin(), dt.end());

timeToTryMapLoad = 200;

statusString = _Tr("NetClient", "Loading snapshot ({0}/{1})",
mapData.size(), mapSize);

if (mapSize == mapData.size()) {
status = NetClientStatusConnected;
statusString = _Tr("NetClient", "Connected");

try {
MapLoaded();
} catch (const std::exception &ex) {
if (strstr(ex.what(), "File truncated") ||
strstr(ex.what(), "EOF reached")) {
SPLog("Map decoder returned error. Maybe we will get more "
"data...:\n%s",
ex.what());
// hack: more data to load...
status = NetClientStatusReceivingMap;
statusString = _Tr("NetClient", "Still loading...");
} else {
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
}

} catch (...) {
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
}
}

} else {
reader.DumpDebug();

// On pyspades and derivative servers the actual size of the map data
// cannot be known in beforehand, so we have to find the end of the data
// by one of other means. One indicator for this would be a packet of a
// type other than MapChunk, which usually marks the end of map data
// transfer.
// The actual size of the map data cannot be known beforehand because
// of compression. This means we must detect the end of the map
// transfer in another way.
//
// However, we can't rely on this heuristics entirely because there are
// several occasions where the server would send non-MapChunk packets
// during map loading sequence, for example:
// We do this by checking for a StateData packet, which is sent
// directly after the map transfer completes.
//
// A number of other packets can also be received while loading the map:
//
// - World update packets (WorldUpdate, ExistingPlayer, and
// CreatePlayer) for the current round. We must store such packets
// temporarily and process them later when a `World` is created.
// temporarily and process them later when a `World` is created.
//
// - Leftover reload packet from the previous round. This happens when
// you initiate the reload action and a map change occurs before it
// is completed. In pyspades, sending a reload packet is implemented
// by registering a callback function to the Twisted reactor. This
// is completed. In pyspades, sending a reload packet is implemented
// by registering a callback function to the Twisted reactor. This
// callback function sends a reload packet, but it does not check if
// the current game round is finished, nor is it unregistered on a
// map change.
Expand All @@ -604,29 +570,18 @@ namespace spades {
// an "invalid player ID" exception, so we simply drop it during
// map load sequence.
//
if (reader.GetType() == PacketTypeWeaponReload) {
// Drop reload packets
} else if (reader.GetType() != PacketTypeWorldUpdate &&
reader.GetType() != PacketTypeExistingPlayer &&
reader.GetType() != PacketTypeCreatePlayer &&
tryMapLoadOnPacketType) {

if (reader.GetType() == PacketTypeStateData) {
status = NetClientStatusConnected;
statusString = _Tr("NetClient", "Connected");

try {
MapLoaded();
} catch (const std::exception &ex) {
tryMapLoadOnPacketType = false;
if (strstr(ex.what(), "File truncated") ||
strstr(ex.what(), "EOF reached")) {
SPLog("Map decoder returned error. Maybe we will get more "
"data...:\n%s",
SPLog("Map decoder returned error:\n%s",
ex.what());
// hack: more data to load...
status = NetClientStatusReceivingMap;
statusString = _Tr("NetClient", "Still loading...");
goto stillLoading;
} else {
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
Expand All @@ -637,12 +592,15 @@ namespace spades {
throw;
}
HandleGamePacket(reader);
} else {
stillLoading:
} else if (reader.GetType() == PacketTypeWeaponReload) {
// Drop the reload packet. Pyspades does not
// cancel the reload packets on map change and
// they would cause an error if we would
// process them
} else {
// Save the packet for later
savedPackets.push_back(reader.GetData());
}

// HandleGamePacket(reader);
}
}
} else if (status == NetClientStatusConnected) {
Expand All @@ -660,37 +618,6 @@ namespace spades {
}
}
}

if (status == NetClientStatusReceivingMap) {
if (timeToTryMapLoad > 0) {
timeToTryMapLoad--;
if (timeToTryMapLoad == 0) {
try {
MapLoaded();
} catch (const std::exception &ex) {
if ((strstr(ex.what(), "File truncated") ||
strstr(ex.what(), "EOF reached")) &&
savedPackets.size() < 400) {
// hack: more data to load...
SPLog(
"Map decoder returned error. Maybe we will get more data...:\n%s",
ex.what());
status = NetClientStatusReceivingMap;
statusString = _Tr("NetClient", "Still loading...");
timeToTryMapLoad = 200;
} else {
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
}
} catch (...) {
Disconnect();
statusString = _Tr("NetClient", "Error");
throw;
}
}
}
}
}

World *NetClient::GetWorld() { return client->GetWorld(); }
Expand Down
Loading

0 comments on commit cb82969

Please sign in to comment.