mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-12 10:40:53 +01:00
uopdate
This commit is contained in:
parent
90468cb725
commit
776a04b6e8
171 changed files with 0 additions and 36563 deletions
2
f4mp_originalcode/.gitattributes
vendored
2
f4mp_originalcode/.gitattributes
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
# Auto detect text files and perform LF normalization
|
|
||||||
* text=auto
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: bug
|
|
||||||
assignees: Genetical
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Files**
|
|
||||||
Please attach the following files
|
|
||||||
- config.txt (Documents\My Games\Fallout4\F4MP\config.txt)
|
|
||||||
- F4MP.log (Documents\My Games\Fallout4\F4MP\F4MP.log)
|
|
||||||
- server_config.txt (Fallout 4\Data\f4mp_bin\server_config.txt)
|
|
||||||
|
|
||||||
**Load Order**
|
|
||||||
```
|
|
||||||
Please provide your full load order here
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
57
f4mp_originalcode/.gitignore
vendored
57
f4mp_originalcode/.gitignore
vendored
|
|
@ -1,57 +0,0 @@
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
*.pdb
|
|
||||||
*.log
|
|
||||||
*.tlog
|
|
||||||
*.cache
|
|
||||||
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
.vs/
|
|
||||||
|
|
||||||
f4se/
|
|
||||||
f4se_common/
|
|
||||||
f4se_loader/
|
|
||||||
f4se_loader_common/
|
|
||||||
f4se_steam_loader/
|
|
||||||
|
|
||||||
x64/
|
|
||||||
x64_vc11/
|
|
||||||
xbyak/
|
|
||||||
|
|
||||||
f4mp/scripts/.vscode/.ropeproject/config.py
|
|
||||||
f4mp/scripts/.vscode/.ropeproject/objectdb
|
|
||||||
f4mp/scripts/.vscode/settings.json
|
|
||||||
f4mp/scripts/copy.bat
|
|
||||||
|
|
||||||
f4mp_server/scripts/bin
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
namespace animations
|
|
||||||
{
|
|
||||||
extern const UCHAR idle[];
|
|
||||||
extern const UCHAR jogForward[];
|
|
||||||
extern const UCHAR jogForwardRight[];
|
|
||||||
extern const UCHAR jogRight[];
|
|
||||||
extern const UCHAR jogBackwardRight[];
|
|
||||||
extern const UCHAR jogBackward[];
|
|
||||||
extern const UCHAR jogBackwardLeft[];
|
|
||||||
extern const UCHAR jogLeft[];
|
|
||||||
extern const UCHAR jogForwardLeft[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
#include "Animator.h"
|
|
||||||
#include "Animations.h"
|
|
||||||
#include "Player.h"
|
|
||||||
|
|
||||||
#include "f4se/NiNodes.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> f4mp::Animator::animatedNodes;
|
|
||||||
std::vector<std::unordered_map<std::string, UInt32>> f4mp::Animator::animatedNodeIndices;
|
|
||||||
|
|
||||||
std::vector<std::string> f4mp::Animator::stateNames;
|
|
||||||
std::unordered_map<std::string, SInt32> f4mp::Animator::stateIDs;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, f4mp::Animator::Animation> f4mp::Animator::animations;
|
|
||||||
|
|
||||||
f4mp::Animator::Animator(Type type) : type(type), startTime(zpl_time_now())
|
|
||||||
{
|
|
||||||
Play(&animations["idle"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Animator::Play(const Animation* newAnimation)
|
|
||||||
{
|
|
||||||
animation = newAnimation;
|
|
||||||
startTime = zpl_time_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t f4mp::Animator::GetAnimatedNodeCount() const
|
|
||||||
{
|
|
||||||
return animatedNodes[type].size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool f4mp::Animator::IsAnimatedNode(const std::string& nodeName) const
|
|
||||||
{
|
|
||||||
return animatedNodeIndices[type].count(nodeName) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& f4mp::Animator::GetNodeName(UInt32 nodeIndex) const
|
|
||||||
{
|
|
||||||
return animatedNodes[type][nodeIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 f4mp::Animator::GetNodeIndex(const std::string& nodeName) const
|
|
||||||
{
|
|
||||||
auto foundNode = animatedNodeIndices[type].find(nodeName);
|
|
||||||
if (foundNode == animatedNodeIndices[type].end())
|
|
||||||
{
|
|
||||||
return (UInt32)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundNode->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f4mp::Animator::Animation* f4mp::Animator::GetAnimation() const
|
|
||||||
{
|
|
||||||
return animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<f4mp::Animator::Transform> f4mp::Animator::GetTransforms() const
|
|
||||||
{
|
|
||||||
if (!animation)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: non-looping animations
|
|
||||||
|
|
||||||
float t = fmod(zpl_time_now() - startTime, animation->duration);
|
|
||||||
size_t frame = 0;
|
|
||||||
|
|
||||||
while (animation->frames[frame].duration < t)
|
|
||||||
{
|
|
||||||
t -= animation->frames[frame].duration;
|
|
||||||
frame++;
|
|
||||||
if (frame >= animation->frames.size())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Frame& prevFrame = animation->frames[frame];
|
|
||||||
const Frame& nextFrame = animation->frames[(frame + 1) % animation->frames.size()];
|
|
||||||
t /= prevFrame.duration;
|
|
||||||
|
|
||||||
std::vector<Transform> curFrame(animation->nodes.size());
|
|
||||||
|
|
||||||
for (size_t node = 0; node < curFrame.size(); node++)
|
|
||||||
{
|
|
||||||
Transform& curTransform = curFrame[node];
|
|
||||||
const Transform& prevTransform = prevFrame.transforms[node];
|
|
||||||
const Transform& nextTransform = nextFrame.transforms[node];
|
|
||||||
zpl_vec3_lerp(&curTransform.position, prevTransform.position, nextTransform.position, t);
|
|
||||||
zpl_quat_slerp_approx(&curTransform.rotation, prevTransform.rotation, nextTransform.rotation, t);
|
|
||||||
curTransform.scale = zpl_lerp(prevTransform.scale, nextTransform.scale, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
return curFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool f4mp::Animator::ForEachNode(TESObjectREFR* ref, const std::function<bool(NiNode*, UInt32)>& callback)
|
|
||||||
{
|
|
||||||
if (!ref)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NiNode* root = ref->GetActorRootNode(false);
|
|
||||||
if (!root)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return root->Visit([&](NiAVObject* obj)
|
|
||||||
{
|
|
||||||
NiNode* node = DYNAMIC_CAST(obj, NiAVObject, NiNode);
|
|
||||||
if (!node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 nodeIndex = GetNodeIndex(node->m_name.c_str());
|
|
||||||
if (nodeIndex >= GetAnimatedNodeCount())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback(node, nodeIndex);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool f4mp::Animator::Save(const std::string& path, const Animation& animation, bool binary) const
|
|
||||||
{
|
|
||||||
std::ofstream file(path);
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<UCHAR> data;
|
|
||||||
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
const size_t nodes = animation.nodes.size(), frames = animation.frames.size();
|
|
||||||
data.insert(data.end(), (UCHAR*)(&animation.loops), (UCHAR*)(&animation.loops + 1));
|
|
||||||
data.insert(data.end(), (UCHAR*)(&nodes), (UCHAR*)(&nodes + 1));
|
|
||||||
data.insert(data.end(), (UCHAR*)(&frames), (UCHAR*)(&frames + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file << animation.loops << ' ' << animation.nodes.size() << ' ' << animation.frames.size() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string& nodeName : animation.nodes)
|
|
||||||
{
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
const size_t length = nodeName.length();
|
|
||||||
data.insert(data.end(), (UCHAR*)(&length), (UCHAR*)(&length + 1));
|
|
||||||
data.insert(data.end(), (UCHAR*)(&nodeName[0]), (UCHAR*)(&nodeName[0] + length));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file << nodeName << ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
file << std::hex;
|
|
||||||
|
|
||||||
for (UCHAR byte : data)
|
|
||||||
{
|
|
||||||
file << "0x" << (UINT)byte << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
data.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Frame& frame : animation.frames)
|
|
||||||
{
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
data.insert(data.end(), (UCHAR*)(&frame.duration), (UCHAR*)(&frame.duration + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file << frame.duration << ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Transform& transform : frame.transforms)
|
|
||||||
{
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
data.insert(data.end(), (UCHAR*)(&transform), (UCHAR*)(&transform + 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file << transform.position.x << ' ' << transform.position.y << ' ' << transform.position.z << ' ';
|
|
||||||
file << transform.rotation.x << ' ' << transform.rotation.y << ' ' << transform.rotation.z << ' ' << transform.rotation.w << ' ';
|
|
||||||
file << transform.scale << ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file << std::endl;
|
|
||||||
|
|
||||||
if (binary)
|
|
||||||
{
|
|
||||||
for (UCHAR byte : data)
|
|
||||||
{
|
|
||||||
file << "0x" << (UINT)byte << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
data.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Animator::Animation f4mp::Animator::Load(const std::string& path) const
|
|
||||||
{
|
|
||||||
std::ifstream file(path);
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
return Animation(-1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t nodes, frames;
|
|
||||||
std::string nodeName;
|
|
||||||
|
|
||||||
Animation animation;
|
|
||||||
|
|
||||||
file >> animation.loops >> nodes >> frames;
|
|
||||||
|
|
||||||
animation.nodes.resize(nodes);
|
|
||||||
animation.frames.resize(frames);
|
|
||||||
|
|
||||||
for (std::string& nodeName : animation.nodes)
|
|
||||||
{
|
|
||||||
file >> nodeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Frame& frame : animation.frames)
|
|
||||||
{
|
|
||||||
file >> frame.duration;
|
|
||||||
animation.duration += frame.duration;
|
|
||||||
|
|
||||||
frame.transforms.resize(nodes);
|
|
||||||
|
|
||||||
for (Transform& transform : frame.transforms)
|
|
||||||
{
|
|
||||||
file >> transform.position.x >> transform.position.y >> transform.position.z;
|
|
||||||
file >> transform.rotation.x >> transform.rotation.y >> transform.rotation.z >> transform.rotation.w;
|
|
||||||
file >> transform.scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Animator::OnClientUpdate(const Player& player)
|
|
||||||
{
|
|
||||||
const Animation* newAnimation = &animations["idle"];
|
|
||||||
|
|
||||||
int walkDir = player.GetWalkDir(player.GetDisplacement().xy, player.GetLookAngle());
|
|
||||||
if (walkDir >= 0)
|
|
||||||
{
|
|
||||||
const Animation* walkAnimations[]
|
|
||||||
{
|
|
||||||
&animations["jog_forward"],
|
|
||||||
&animations["jog_forward_right"],
|
|
||||||
&animations["jog_right"],
|
|
||||||
&animations["jog_backward_right"],
|
|
||||||
&animations["jog_backward"],
|
|
||||||
&animations["jog_backward_left"],
|
|
||||||
&animations["jog_left"],
|
|
||||||
&animations["jog_forward_left"],
|
|
||||||
};
|
|
||||||
newAnimation = walkAnimations[walkDir];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animation != newAnimation)
|
|
||||||
{
|
|
||||||
Play(newAnimation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Animator::Animation f4mp::Animator::Load(const UCHAR data[])
|
|
||||||
{
|
|
||||||
const UCHAR* curData = data;
|
|
||||||
|
|
||||||
Animation animation;
|
|
||||||
|
|
||||||
animation.loops = *(((const bool*&)curData)++);
|
|
||||||
|
|
||||||
const size_t nodes = *(((const size_t*&)curData)++), frames = *(((const size_t*&)curData)++);
|
|
||||||
animation.nodes.resize(nodes);
|
|
||||||
animation.frames.resize(frames);
|
|
||||||
|
|
||||||
for (std::string& nodeName : animation.nodes)
|
|
||||||
{
|
|
||||||
const size_t length = *(((const size_t*&)curData)++);
|
|
||||||
nodeName = std::string((const char*)curData, (const char*)curData + length);
|
|
||||||
curData += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t frameCount = 0;
|
|
||||||
|
|
||||||
for (Frame& frame : animation.frames)
|
|
||||||
{
|
|
||||||
frame.duration = *(((const float*&)curData)++);
|
|
||||||
if (frame.duration <= 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
animation.duration += frame.duration;
|
|
||||||
|
|
||||||
frame.transforms.resize(nodes);
|
|
||||||
|
|
||||||
for (Transform& transform : frame.transforms)
|
|
||||||
{
|
|
||||||
transform = *(((const Transform*&)curData)++);
|
|
||||||
}
|
|
||||||
|
|
||||||
frameCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
animation.frames.resize(frameCount);
|
|
||||||
|
|
||||||
return animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Animator::Init()
|
|
||||||
{
|
|
||||||
animations["idle"] = Load(animations::idle);
|
|
||||||
animations["jog_forward"] = Load(animations::jogForward);
|
|
||||||
animations["jog_forward_left"] = Load(animations::jogForwardLeft);
|
|
||||||
animations["jog_forward_right"] = Load(animations::jogForwardRight);
|
|
||||||
animations["jog_backward"] = Load(animations::jogBackward);
|
|
||||||
animations["jog_backward_left"] = Load(animations::jogBackwardLeft);
|
|
||||||
animations["jog_backward_right"] = Load(animations::jogBackwardRight);
|
|
||||||
animations["jog_left"] = Load(animations::jogLeft);
|
|
||||||
animations["jog_right"] = Load(animations::jogRight);
|
|
||||||
|
|
||||||
if (stateNames.size() == 0)
|
|
||||||
{
|
|
||||||
animatedNodes =
|
|
||||||
{
|
|
||||||
// Human
|
|
||||||
{
|
|
||||||
"skeleton.nif" ,
|
|
||||||
"COM" ,
|
|
||||||
"Pelvis" ,
|
|
||||||
"LLeg_Thigh" ,
|
|
||||||
"LLeg_Calf" ,
|
|
||||||
"LLeg_Foot" ,
|
|
||||||
"LLeg_Toe1" ,
|
|
||||||
"RLeg_Thigh" ,
|
|
||||||
"RLeg_Calf" ,
|
|
||||||
"RLeg_Foot" ,
|
|
||||||
"RLeg_Toe1" ,
|
|
||||||
"SPINE1" ,
|
|
||||||
"SPINE2" ,
|
|
||||||
"Chest" ,
|
|
||||||
"LArm_Collarbone",
|
|
||||||
"LArm_UpperArm" ,
|
|
||||||
"LArm_ForeArm1" ,
|
|
||||||
"LArm_ForeArm2" ,
|
|
||||||
"LArm_ForeArm3" ,
|
|
||||||
"LArm_Hand" ,
|
|
||||||
"LArm_Finger11" ,
|
|
||||||
"LArm_Finger12" ,
|
|
||||||
"LArm_Finger13" ,
|
|
||||||
"LArm_Finger21" ,
|
|
||||||
"LArm_Finger22" ,
|
|
||||||
"LArm_Finger23" ,
|
|
||||||
"LArm_Finger31" ,
|
|
||||||
"LArm_Finger32" ,
|
|
||||||
"LArm_Finger33" ,
|
|
||||||
"LArm_Finger41" ,
|
|
||||||
"LArm_Finger42" ,
|
|
||||||
"LArm_Finger43" ,
|
|
||||||
"LArm_Finger51" ,
|
|
||||||
"LArm_Finger52" ,
|
|
||||||
"LArm_Finger53" ,
|
|
||||||
"Neck" ,
|
|
||||||
"Head" ,
|
|
||||||
"RArm_Collarbone",
|
|
||||||
"RArm_UpperArm" ,
|
|
||||||
"RArm_ForeArm1" ,
|
|
||||||
"RArm_ForeArm2" ,
|
|
||||||
"RArm_ForeArm3" ,
|
|
||||||
"RArm_Hand" ,
|
|
||||||
"RArm_Finger11" ,
|
|
||||||
"RArm_Finger12" ,
|
|
||||||
"RArm_Finger13" ,
|
|
||||||
"RArm_Finger21" ,
|
|
||||||
"RArm_Finger22" ,
|
|
||||||
"RArm_Finger23" ,
|
|
||||||
"RArm_Finger31" ,
|
|
||||||
"RArm_Finger32" ,
|
|
||||||
"RArm_Finger33" ,
|
|
||||||
"RArm_Finger41" ,
|
|
||||||
"RArm_Finger42" ,
|
|
||||||
"RArm_Finger43" ,
|
|
||||||
"RArm_Finger51" ,
|
|
||||||
"RArm_Finger52" ,
|
|
||||||
"RArm_Finger53" ,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const std::vector<std::string>& allowedNodesInType : animatedNodes)
|
|
||||||
{
|
|
||||||
std::unordered_map<std::string, UInt32> allowedNodeIndicesInType;
|
|
||||||
|
|
||||||
for (const std::string& allowedNode : allowedNodesInType)
|
|
||||||
{
|
|
||||||
allowedNodeIndicesInType[allowedNode] = allowedNodeIndicesInType.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
animatedNodeIndices.push_back(allowedNodeIndicesInType);
|
|
||||||
}
|
|
||||||
|
|
||||||
stateNames =
|
|
||||||
{
|
|
||||||
"None",
|
|
||||||
|
|
||||||
"JogForward",
|
|
||||||
"JogBackward",
|
|
||||||
"JogLeft",
|
|
||||||
"JogRight",
|
|
||||||
|
|
||||||
"JumpUp",
|
|
||||||
"JumpFall",
|
|
||||||
"JumpLand",
|
|
||||||
|
|
||||||
"FireWeapon"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (SInt32 i = 0; i < static_cast<SInt32>(stateNames.size()); i++)
|
|
||||||
{
|
|
||||||
const std::string& state = stateNames[i];
|
|
||||||
std::string lowerState(state.length(), '\0');
|
|
||||||
|
|
||||||
for (size_t i = 0; i < state.length(); i++)
|
|
||||||
{
|
|
||||||
lowerState[i] = tolower(state[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
stateIDs[lowerState] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& f4mp::Animator::GetStateName(SInt32 id)
|
|
||||||
{
|
|
||||||
if (id < 0 || id >= stateNames.size())
|
|
||||||
{
|
|
||||||
id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stateNames[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt32 f4mp::Animator::GetStateID(const std::string& name)
|
|
||||||
{
|
|
||||||
auto id = stateIDs.find(Lower(name));
|
|
||||||
if (id == stateIDs.end())
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return id->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool f4mp::Animator::Loops(SInt32 id)
|
|
||||||
{
|
|
||||||
std::string animStateName = GetStateName(id);
|
|
||||||
|
|
||||||
if (animStateName == "None")
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animStateName.find("Jog") != std::string::npos)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TOOD: add more
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Animator::Animation::Animation(float duration) : loops(true), duration(duration)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Player;
|
|
||||||
|
|
||||||
class Animator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
Human
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Transform
|
|
||||||
{
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_quat rotation;
|
|
||||||
float scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Frame
|
|
||||||
{
|
|
||||||
float duration;
|
|
||||||
std::vector<Transform> transforms;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Animation
|
|
||||||
{
|
|
||||||
bool loops;
|
|
||||||
float duration;
|
|
||||||
std::vector<std::string> nodes;
|
|
||||||
std::vector<Frame> frames;
|
|
||||||
|
|
||||||
Animation(float duration = 0.f);
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::vector<std::vector<std::string>> animatedNodes;
|
|
||||||
static std::vector<std::unordered_map<std::string, UInt32>> animatedNodeIndices;
|
|
||||||
|
|
||||||
static std::vector<std::string> stateNames;
|
|
||||||
static std::unordered_map<std::string, SInt32> stateIDs;
|
|
||||||
|
|
||||||
static std::unordered_map<std::string, Animation> animations;
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
|
|
||||||
const Animation* animation;
|
|
||||||
double startTime;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Animator(Type type);
|
|
||||||
|
|
||||||
void Play(const Animation* newAnimation);
|
|
||||||
|
|
||||||
size_t GetAnimatedNodeCount() const;
|
|
||||||
|
|
||||||
bool IsAnimatedNode(const std::string& nodeName) const;
|
|
||||||
|
|
||||||
const std::string& GetNodeName(UInt32 nodeIndex) const;
|
|
||||||
UInt32 GetNodeIndex(const std::string& nodeName) const;
|
|
||||||
|
|
||||||
const Animation* GetAnimation() const;
|
|
||||||
|
|
||||||
std::vector<Transform> GetTransforms() const;
|
|
||||||
|
|
||||||
bool ForEachNode(TESObjectREFR* ref, const std::function<bool(NiNode*, UInt32)>& callback);
|
|
||||||
|
|
||||||
bool Save(const std::string& path, const Animation& animation, bool binary = true) const;
|
|
||||||
Animation Load(const std::string& path) const;
|
|
||||||
|
|
||||||
void OnClientUpdate(const Player& player);
|
|
||||||
|
|
||||||
static void Init();
|
|
||||||
|
|
||||||
static Animation Load(const UCHAR data[]);
|
|
||||||
|
|
||||||
static const std::string& GetStateName(SInt32 id);
|
|
||||||
static SInt32 GetStateID(const std::string& name);
|
|
||||||
|
|
||||||
static bool Loops(SInt32 id);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
||||||
#include "Character.h"
|
|
||||||
#include "f4mp.h"
|
|
||||||
|
|
||||||
#include "f4se/NiNodes.h"
|
|
||||||
|
|
||||||
f4mp::Character::Character()
|
|
||||||
{
|
|
||||||
animator = std::make_unique<Animator>(Animator::Human);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Animator& f4mp::Character::GetAnimator()
|
|
||||||
{
|
|
||||||
return *animator;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f4mp::Animator& f4mp::Character::GetAnimator() const
|
|
||||||
{
|
|
||||||
return *animator;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Character::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity::OnEntityUpdate(event, F4MP::GetInstance().player.get() != this);
|
|
||||||
|
|
||||||
std::vector<float> transforms;
|
|
||||||
double syncTime;
|
|
||||||
|
|
||||||
Utils::Read(event->data, transforms);
|
|
||||||
Utils::Read(event->data, syncTime);
|
|
||||||
|
|
||||||
if (transforms.size() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float deltaTime = syncTime - transformBuffer.syncTime;
|
|
||||||
|
|
||||||
if (deltaTime < 1e-2f)
|
|
||||||
{
|
|
||||||
//transformBuffer.syncTime = syncTime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransformBuffer newTransformBuffer(transforms.size() / 8, syncTime, zpl_time_now(), deltaTime);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < newTransformBuffer.next.size(); i++)
|
|
||||||
{
|
|
||||||
size_t ti = i * 8;
|
|
||||||
|
|
||||||
Transform& transform = newTransformBuffer.next[i];
|
|
||||||
transform.position = { transforms[ti], transforms[ti + 1], transforms[ti + 2] };
|
|
||||||
transform.rotation = { transforms[ti + 3], transforms[ti + 4], transforms[ti + 5], transforms[ti + 6] };
|
|
||||||
transform.scale = transforms[ti + 7];
|
|
||||||
|
|
||||||
float mag = zpl_quat_mag(transform.rotation);
|
|
||||||
if (isnan(mag) || fabsf(mag - 1.f) > 1e-2f)
|
|
||||||
{
|
|
||||||
transform.rotation = { 0, 0, 0, 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transformBuffer.prev.size() == 0)
|
|
||||||
{
|
|
||||||
newTransformBuffer.prev = newTransformBuffer.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
float t = min((newTransformBuffer.time - transformBuffer.time) / transformBuffer.deltaTime, 1.f);
|
|
||||||
|
|
||||||
for (size_t nodeIndex = 0; nodeIndex < transformBuffer.prev.size(); nodeIndex++)
|
|
||||||
{
|
|
||||||
const Transform& prevTransform = transformBuffer.prev[nodeIndex];
|
|
||||||
const Transform& nextTransform = transformBuffer.next[nodeIndex];
|
|
||||||
Transform& curTransform = newTransformBuffer.prev[nodeIndex];
|
|
||||||
|
|
||||||
if (zpl_quat_dot(newTransformBuffer.next[nodeIndex].rotation, nextTransform.rotation) < 0.f)
|
|
||||||
{
|
|
||||||
newTransformBuffer.next[nodeIndex].rotation *= -1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_vec3_lerp(&curTransform.position, prevTransform.position, nextTransform.position, t);
|
|
||||||
zpl_quat_slerp_approx(&curTransform.rotation, prevTransform.rotation, nextTransform.rotation, t);
|
|
||||||
curTransform.scale = zpl_lerp(prevTransform.scale, nextTransform.scale, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lock.test_and_set(std::memory_order_acquire));
|
|
||||||
transformBuffer = newTransformBuffer;
|
|
||||||
lock.clear(std::memory_order_release);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Character::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity::OnClientUpdate(event);
|
|
||||||
|
|
||||||
std::vector<float> transforms;
|
|
||||||
|
|
||||||
TESObjectREFR* ref = GetRef();
|
|
||||||
if (ref)
|
|
||||||
{
|
|
||||||
NiNode* root = ref->GetActorRootNode(false);
|
|
||||||
if (root)
|
|
||||||
{
|
|
||||||
transforms.resize(animator->GetAnimatedNodeCount() * 8);
|
|
||||||
|
|
||||||
root->Visit([&](NiAVObject* obj)
|
|
||||||
{
|
|
||||||
NiNode* node = dynamic_cast<NiNode*>(obj);
|
|
||||||
if (!node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 nodeIndex = animator->GetNodeIndex(node->m_name.c_str());
|
|
||||||
if (nodeIndex >= animator->GetAnimatedNodeCount())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 index = nodeIndex * 8;
|
|
||||||
|
|
||||||
const NiMatrix43 rot = node->m_localTransform.rot;
|
|
||||||
zpl_mat4 mat
|
|
||||||
{
|
|
||||||
rot.data[0][0], rot.data[0][1], rot.data[0][2], rot.data[0][3],
|
|
||||||
rot.data[1][0], rot.data[1][1], rot.data[1][2], rot.data[1][3],
|
|
||||||
rot.data[2][0], rot.data[2][1], rot.data[2][2], rot.data[2][3],
|
|
||||||
};
|
|
||||||
zpl_quat quat;
|
|
||||||
zpl_quat_from_mat4(&quat, &mat);
|
|
||||||
|
|
||||||
transforms[index + 0] = node->m_localTransform.pos.x;
|
|
||||||
transforms[index + 1] = node->m_localTransform.pos.y;
|
|
||||||
transforms[index + 2] = node->m_localTransform.pos.z;
|
|
||||||
transforms[index + 3] = quat.x;
|
|
||||||
transforms[index + 4] = quat.y;
|
|
||||||
transforms[index + 5] = quat.z;
|
|
||||||
transforms[index + 6] = quat.w;
|
|
||||||
transforms[index + 7] = node->m_localTransform.scale;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ref->GetObjectRootNode() != root)
|
|
||||||
{
|
|
||||||
// TODO: temporary
|
|
||||||
const Animator::Animation* animation = animator->GetAnimation();
|
|
||||||
if (animation)
|
|
||||||
{
|
|
||||||
std::vector<Animator::Transform> animationTransforms = animator->GetTransforms();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < animationTransforms.size(); i++)
|
|
||||||
{
|
|
||||||
const Animator::Transform& transform = animationTransforms[i];
|
|
||||||
size_t index = animator->GetNodeIndex(animation->nodes[i]) * 8;
|
|
||||||
transforms[index + 0] = transform.position.x;
|
|
||||||
transforms[index + 1] = transform.position.y;
|
|
||||||
transforms[index + 2] = transform.position.z;
|
|
||||||
transforms[index + 3] = transform.rotation.x;
|
|
||||||
transforms[index + 4] = transform.rotation.y;
|
|
||||||
transforms[index + 5] = transform.rotation.z;
|
|
||||||
transforms[index + 6] = transform.rotation.w;
|
|
||||||
transforms[index + 7] = transform.scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
transformBuffer.syncTime = zpl_time_now();
|
|
||||||
|
|
||||||
Utils::Write(event->data, transforms);
|
|
||||||
Utils::Write(event->data, transformBuffer.syncTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Character::OnTick()
|
|
||||||
{
|
|
||||||
F4MP& f4mp = F4MP::GetInstance();
|
|
||||||
|
|
||||||
if (this == f4mp.player.get())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lock.test_and_set(std::memory_order_acquire));
|
|
||||||
TransformBuffer transforms = transformBuffer;
|
|
||||||
lock.clear(std::memory_order_release);
|
|
||||||
|
|
||||||
f4mp.task->AddTask(new Task([=]()
|
|
||||||
{
|
|
||||||
TESObjectREFR* ref = GetRef();
|
|
||||||
if (!ref)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NiNode* root = ref->GetActorRootNode(false);
|
|
||||||
if (!root)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float t = min((zpl_time_now() - transforms.time) / transforms.deltaTime, 1.f);
|
|
||||||
|
|
||||||
root->Visit([&](NiAVObject* obj)
|
|
||||||
{
|
|
||||||
NiNode* node = dynamic_cast<NiNode*>(obj);
|
|
||||||
if (!node)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 nodeIndex = animator->GetNodeIndex(node->m_name.c_str());
|
|
||||||
if (nodeIndex >= transforms.prev.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Transform& prevTransform = transforms.prev[nodeIndex];
|
|
||||||
const Transform& nextTransform = transforms.next[nodeIndex];
|
|
||||||
Transform curTransform;
|
|
||||||
|
|
||||||
zpl_vec3_lerp(&curTransform.position, prevTransform.position, nextTransform.position, t);
|
|
||||||
zpl_quat_slerp_approx(&curTransform.rotation, prevTransform.rotation, nextTransform.rotation, t);
|
|
||||||
curTransform.scale = zpl_lerp(prevTransform.scale, nextTransform.scale, t);
|
|
||||||
|
|
||||||
node->m_localTransform.pos = (NiPoint3&)curTransform.position;
|
|
||||||
node->m_localTransform.scale = curTransform.scale;
|
|
||||||
|
|
||||||
if (fabsf(zpl_quat_mag(nextTransform.rotation) - 1.f) > 1e-2f || fabsf(zpl_quat_mag(prevTransform.rotation) - 1.f) > 1e-2f)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_mat4 rot;
|
|
||||||
zpl_mat4_from_quat(&rot, curTransform.rotation);
|
|
||||||
zpl_float4* m = zpl_float44_m(&rot);
|
|
||||||
|
|
||||||
node->m_localTransform.rot =
|
|
||||||
{
|
|
||||||
m[0][0], m[0][1], m[0][2], m[0][3],
|
|
||||||
m[1][0], m[1][1], m[1][2], m[1][3],
|
|
||||||
m[2][0], m[2][1], m[2][2], m[2][3],
|
|
||||||
};
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
NiAVObject::NiUpdateData updateData;
|
|
||||||
root->UpdateWorldData(&updateData);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Character::TransformBuffer::TransformBuffer() : TransformBuffer(0, -1.0, -1.0, 0.f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Character::TransformBuffer::TransformBuffer(size_t transforms, double syncTime, double time, float deltaTime) : prev(transforms), next(transforms), syncTime(syncTime), time(time), deltaTime(deltaTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "Animator.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Character : public Entity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Transform
|
|
||||||
{
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_quat rotation;
|
|
||||||
float scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TransformBuffer
|
|
||||||
{
|
|
||||||
std::vector<Transform> prev, next;
|
|
||||||
|
|
||||||
double syncTime, time;
|
|
||||||
float deltaTime;
|
|
||||||
|
|
||||||
TransformBuffer();
|
|
||||||
TransformBuffer(size_t transforms, double syncTime, double time, float deltaTime);
|
|
||||||
};
|
|
||||||
|
|
||||||
Character();
|
|
||||||
|
|
||||||
Animator& GetAnimator();
|
|
||||||
const Animator& GetAnimator() const;
|
|
||||||
|
|
||||||
void OnEntityUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnClientUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnTick() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<Animator> animator;
|
|
||||||
|
|
||||||
std::atomic_flag lock = ATOMIC_FLAG_INIT;
|
|
||||||
TransformBuffer transformBuffer;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Clone
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::queue<PlayerData> records;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
#include "Entity.h"
|
|
||||||
#include "Player.h"
|
|
||||||
#include "NPC.h"
|
|
||||||
#include "f4mp.h"
|
|
||||||
|
|
||||||
#include "f4se/NiNodes.h"
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Get(librg_event* event)
|
|
||||||
{
|
|
||||||
return Get(event->entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Get(librg_entity* entity)
|
|
||||||
{
|
|
||||||
if (entity == nullptr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Entity*)entity->user_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity::Entity() : entity(nullptr), refFormID((UInt32)-1)
|
|
||||||
{
|
|
||||||
SetNumber("angleX", 0.f);
|
|
||||||
SetNumber("angleY", 0.f);
|
|
||||||
SetNumber("angleZ", 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity::~Entity()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Create(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity* entity = nullptr;
|
|
||||||
|
|
||||||
switch (event->entity->type)
|
|
||||||
{
|
|
||||||
case EntityType::Player:
|
|
||||||
entity = new Player();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EntityType::NPC:
|
|
||||||
entity = new NPC();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->entity = event->entity;
|
|
||||||
|
|
||||||
event->entity->user_data = entity;
|
|
||||||
|
|
||||||
entity->OnEntityCreate(event);
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnConnectRequest(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnConnectAccept(librg_event* event)
|
|
||||||
{
|
|
||||||
// HACK: weird?
|
|
||||||
entity = event->entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnDisonnect(librg_event* event)
|
|
||||||
{
|
|
||||||
event->entity->user_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
OnEntityUpdate(event, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityRemove(librg_event* event)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
event->entity->user_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
TESObjectREFR* ref = GetRef();
|
|
||||||
if (ref)
|
|
||||||
{
|
|
||||||
entity->position = (zpl_vec3&)ref->pos;
|
|
||||||
|
|
||||||
SetNumber("angleX", ToDegrees(ref->rot.x));
|
|
||||||
SetNumber("angleY", ToDegrees(ref->rot.y));
|
|
||||||
SetNumber("angleZ", ToDegrees(ref->rot.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
librg_data_wf32(event->data, GetNumber("angleX"));
|
|
||||||
librg_data_wf32(event->data, GetNumber("angleY"));
|
|
||||||
librg_data_wf32(event->data, GetNumber("angleZ"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnTick()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const librg_entity* f4mp::Entity::GetNetworkEntity() const
|
|
||||||
{
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
librg_entity* f4mp::Entity::GetNetworkEntity()
|
|
||||||
{
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 f4mp::Entity::GetRefFormID() const
|
|
||||||
{
|
|
||||||
return refFormID;
|
|
||||||
}
|
|
||||||
|
|
||||||
TESObjectREFR* f4mp::Entity::GetRef()
|
|
||||||
{
|
|
||||||
//return ref;
|
|
||||||
return dynamic_cast<TESObjectREFR*>(LookupFormByID(refFormID));
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::SetRef(TESObjectREFR* ref)
|
|
||||||
{
|
|
||||||
refFormID = ref->formID;
|
|
||||||
|
|
||||||
//this->ref = ref;
|
|
||||||
|
|
||||||
/*NiNode* root = ref->GetActorRootNode(false);
|
|
||||||
if (root)
|
|
||||||
{
|
|
||||||
printf("-----------\n");
|
|
||||||
|
|
||||||
root->Visit([&](NiAVObject* obj)
|
|
||||||
{
|
|
||||||
printf("%s\n", obj->m_name.c_str());
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
printf("-----------\n");
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
Float32 f4mp::Entity::GetNumber(const std::string& name) const
|
|
||||||
{
|
|
||||||
// HACK: horrible
|
|
||||||
return numbers.find(name)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::SetNumber(const std::string& name, Float32 number)
|
|
||||||
{
|
|
||||||
if (F4MP::GetInstance().player.get() == this)
|
|
||||||
{
|
|
||||||
for (auto& instance : F4MP::instances)
|
|
||||||
{
|
|
||||||
instance->player->numbers[name] = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
numbers[name] = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityUpdate(librg_event* event, bool syncTransform)
|
|
||||||
{
|
|
||||||
zpl_vec3 angles{ librg_data_rf32(event->data), librg_data_rf32(event->data), librg_data_rf32(event->data) };
|
|
||||||
|
|
||||||
SetNumber("angleX", angles.x);
|
|
||||||
SetNumber("angleY", angles.y);
|
|
||||||
SetNumber("angleZ", angles.z);
|
|
||||||
|
|
||||||
if (syncTransform)
|
|
||||||
{
|
|
||||||
TESObjectREFR* ref = GetRef();
|
|
||||||
F4MP::SyncTransform(ref, entity->position, angles, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Entity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static Entity* Get(librg_event* event);
|
|
||||||
static Entity* Get(librg_entity* entity);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static T* GetAs(librg_event* event);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static T* GetAs(librg_entity* entity);
|
|
||||||
|
|
||||||
public:
|
|
||||||
Entity();
|
|
||||||
virtual ~Entity();
|
|
||||||
|
|
||||||
static Entity* Create(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnConnectRequest(librg_event* event);
|
|
||||||
virtual void OnConnectAccept(librg_event* event);
|
|
||||||
virtual void OnDisonnect(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnEntityCreate(librg_event* event);
|
|
||||||
virtual void OnEntityUpdate(librg_event* event);
|
|
||||||
virtual void OnEntityRemove(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnClientUpdate(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnTick();
|
|
||||||
|
|
||||||
const librg_entity* GetNetworkEntity() const;
|
|
||||||
librg_entity* GetNetworkEntity();
|
|
||||||
UInt32 GetRefFormID() const;
|
|
||||||
TESObjectREFR* GetRef();
|
|
||||||
void SetRef(TESObjectREFR* ref);
|
|
||||||
|
|
||||||
Float32 GetNumber(const std::string& name) const;
|
|
||||||
void SetNumber(const std::string& name, Float32 number);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void OnEntityUpdate(librg_event* event, bool syncTransform);
|
|
||||||
|
|
||||||
private:
|
|
||||||
librg_entity* entity;
|
|
||||||
//TESObjectREFR* ref;
|
|
||||||
UInt32 refFormID;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, Float32> numbers;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline T* Entity::GetAs(librg_event* event)
|
|
||||||
{
|
|
||||||
return dynamic_cast<T*>(Get(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline T* Entity::GetAs(librg_entity* entity)
|
|
||||||
{
|
|
||||||
return dynamic_cast<T*>(Get(entity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
#include "NPC.h"
|
|
||||||
#include "f4mp.h"
|
|
||||||
|
|
||||||
f4mp::NPC::NPC() : formID(0), ownerEntityID((UInt32)-1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::NPC::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityCreate(event);
|
|
||||||
|
|
||||||
UInt32 entityID = GetNetworkEntity()->id;
|
|
||||||
|
|
||||||
formID = librg_data_ri32(event->data);
|
|
||||||
ownerEntityID = librg_data_ri32(event->data);
|
|
||||||
|
|
||||||
F4MP& f4mp = F4MP::GetInstance();
|
|
||||||
|
|
||||||
f4mp.entityIDs[formID] = entityID;
|
|
||||||
|
|
||||||
_MESSAGE("OnSpawnEntity: %u(%x)", entityID, formID);
|
|
||||||
|
|
||||||
TESObjectREFR* gameEntity = DYNAMIC_CAST(LookupFormByID(formID), TESForm, TESObjectREFR);
|
|
||||||
if (!gameEntity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetRef(gameEntity);
|
|
||||||
|
|
||||||
printf("%u %x\n", entityID, formID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::NPC::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityUpdate(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::NPC::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnClientUpdate(event);
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Character.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class NPC : public Character
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NPC();
|
|
||||||
|
|
||||||
void OnEntityCreate(librg_event* event) override;
|
|
||||||
void OnEntityUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnClientUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
UInt32 formID, ownerEntityID;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,408 +0,0 @@
|
||||||
#include "Player.h"
|
|
||||||
#include "f4mp.h"
|
|
||||||
|
|
||||||
#include "f4se/NiNodes.h"
|
|
||||||
|
|
||||||
void f4mp::Player::OnConnect(Actor* player, TESNPC* playerActorBase)
|
|
||||||
{
|
|
||||||
SetRef(player);
|
|
||||||
|
|
||||||
appearance.Fill(playerActorBase);
|
|
||||||
wornItems.Fill(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityCreate(event);
|
|
||||||
|
|
||||||
Utils::Read(event->data, appearance.female);
|
|
||||||
Utils::Read(event->data, appearance.weights);
|
|
||||||
Utils::Read(event->data, appearance.hairColor);
|
|
||||||
Utils::Read(event->data, appearance.headParts);
|
|
||||||
Utils::Read(event->data, appearance.morphSetValue);
|
|
||||||
Utils::Read(event->data, appearance.morphRegionData1);
|
|
||||||
Utils::Read(event->data, appearance.morphRegionData2);
|
|
||||||
Utils::Read(event->data, appearance.morphSetData1);
|
|
||||||
Utils::Read(event->data, appearance.morphSetData2);
|
|
||||||
|
|
||||||
Utils::Read(event->data, wornItems.data1);
|
|
||||||
Utils::Read(event->data, wornItems.data2);
|
|
||||||
|
|
||||||
for (const auto& item : wornItems.data2)
|
|
||||||
{
|
|
||||||
_MESSAGE("%s", item.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& npcs = (*g_dataHandler)->arrNPC_;
|
|
||||||
for (UInt32 i = 0; i < npcs.count; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(npcs[i]->fullName.name.c_str(), "F4MP Player") == 0)
|
|
||||||
{
|
|
||||||
SetAppearance(npcs[i], appearance);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Tmp
|
|
||||||
{
|
|
||||||
UInt32 id;
|
|
||||||
const WornItemsData& wornItems;
|
|
||||||
} tmp{ event->entity->id, GetWornItems() };
|
|
||||||
|
|
||||||
F4MP& self = F4MP::GetInstance();
|
|
||||||
|
|
||||||
self.papyrus->GetExternalEventRegistrations("OnEntityCreate", &tmp, [](UInt64 handle, const char* scriptName, const char* callbackName, void* dataPtr)
|
|
||||||
{
|
|
||||||
Tmp* tmp = static_cast<Tmp*>(dataPtr);
|
|
||||||
VMArray<TESForm*> wornItems(F4MP::DecodeWornItems(tmp->wornItems));
|
|
||||||
|
|
||||||
SendPapyrusEvent2<UInt32, VMArray<TESForm*>>(handle, scriptName, callbackName, tmp->id, wornItems);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityUpdate(event);
|
|
||||||
|
|
||||||
SetNumber("health", librg_data_rf32(event->data));
|
|
||||||
|
|
||||||
SetAnimStateID(librg_data_ri32(event->data));
|
|
||||||
|
|
||||||
//transformDeltaTime = transformDeltaTime * transformDeltaTimeInertia + (curTransformTime - prevTransformTime) * (1.f - transformDeltaTimeInertia);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnEntityRemove(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityRemove(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnClientUpdate(event);
|
|
||||||
|
|
||||||
displacement = event->entity->position - prevPosition;
|
|
||||||
|
|
||||||
GetAnimator().OnClientUpdate(*this);
|
|
||||||
|
|
||||||
// TODO: move this to the Animation class.
|
|
||||||
|
|
||||||
const std::string& animState = GetAnimState();
|
|
||||||
const char* newAnimState;
|
|
||||||
|
|
||||||
switch (GetWalkDir(displacement.xy, GetLookAngle()))
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
newAnimState = "JogForward";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
newAnimState = "JogRight";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
newAnimState = "JogBackward";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
newAnimState = "JogLeft";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
newAnimState = "None";
|
|
||||||
}
|
|
||||||
|
|
||||||
SetAnimState(newAnimState);
|
|
||||||
|
|
||||||
prevPosition = event->entity->position;
|
|
||||||
|
|
||||||
librg_data_wf32(event->data, GetNumber("health"));
|
|
||||||
|
|
||||||
librg_data_wi32(event->data, GetAnimStateID());
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnTick()
|
|
||||||
{
|
|
||||||
Character::OnTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt32 f4mp::Player::GetInteger(const std::string& name) const
|
|
||||||
{
|
|
||||||
// HACK: horrible
|
|
||||||
return integers.find(name)->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::SetInteger(const std::string& name, SInt32 integer)
|
|
||||||
{
|
|
||||||
if (F4MP::GetInstance().player.get() == this)
|
|
||||||
{
|
|
||||||
for (auto& instance : F4MP::instances)
|
|
||||||
{
|
|
||||||
instance->player->integers[name] = integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
integers[name] = integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt32 f4mp::Player::GetAnimStateID() const
|
|
||||||
{
|
|
||||||
return GetInteger("animState");
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& f4mp::Player::GetAnimState() const
|
|
||||||
{
|
|
||||||
return Animator::GetStateName(GetAnimStateID());
|
|
||||||
}
|
|
||||||
|
|
||||||
float f4mp::Player::GetLookAngle() const
|
|
||||||
{
|
|
||||||
return GetNumber("angleZ");
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::SetAnimStateID(SInt32 id)
|
|
||||||
{
|
|
||||||
SetInteger("animState", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::SetAnimState(const std::string& name)
|
|
||||||
{
|
|
||||||
SetAnimStateID(Animator::GetStateID(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 f4mp::Player::GetEntityID() const
|
|
||||||
{
|
|
||||||
return entityID;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f4mp::client::AppearanceData& f4mp::Player::GetAppearance() const
|
|
||||||
{
|
|
||||||
return appearance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f4mp::client::WornItemsData& f4mp::Player::GetWornItems() const
|
|
||||||
{
|
|
||||||
return wornItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
const zpl_vec3& f4mp::Player::GetDisplacement() const
|
|
||||||
{
|
|
||||||
return displacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnConnectRequest(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnConnectRequest(event);
|
|
||||||
|
|
||||||
Utils::Write(event->data, appearance.female);
|
|
||||||
Utils::Write(event->data, appearance.weights);
|
|
||||||
Utils::Write(event->data, appearance.hairColor);
|
|
||||||
Utils::Write(event->data, appearance.headParts);
|
|
||||||
Utils::Write(event->data, appearance.morphSetValue);
|
|
||||||
Utils::Write(event->data, appearance.morphRegionData1);
|
|
||||||
Utils::Write(event->data, appearance.morphRegionData2);
|
|
||||||
Utils::Write(event->data, appearance.morphSetData1);
|
|
||||||
Utils::Write(event->data, appearance.morphSetData2);
|
|
||||||
|
|
||||||
Utils::Write(event->data, wornItems.data1);
|
|
||||||
Utils::Write(event->data, wornItems.data2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnConnectAccept(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnConnectAccept(event);
|
|
||||||
|
|
||||||
entityID = event->entity->id;
|
|
||||||
|
|
||||||
event->entity->user_data = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnDisonnect(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnDisonnect(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
int f4mp::Player::GetWalkDir(const zpl_vec2& displacement, float lookAngle)
|
|
||||||
{
|
|
||||||
const float walkThreshold = 1.f;
|
|
||||||
|
|
||||||
float speed = zpl_vec2_mag(displacement);
|
|
||||||
if (speed < walkThreshold)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float angle = atan2(displacement.x, displacement.y) - zpl_to_radians(lookAngle) + ZPL_TAU / 16.f;
|
|
||||||
angle = angle - floor(angle / ZPL_TAU) * ZPL_TAU;
|
|
||||||
|
|
||||||
return (int)floor(angle / ZPL_TAU * 8.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::SetAppearance(TESNPC* actorBase, const AppearanceData& appearance)
|
|
||||||
{
|
|
||||||
//sex
|
|
||||||
//HACK: i don't know if it's legit or not
|
|
||||||
if (appearance.female)
|
|
||||||
{
|
|
||||||
actorBase->actorData.flags |= TESActorBaseData::kFlagFemale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
actorBase->actorData.flags &= ~TESActorBaseData::kFlagFemale;
|
|
||||||
}
|
|
||||||
|
|
||||||
//HACK: there might be some memory leaks going around that might cause horrible problems. i'm sorry i don't know better..
|
|
||||||
|
|
||||||
if (actorBase->headData)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->headData);
|
|
||||||
actorBase->headData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorBase->headParts)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->headParts);
|
|
||||||
actorBase->headParts = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorBase->morphSetValue)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->morphSetValue);
|
|
||||||
actorBase->morphSetValue = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorBase->morphRegionData)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->morphRegionData);
|
|
||||||
actorBase->morphRegionData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorBase->morphSetData)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->morphSetData);
|
|
||||||
actorBase->morphSetData = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actorBase->tints)
|
|
||||||
{
|
|
||||||
Heap_Free(actorBase->tints);
|
|
||||||
actorBase->tints = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
actorBase->headData = new TESNPC::HeadData();
|
|
||||||
tArray<BGSColorForm*>& colors = (*g_dataHandler)->arrCLFM;
|
|
||||||
|
|
||||||
UInt32 j;
|
|
||||||
|
|
||||||
for (j = 0; j < colors.count; j++)
|
|
||||||
{
|
|
||||||
if (appearance.hairColor.compare(colors[j]->fullName.name.c_str()) == 0)
|
|
||||||
{
|
|
||||||
actorBase->headData->hairColor = colors[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == colors.count)
|
|
||||||
{
|
|
||||||
_MESSAGE("hairColor: %s", appearance.hairColor.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: texture sync
|
|
||||||
//dest->headData->faceTextures = src->headData->faceTextures;
|
|
||||||
|
|
||||||
actorBase->weightThin = appearance.weights[0];
|
|
||||||
actorBase->weightMuscular = appearance.weights[1];
|
|
||||||
actorBase->weightLarge = appearance.weights[2];
|
|
||||||
|
|
||||||
actorBase->numHeadParts = appearance.headParts.size();
|
|
||||||
actorBase->headParts = (BGSHeadPart**)Heap_Allocate(sizeof(BGSHeadPart*) * actorBase->numHeadParts);
|
|
||||||
|
|
||||||
for (UInt8 i = 0; i < actorBase->numHeadParts; i++)
|
|
||||||
{
|
|
||||||
tArray<BGSHeadPart*>& headParts = (*g_dataHandler)->arrHDPT;
|
|
||||||
|
|
||||||
for (j = 0; j < headParts.count; j++)
|
|
||||||
{
|
|
||||||
if (appearance.headParts[i].compare(headParts[j]->partName.c_str()) == 0)
|
|
||||||
{
|
|
||||||
actorBase->headParts[i] = headParts[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == headParts.count)
|
|
||||||
{
|
|
||||||
_MESSAGE("hairPart: %s", appearance.headParts[i].c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actorBase->morphSetValue = new tArray<float>();
|
|
||||||
for (UInt32 i = 0; i < appearance.morphSetValue.size(); i++)
|
|
||||||
{
|
|
||||||
actorBase->morphSetValue->Push(appearance.morphSetValue[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
actorBase->morphRegionData = new tHashSet<TESNPC::FaceMorphRegion, UInt32>();
|
|
||||||
/*for(const auto& region : appearance.morphRegionData)
|
|
||||||
{
|
|
||||||
TESNPC::FaceMorphRegion tmp;
|
|
||||||
tmp.index = std::get<0>(region);
|
|
||||||
std::copy(std::get<1>(region).begin(), std::get<1>(region).end(), tmp.value);
|
|
||||||
actorBase->morphRegionData->Add(&tmp);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for (size_t i = 0; i < appearance.morphRegionData1.size(); i++)
|
|
||||||
{
|
|
||||||
TESNPC::FaceMorphRegion tmp;
|
|
||||||
tmp.index = appearance.morphRegionData1[i];
|
|
||||||
std::copy(appearance.morphRegionData2[i].begin(), appearance.morphRegionData2[i].end(), tmp.value);
|
|
||||||
actorBase->morphRegionData->Add(&tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
actorBase->morphSetData = new tHashSet<TESNPC::MorphSetData, UInt32>();
|
|
||||||
for (size_t i = 0; i < appearance.morphSetData1.size(); i++)
|
|
||||||
{
|
|
||||||
TESNPC::MorphSetData tmp;
|
|
||||||
tmp.key = appearance.morphSetData1[i];
|
|
||||||
tmp.value = appearance.morphSetData2[i];
|
|
||||||
actorBase->morphSetData->Add(&tmp);
|
|
||||||
}
|
|
||||||
/*for (const auto& data : appearance.morphSetData)
|
|
||||||
{
|
|
||||||
TESNPC::MorphSetData tmp;
|
|
||||||
tmp.key = std::get<0>(data);
|
|
||||||
tmp.value = std::get<1>(data);
|
|
||||||
actorBase->morphSetData->Add(&tmp);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//TODO: tint sync
|
|
||||||
//dest->tints = src->tints;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::SetWornItems(Actor* actor, const WornItemsData& wornItems)
|
|
||||||
{
|
|
||||||
F4MP& self = F4MP::GetInstance();
|
|
||||||
|
|
||||||
struct Args
|
|
||||||
{
|
|
||||||
Actor* actor;
|
|
||||||
const WornItemsData& wornItems;
|
|
||||||
} args{ actor, wornItems };
|
|
||||||
|
|
||||||
self.papyrus->GetExternalEventRegistrations("OnCopyWornItems", &args, [](UInt64 handle, const char* scriptName, const char* callbackName, void* dataPtr)
|
|
||||||
{
|
|
||||||
Args* args = static_cast<Args*>(dataPtr);
|
|
||||||
VMArray<TESForm*> itemsToWear(F4MP::DecodeWornItems(args->wornItems));
|
|
||||||
|
|
||||||
SendPapyrusEvent2<Actor*, VMArray<TESForm*>>(handle, scriptName, callbackName, args->actor, itemsToWear);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Player::Player() : entityID((UInt32)-1)
|
|
||||||
{
|
|
||||||
SetAnimStateID(0);
|
|
||||||
|
|
||||||
SetNumber("health", 1.f);
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Character.h"
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Player : public Character
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
UInt32 entityID;
|
|
||||||
|
|
||||||
zpl_vec3 prevPosition;
|
|
||||||
zpl_vec3 displacement;
|
|
||||||
|
|
||||||
client::AppearanceData appearance;
|
|
||||||
client::WornItemsData wornItems;
|
|
||||||
|
|
||||||
// TODO: might wanna move them to the Entity class.
|
|
||||||
// NOTE: in that case, fix the ~EntVar~ functions to also work with the Entity class.
|
|
||||||
std::unordered_map<std::string, SInt32> integers;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static int GetWalkDir(const zpl_vec2& displacement, float lookAngle);
|
|
||||||
|
|
||||||
static void SetAppearance(TESNPC* actorBase, const AppearanceData& appearance);
|
|
||||||
static void SetWornItems(Actor* actor, const WornItemsData& wornItems);
|
|
||||||
|
|
||||||
Player();
|
|
||||||
|
|
||||||
void OnConnect(Actor* player, TESNPC* playerActorBase);
|
|
||||||
void OnConnectRequest(librg_event* event) override;
|
|
||||||
void OnConnectAccept(librg_event* event) override;
|
|
||||||
void OnDisonnect(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnEntityCreate(librg_event* event) override;
|
|
||||||
void OnEntityUpdate(librg_event* event) override;
|
|
||||||
void OnEntityRemove(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnClientUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnTick() override;
|
|
||||||
|
|
||||||
SInt32 GetInteger(const std::string& name) const;
|
|
||||||
void SetInteger(const std::string& name, SInt32 integer);
|
|
||||||
|
|
||||||
SInt32 GetAnimStateID() const;
|
|
||||||
const std::string& GetAnimState() const;
|
|
||||||
void SetAnimStateID(SInt32 id);
|
|
||||||
void SetAnimState(const std::string& name);
|
|
||||||
|
|
||||||
UInt32 GetEntityID() const;
|
|
||||||
const client::AppearanceData& GetAppearance() const;
|
|
||||||
const client::WornItemsData& GetWornItems() const;
|
|
||||||
|
|
||||||
const zpl_vec3& GetDisplacement() const;
|
|
||||||
|
|
||||||
float GetLookAngle() const;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
extern UInt32 topicInfoIDs[68227];
|
|
||||||
}
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "f4se/PapyrusNativeFunctions.h"
|
|
||||||
#include "f4se/PluginAPI.h"
|
|
||||||
#include "f4se/PapyrusEvents.h"
|
|
||||||
#include "f4se/GameThreads.h"
|
|
||||||
#include "f4se/GameObjects.h"
|
|
||||||
#include "f4se/GameForms.h"
|
|
||||||
#include "f4se/GameFormComponents.h"
|
|
||||||
#include "f4se/GameData.h"
|
|
||||||
#include "f4se/GameReferences.h"
|
|
||||||
#include "f4se/GameExtraData.h"
|
|
||||||
#include "f4se/GameRTTI.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
template<class T>
|
|
||||||
T ToDegrees(const T& radians)
|
|
||||||
{
|
|
||||||
return radians * 360.0f / ZPL_TAU;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace client
|
|
||||||
{
|
|
||||||
struct AppearanceData : public f4mp::AppearanceData
|
|
||||||
{
|
|
||||||
void Fill(TESNPC* actorBase)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
|
|
||||||
female = CALL_MEMBER_FN(actorBase, GetSex)() == 1;
|
|
||||||
weights = { actorBase->weightThin, actorBase->weightMuscular, actorBase->weightLarge };
|
|
||||||
hairColor = actorBase->headData->hairColor->fullName.name;
|
|
||||||
|
|
||||||
for (UInt8 i = 0; i < actorBase->numHeadParts; i++)
|
|
||||||
{
|
|
||||||
headParts.push_back(actorBase->headParts[i]->partName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UInt32 i = 0; i < actorBase->morphSetValue->count; i++)
|
|
||||||
{
|
|
||||||
morphSetValue.push_back((*actorBase->morphSetValue)[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
actorBase->morphRegionData->ForEach([=](TESNPC::FaceMorphRegion* region)
|
|
||||||
{
|
|
||||||
//morphRegionData.push_back(std::make_tuple(region->index, std::vector<f32>(®ion->value[0], ®ion->value[8])));
|
|
||||||
morphRegionData1.push_back(region->index);
|
|
||||||
morphRegionData2.push_back(std::vector<f32>(®ion->value[0], ®ion->value[8]));
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
actorBase->morphSetData->ForEach([&](TESNPC::MorphSetData* data)
|
|
||||||
{
|
|
||||||
//morphSetData.push_back(std::make_tuple(data->key, data->value));
|
|
||||||
morphSetData1.push_back(data->key);
|
|
||||||
morphSetData2.push_back(data->value);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WornItemsData : public f4mp::WornItemsData
|
|
||||||
{
|
|
||||||
void Fill(Actor* actor)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
|
|
||||||
for (UInt32 i = 0; i < ActorEquipData::kMaxSlots; i++)
|
|
||||||
{
|
|
||||||
TESForm* item = actor->equipData->slots[i].item;
|
|
||||||
if (item)
|
|
||||||
{
|
|
||||||
/*if (std::find_if(data.begin(), data.end(), [&](const std::tuple<u8, std::string>& wornItem)
|
|
||||||
{
|
|
||||||
return std::get<0>(wornItem) == item->formType && std::get<1>(wornItem).compare(item->GetFullName()) == 0;
|
|
||||||
}) == data.end())
|
|
||||||
{
|
|
||||||
data.push_back(std::make_pair(item->formType, item->GetFullName()));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
size_t j;
|
|
||||||
for (j = 0; j < data1.size(); j++)
|
|
||||||
{
|
|
||||||
if (data1[j] == item->formType && data2[j].compare(item->GetFullName()) == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == data1.size())
|
|
||||||
{
|
|
||||||
data1.push_back(item->formType);
|
|
||||||
data2.push_back(item->GetFullName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class Task : public ITaskDelegate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Task(const std::function<void()>& callback) : callback(callback)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() override
|
|
||||||
{
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void()> callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Config
|
|
||||||
{
|
|
||||||
std::string hostAddress;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
u64 f4mp::GetUniqueFormID(u32 ownerEntityID, u32 entityFormID)
|
|
||||||
{
|
|
||||||
return ((u64)ownerEntityID << 32) | entityFormID;
|
|
||||||
}
|
|
||||||
|
|
@ -1,306 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <librg.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
struct MessageType
|
|
||||||
{
|
|
||||||
enum : u16
|
|
||||||
{
|
|
||||||
Hit = LIBRG_EVENT_LAST + 1u,
|
|
||||||
FireWeapon,
|
|
||||||
SpawnEntity,
|
|
||||||
SyncEntity,
|
|
||||||
SpawnBuilding,
|
|
||||||
RemoveBuilding,
|
|
||||||
Speak
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EntityType
|
|
||||||
{
|
|
||||||
enum : u32
|
|
||||||
{
|
|
||||||
Player = 0,
|
|
||||||
NPC
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HitData
|
|
||||||
{
|
|
||||||
u32 hitter, hittee;
|
|
||||||
f32 damage;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpawnEntityData
|
|
||||||
{
|
|
||||||
u32 formID;
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_vec3 angles;
|
|
||||||
|
|
||||||
u32 entityID;
|
|
||||||
u32 ownerEntityID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SyncEntityData
|
|
||||||
{
|
|
||||||
u32 formID;
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_vec3 angles;
|
|
||||||
|
|
||||||
f64 syncedTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpawnBuildingData
|
|
||||||
{
|
|
||||||
u32 ownerEntityID;
|
|
||||||
u32 formID;
|
|
||||||
u32 baseFormID; // HACK: 0 if it's just a transform update
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_vec3 angles;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RemoveBuildingData
|
|
||||||
{
|
|
||||||
u64 uniqueFormID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TransformData
|
|
||||||
{
|
|
||||||
u32 formID;
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_vec3 angles;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpeakData
|
|
||||||
{
|
|
||||||
u32 clientEntityID;
|
|
||||||
u32 speakerFormID; // 0 if client
|
|
||||||
u32 topicInfoFormID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AppearanceData
|
|
||||||
{
|
|
||||||
bool female;
|
|
||||||
std::vector<f32> weights;
|
|
||||||
std::string hairColor;
|
|
||||||
std::vector<std::string> headParts;
|
|
||||||
std::vector<f32> morphSetValue;
|
|
||||||
std::vector<u32> morphRegionData1;
|
|
||||||
std::vector<std::vector<f32>> morphRegionData2;
|
|
||||||
std::vector<u32> morphSetData1;
|
|
||||||
std::vector<f32> morphSetData2;
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
headParts.clear();
|
|
||||||
morphSetValue.clear();
|
|
||||||
morphRegionData1.clear();
|
|
||||||
morphRegionData2.clear();
|
|
||||||
morphSetData1.clear();
|
|
||||||
morphSetData2.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WornItemsData
|
|
||||||
{
|
|
||||||
std::vector<u8> data1;
|
|
||||||
std::vector<std::string> data2;
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
//data.clear();
|
|
||||||
data1.clear();
|
|
||||||
data2.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: the ones for tuple seem to be broken
|
|
||||||
|
|
||||||
class Utils
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
template<class T>
|
|
||||||
static void WriteForTuple(librg_data* data, const T& value)
|
|
||||||
{
|
|
||||||
Write(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class... Ts>
|
|
||||||
static void WriteForTuple(librg_data* data, const T& value, Ts... values)
|
|
||||||
{
|
|
||||||
Write(data, value);
|
|
||||||
WriteForTuple(data, values...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, size_t... I>
|
|
||||||
static void WriteTuple(librg_data* data, const T& tuple, std::index_sequence<I...>)
|
|
||||||
{
|
|
||||||
WriteForTuple(data, std::get<I>(tuple)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void ReadForTuple(librg_data* data, T& value)
|
|
||||||
{
|
|
||||||
Read(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, class... Ts>
|
|
||||||
static void ReadForTuple(librg_data* data, T& value, Ts... values)
|
|
||||||
{
|
|
||||||
Read(data, value);
|
|
||||||
ReadForTuple(data, values...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T, size_t... I>
|
|
||||||
static void ReadTuple(librg_data* data, T& tuple, std::index_sequence<I...>)
|
|
||||||
{
|
|
||||||
ReadForTuple(data, std::get<I>(tuple)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<class T>
|
|
||||||
static void Write(librg_data* data, const T& value);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void Write(librg_data* data, const std::vector<T>& values)
|
|
||||||
{
|
|
||||||
//_MESSAGE("size: %u", values.size());
|
|
||||||
|
|
||||||
librg_data_wu32(data, static_cast<u32>(values.size()));
|
|
||||||
|
|
||||||
for (const T& value : values)
|
|
||||||
{
|
|
||||||
Write(data, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
static void Write(librg_data* data, const std::tuple<Ts...>& values)
|
|
||||||
{
|
|
||||||
static constexpr auto size = std::tuple_size<std::tuple<Ts...>>::value;
|
|
||||||
WriteTuple(data, values, std::make_index_sequence<size>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const bool& value)
|
|
||||||
{
|
|
||||||
//_MESSAGE("%s", value ? "true" : "false");
|
|
||||||
|
|
||||||
librg_data_wb8(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const u8& value)
|
|
||||||
{
|
|
||||||
//_MESSAGE("%u", value);
|
|
||||||
|
|
||||||
librg_data_wu8(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const u32& value)
|
|
||||||
{
|
|
||||||
//_MESSAGE("%u", value);
|
|
||||||
|
|
||||||
librg_data_wu32(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const f32& value)
|
|
||||||
{
|
|
||||||
//_MESSAGE("%f", value);
|
|
||||||
|
|
||||||
librg_data_wf32(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const f64& value)
|
|
||||||
{
|
|
||||||
librg_data_wf64(data, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(librg_data* data, const std::string& value)
|
|
||||||
{
|
|
||||||
//_MESSAGE("%s", value.c_str());
|
|
||||||
|
|
||||||
librg_data_wu32(data, static_cast<u32>(value.size()));
|
|
||||||
|
|
||||||
for (char ch : value)
|
|
||||||
{
|
|
||||||
librg_data_wb8(data, ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void Read(librg_data* data, T& value);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void Read(librg_data* data, std::vector<T>& values)
|
|
||||||
{
|
|
||||||
values.resize(librg_data_ru32(data));
|
|
||||||
|
|
||||||
for (T& value : values)
|
|
||||||
{
|
|
||||||
Read(data, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
static void Read(librg_data* data, std::tuple<Ts...>& values)
|
|
||||||
{
|
|
||||||
static constexpr auto size = std::tuple_size<std::tuple<Ts...>>::value;
|
|
||||||
ReadTuple(data, values, std::make_index_sequence<size>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, bool& value)
|
|
||||||
{
|
|
||||||
value = !!librg_data_rb8(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, u8& value)
|
|
||||||
{
|
|
||||||
value = librg_data_ru8(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, u32& value)
|
|
||||||
{
|
|
||||||
value = librg_data_ru32(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, f32& value)
|
|
||||||
{
|
|
||||||
value = librg_data_rf32(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, f64& value)
|
|
||||||
{
|
|
||||||
value = librg_data_rf64(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Read(librg_data* data, std::string& value)
|
|
||||||
{
|
|
||||||
value.resize(librg_data_ru32(data));
|
|
||||||
|
|
||||||
for (char& ch : value)
|
|
||||||
{
|
|
||||||
ch = librg_data_rb8(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
std::string Lower(const T& string)
|
|
||||||
{
|
|
||||||
std::string lower = string;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < lower.length(); i++)
|
|
||||||
{
|
|
||||||
lower[i] = tolower(lower[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lower;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 GetUniqueFormID(u32 ownerEntityID, u32 entityFormID);
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
LIBRARY "f4mp"
|
|
||||||
EXPORTS
|
|
||||||
F4SEPlugin_Query
|
|
||||||
F4SEPlugin_Load
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,156 +0,0 @@
|
||||||
#include "client.h"
|
|
||||||
#include "Player.h"
|
|
||||||
|
|
||||||
#include <librg.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <functional>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
// TODO: completely separate static functions and member variable access with instance function copies of them.
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
struct SyncDataForPapyrus
|
|
||||||
{
|
|
||||||
TESObjectREFR* ref;
|
|
||||||
zpl_vec3 position;
|
|
||||||
zpl_vec3 angles;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Topic : public TESForm
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum { kTypeID = kFormType_DIAL };
|
|
||||||
|
|
||||||
UInt8 unkTopic1[48];
|
|
||||||
|
|
||||||
TESForm** infos;
|
|
||||||
|
|
||||||
UInt8 unkTopic2[8];
|
|
||||||
|
|
||||||
UInt32 count;
|
|
||||||
UInt32 count2;
|
|
||||||
|
|
||||||
UInt8 unkTopic3[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
class F4MP
|
|
||||||
{
|
|
||||||
friend class Entity;
|
|
||||||
friend class Character;
|
|
||||||
friend class Player;
|
|
||||||
friend class NPC;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static F4MP& GetInstance();
|
|
||||||
|
|
||||||
static std::string GetPath();
|
|
||||||
|
|
||||||
F4MP();
|
|
||||||
|
|
||||||
virtual ~F4MP();
|
|
||||||
|
|
||||||
bool Init(const F4SEInterface* f4se);
|
|
||||||
|
|
||||||
librg_entity* FetchEntity(UInt32 id, const std::string& errorMsg = "no entity with ID '%d'!");
|
|
||||||
|
|
||||||
static std::vector<TESForm*> DecodeWornItems(const WornItemsData& wornItems);
|
|
||||||
|
|
||||||
static void SyncTransform(TESObjectREFR* ref, zpl_vec3 position, zpl_vec3 angles, bool ignoreAngleXY = false);
|
|
||||||
|
|
||||||
static void TranslateTo(TESObjectREFR* ref, zpl_vec3 position, zpl_vec3 angles, Float32 speed, Float32 rotSpeed);
|
|
||||||
static void MoveTo(TESObjectREFR* ref, zpl_vec3 position, zpl_vec3 angles);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::vector<std::unique_ptr<F4MP>> instances;
|
|
||||||
static size_t activeInstance, nextActiveInstance;
|
|
||||||
|
|
||||||
Config config;
|
|
||||||
|
|
||||||
std::string address;
|
|
||||||
SInt32 port;
|
|
||||||
|
|
||||||
librg_ctx ctx;
|
|
||||||
|
|
||||||
PluginHandle handle;
|
|
||||||
|
|
||||||
F4SEMessagingInterface* messaging;
|
|
||||||
F4SEPapyrusInterface* papyrus;
|
|
||||||
F4SETaskInterface* task;
|
|
||||||
F4SEObjectInterface* object;
|
|
||||||
|
|
||||||
std::unique_ptr<Player> player;
|
|
||||||
|
|
||||||
std::unordered_map<UInt32, UInt32> entityIDs;
|
|
||||||
|
|
||||||
std::unordered_map<UInt64, TransformData> buildings;
|
|
||||||
std::unordered_set<UInt32> knownBuildings;
|
|
||||||
|
|
||||||
std::unordered_map<UInt32, std::unordered_multiset<UInt32>> linesToSpeak;
|
|
||||||
|
|
||||||
std::list<UInt32> topicInfoRemainders;
|
|
||||||
|
|
||||||
Topic* topicInstance;
|
|
||||||
|
|
||||||
static void OnConnectRequest(librg_event* event);
|
|
||||||
static void OnConnectAccept(librg_event* event);
|
|
||||||
static void OnConnectRefuse(librg_event* event);
|
|
||||||
static void OnDisonnect(librg_event* event);
|
|
||||||
|
|
||||||
//TODO: abstract event handlers as they're basically the same
|
|
||||||
|
|
||||||
static void OnEntityCreate(librg_event* event);
|
|
||||||
static void OnEntityUpdate(librg_event* event);
|
|
||||||
static void OnEntityRemove(librg_event* event);
|
|
||||||
|
|
||||||
static void OnClientUpdate(librg_event* event);
|
|
||||||
|
|
||||||
static void OnHit(librg_message* msg);
|
|
||||||
static void OnFireWeapon(librg_message* msg);
|
|
||||||
static void OnSyncEntity(librg_message* msg);
|
|
||||||
static void OnSpawnBuilding(librg_message* msg);
|
|
||||||
static void OnRemoveBuilding(librg_message* msg);
|
|
||||||
static void OnSpeak(librg_message* msg);
|
|
||||||
|
|
||||||
static UInt32 GetClientInstanceID(StaticFunctionTag* base);
|
|
||||||
static void SetClient(StaticFunctionTag* base, UInt32 instance);
|
|
||||||
|
|
||||||
static bool IsConnected(StaticFunctionTag* base);
|
|
||||||
static bool Connect(StaticFunctionTag* base, Actor* player, TESNPC* playerActorBase, BSFixedString address, SInt32 port);
|
|
||||||
static bool Disconnect(StaticFunctionTag* base);
|
|
||||||
static void Tick(StaticFunctionTag* base);
|
|
||||||
static void SyncWorld(StaticFunctionTag* base);
|
|
||||||
|
|
||||||
static UInt32 GetPlayerEntityID(StaticFunctionTag* base);
|
|
||||||
static UInt32 GetEntityID(StaticFunctionTag* base, TESObjectREFR* ref);
|
|
||||||
static void SetEntityRef(StaticFunctionTag* base, UInt32 entityID, TESObjectREFR* ref);
|
|
||||||
|
|
||||||
static bool IsEntityValid(StaticFunctionTag* base, UInt32 entityID);
|
|
||||||
|
|
||||||
static VMArray<Float32> GetEntityPosition(StaticFunctionTag* base, UInt32 entityID);
|
|
||||||
static void SetEntityPosition(StaticFunctionTag* base, UInt32 entityID, float x, float y, float z);
|
|
||||||
|
|
||||||
//TODO: abstract ...EntVar...
|
|
||||||
|
|
||||||
static void SetEntVarNum(StaticFunctionTag* base, UInt32 entityID, BSFixedString name, Float32 value);
|
|
||||||
static void SetEntVarAnim(StaticFunctionTag* base, UInt32 entityID, BSFixedString animState);
|
|
||||||
static Float32 GetEntVarNum(StaticFunctionTag* base, UInt32 entityID, BSFixedString name);
|
|
||||||
static BSFixedString GetEntVarAnim(StaticFunctionTag* base, UInt32 entityID);
|
|
||||||
|
|
||||||
static VMArray<TESObjectREFR*> GetRefsInCell(StaticFunctionTag* base, TESObjectCELL* cell);
|
|
||||||
static Float32 Atan2(StaticFunctionTag* base, Float32 y, Float32 x);
|
|
||||||
static BSFixedString GetWalkDir(StaticFunctionTag* base, Float32 dX, Float32 dY, Float32 angleZ);
|
|
||||||
static bool AnimLoops(StaticFunctionTag* base, BSFixedString animState);
|
|
||||||
|
|
||||||
static void CopyAppearance(StaticFunctionTag* base, TESNPC* src, TESNPC* dest);
|
|
||||||
static void CopyWornItems(StaticFunctionTag* base, Actor* src, Actor* dest);
|
|
||||||
|
|
||||||
static void PlayerHit(StaticFunctionTag* base, UInt32 hitter, UInt32 hittee, Float32 damage);
|
|
||||||
static void PlayerFireWeapon(StaticFunctionTag* base);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,238 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</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">
|
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
|
||||||
<ProjectGuid>{F021FA50-A159-46F9-8455-B079C458E5AF}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>f4mp</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;F4MP_EXPORTS;_WINDOWS;_USRDLL;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PrecompiledHeaderFile>
|
|
||||||
</PrecompiledHeaderFile>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)\..;$(SolutionDir)\thirdparty\enet\include;$(SolutionDir)\thirdparty\zpl\code;$(SolutionDir)\thirdparty\librg\include</AdditionalIncludeDirectories>
|
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
||||||
<ForcedIncludeFiles>common/IPrefix.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableUAC>false</EnableUAC>
|
|
||||||
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>copy "$(TargetPath)" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\F4SE\Plugins\$(TargetFileName)"
|
|
||||||
copy "$(ProjectDir)\scripts\F4MP.psc" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\Scripts\Source\User\F4MP.psc"
|
|
||||||
copy "$(ProjectDir)\scripts\F4MPFirePoint.psc" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\Scripts\Source\User\F4MPFirePoint.psc"
|
|
||||||
copy "$(ProjectDir)\scripts\F4MPPlayer.psc" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\Scripts\Source\User\F4MPPlayer.psc"
|
|
||||||
copy "$(ProjectDir)\scripts\F4MPQuest.psc" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\Scripts\Source\User\F4MPQuest.psc"</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;F4MP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableUAC>false</EnableUAC>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;F4MP_EXPORTS;_WINDOWS;_USRDLL;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)\..;$(SolutionDir)\thirdparty\enet\include;$(SolutionDir)\thirdparty\zpl\code;$(SolutionDir)\thirdparty\librg\include</AdditionalIncludeDirectories>
|
|
||||||
<ForcedIncludeFiles>common/IPrefix.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableUAC>false</EnableUAC>
|
|
||||||
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
|
|
||||||
</Link>
|
|
||||||
<PostBuildEvent>
|
|
||||||
<Command>copy "$(TargetPath)" "D:\SteamLibrary\steamapps\common\Fallout 4\Data\F4SE\Plugins\$(TargetFileName)"</Command>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;F4MP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Windows</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableUAC>false</EnableUAC>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\common\common_vc11.vcxproj">
|
|
||||||
<Project>{d4c128a1-73dc-4941-a453-ce55af239ba8}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\f4se\f4se.vcxproj">
|
|
||||||
<Project>{a236f69d-8ff9-4491-ac5f-45bf49448bbe}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\f4se_common\f4se_common.vcxproj">
|
|
||||||
<Project>{20c6411c-596f-4b85-be4e-8bc91f59d8a6}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\f4se\GameAPI.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameData.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameEvents.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameExtraData.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameFormComponents.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameForms.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameObjects.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameReferences.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameRTTI.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameTypes.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\GameUtilities.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\NiObjects.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\NiTypes.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusArgs.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusEvents.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusForm.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusInterfaces.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusValue.cpp" />
|
|
||||||
<ClCompile Include="..\f4se\PapyrusVM.cpp" />
|
|
||||||
<ClCompile Include="Animations.cpp" />
|
|
||||||
<ClCompile Include="Animator.cpp" />
|
|
||||||
<ClCompile Include="Character.cpp" />
|
|
||||||
<ClCompile Include="common.cpp" />
|
|
||||||
<ClCompile Include="Entity.cpp" />
|
|
||||||
<ClCompile Include="main.cpp" />
|
|
||||||
<ClCompile Include="f4mp.cpp" />
|
|
||||||
<ClCompile Include="NPC.cpp" />
|
|
||||||
<ClCompile Include="Player.cpp" />
|
|
||||||
<ClCompile Include="TopicInfoIDs.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="Animations.h" />
|
|
||||||
<ClInclude Include="Animator.h" />
|
|
||||||
<ClInclude Include="Character.h" />
|
|
||||||
<ClInclude Include="client.h" />
|
|
||||||
<ClInclude Include="Clone.h" />
|
|
||||||
<ClInclude Include="Entity.h" />
|
|
||||||
<ClInclude Include="f4mp.h" />
|
|
||||||
<ClInclude Include="common.h" />
|
|
||||||
<ClInclude Include="NPC.h" />
|
|
||||||
<ClInclude Include="Player.h" />
|
|
||||||
<ClInclude Include="TopicInfoIDs.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="exports.def" />
|
|
||||||
<None Include="scripts\F4MP.psc" />
|
|
||||||
<None Include="scripts\F4MPFirePoint.psc" />
|
|
||||||
<None Include="scripts\F4MPPlayer.psc" />
|
|
||||||
<None Include="scripts\F4MPQuest.psc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="소스 파일">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="헤더 파일">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="리소스 파일">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="scripts">
|
|
||||||
<UniqueIdentifier>{beb86421-8d4e-4371-821a-5300dbf76c64}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="f4se">
|
|
||||||
<UniqueIdentifier>{2009725f-77b9-4ae9-9786-54d49666f207}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="main.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusArgs.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusVM.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameExtraData.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameTypes.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameAPI.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusInterfaces.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusValue.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameUtilities.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="f4mp.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusEvents.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\NiObjects.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\NiTypes.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameData.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameFormComponents.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameForms.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameRTTI.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Entity.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Player.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameReferences.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="NPC.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\PapyrusForm.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameObjects.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="common.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Character.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4se\GameEvents.cpp">
|
|
||||||
<Filter>f4se</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="TopicInfoIDs.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Animator.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Animations.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="exports.def">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="scripts\F4MP.psc">
|
|
||||||
<Filter>scripts</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="scripts\F4MPFirePoint.psc">
|
|
||||||
<Filter>scripts</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="scripts\F4MPPlayer.psc">
|
|
||||||
<Filter>scripts</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="scripts\F4MPQuest.psc">
|
|
||||||
<Filter>scripts</Filter>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="f4mp.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="common.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Clone.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="client.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Player.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Entity.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="NPC.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Character.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="TopicInfoIDs.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Animator.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Animations.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LocalDebuggerCommand>D:\SteamLibrary\steamapps\common\Fallout 4\f4se_loader.exe</LocalDebuggerCommand>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
<LocalDebuggerCommandArguments>
|
|
||||||
</LocalDebuggerCommandArguments>
|
|
||||||
<LocalDebuggerWorkingDirectory>D:\SteamLibrary\steamapps\common\Fallout 4\</LocalDebuggerWorkingDirectory>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LocalDebuggerCommand>D:\SteamLibrary\steamapps\common\Fallout 4\f4se_loader.exe</LocalDebuggerCommand>
|
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
|
||||||
<LocalDebuggerCommandArguments>
|
|
||||||
</LocalDebuggerCommandArguments>
|
|
||||||
<LocalDebuggerWorkingDirectory>D:\SteamLibrary\steamapps\common\Fallout 4\</LocalDebuggerWorkingDirectory>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#include "f4se/PluginAPI.h" // super
|
|
||||||
#include "f4se_common/f4se_version.h" // What version of SKSE is running?
|
|
||||||
#include <shlobj.h> // CSIDL_MYCODUMENTS
|
|
||||||
|
|
||||||
#include "f4mp.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool F4SEPlugin_Query(const F4SEInterface* f4se, PluginInfo* info) { // Called by SKSE to learn about this plugin and check that it's safe to load it
|
|
||||||
gLog.OpenRelative(CSIDL_MYDOCUMENTS, "\\My Games\\Fallout4\\F4MP\\F4MP.log");
|
|
||||||
gLog.SetPrintLevel(IDebugLog::kLevel_Error);
|
|
||||||
gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage);
|
|
||||||
|
|
||||||
// populate info structure
|
|
||||||
info->infoVersion = PluginInfo::kInfoVersion;
|
|
||||||
info->name = "F4MP";
|
|
||||||
info->version = 1;
|
|
||||||
|
|
||||||
// store plugin handle so we can identify ourselves later
|
|
||||||
// g_pluginHandle = f4se->GetPluginHandle();
|
|
||||||
|
|
||||||
if (f4se->isEditor)
|
|
||||||
{
|
|
||||||
_MESSAGE("loaded in editor, marking as incompatible");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (f4se->runtimeVersion != RUNTIME_VERSION_1_10_163)
|
|
||||||
{
|
|
||||||
_MESSAGE("unsupported runtime version %08X", f4se->runtimeVersion);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ### do not do anything else in this callback
|
|
||||||
// ### only fill out PluginInfo and return true/false
|
|
||||||
|
|
||||||
// supported runtime version
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool F4SEPlugin_Load(const F4SEInterface* f4se) { // Called by SKSE to load this plugin
|
|
||||||
_MESSAGE("F4MP loaded");
|
|
||||||
|
|
||||||
//Check if the function registration was a success...
|
|
||||||
bool btest = f4mp::F4MP::GetInstance().Init(f4se);
|
|
||||||
|
|
||||||
if (btest) {
|
|
||||||
_MESSAGE("Register succeeded");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
Scriptname F4MP Native Hidden
|
|
||||||
|
|
||||||
int Function GetClientInstanceID() global native
|
|
||||||
Function SetClient(int instanceID) global native
|
|
||||||
|
|
||||||
bool Function IsConnected() global native
|
|
||||||
bool Function Connect(Actor player, ActorBase playerActorBase, string address, int port) global native
|
|
||||||
bool Function Disconnect() global native
|
|
||||||
Function Tick() global native
|
|
||||||
Function SyncWorld() global native
|
|
||||||
|
|
||||||
int Function GetPlayerEntityID() global native
|
|
||||||
int Function GetEntityID(ObjectReference ref) global native
|
|
||||||
Function SetEntityRef(int entityID, ObjectReference ref) global native
|
|
||||||
|
|
||||||
bool Function IsEntityValid(int entityID) global native
|
|
||||||
|
|
||||||
float[] Function GetEntityPosition(int entityID) global native
|
|
||||||
Function SetEntityPosition(int entityID, float x, float y, float z) global native
|
|
||||||
Function SetEntVarNum(int entityID, string name, float value) global native
|
|
||||||
Function SetEntVarAnim(int entityID, string animState) global native
|
|
||||||
float Function GetEntVarNum(int entityID, string name) global native
|
|
||||||
string Function GetEntVarAnim(int entityID) global native
|
|
||||||
|
|
||||||
ObjectReference[] Function GetRefsInCell(Cell cell) global native
|
|
||||||
float Function Atan2(float y, float x) global native
|
|
||||||
string Function GetWalkDir(float dX, float dY, float angleZ) global native
|
|
||||||
Action Function GetAction(string name) global native
|
|
||||||
Function Inspect(Form[] forms) global native
|
|
||||||
bool Function AnimLoops(string animState) global native
|
|
||||||
|
|
||||||
Function CopyAppearance(ActorBase src, ActorBase dest) global native
|
|
||||||
Function CopyWornItems(Actor src, Actor dest) global native
|
|
||||||
|
|
||||||
Function PlayerHit(int hitter, int hittee, float damage) global native
|
|
||||||
Function PlayerFireWeapon() global native
|
|
||||||
Function TopicInfoBegin(Form info, ObjectReference speaker) global native
|
|
||||||
|
|
||||||
ObjectReference[] Function GetEntitySyncRefs(bool clear) global native
|
|
||||||
float[] Function GetEntitySyncTransforms(bool clear) global native
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
Scriptname F4MPEntitySync extends activemagiceffect
|
|
||||||
|
|
||||||
;int updateTimer = 10
|
|
||||||
;
|
|
||||||
;int entityID = -1
|
|
||||||
;bool mine = false
|
|
||||||
;
|
|
||||||
;Event OnEffectStart(Actor akTarget, Actor akCaster)
|
|
||||||
; entityID = F4MP.GetEntityID(akTarget)
|
|
||||||
; mine = F4MP.IsEntityMine(entityID)
|
|
||||||
;
|
|
||||||
; StartTimer(0, updateTimer)
|
|
||||||
;EndEvent
|
|
||||||
;
|
|
||||||
;Event OnTimer(int timerID)
|
|
||||||
; If timerID == updateTimer
|
|
||||||
; Actor entity = GetCasterActor()
|
|
||||||
; If F4MP.IsEntityValid(entityID)
|
|
||||||
; If mine
|
|
||||||
; F4MP.SetEntityPosition(entityID, entity.x, entity.y, entity.z)
|
|
||||||
; Else
|
|
||||||
; float[] position = F4MP.GetEntityPosition(entityID)
|
|
||||||
; float angleZ = F4MP.GetEntVarNum(entityID, "angleZ")
|
|
||||||
; float distance = Math.Sqrt(Math.Pow(position[0] - entity.x, 2) + Math.Pow(position[1] - entity.y, 2) + Math.Pow(position[2] - entity.z, 2))
|
|
||||||
; entity.TranslateTo(position[0], position[1], position[2], 0.0, 0.0, angleZ, distance * 3.0, 500.0)
|
|
||||||
; EndIf
|
|
||||||
; EndIf
|
|
||||||
; StartTimer(0, updateTimer)
|
|
||||||
; EndIf
|
|
||||||
;EndEvent
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
Scriptname F4MPFirePoint extends ObjectReference
|
|
||||||
|
|
||||||
Weapon Property myWeapon = None Auto
|
|
||||||
Ammo Property myAmmo = None Auto
|
|
||||||
|
|
||||||
F4MPPlayer Property myOwner = None Auto
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
; SetPosition(x + 100.0, y + 100.0, z + 100.0)
|
|
||||||
SetScale(0.0)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnLoad()
|
|
||||||
SetMotionType(Motion_Keyframed)
|
|
||||||
|
|
||||||
float[] position = F4MP.GetEntityPosition(myOwner.entityID)
|
|
||||||
float ax = F4MP.GetEntVarNum(myOwner.entityID, "angleX")
|
|
||||||
float az = F4MP.GetEntVarNum(myOwner.entityID, "angleZ")
|
|
||||||
SetPosition(position[0] + Math.Sin(az) * 100.0 + Math.Cos(az) * 10.0, position[1] + Math.Cos(az) * 100.0 - Math.Sin(az) * 10.0, position[2] + 90.0)
|
|
||||||
SetAngle(ax, 0.0, az)
|
|
||||||
|
|
||||||
; Actor player = Game.GetPlayer()
|
|
||||||
; float dx = player.x - x
|
|
||||||
; float dy = player.y - y
|
|
||||||
; SetAngle(0.0, 0.0, Math.RadiansToDegrees(F4MP.Atan2(dx, dy)))
|
|
||||||
|
|
||||||
InstanceData:Owner owner = myWeapon.GetInstanceOwner()
|
|
||||||
InstanceData.SetAttackDamage(owner, 0)
|
|
||||||
InstanceData.SetDamageTypes(owner, new InstanceData:DamageTypeInfo[0])
|
|
||||||
|
|
||||||
myWeapon.Fire(self, myAmmo)
|
|
||||||
Delete()
|
|
||||||
EndEvent
|
|
||||||
|
|
@ -1,407 +0,0 @@
|
||||||
Scriptname F4MPPlayer extends Actor
|
|
||||||
|
|
||||||
int Property entityID = -1 Auto
|
|
||||||
|
|
||||||
Idle Property animNull Auto
|
|
||||||
Idle Property animIdle Auto
|
|
||||||
Idle Property animJogForward Auto
|
|
||||||
Idle Property animJogBackward Auto
|
|
||||||
Idle Property animJogLeft Auto
|
|
||||||
Idle Property animJogRight Auto
|
|
||||||
Idle Property animJumpUp Auto
|
|
||||||
Idle Property animJumpFall Auto
|
|
||||||
Idle Property animJumpLand Auto
|
|
||||||
Idle Property animFireWeapon Auto
|
|
||||||
|
|
||||||
Idle Property animTest Auto
|
|
||||||
|
|
||||||
Action Property actionAnim Auto
|
|
||||||
|
|
||||||
ActorValue Property avType Auto
|
|
||||||
|
|
||||||
Keyword Property animKeyword Auto
|
|
||||||
Keyword Property animType Auto
|
|
||||||
|
|
||||||
Actor Property playerRef Auto
|
|
||||||
|
|
||||||
ActorValue Property HealthAV Auto
|
|
||||||
|
|
||||||
int tickTimerID = 10
|
|
||||||
int animTimerID = 20
|
|
||||||
int tidyTimerID = 30
|
|
||||||
|
|
||||||
string animState = "INIT"
|
|
||||||
|
|
||||||
Form[] Property itemsToWear = None Auto
|
|
||||||
|
|
||||||
Weapon Property myWeapon Auto
|
|
||||||
Ammo Property myAmmo Auto
|
|
||||||
Form Property firePoint Auto
|
|
||||||
Projectile[] Property myProjectiles Auto
|
|
||||||
|
|
||||||
float Property health = 1.0 Auto
|
|
||||||
|
|
||||||
bool Property initialized = false Auto
|
|
||||||
|
|
||||||
Weapon Property weaponEquipped = None Auto
|
|
||||||
|
|
||||||
int stage = 0
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
StartTimer(0, animTimerID)
|
|
||||||
StartTimer(0, tidyTimerID)
|
|
||||||
|
|
||||||
RegisterForKey(113)
|
|
||||||
|
|
||||||
; self.EnableAI(false, true)
|
|
||||||
|
|
||||||
;EquipItem(myWeapon)
|
|
||||||
|
|
||||||
RegisterForHitEvent(self)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)
|
|
||||||
Weapon equippedWeapon = akBaseObject as Weapon
|
|
||||||
If equippedWeapon
|
|
||||||
weaponEquipped = equippedWeapon
|
|
||||||
|
|
||||||
InstanceData:Owner owner = equippedWeapon.GetInstanceOwner()
|
|
||||||
InstanceData.SetAttackDamage(owner, 0)
|
|
||||||
InstanceData.SetDamageTypes(owner, new InstanceData:DamageTypeInfo[0])
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial)
|
|
||||||
If akTarget == self && akAggressor == Game.GetPlayer()
|
|
||||||
Weapon sourceWeapon = akSource as Weapon
|
|
||||||
If sourceWeapon
|
|
||||||
InstanceData:Owner owner = sourceWeapon.GetInstanceOwner()
|
|
||||||
float damage = InstanceData.GetAttackDamage(owner)
|
|
||||||
F4MP.PlayerHit(F4MP.GetPlayerEntityID(), entityID, damage)
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
RegisterForHitEvent(self)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
;Event OnAnimationEvent(ObjectReference akSource, string asEventName)
|
|
||||||
; Debug.Trace(akSource + " " + asEventName)
|
|
||||||
; Debug.Notification(asEventName)
|
|
||||||
|
|
||||||
;If akSource == Game.GetPlayer() && asEventName == "weaponFire"
|
|
||||||
; Debug.Trace(asEventName)
|
|
||||||
;EndIf
|
|
||||||
;EndEvent
|
|
||||||
|
|
||||||
Event OnKeyDown(int keyCode)
|
|
||||||
If keyCode == 113
|
|
||||||
; Debug.Notification(self.PlayIdle(idleAnim))
|
|
||||||
; self.SetValue(avType, 1)
|
|
||||||
; self.PushActorAway(self, 0)
|
|
||||||
|
|
||||||
; TranslateTo(x + 200.0, y, z, 0, 0, 0, 500.0)
|
|
||||||
; PlayIdleAction(F4MP.GetAction("ActionSprintStart"))
|
|
||||||
|
|
||||||
; Debug.Notification(ChangeAnimArchetype(animKeyword))
|
|
||||||
|
|
||||||
|
|
||||||
; Debug.Notification(ChangeAnimArchetype(animKeyword))
|
|
||||||
; Game.GetPlayer().PlayIdleAction(F4MP.GetAction("ActionMoveBackward"))
|
|
||||||
|
|
||||||
|
|
||||||
; playerRef .PlayIdleAction(F4MP.GetAction("ActionSprintStart"))
|
|
||||||
|
|
||||||
|
|
||||||
; TranslateTo(x + 1000.0, y, z, 0.0, 0.0, 0.0, 100.0)
|
|
||||||
|
|
||||||
; ChangeAnimArchetype()
|
|
||||||
; ChangeAnimArchetype(animType)
|
|
||||||
|
|
||||||
; PlayIdle(animJumpUp)
|
|
||||||
|
|
||||||
; ActorBase base = GetActorBase()
|
|
||||||
; F4MP.SetSex(base, base.GetSex() == 0)
|
|
||||||
; Debug.Notification(base.GetSex())
|
|
||||||
|
|
||||||
; SetOutfit(Game.GetPlayer().GetActorBase().GetOutfit())
|
|
||||||
|
|
||||||
; F4MP.CopyAppearance(Game.GetPlayer().GetActorBase(), GetActorBase())
|
|
||||||
; F4MP.CopyWornItems(Game.GetPlayer(), self)
|
|
||||||
|
|
||||||
; StartCombat(Game.GetPlayer())
|
|
||||||
; DrawWeapon()
|
|
||||||
|
|
||||||
; Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
; If equippedWeapon != None
|
|
||||||
; equippedWeapon.Fire(self, myAmmo)
|
|
||||||
; EndIf
|
|
||||||
|
|
||||||
; Game.GetPlayer().GetEquippedWeapon().Fire(Game.GetPlayer(), myAmmo)
|
|
||||||
|
|
||||||
; Form[] args = new Form[0];
|
|
||||||
; args.Add(animIdle)
|
|
||||||
; args.Add(animJogForward)
|
|
||||||
; args.Add(animJogBackward)
|
|
||||||
; args.Add(animJogLeft)
|
|
||||||
; args.Add(animJogRight)
|
|
||||||
; args.Add(animJumpUp)
|
|
||||||
; F4MP.Inspect(args)
|
|
||||||
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = myWeapon
|
|
||||||
; newFirePoint.myAmmo = myAmmo
|
|
||||||
; newFirePoint.SetAngle(GetAngleX(), GetAngleY(), GetAngleZ())
|
|
||||||
|
|
||||||
;Debug.Notification(equippedWeaponRef)
|
|
||||||
;Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
;Ammo equippedWeaponAmmo = equippedWeapon.GetAmmo()
|
|
||||||
;equippedWeapon.Fire(equippedWeaponRef, equippedWeaponAmmo)
|
|
||||||
|
|
||||||
;DrawWeapon()
|
|
||||||
;StartTimer(0.5, animTimerID)
|
|
||||||
|
|
||||||
;PlayIdle(animIdle)
|
|
||||||
;Utility.Wait(0.5)
|
|
||||||
|
|
||||||
;Idle animToPlay = None
|
|
||||||
|
|
||||||
;If stage == 0
|
|
||||||
; animToPlay = animJogForward
|
|
||||||
;ElseIf stage == 1
|
|
||||||
; animToPlay = animFireWeapon
|
|
||||||
;ElseIf stage == 2
|
|
||||||
; animToPlay = animJumpUp
|
|
||||||
;ElseIf stage == 3
|
|
||||||
; animToPlay = animIdle
|
|
||||||
;EndIf
|
|
||||||
;stage = (stage + 1) % 4
|
|
||||||
|
|
||||||
;If animToPlay != animIdle
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; Utility.Wait(0.3)
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
;If !IsWeaponDrawn()
|
|
||||||
; If GetEquippedWeapon() != myWeapon
|
|
||||||
; EquipItem(myWeapon)
|
|
||||||
; Utility.Wait(0.1)
|
|
||||||
; EndIf
|
|
||||||
; DrawWeapon()
|
|
||||||
; Utility.Wait(0.4)
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
;PlayIdle(animToPlay)
|
|
||||||
|
|
||||||
;TranslateTo(x + 10.0, y, z, 0, 0, 0, 0.01)
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnTimer(int aiTimerID)
|
|
||||||
;int k = 0
|
|
||||||
;While k < myProjectiles.length
|
|
||||||
; ObjectReference ref = Game.FindClosestReferenceOfTypeFromRef(myProjectiles[k], Game.GetPlayer(), 100000.0)
|
|
||||||
; If ref != None
|
|
||||||
; float ax = ref.GetAngleX()
|
|
||||||
; float ay = ref.GetAngleY()
|
|
||||||
; float az = ref.GetAngleZ()
|
|
||||||
; If ax != 0.0 && az != 0.0
|
|
||||||
; string msg = k + ": (" + ref.x + ", " + ref.y + ", " + ref.z + "), (" + ax + ", " + ay + ", " + az + ")"
|
|
||||||
; Debug.Trace(msg)
|
|
||||||
; Debug.Notification(msg)
|
|
||||||
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = myWeapon
|
|
||||||
; newFirePoint.myAmmo = myAmmo
|
|
||||||
; newFirePoint.SetAngle(ax, ay, az - GetAngleZ())
|
|
||||||
; EndIf
|
|
||||||
; k = myProjectiles.length
|
|
||||||
; EndIf
|
|
||||||
|
|
||||||
; k += 1
|
|
||||||
;EndWhile
|
|
||||||
|
|
||||||
; PlayIdleAction(F4MP.GetAction("ActionMoveStart"))
|
|
||||||
|
|
||||||
; SetAnimationVariableFloat("Speed", 100.0)
|
|
||||||
|
|
||||||
; Debug.Trace(Game.GetPlayer().GetAnimationVariableFloat("Speed"))
|
|
||||||
|
|
||||||
; Game.GetPlayer().SetAnimationVariableFloat("Speed", 10.0)
|
|
||||||
|
|
||||||
; F4MP.SetTransforms(self)
|
|
||||||
|
|
||||||
If aiTimerID == tickTimerID
|
|
||||||
If itemsToWear != None
|
|
||||||
int i = 0
|
|
||||||
While i < itemsToWear.length
|
|
||||||
EquipItem(itemsToWear[i])
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
itemsToWear = None
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If F4MP.IsEntityValid(entityID)
|
|
||||||
If !initialized
|
|
||||||
initialized = true
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;float[] position = F4MP.GetEntityPosition(entityID)
|
|
||||||
;float angleZ = F4MP.GetEntVarNum(entityID, "angleZ")
|
|
||||||
;float distance = Math.Sqrt(Math.Pow(position[0] - x, 2) + Math.Pow(position[1] - y, 2) + Math.Pow(position[2] - z, 2))
|
|
||||||
|
|
||||||
;health = F4MP.GetEntVarNum(entityID, "health")
|
|
||||||
|
|
||||||
;TranslateTo(position[0], position[1], position[2], 0.0, 0.0, angleZ, distance * 3.0, 500.0)
|
|
||||||
;self.SetPosition(position[0], position[1], position[2])
|
|
||||||
;self.SetAngle(0.0, 0.0, angleZ)
|
|
||||||
|
|
||||||
; Debug.Notification(entityID + " " + position[0] + " " + position[1] + " " + position[2])
|
|
||||||
Else
|
|
||||||
If initialized
|
|
||||||
;Debug.Trace("entity with ID " + entityID + " is supposed to be deleted but I saved it for ya! ;)")
|
|
||||||
Delete()
|
|
||||||
EndIf
|
|
||||||
; Debug.Notification(entityID + "!")
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
ElseIf aiTimerID == animTimerID
|
|
||||||
string newAnimState = F4MP.GetEntVarAnim(entityID)
|
|
||||||
If newAnimState != animState
|
|
||||||
string oldAnimState = animState
|
|
||||||
animState = newAnimState
|
|
||||||
|
|
||||||
If !IsWeaponDrawn()
|
|
||||||
DrawWeapon()
|
|
||||||
Utility.Wait(0.4)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If F4MP.AnimLoops(oldAnimState)
|
|
||||||
PlayIdle(animNull)
|
|
||||||
Utility.Wait(0.2)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
PlayAnimByState(newAnimState)
|
|
||||||
EndIf
|
|
||||||
StartTimer(0, animTimerID)
|
|
||||||
Elseif aiTimerID == tidyTimerID
|
|
||||||
StartTimer(0, tidyTimerID)
|
|
||||||
|
|
||||||
If GetEquippedWeapon() != weaponEquipped
|
|
||||||
EquipItem(weaponEquipped)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If !IsWeaponDrawn()
|
|
||||||
animState = "INIT"
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;string[] animStates = new string[0]
|
|
||||||
;animStates.Add("None")
|
|
||||||
;animStates.Add("JogForward")
|
|
||||||
;animStates.Add("JogBackward")
|
|
||||||
;animStates.Add("JogLeft")
|
|
||||||
;animStates.Add("JogRight")
|
|
||||||
;animStates.Add("JumpUp")
|
|
||||||
;animStates.Add("WeaponFire")
|
|
||||||
;
|
|
||||||
;string newAnimState = animStates[Utility.RandomInt(0, animStates.length - 1)];nextAnimState;
|
|
||||||
;If newAnimState != animState
|
|
||||||
; If GetEquippedWeapon() != weaponEquipped
|
|
||||||
; EquipItem(weaponEquipped)
|
|
||||||
; EndIf
|
|
||||||
;
|
|
||||||
; If IsWeaponDrawn()
|
|
||||||
; ;If newAnimState == "None"
|
|
||||||
; ; PlayAnimByState(newAnimState)
|
|
||||||
; ;Else
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; ;StartTimer(0.3, animTimerID)
|
|
||||||
; Utility.Wait(0.3)
|
|
||||||
; PlayAnimByState(newAnimState)
|
|
||||||
; ;EndIf
|
|
||||||
; Else
|
|
||||||
; DrawWeapon()
|
|
||||||
;
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; ;StartTimer(0.4, animTimerID)
|
|
||||||
; Utility.Wait(0.4)
|
|
||||||
; PlayAnimByState(newAnimState)
|
|
||||||
; EndIf
|
|
||||||
; animState = newAnimState
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
SetValuePercentage(HealthAV, health)
|
|
||||||
|
|
||||||
If IsInCombat()
|
|
||||||
StopCombat()
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Function FireWeapon()
|
|
||||||
Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
If equippedWeapon
|
|
||||||
F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
newFirePoint.myWeapon = equippedWeapon
|
|
||||||
newFirePoint.myAmmo = equippedWeapon.GetAmmo()
|
|
||||||
newFirePoint.myOwner = self
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function PlayAnimByState(string newAnimState)
|
|
||||||
Idle animToPlay = GetAnimByState(newAnimState)
|
|
||||||
If animToPlay
|
|
||||||
PlayIdle(animToPlay)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;If newAnimState == "FireWeapon"
|
|
||||||
; Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
; If equippedWeapon
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = equippedWeapon
|
|
||||||
; newFirePoint.myAmmo = equippedWeapon.GetAmmo()
|
|
||||||
; newFirePoint.myOwner = self
|
|
||||||
; EndIf
|
|
||||||
; animState = "INIT"
|
|
||||||
;EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Idle Function GetAnimByState(string newAnimState)
|
|
||||||
Idle animToPlay = animIdle
|
|
||||||
|
|
||||||
If newAnimState == "None"
|
|
||||||
animToPlay = animIdle
|
|
||||||
ElseIf newAnimState == "JogForward"
|
|
||||||
animToPlay = animJogForward
|
|
||||||
ElseIf newAnimState == "JogBackward"
|
|
||||||
animToPlay = animJogBackward
|
|
||||||
ElseIf newAnimState == "JogLeft"
|
|
||||||
animToPlay = animJogLeft
|
|
||||||
ElseIf newAnimState == "JogRight"
|
|
||||||
animToPlay = animJogRight
|
|
||||||
ElseIf newAnimState == "JumpUp"
|
|
||||||
; animToPlay = animJumpUp
|
|
||||||
ElseIf newAnimState == "JumpFall"
|
|
||||||
; animToPlay = animJumpFall
|
|
||||||
ElseIf newAnimState == "JumpLand"
|
|
||||||
; animToPlay = animJumpLand
|
|
||||||
ElseIf newAnimState == "FireWeapon"
|
|
||||||
animToPlay = animFireWeapon
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
return animToPlay
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function SetValueActually(ActorValue type, float value)
|
|
||||||
float diff = value - GetValue(type)
|
|
||||||
If diff < 0
|
|
||||||
DamageValue(type, -diff)
|
|
||||||
Else
|
|
||||||
RestoreValue(type, diff)
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function SetValuePercentage(ActorValue type, float percentage)
|
|
||||||
SetValueActually(type, percentage * GetBaseValue(type))
|
|
||||||
EndFunction
|
|
||||||
|
|
@ -1,214 +0,0 @@
|
||||||
Scriptname F4MPQuest extends Quest
|
|
||||||
|
|
||||||
int tickTimerID = 10
|
|
||||||
int updateTimerID = 20
|
|
||||||
|
|
||||||
Actor Property playerRef Auto
|
|
||||||
|
|
||||||
ActorBase Property f4mpPlayerBase Auto
|
|
||||||
|
|
||||||
ActorValue Property healthAV Auto
|
|
||||||
|
|
||||||
Spell Property entitySyncSpell Auto
|
|
||||||
|
|
||||||
VoiceType Property malePlayerVoiceType Auto
|
|
||||||
VoiceType Property femalePlayerVoiceType Auto
|
|
||||||
|
|
||||||
int[] playerIDs
|
|
||||||
F4MPPlayer[] players
|
|
||||||
|
|
||||||
bool topicInfosRegistered = false
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
RegisterForKey(112)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Function OnEntityCreate(int entityID, Form[] itemsToWear)
|
|
||||||
Debug.Notification(entityID + " has entered the world.")
|
|
||||||
|
|
||||||
If entityID != F4MP.GetPlayerEntityID()
|
|
||||||
Actor player = Game.GetPlayer()
|
|
||||||
F4MPPlayer entity = player.PlaceActorAtMe(f4mpPlayerBase) as F4MPPlayer
|
|
||||||
F4MP.SetEntityRef(entityID, entity)
|
|
||||||
entity.entityID = entityID
|
|
||||||
|
|
||||||
If f4mpPlayerBase.GetSex() == 0
|
|
||||||
entity.SetOverrideVoiceType(malePlayerVoiceType)
|
|
||||||
Else
|
|
||||||
entity.SetOverrideVoiceType(femalePlayerVoiceType)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
entity.itemsToWear = itemsToWear
|
|
||||||
; SetWornItems(entity, itemsToWear)
|
|
||||||
|
|
||||||
playerIDs.Add(entityID)
|
|
||||||
players.Add(entity)
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnEntityRemove(int entityID)
|
|
||||||
int index = playerIDs.Find(entityID)
|
|
||||||
If index < 0
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
players[index].Delete()
|
|
||||||
playerIDs.Remove(index)
|
|
||||||
players.Remove(index)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnPlayerHit(float damage)
|
|
||||||
Game.GetPlayer().DamageValue(healthAV, damage)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function RegisterTopicInfos(Form[] targets)
|
|
||||||
int i = 0
|
|
||||||
While i < targets.length
|
|
||||||
RegisterForRemoteEvent(targets[i] as TopicInfo, "OnBegin")
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnTopicInfoRegister(Form[] targets)
|
|
||||||
If topicInfosRegistered
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
topicInfosRegistered = true
|
|
||||||
|
|
||||||
RegisterTopicInfos(targets)
|
|
||||||
|
|
||||||
Debug.Trace(targets.length + " topic infos have registered.")
|
|
||||||
Debug.Notification(targets.length + " topic infos have registered.")
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Event TopicInfo.OnBegin(TopicInfo akSender, ObjectReference akSpeakerRef, bool abHasBeenSaid)
|
|
||||||
;Debug.Trace("Topic info " + akSender + " is being said by " + akSpeakerRef.GetDisplayName())
|
|
||||||
;Debug.Notification("Topic info " + akSender + " is being said by " + akSpeakerRef)
|
|
||||||
F4MP.TopicInfoBegin(akSender, akSpeakerRef)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
;Function OnFireWeapon(int entityID)
|
|
||||||
; int index = playerIDs.Find(entityID)
|
|
||||||
; If index < 0
|
|
||||||
; return
|
|
||||||
; EndIf
|
|
||||||
;
|
|
||||||
; players[index].FireWeapon()
|
|
||||||
;EndFunction
|
|
||||||
|
|
||||||
;Function OnSpawnEntity(int formID)
|
|
||||||
; ObjectReference ref = Game.GetForm(formID) as ObjectReference
|
|
||||||
; If ref == None
|
|
||||||
; return
|
|
||||||
; EndIf
|
|
||||||
;
|
|
||||||
; Actor actorRef = ref as Actor
|
|
||||||
; If actorRef != None
|
|
||||||
; actorRef.AddSpell(entitySyncSpell)
|
|
||||||
; EndIf
|
|
||||||
;EndFunction
|
|
||||||
|
|
||||||
Function SetWornItems(Actor dest, Form[] wornItems)
|
|
||||||
int i = 0
|
|
||||||
While i < wornItems.length
|
|
||||||
Debug.Trace(i + ": " + wornItems[i])
|
|
||||||
dest.EquipItem(wornItems[i])
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
; TODO: mutiple timers
|
|
||||||
bool Function Connect(string address, int port)
|
|
||||||
Actor client = Game.GetPlayer()
|
|
||||||
ActorBase clientActorBase = client.GetActorBase()
|
|
||||||
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
StartTimer(0, updateTimerID)
|
|
||||||
|
|
||||||
return F4MP.Connect(client, clientActorBase, address, port)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Sound Property mySound Auto
|
|
||||||
Topic Property myTopic Auto
|
|
||||||
|
|
||||||
Event OnKeyDown(int keyCode)
|
|
||||||
If keyCode == 112
|
|
||||||
RegisterForExternalEvent("OnTopicInfoRegister", "OnTopicInfoRegister")
|
|
||||||
RegisterForExternalEvent("OnAdditionalTopicInfoRegister", "RegisterTopicInfos")
|
|
||||||
|
|
||||||
Connect("", 7779)
|
|
||||||
|
|
||||||
playerIDs = new int[0]
|
|
||||||
players = new F4MPPlayer[0]
|
|
||||||
|
|
||||||
;Actor player = Game.GetPlayer()
|
|
||||||
;F4MPPlayer entity = player.PlaceActorAtMe(f4mpPlayerBase) as F4MPPlayer
|
|
||||||
|
|
||||||
Actor client = Game.GetPlayer()
|
|
||||||
RegisterForAnimationEvent(client, "JumpUp")
|
|
||||||
RegisterForAnimationEvent(client, "weaponFire")
|
|
||||||
; RegisterForAnimationEvent(client, "JumpFall")
|
|
||||||
; RegisterForAnimationEvent(client, "JumpDown")
|
|
||||||
|
|
||||||
; RegisterForExternalEvent("OnCopyWornItems", "OnCopyWornItems")
|
|
||||||
|
|
||||||
RegisterForExternalEvent("OnEntityCreate", "OnEntityCreate")
|
|
||||||
RegisterForExternalEvent("OnEntityRemove", "OnEntityRemove")
|
|
||||||
|
|
||||||
RegisterForExternalEvent("OnPlayerHit", "OnPlayerHit")
|
|
||||||
|
|
||||||
RegisterForKey(113)
|
|
||||||
RegisterForKey(114)
|
|
||||||
ElseIf keyCode == 113
|
|
||||||
F4MP.SetClient(1 - F4MP.GetClientInstanceID())
|
|
||||||
ElseIf keyCode == 114
|
|
||||||
mySound.Play(Game.GetPlayer())
|
|
||||||
;Debug.Notification(myTopic)
|
|
||||||
;Game.GetPlayer().Say(myTopic)
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Form Property targetForm Auto
|
|
||||||
Actor Property chosenActor Auto
|
|
||||||
ObjectReference Property targetRef Auto
|
|
||||||
|
|
||||||
Event OnAnimationEvent(ObjectReference akSource, string asEventName)
|
|
||||||
If !F4MP.IsConnected()
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
int playerEntityID = F4MP.GetPlayerEntityID()
|
|
||||||
If F4MP.IsEntityValid(playerEntityID)
|
|
||||||
If asEventName == "JumpUp"
|
|
||||||
F4MP.SetEntVarAnim(playerEntityID, "JumpUp")
|
|
||||||
; ElseIf asEventName == "JumpFall"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "JumpFall")
|
|
||||||
; ElseIf asEventName == "JumpDown"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "JumpLand")
|
|
||||||
ElseIf asEventName == "weaponFire"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "FireWeapon")
|
|
||||||
F4MP.PlayerFireWeapon()
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnTimer(int aiTimerID)
|
|
||||||
If aiTimerID == tickTimerID
|
|
||||||
F4MP.Tick()
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
ElseIf aiTimerID == updateTimerID
|
|
||||||
;; ***************************************
|
|
||||||
;If chosenActor != None
|
|
||||||
; chosenActor.PathToReference(targetRef, 1.0)
|
|
||||||
;EndIf
|
|
||||||
;
|
|
||||||
;; ***************************************
|
|
||||||
|
|
||||||
int playerEntityID = F4MP.GetPlayerEntityID()
|
|
||||||
If F4MP.IsEntityValid(playerEntityID)
|
|
||||||
F4MP.SetEntVarNum(playerEntityID, "health", playerRef.GetValuePercentage(healthAV))
|
|
||||||
EndIf
|
|
||||||
StartTimer(0, updateTimerID)
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
Scriptname F4MP Native Hidden
|
|
||||||
|
|
||||||
int Function GetClientInstanceID() global native
|
|
||||||
Function SetClient(int instanceID) global native
|
|
||||||
|
|
||||||
bool Function IsConnected() global native
|
|
||||||
bool Function Connect(Actor player, ActorBase playerActorBase, string address, int port) global native
|
|
||||||
bool Function Disconnect() global native
|
|
||||||
Function Tick() global native
|
|
||||||
|
|
||||||
int Function GetPlayerEntityID() global native
|
|
||||||
int Function GetEntityID(ObjectReference ref) global native
|
|
||||||
|
|
||||||
bool Function IsEntityValid(int entityID) global native
|
|
||||||
|
|
||||||
float[] Function GetEntityPosition(int entityID) global native
|
|
||||||
Function SetEntityPosition(int entityID, float x, float y, float z) global native
|
|
||||||
Function SetEntVarNum(int entityID, string name, float value) global native
|
|
||||||
Function SetEntVarAnim(int entityID, string animState) global native
|
|
||||||
float Function GetEntVarNum(int entityID, string name) global native
|
|
||||||
string Function GetEntVarAnim(int entityID) global native
|
|
||||||
|
|
||||||
float Function Atan2(float y, float x) global native
|
|
||||||
string Function GetWalkDir(float dX, float dY, float angleZ) global native
|
|
||||||
Action Function GetAction(string name) global native
|
|
||||||
Function Inspect(Form[] forms) global native
|
|
||||||
bool Function AnimLoops(string animState) global native
|
|
||||||
|
|
||||||
Function CopyAppearance(ActorBase src, ActorBase dest) global native
|
|
||||||
Function CopyWornItems(Actor src, Actor dest) global native
|
|
||||||
|
|
||||||
Function PlayerHit(int hitter, int hittee, float damage) global native
|
|
||||||
Function PlayerFireWeapon() global native
|
|
||||||
Function SpawnEntity(ObjectReference ref, float x, float y, float z, float angleX, float angleY, float angleZ) global native
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
Scriptname F4MPFirePoint extends ObjectReference
|
|
||||||
|
|
||||||
Weapon Property myWeapon = None Auto
|
|
||||||
Ammo Property myAmmo = None Auto
|
|
||||||
|
|
||||||
F4MPPlayer Property myOwner = None Auto
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
; SetPosition(x + 100.0, y + 100.0, z + 100.0)
|
|
||||||
SetScale(0.0)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnLoad()
|
|
||||||
SetMotionType(Motion_Keyframed)
|
|
||||||
|
|
||||||
float[] position = F4MP.GetEntityPosition(myOwner.entityID)
|
|
||||||
float angleZ = GetAngleZ()
|
|
||||||
SetPosition(position[0] + Math.Sin(angleZ) * 100.0 + Math.Cos(angleZ) * 10.0, position[1] + Math.Cos(angleZ) * 100.0 - Math.Sin(angleZ) * 10.0, position[2] + 90.0)
|
|
||||||
|
|
||||||
float ax = F4MP.GetEntVarNum(myOwner.entityID, "angleX")
|
|
||||||
float ay = F4MP.GetEntVarNum(myOwner.entityID, "angleY")
|
|
||||||
float az = F4MP.GetEntVarNum(myOwner.entityID, "angleZ")
|
|
||||||
SetAngle(ax, ay, az)
|
|
||||||
|
|
||||||
; Actor player = Game.GetPlayer()
|
|
||||||
; float dx = player.x - x
|
|
||||||
; float dy = player.y - y
|
|
||||||
; SetAngle(0.0, 0.0, Math.RadiansToDegrees(F4MP.Atan2(dx, dy)))
|
|
||||||
|
|
||||||
InstanceData:Owner owner = myWeapon.GetInstanceOwner()
|
|
||||||
InstanceData.SetAttackDamage(owner, 0)
|
|
||||||
InstanceData.SetDamageTypes(owner, new InstanceData:DamageTypeInfo[0])
|
|
||||||
|
|
||||||
myWeapon.Fire(self, myAmmo)
|
|
||||||
Delete()
|
|
||||||
EndEvent
|
|
||||||
|
|
@ -1,415 +0,0 @@
|
||||||
Scriptname F4MPPlayer extends Actor
|
|
||||||
|
|
||||||
int Property entityID = -1 Auto
|
|
||||||
|
|
||||||
Idle Property animNull Auto
|
|
||||||
Idle Property animIdle Auto
|
|
||||||
Idle Property animJogForward Auto
|
|
||||||
Idle Property animJogBackward Auto
|
|
||||||
Idle Property animJogLeft Auto
|
|
||||||
Idle Property animJogRight Auto
|
|
||||||
Idle Property animJumpUp Auto
|
|
||||||
Idle Property animJumpFall Auto
|
|
||||||
Idle Property animJumpLand Auto
|
|
||||||
Idle Property animFireWeapon Auto
|
|
||||||
|
|
||||||
Idle Property animTest Auto
|
|
||||||
|
|
||||||
Action Property actionAnim Auto
|
|
||||||
|
|
||||||
ActorValue Property avType Auto
|
|
||||||
|
|
||||||
Keyword Property animKeyword Auto
|
|
||||||
Keyword Property animType Auto
|
|
||||||
|
|
||||||
Actor Property playerRef Auto
|
|
||||||
|
|
||||||
ActorValue Property HealthAV Auto
|
|
||||||
|
|
||||||
int tickTimerID = 10
|
|
||||||
int animTimerID = 20
|
|
||||||
int tidyTimerID = 30
|
|
||||||
|
|
||||||
string animState = "INIT"
|
|
||||||
|
|
||||||
Form[] Property itemsToWear = None Auto
|
|
||||||
|
|
||||||
Weapon Property myWeapon Auto
|
|
||||||
Ammo Property myAmmo Auto
|
|
||||||
Form Property firePoint Auto
|
|
||||||
Projectile[] Property myProjectiles Auto
|
|
||||||
|
|
||||||
float Property health = 1.0 Auto
|
|
||||||
|
|
||||||
bool Property initialized = false Auto
|
|
||||||
|
|
||||||
Weapon Property weaponEquipped = None Auto
|
|
||||||
|
|
||||||
int stage = 0
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
StartTimer(0, animTimerID)
|
|
||||||
StartTimer(0, tidyTimerID)
|
|
||||||
|
|
||||||
RegisterForKey(113)
|
|
||||||
|
|
||||||
; self.EnableAI(false, true)
|
|
||||||
|
|
||||||
;EquipItem(myWeapon)
|
|
||||||
|
|
||||||
RegisterForHitEvent(self)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)
|
|
||||||
Weapon equippedWeapon = akBaseObject as Weapon
|
|
||||||
If equippedWeapon
|
|
||||||
weaponEquipped = equippedWeapon
|
|
||||||
|
|
||||||
InstanceData:Owner owner = equippedWeapon.GetInstanceOwner()
|
|
||||||
InstanceData.SetAttackDamage(owner, 0)
|
|
||||||
InstanceData.SetDamageTypes(owner, new InstanceData:DamageTypeInfo[0])
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnHit(ObjectReference akTarget, ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked, string apMaterial)
|
|
||||||
If akTarget == self && akAggressor == Game.GetPlayer()
|
|
||||||
Weapon sourceWeapon = akSource as Weapon
|
|
||||||
If sourceWeapon
|
|
||||||
InstanceData:Owner owner = sourceWeapon.GetInstanceOwner()
|
|
||||||
float damage = InstanceData.GetAttackDamage(owner)
|
|
||||||
F4MP.PlayerHit(F4MP.GetPlayerEntityID(), entityID, damage)
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
RegisterForHitEvent(self)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
;Event OnAnimationEvent(ObjectReference akSource, string asEventName)
|
|
||||||
; Debug.Trace(akSource + " " + asEventName)
|
|
||||||
; Debug.Notification(asEventName)
|
|
||||||
|
|
||||||
;If akSource == Game.GetPlayer() && asEventName == "weaponFire"
|
|
||||||
; Debug.Trace(asEventName)
|
|
||||||
;EndIf
|
|
||||||
;EndEvent
|
|
||||||
|
|
||||||
Event OnKeyDown(int keyCode)
|
|
||||||
If keyCode == 113
|
|
||||||
; Debug.Notification(self.PlayIdle(idleAnim))
|
|
||||||
; self.SetValue(avType, 1)
|
|
||||||
; self.PushActorAway(self, 0)
|
|
||||||
|
|
||||||
; TranslateTo(x + 200.0, y, z, 0, 0, 0, 500.0)
|
|
||||||
; PlayIdleAction(F4MP.GetAction("ActionSprintStart"))
|
|
||||||
|
|
||||||
; Debug.Notification(ChangeAnimArchetype(animKeyword))
|
|
||||||
|
|
||||||
|
|
||||||
; Debug.Notification(ChangeAnimArchetype(animKeyword))
|
|
||||||
; Game.GetPlayer().PlayIdleAction(F4MP.GetAction("ActionMoveBackward"))
|
|
||||||
|
|
||||||
|
|
||||||
; playerRef .PlayIdleAction(F4MP.GetAction("ActionSprintStart"))
|
|
||||||
|
|
||||||
|
|
||||||
; TranslateTo(x + 1000.0, y, z, 0.0, 0.0, 0.0, 100.0)
|
|
||||||
|
|
||||||
; ChangeAnimArchetype()
|
|
||||||
; ChangeAnimArchetype(animType)
|
|
||||||
|
|
||||||
; PlayIdle(animJumpUp)
|
|
||||||
|
|
||||||
; ActorBase base = GetActorBase()
|
|
||||||
; F4MP.SetSex(base, base.GetSex() == 0)
|
|
||||||
; Debug.Notification(base.GetSex())
|
|
||||||
|
|
||||||
; SetOutfit(Game.GetPlayer().GetActorBase().GetOutfit())
|
|
||||||
|
|
||||||
; F4MP.CopyAppearance(Game.GetPlayer().GetActorBase(), GetActorBase())
|
|
||||||
; F4MP.CopyWornItems(Game.GetPlayer(), self)
|
|
||||||
|
|
||||||
; StartCombat(Game.GetPlayer())
|
|
||||||
; DrawWeapon()
|
|
||||||
|
|
||||||
; Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
; If equippedWeapon != None
|
|
||||||
; equippedWeapon.Fire(self, myAmmo)
|
|
||||||
; EndIf
|
|
||||||
|
|
||||||
; Game.GetPlayer().GetEquippedWeapon().Fire(Game.GetPlayer(), myAmmo)
|
|
||||||
|
|
||||||
; Form[] args = new Form[0];
|
|
||||||
; args.Add(animIdle)
|
|
||||||
; args.Add(animJogForward)
|
|
||||||
; args.Add(animJogBackward)
|
|
||||||
; args.Add(animJogLeft)
|
|
||||||
; args.Add(animJogRight)
|
|
||||||
; args.Add(animJumpUp)
|
|
||||||
; F4MP.Inspect(args)
|
|
||||||
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = myWeapon
|
|
||||||
; newFirePoint.myAmmo = myAmmo
|
|
||||||
; newFirePoint.SetAngle(GetAngleX(), GetAngleY(), GetAngleZ())
|
|
||||||
|
|
||||||
;Debug.Notification(equippedWeaponRef)
|
|
||||||
;Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
;Ammo equippedWeaponAmmo = equippedWeapon.GetAmmo()
|
|
||||||
;equippedWeapon.Fire(equippedWeaponRef, equippedWeaponAmmo)
|
|
||||||
|
|
||||||
;DrawWeapon()
|
|
||||||
;StartTimer(0.5, animTimerID)
|
|
||||||
|
|
||||||
;PlayIdle(animIdle)
|
|
||||||
;Utility.Wait(0.5)
|
|
||||||
|
|
||||||
;Idle animToPlay = None
|
|
||||||
|
|
||||||
;If stage == 0
|
|
||||||
; animToPlay = animJogForward
|
|
||||||
;ElseIf stage == 1
|
|
||||||
; animToPlay = animFireWeapon
|
|
||||||
;ElseIf stage == 2
|
|
||||||
; animToPlay = animJumpUp
|
|
||||||
;ElseIf stage == 3
|
|
||||||
; animToPlay = animIdle
|
|
||||||
;EndIf
|
|
||||||
;stage = (stage + 1) % 4
|
|
||||||
|
|
||||||
;If animToPlay != animIdle
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; Utility.Wait(0.3)
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
;If !IsWeaponDrawn()
|
|
||||||
; If GetEquippedWeapon() != myWeapon
|
|
||||||
; EquipItem(myWeapon)
|
|
||||||
; Utility.Wait(0.1)
|
|
||||||
; EndIf
|
|
||||||
; DrawWeapon()
|
|
||||||
; Utility.Wait(0.4)
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
;PlayIdle(animToPlay)
|
|
||||||
|
|
||||||
;TranslateTo(x + 10.0, y, z, 0, 0, 0, 0.01)
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnTimer(int aiTimerID)
|
|
||||||
;int k = 0
|
|
||||||
;While k < myProjectiles.length
|
|
||||||
; ObjectReference ref = Game.FindClosestReferenceOfTypeFromRef(myProjectiles[k], Game.GetPlayer(), 100000.0)
|
|
||||||
; If ref != None
|
|
||||||
; float ax = ref.GetAngleX()
|
|
||||||
; float ay = ref.GetAngleY()
|
|
||||||
; float az = ref.GetAngleZ()
|
|
||||||
; If ax != 0.0 && az != 0.0
|
|
||||||
; string msg = k + ": (" + ref.x + ", " + ref.y + ", " + ref.z + "), (" + ax + ", " + ay + ", " + az + ")"
|
|
||||||
; Debug.Trace(msg)
|
|
||||||
; Debug.Notification(msg)
|
|
||||||
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = myWeapon
|
|
||||||
; newFirePoint.myAmmo = myAmmo
|
|
||||||
; newFirePoint.SetAngle(ax, ay, az - GetAngleZ())
|
|
||||||
; EndIf
|
|
||||||
; k = myProjectiles.length
|
|
||||||
; EndIf
|
|
||||||
|
|
||||||
; k += 1
|
|
||||||
;EndWhile
|
|
||||||
|
|
||||||
; PlayIdleAction(F4MP.GetAction("ActionMoveStart"))
|
|
||||||
|
|
||||||
; SetAnimationVariableFloat("Speed", 100.0)
|
|
||||||
|
|
||||||
; Debug.Trace(Game.GetPlayer().GetAnimationVariableFloat("Speed"))
|
|
||||||
|
|
||||||
; Game.GetPlayer().SetAnimationVariableFloat("Speed", 10.0)
|
|
||||||
|
|
||||||
; F4MP.SetTransforms(self)
|
|
||||||
|
|
||||||
If aiTimerID == tickTimerID
|
|
||||||
If itemsToWear != None
|
|
||||||
int i = 0
|
|
||||||
While i < itemsToWear.length
|
|
||||||
Debug.Trace(itemsToWear[i].GetName())
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
While i < itemsToWear.length
|
|
||||||
EquipItem(itemsToWear[i])
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
itemsToWear = None
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If F4MP.IsEntityValid(entityID)
|
|
||||||
If !initialized
|
|
||||||
initialized = true
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
float[] position = F4MP.GetEntityPosition(entityID)
|
|
||||||
float angleX = F4MP.GetEntVarNum(entityID, "angleX")
|
|
||||||
float angleY = F4MP.GetEntVarNum(entityID, "angleY")
|
|
||||||
float angleZ = F4MP.GetEntVarNum(entityID, "angleZ")
|
|
||||||
float distance = Math.Sqrt(Math.Pow(position[0] - x, 2) + Math.Pow(position[1] - y, 2) + Math.Pow(position[2] - z, 2))
|
|
||||||
|
|
||||||
;health = F4MP.GetEntVarNum(entityID, "health")
|
|
||||||
|
|
||||||
TranslateTo(position[0], position[1], position[2], 0.0, 0.0, angleZ, distance * 3.0, 200.0)
|
|
||||||
;self.SetPosition(position[0], position[1], position[2])
|
|
||||||
;self.SetAngle(0.0, 0.0, angleZ)
|
|
||||||
|
|
||||||
; Debug.Notification(entityID + " " + position[0] + " " + position[1] + " " + position[2])
|
|
||||||
Else
|
|
||||||
If initialized
|
|
||||||
;Debug.Trace("entity with ID " + entityID + " is supposed to be deleted but I saved it for ya! ;)")
|
|
||||||
Delete()
|
|
||||||
EndIf
|
|
||||||
; Debug.Notification(entityID + "!")
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
ElseIf aiTimerID == animTimerID
|
|
||||||
string newAnimState = F4MP.GetEntVarAnim(entityID)
|
|
||||||
If newAnimState != animState
|
|
||||||
string oldAnimState = animState
|
|
||||||
animState = newAnimState
|
|
||||||
|
|
||||||
If !IsWeaponDrawn()
|
|
||||||
DrawWeapon()
|
|
||||||
Utility.Wait(0.4)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If F4MP.AnimLoops(oldAnimState)
|
|
||||||
PlayIdle(animNull)
|
|
||||||
Utility.Wait(0.2)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
PlayAnimByState(newAnimState)
|
|
||||||
EndIf
|
|
||||||
StartTimer(0, animTimerID)
|
|
||||||
Elseif aiTimerID == tidyTimerID
|
|
||||||
StartTimer(0, tidyTimerID)
|
|
||||||
|
|
||||||
If GetEquippedWeapon() != weaponEquipped
|
|
||||||
EquipItem(weaponEquipped)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If !IsWeaponDrawn()
|
|
||||||
animState = "INIT"
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;string[] animStates = new string[0]
|
|
||||||
;animStates.Add("None")
|
|
||||||
;animStates.Add("JogForward")
|
|
||||||
;animStates.Add("JogBackward")
|
|
||||||
;animStates.Add("JogLeft")
|
|
||||||
;animStates.Add("JogRight")
|
|
||||||
;animStates.Add("JumpUp")
|
|
||||||
;animStates.Add("WeaponFire")
|
|
||||||
;
|
|
||||||
;string newAnimState = animStates[Utility.RandomInt(0, animStates.length - 1)];nextAnimState;
|
|
||||||
;If newAnimState != animState
|
|
||||||
; If GetEquippedWeapon() != weaponEquipped
|
|
||||||
; EquipItem(weaponEquipped)
|
|
||||||
; EndIf
|
|
||||||
;
|
|
||||||
; If IsWeaponDrawn()
|
|
||||||
; ;If newAnimState == "None"
|
|
||||||
; ; PlayAnimByState(newAnimState)
|
|
||||||
; ;Else
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; ;StartTimer(0.3, animTimerID)
|
|
||||||
; Utility.Wait(0.3)
|
|
||||||
; PlayAnimByState(newAnimState)
|
|
||||||
; ;EndIf
|
|
||||||
; Else
|
|
||||||
; DrawWeapon()
|
|
||||||
;
|
|
||||||
; PlayIdle(animNull)
|
|
||||||
; ;StartTimer(0.4, animTimerID)
|
|
||||||
; Utility.Wait(0.4)
|
|
||||||
; PlayAnimByState(newAnimState)
|
|
||||||
; EndIf
|
|
||||||
; animState = newAnimState
|
|
||||||
;EndIf
|
|
||||||
|
|
||||||
SetValuePercentage(HealthAV, health)
|
|
||||||
|
|
||||||
If IsInCombat()
|
|
||||||
StopCombat()
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Function FireWeapon()
|
|
||||||
Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
If equippedWeapon
|
|
||||||
F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
newFirePoint.myWeapon = equippedWeapon
|
|
||||||
newFirePoint.myAmmo = equippedWeapon.GetAmmo()
|
|
||||||
newFirePoint.myOwner = self
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function PlayAnimByState(string newAnimState)
|
|
||||||
Idle animToPlay = GetAnimByState(newAnimState)
|
|
||||||
If animToPlay
|
|
||||||
PlayIdle(animToPlay)
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;If newAnimState == "FireWeapon"
|
|
||||||
; Weapon equippedWeapon = GetEquippedWeapon()
|
|
||||||
; If equippedWeapon
|
|
||||||
; F4MPFirePoint newFirePoint = PlaceAtMe(firePoint) as F4MPFirePoint
|
|
||||||
; newFirePoint.myWeapon = equippedWeapon
|
|
||||||
; newFirePoint.myAmmo = equippedWeapon.GetAmmo()
|
|
||||||
; newFirePoint.myOwner = self
|
|
||||||
; EndIf
|
|
||||||
; animState = "INIT"
|
|
||||||
;EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Idle Function GetAnimByState(string newAnimState)
|
|
||||||
Idle animToPlay = animIdle
|
|
||||||
|
|
||||||
If newAnimState == "None"
|
|
||||||
animToPlay = animIdle
|
|
||||||
ElseIf newAnimState == "JogForward"
|
|
||||||
animToPlay = animJogForward
|
|
||||||
ElseIf newAnimState == "JogBackward"
|
|
||||||
animToPlay = animJogBackward
|
|
||||||
ElseIf newAnimState == "JogLeft"
|
|
||||||
animToPlay = animJogLeft
|
|
||||||
ElseIf newAnimState == "JogRight"
|
|
||||||
animToPlay = animJogRight
|
|
||||||
ElseIf newAnimState == "JumpUp"
|
|
||||||
; animToPlay = animJumpUp
|
|
||||||
ElseIf newAnimState == "JumpFall"
|
|
||||||
; animToPlay = animJumpFall
|
|
||||||
ElseIf newAnimState == "JumpLand"
|
|
||||||
; animToPlay = animJumpLand
|
|
||||||
ElseIf newAnimState == "FireWeapon"
|
|
||||||
animToPlay = animFireWeapon
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
return animToPlay
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function SetValueActually(ActorValue type, float value)
|
|
||||||
float diff = value - GetValue(type)
|
|
||||||
If diff < 0
|
|
||||||
DamageValue(type, -diff)
|
|
||||||
Else
|
|
||||||
RestoreValue(type, diff)
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function SetValuePercentage(ActorValue type, float percentage)
|
|
||||||
SetValueActually(type, percentage * GetBaseValue(type))
|
|
||||||
EndFunction
|
|
||||||
|
|
@ -1,248 +0,0 @@
|
||||||
Scriptname F4MPQuest extends Quest
|
|
||||||
|
|
||||||
int tickTimerID = 10
|
|
||||||
int queryTimerID = 20
|
|
||||||
|
|
||||||
ActorBase Property f4mpPlayerBase Auto
|
|
||||||
|
|
||||||
ActorValue Property healthAV Auto
|
|
||||||
|
|
||||||
int[] playerIDs
|
|
||||||
F4MPPlayer[] players
|
|
||||||
|
|
||||||
Actor[] myNPCs
|
|
||||||
Actor[] othersNPCs
|
|
||||||
|
|
||||||
Event OnInit()
|
|
||||||
RegisterForKey(112)
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Function OnEntityCreate(int entityID, Form[] itemsToWear)
|
|
||||||
Debug.Notification(entityID + " has entered the world.")
|
|
||||||
|
|
||||||
If entityID != F4MP.GetPlayerEntityID()
|
|
||||||
Actor player = Game.GetPlayer()
|
|
||||||
F4MPPlayer entity = player.PlaceActorAtMe(f4mpPlayerBase) as F4MPPlayer
|
|
||||||
entity.entityID = entityID
|
|
||||||
|
|
||||||
entity.itemsToWear = itemsToWear
|
|
||||||
; SetWornItems(entity, itemsToWear)
|
|
||||||
|
|
||||||
playerIDs.Add(entityID)
|
|
||||||
players.Add(entity)
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnEntityUpdate(int entityID)
|
|
||||||
; int index = playerIDs.Find(entityID)
|
|
||||||
; If index < 0
|
|
||||||
; return
|
|
||||||
; EndIf
|
|
||||||
|
|
||||||
; F4MPPlayer player = players[index];
|
|
||||||
; If F4MP.IsEntityValid(player.entityID)
|
|
||||||
; float[] position = F4MP.GetEntityPosition(player.entityID)
|
|
||||||
; float angleX = 0.0; F4MP.ReadNumber()
|
|
||||||
; float angleY = 0.0; F4MP.ReadNumber()
|
|
||||||
; float angleZ = 0.0; F4MP.ReadNumber()
|
|
||||||
; Debug.Trace(position[0] + " " + position[1] + " " + position[2] + " " + angleX + " " + angleY + " " + angleZ)
|
|
||||||
; player.TranslateTo(position[0], position[1], position[2], angleX, angleY, angleZ, 200.0, 100.0)
|
|
||||||
; EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnEntityRemove(int entityID)
|
|
||||||
int index = playerIDs.Find(entityID)
|
|
||||||
If index < 0
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
players[index].Delete()
|
|
||||||
playerIDs.Remove(index)
|
|
||||||
players.Remove(index)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnClientUpdate(int entityID)
|
|
||||||
; Actor player = Game.GetPlayer()
|
|
||||||
|
|
||||||
; int playerEntityID = F4MP.GetPlayerEntityID()
|
|
||||||
; If F4MP.IsEntityValid(playerEntityID)
|
|
||||||
; F4MP.SetEntityPosition(playerEntityID, player.GetPositionX(), player.GetPositionY(), player.GetPositionZ())
|
|
||||||
|
|
||||||
; F4MP.WriteNumber(player.GetAngleX())
|
|
||||||
; F4MP.WriteNumber(player.GetAngleY())
|
|
||||||
; F4MP.WriteNumber(player.GetAngleZ())
|
|
||||||
; EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnPlayerHit(float damage)
|
|
||||||
Game.GetPlayer().DamageValue(healthAV, damage)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnFireWeapon(int entityID)
|
|
||||||
int index = playerIDs.Find(entityID)
|
|
||||||
If index < 0
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
players[index].FireWeapon()
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function OnSpawnEntity(int formID)
|
|
||||||
ObjectReference ref = Game.GetForm(formID) as ObjectReference
|
|
||||||
If ref == None
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
Actor actorRef = ref as Actor
|
|
||||||
If actorRef != None && myNPCs.Find(actorRef) < 0
|
|
||||||
othersNPCs.Add(actorRef)
|
|
||||||
EndIf
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Function SetWornItems(Actor dest, Form[] wornItems)
|
|
||||||
int i = 0
|
|
||||||
While i < wornItems.length
|
|
||||||
Debug.Trace(i + ": " + wornItems[i])
|
|
||||||
dest.EquipItem(wornItems[i])
|
|
||||||
i += 1
|
|
||||||
EndWhile
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
; TODO: mutiple timers
|
|
||||||
bool Function Connect(string address, int port)
|
|
||||||
Actor client = Game.GetPlayer()
|
|
||||||
ActorBase clientActorBase = client.GetActorBase()
|
|
||||||
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
return F4MP.Connect(client, clientActorBase, address, port)
|
|
||||||
EndFunction
|
|
||||||
|
|
||||||
Event OnKeyDown(int keyCode)
|
|
||||||
If keyCode == 112
|
|
||||||
Connect("", 7779)
|
|
||||||
|
|
||||||
playerIDs = new int[0]
|
|
||||||
players = new F4MPPlayer[0]
|
|
||||||
|
|
||||||
othersNPCs = new Actor[0]
|
|
||||||
myNPCs = new Actor[0]
|
|
||||||
StartTimer(0, queryTimerID)
|
|
||||||
|
|
||||||
;Actor player = Game.GetPlayer()
|
|
||||||
;F4MPPlayer entity = player.PlaceActorAtMe(f4mpPlayerBase) as F4MPPlayer
|
|
||||||
|
|
||||||
Actor client = Game.GetPlayer()
|
|
||||||
RegisterForAnimationEvent(client, "JumpUp")
|
|
||||||
RegisterForAnimationEvent(client, "weaponFire")
|
|
||||||
; RegisterForAnimationEvent(client, "JumpFall")
|
|
||||||
; RegisterForAnimationEvent(client, "JumpDown")
|
|
||||||
|
|
||||||
; RegisterForExternalEvent("OnCopyWornItems", "OnCopyWornItems")
|
|
||||||
|
|
||||||
RegisterForExternalEvent("OnEntityCreate", "OnEntityCreate")
|
|
||||||
RegisterForExternalEvent("OnEntityUpdate", "OnEntityUpdate")
|
|
||||||
RegisterForExternalEvent("OnEntityRemove", "OnEntityRemove")
|
|
||||||
RegisterForExternalEvent("OnClientUpdate", "OnClientUpdate")
|
|
||||||
|
|
||||||
RegisterForExternalEvent("OnPlayerHit", "OnPlayerHit")
|
|
||||||
RegisterForExternalEvent("OnFireWeapon", "OnFireWeapon")
|
|
||||||
RegisterForExternalEvent("OnSpawnEntity", "OnSpawnEntity")
|
|
||||||
|
|
||||||
RegisterForKey(113)
|
|
||||||
RegisterForKey(114)
|
|
||||||
ElseIf keyCode == 113
|
|
||||||
F4MP.SetClient(1 - F4MP.GetClientInstanceID())
|
|
||||||
ElseIf keyCode == 114
|
|
||||||
; Actor randomActor = Game.FindRandomActorFromRef(Game.GetPlayer(), 1000.0)
|
|
||||||
; If randomActor != None && randomActor != Game.GetPlayer()
|
|
||||||
; chosenActor = randomActor
|
|
||||||
; targetRef = Game.GetPlayer().PlaceAtMe(targetForm)
|
|
||||||
|
|
||||||
; Debug.Notification(chosenActor.GetDisplayName() + " " + targetRef.GetDisplayName())
|
|
||||||
; EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Form Property targetForm Auto
|
|
||||||
Actor Property chosenActor Auto
|
|
||||||
ObjectReference Property targetRef Auto
|
|
||||||
|
|
||||||
Event OnAnimationEvent(ObjectReference akSource, string asEventName)
|
|
||||||
If !F4MP.IsConnected()
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
int playerEntityID = F4MP.GetPlayerEntityID()
|
|
||||||
If F4MP.IsEntityValid(playerEntityID)
|
|
||||||
If asEventName == "JumpUp"
|
|
||||||
F4MP.SetEntVarAnim(playerEntityID, "JumpUp")
|
|
||||||
; ElseIf asEventName == "JumpFall"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "JumpFall")
|
|
||||||
; ElseIf asEventName == "JumpDown"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "JumpLand")
|
|
||||||
ElseIf asEventName == "weaponFire"
|
|
||||||
; F4MP.SetEntVarAnim(playerEntityID, "FireWeapon")
|
|
||||||
F4MP.PlayerFireWeapon()
|
|
||||||
EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
||||||
Event OnTimer(int aiTimerID)
|
|
||||||
If !F4MP.IsConnected()
|
|
||||||
F4MP.Tick()
|
|
||||||
StartTimer(0, aiTimerID)
|
|
||||||
return
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
If aiTimerID == tickTimerID
|
|
||||||
StartTimer(0, tickTimerID)
|
|
||||||
|
|
||||||
;; ***************************************
|
|
||||||
;If chosenActor != None
|
|
||||||
; chosenActor.PathToReference(targetRef, 1.0)
|
|
||||||
;EndIf
|
|
||||||
;
|
|
||||||
;; ***************************************
|
|
||||||
|
|
||||||
Actor player = Game.GetPlayer()
|
|
||||||
|
|
||||||
int playerEntityID = F4MP.GetPlayerEntityID()
|
|
||||||
If F4MP.IsEntityValid(playerEntityID)
|
|
||||||
F4MP.SetEntityPosition(playerEntityID, player.GetPositionX(), player.GetPositionY(), player.GetPositionZ())
|
|
||||||
F4MP.SetEntVarNum(playerEntityID, "angleX", player.GetAngleX())
|
|
||||||
F4MP.SetEntVarNum(playerEntityID, "angleY", player.GetAngleY())
|
|
||||||
F4MP.SetEntVarNum(playerEntityID, "angleZ", player.GetAngleZ())
|
|
||||||
F4MP.SetEntVarNum(playerEntityID, "health", player.GetValuePercentage(healthAV))
|
|
||||||
EndIf
|
|
||||||
|
|
||||||
;int i = 0
|
|
||||||
;While i < myNPCs.length
|
|
||||||
; Actor myNPC = myNPCs[i]
|
|
||||||
; F4MP.SetEntityPosition(F4MP.GetEntityID(myNPC), myNPC.x, myNPC.y, myNPC.z)
|
|
||||||
; i += 1
|
|
||||||
;EndWhile
|
|
||||||
|
|
||||||
F4MP.Tick()
|
|
||||||
|
|
||||||
;i = 0
|
|
||||||
;While i < othersNPCs.length
|
|
||||||
; Actor othersNPC = othersNPCs[i]
|
|
||||||
; float[] position = F4MP.GetEntityPosition(F4MP.GetEntityID(othersNPC))
|
|
||||||
; float distance = Math.Sqrt(Math.Pow(position[0] - othersNPC.x, 2) + Math.Pow(position[1] - othersNPC.y, 2) + Math.Pow(position[2] - othersNPC.z, 2))
|
|
||||||
; othersNPC.TranslateTo(position[0], position[1], position[2], 0.0, 0.0, othersNPC.GetAngleZ(), distance * 3.0, 200.0)
|
|
||||||
; i += 1
|
|
||||||
;EndWhile
|
|
||||||
|
|
||||||
; Debug.Notification(F4MP.GetPlayerEntityID() + " " + player.GetPositionX() + " " + player.GetPositionY() + " " + player.GetPositionZ())
|
|
||||||
ElseIf aiTimerID == queryTimerID
|
|
||||||
StartTimer(0, queryTimerID)
|
|
||||||
|
|
||||||
;Actor randomActor = Game.FindRandomActorFromRef(Game.GetPlayer(), 10000.0)
|
|
||||||
;If randomActor != None && randomActor as F4MPPlayer == None && randomActor != Game.GetPlayer()
|
|
||||||
; If myNPCs.Find(randomActor) < 0 && othersNPCs.Find(randomActor) < 0
|
|
||||||
; myNPCs.Add(randomActor)
|
|
||||||
; F4MP.SpawnEntity(randomActor, randomActor.x, randomActor.y, randomActor.z, randomActor.GetAngleX(), randomActor.GetAngleY(), randomActor.GetAngleZ())
|
|
||||||
; EndIf
|
|
||||||
;EndIf
|
|
||||||
EndIf
|
|
||||||
EndEvent
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#include "Character.h"
|
|
||||||
|
|
||||||
f4mp::Character::Character()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Character::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity::OnEntityUpdate(event);
|
|
||||||
|
|
||||||
Utils::Write(event->data, nodeTransforms);
|
|
||||||
Utils::Write(event->data, transformTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Character::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity::OnClientUpdate(event);
|
|
||||||
|
|
||||||
Utils::Read(event->data, nodeTransforms);
|
|
||||||
Utils::Read(event->data, transformTime);
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Entity.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Character : public Entity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Character();
|
|
||||||
|
|
||||||
void OnEntityUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnClientUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<float> nodeTransforms;
|
|
||||||
|
|
||||||
double transformTime;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
#include "Entity.h"
|
|
||||||
#include "Player.h"
|
|
||||||
#include "NPC.h"
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Get(librg_entity* entity)
|
|
||||||
{
|
|
||||||
if (entity == nullptr)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Entity*)entity->user_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Get(librg_event* event)
|
|
||||||
{
|
|
||||||
return Get(event->entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Get(librg_peer* peer)
|
|
||||||
{
|
|
||||||
return (Entity*)peer->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Create(librg_entity* entity)
|
|
||||||
{
|
|
||||||
Entity* instance = nullptr;
|
|
||||||
|
|
||||||
switch (entity->type)
|
|
||||||
{
|
|
||||||
case EntityType::Player:
|
|
||||||
instance = new Player();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EntityType::NPC:
|
|
||||||
instance = new NPC();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Create(entity, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity* f4mp::Entity::Create(librg_event* event)
|
|
||||||
{
|
|
||||||
return Create(event->entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity::Entity() : entityID((u32)-1)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Entity::~Entity()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnConnectRequest(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnConnectAccept(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnConnectRefuse(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnDisonnect(librg_event* event)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
event->entity->user_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
librg_data_wf32(event->data, angles[0]);
|
|
||||||
librg_data_wf32(event->data, angles[1]);
|
|
||||||
librg_data_wf32(event->data, angles[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnEntityRemove(librg_event* event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
angles[0] = librg_data_rf32(event->data);
|
|
||||||
angles[1] = librg_data_rf32(event->data);
|
|
||||||
angles[2] = librg_data_rf32(event->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 f4mp::Entity::GetEntityID() const
|
|
||||||
{
|
|
||||||
return entityID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Entity::SetEntityID(u32 id)
|
|
||||||
{
|
|
||||||
entityID = id;
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "server_common.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Entity
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static Entity* Get(librg_entity* entity);
|
|
||||||
static Entity* Get(librg_event* event);
|
|
||||||
static Entity* Get(librg_peer* peer);
|
|
||||||
|
|
||||||
template<class T, class U> static T* GetAs(U entity);
|
|
||||||
|
|
||||||
static Entity* Create(librg_entity* entity);
|
|
||||||
static Entity* Create(librg_event* event);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static T* Create(librg_entity* entity, T* instance);
|
|
||||||
|
|
||||||
Entity();
|
|
||||||
virtual ~Entity();
|
|
||||||
|
|
||||||
virtual void OnConnectRequest(librg_event* event);
|
|
||||||
virtual void OnConnectAccept(librg_event* event);
|
|
||||||
virtual void OnConnectRefuse(librg_event* event);
|
|
||||||
virtual void OnDisonnect(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnEntityCreate(librg_event* event);
|
|
||||||
virtual void OnEntityUpdate(librg_event* event);
|
|
||||||
virtual void OnEntityRemove(librg_event* event);
|
|
||||||
|
|
||||||
virtual void OnClientUpdate(librg_event* event);
|
|
||||||
|
|
||||||
u32 GetEntityID() const;
|
|
||||||
void SetEntityID(u32 id);
|
|
||||||
|
|
||||||
private:
|
|
||||||
u32 entityID;
|
|
||||||
|
|
||||||
float angles[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T, class U>
|
|
||||||
T* Entity::GetAs(U entity)
|
|
||||||
{
|
|
||||||
return dynamic_cast<T*>(Get(entity));
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
inline T* Entity::Create(librg_entity* entity, T* instance)
|
|
||||||
{
|
|
||||||
instance->SetEntityID(entity->id);
|
|
||||||
entity->user_data = instance;
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#include "NPC.h"
|
|
||||||
|
|
||||||
f4mp::NPC::NPC(u32 formID, u32 ownerEntityID) : formID(formID), ownerEntityID(ownerEntityID)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::NPC::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityCreate(event);
|
|
||||||
|
|
||||||
librg_data_wi32(event->data, formID);
|
|
||||||
librg_data_wi32(event->data, ownerEntityID);
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Character.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class NPC : public Character
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NPC(u32 formID = 0, u32 ownerEntityID = (u32)-1);
|
|
||||||
|
|
||||||
void OnEntityCreate(librg_event* event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
u32 formID;
|
|
||||||
|
|
||||||
u32 ownerEntityID;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
#include "Player.h"
|
|
||||||
|
|
||||||
const f4mp::AppearanceData& f4mp::Player::GetAppearance() const
|
|
||||||
{
|
|
||||||
return appearance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const f4mp::WornItemsData& f4mp::Player::GetWornItems() const
|
|
||||||
{
|
|
||||||
return wornItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnConnectRequest(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnConnectRequest(event);
|
|
||||||
|
|
||||||
AppearanceData& playerAppearance = appearance;
|
|
||||||
WornItemsData& playerWornItems = wornItems;
|
|
||||||
|
|
||||||
Utils::Read(event->data, playerAppearance.female);
|
|
||||||
Utils::Read(event->data, playerAppearance.weights);
|
|
||||||
Utils::Read(event->data, playerAppearance.hairColor);
|
|
||||||
Utils::Read(event->data, playerAppearance.headParts);
|
|
||||||
Utils::Read(event->data, playerAppearance.morphSetValue);
|
|
||||||
Utils::Read(event->data, playerAppearance.morphRegionData1);
|
|
||||||
Utils::Read(event->data, playerAppearance.morphRegionData2);
|
|
||||||
Utils::Read(event->data, playerAppearance.morphSetData1);
|
|
||||||
Utils::Read(event->data, playerAppearance.morphSetData2);
|
|
||||||
|
|
||||||
Utils::Read(event->data, playerWornItems.data1);
|
|
||||||
Utils::Read(event->data, playerWornItems.data2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnConnectRefuse(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnConnectRefuse(event);
|
|
||||||
|
|
||||||
delete this;
|
|
||||||
event->user_data = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnEntityCreate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityCreate(event);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AppearanceData& playerAppearance = appearance;
|
|
||||||
WornItemsData& playerWornItems = wornItems;
|
|
||||||
|
|
||||||
Utils::Write(event->data, playerAppearance.female);
|
|
||||||
Utils::Write(event->data, playerAppearance.weights);
|
|
||||||
Utils::Write(event->data, playerAppearance.hairColor);
|
|
||||||
Utils::Write(event->data, playerAppearance.headParts);
|
|
||||||
Utils::Write(event->data, playerAppearance.morphSetValue);
|
|
||||||
Utils::Write(event->data, playerAppearance.morphRegionData1);
|
|
||||||
Utils::Write(event->data, playerAppearance.morphRegionData2);
|
|
||||||
Utils::Write(event->data, playerAppearance.morphSetData1);
|
|
||||||
Utils::Write(event->data, playerAppearance.morphSetData2);
|
|
||||||
|
|
||||||
Utils::Write(event->data, playerWornItems.data1);
|
|
||||||
Utils::Write(event->data, playerWornItems.data2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnEntityUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnEntityUpdate(event);
|
|
||||||
|
|
||||||
librg_data_wf32(event->data, health);
|
|
||||||
|
|
||||||
librg_data_wi32(event->data, animState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void f4mp::Player::OnClientUpdate(librg_event* event)
|
|
||||||
{
|
|
||||||
Character::OnClientUpdate(event);
|
|
||||||
|
|
||||||
health = librg_data_rf32(event->data);
|
|
||||||
|
|
||||||
animState = librg_data_ri32(event->data);
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Character.h"
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Player : public Character
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void OnConnectRequest(librg_event* event) override;
|
|
||||||
void OnConnectRefuse(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnEntityCreate(librg_event* event) override;
|
|
||||||
void OnEntityUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
void OnClientUpdate(librg_event* event) override;
|
|
||||||
|
|
||||||
const AppearanceData& GetAppearance() const;
|
|
||||||
const WornItemsData& GetWornItems() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
float health;
|
|
||||||
|
|
||||||
int animState;
|
|
||||||
|
|
||||||
AppearanceData appearance;
|
|
||||||
WornItemsData wornItems;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,330 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <librg.h>
|
|
||||||
|
|
||||||
#include "server_common.h"
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "Player.h"
|
|
||||||
#include "NPC.h"
|
|
||||||
|
|
||||||
#include <cfloat>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace f4mp
|
|
||||||
{
|
|
||||||
class Server
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static Server* instance;
|
|
||||||
|
|
||||||
std::string address;
|
|
||||||
i32 port;
|
|
||||||
|
|
||||||
librg_ctx ctx;
|
|
||||||
|
|
||||||
std::unordered_map<u32, u32> entityIDs;
|
|
||||||
|
|
||||||
std::unordered_map<u32, f64> entitiesSyncedTime;
|
|
||||||
|
|
||||||
static void on_connect_request(librg_event* event)
|
|
||||||
{
|
|
||||||
Player* player = new Player{};
|
|
||||||
event->user_data = player;
|
|
||||||
event->peer->data = player;
|
|
||||||
|
|
||||||
player->OnConnectRequest(event);
|
|
||||||
|
|
||||||
librg_log("connection requested\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_connect_accepted(librg_event* event)
|
|
||||||
{
|
|
||||||
librg_log("on_connect_accepted %x\n", event->peer);
|
|
||||||
librg_entity* blob = event->entity;
|
|
||||||
|
|
||||||
blob->position = zpl_vec3{ 886.134460f, -426.953460f, -1550.012817f };
|
|
||||||
|
|
||||||
librg_log("spawning player %u at: %f %f %f\n",
|
|
||||||
event->entity->id,
|
|
||||||
blob->position.x,
|
|
||||||
blob->position.y,
|
|
||||||
blob->position.z
|
|
||||||
);
|
|
||||||
|
|
||||||
Server* self = (Server*)event->ctx->user_data;
|
|
||||||
|
|
||||||
enet_peer_timeout(event->peer, UINT32_MAX, UINT32_MAX, UINT32_MAX);
|
|
||||||
librg_entity_control_set(event->ctx, event->entity->id, event->peer);
|
|
||||||
librg_entity_visibility_set(event->ctx, event->entity->id, LIBRG_ALWAYS_VISIBLE);
|
|
||||||
//librg_entity_world_set(event->ctx, event->entity->id, 0);
|
|
||||||
|
|
||||||
event->entity->user_data = event->user_data;
|
|
||||||
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->SetEntityID(event->entity->id);
|
|
||||||
entity->OnConnectAccept(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_connect_refused(librg_event* event)
|
|
||||||
{
|
|
||||||
librg_log("on_connect_refused\n");
|
|
||||||
|
|
||||||
Player* player = (Player*)event->user_data;
|
|
||||||
if (!player)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
player->OnConnectRefuse(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_connect_disconnect(librg_event* event)
|
|
||||||
{
|
|
||||||
librg_log("entity %d peer disconnected: %x\n", event->entity->id, event->peer);
|
|
||||||
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->OnDisonnect(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_entity_create(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->OnEntityCreate(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_entity_update(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->OnEntityUpdate(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_entity_remove(librg_event* event)
|
|
||||||
{
|
|
||||||
librg_log("remove ent %d for client %x\n", event->entity->id, event->peer);
|
|
||||||
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->OnEntityRemove(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_update(librg_event* event)
|
|
||||||
{
|
|
||||||
Entity* entity = Entity::Get(event);
|
|
||||||
if (!entity)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->OnClientUpdate(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnHit(librg_message* msg)
|
|
||||||
{
|
|
||||||
HitData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(HitData));
|
|
||||||
|
|
||||||
librg_message_send_to(msg->ctx, MessageType::Hit, librg_entity_control_get(msg->ctx, data.hittee), &data, sizeof(HitData));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnFireWeapon(librg_message* msg)
|
|
||||||
{
|
|
||||||
u32 entity;
|
|
||||||
librg_data_rptr(msg->data, &entity, sizeof(u32));
|
|
||||||
|
|
||||||
librg_message_send_except(msg->ctx, MessageType::FireWeapon, msg->peer, &entity, sizeof(u32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnSpawnEntity(librg_message* msg)
|
|
||||||
{
|
|
||||||
SpawnEntityData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(SpawnEntityData));
|
|
||||||
|
|
||||||
auto entityID = instance->entityIDs.find(data.formID);
|
|
||||||
if (entityID != instance->entityIDs.end())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
librg_log("entity spawned: %x (%f, %f, %f) (%f, %f, %f)\n", data.formID, data.position.x, data.position.y, data.position.z, data.angles.x, data.angles.y, data.angles.z);
|
|
||||||
|
|
||||||
// TODO: change it so only the host can add entities?
|
|
||||||
|
|
||||||
librg_entity* entity = librg_entity_create(msg->ctx, EntityType::NPC);
|
|
||||||
librg_entity_control_set(msg->ctx, entity->id, msg->peer);
|
|
||||||
librg_entity_visibility_set(msg->ctx, entity->id, LIBRG_ALWAYS_VISIBLE);
|
|
||||||
|
|
||||||
entity->position = data.position;
|
|
||||||
|
|
||||||
NPC* npc = Entity::Create(entity, new NPC(data.formID, data.ownerEntityID));
|
|
||||||
|
|
||||||
data.entityID = entity->id;
|
|
||||||
data.ownerEntityID = Entity::GetAs<Player>(msg->peer)->GetEntityID();
|
|
||||||
|
|
||||||
instance->entityIDs[data.formID] = data.entityID;
|
|
||||||
|
|
||||||
//librg_message_send_all(msg->ctx, MessageType::SpawnEntity, &data, sizeof(SpawnEntityData));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnSyncEntity(librg_message* msg)
|
|
||||||
{
|
|
||||||
SyncEntityData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(SyncEntityData));
|
|
||||||
|
|
||||||
auto syncedTime = instance->entitiesSyncedTime.find(data.formID);
|
|
||||||
if (syncedTime != instance->entitiesSyncedTime.end())
|
|
||||||
{
|
|
||||||
if (data.syncedTime < syncedTime->second)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 callerID = Entity::Get(msg->peer)->GetEntityID();
|
|
||||||
float minDist = zpl_vec3_mag2(data.position - librg_entity_fetch(msg->ctx, callerID)->position);
|
|
||||||
|
|
||||||
librg_entity_iteratex(msg->ctx, LIBRG_ENTITY_ALIVE | LIBRG_ENTITY_CLIENT, id,
|
|
||||||
{
|
|
||||||
if (id == callerID)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
librg_entity* entity = librg_entity_fetch(msg->ctx, id);
|
|
||||||
if (zpl_vec3_mag2(data.position - entity->position) < minDist)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
instance->entitiesSyncedTime[data.formID] = data.syncedTime;
|
|
||||||
|
|
||||||
librg_message_send_except(msg->ctx, MessageType::SyncEntity, msg->peer, &data, sizeof(SyncEntityData));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnSpawnBuilding(librg_message* msg)
|
|
||||||
{
|
|
||||||
SpawnBuildingData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(SpawnBuildingData));
|
|
||||||
|
|
||||||
librg_log("building spawned: %llx %f %f %f\n", GetUniqueFormID(data.ownerEntityID, data.formID), data.position.x, data.position.y, data.position.z);
|
|
||||||
|
|
||||||
librg_message_send_except(msg->ctx, MessageType::SpawnBuilding, msg->peer, &data, sizeof(SpawnBuildingData));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnRemoveBuilding(librg_message* msg)
|
|
||||||
{
|
|
||||||
RemoveBuildingData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(RemoveBuildingData));
|
|
||||||
|
|
||||||
librg_log("building removed: %llx\n", data.uniqueFormID);
|
|
||||||
|
|
||||||
librg_message_send_except(msg->ctx, MessageType::RemoveBuilding, msg->peer, &data, sizeof(RemoveBuildingData));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnSpeak(librg_message* msg)
|
|
||||||
{
|
|
||||||
SpeakData data;
|
|
||||||
librg_data_rptr(msg->data, &data, sizeof(SpeakData));
|
|
||||||
|
|
||||||
printf("%u: %X spoke %X\n", data.clientEntityID, data.speakerFormID, data.topicInfoFormID);
|
|
||||||
|
|
||||||
librg_message_send_except(msg->ctx, MessageType::Speak, msg->peer, &data, sizeof(SpeakData));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Server(const std::string& address, i32 port) : address(address), port(port), ctx{}
|
|
||||||
{
|
|
||||||
instance = this;
|
|
||||||
|
|
||||||
librg_option_set(LIBRG_MAX_ENTITIES_PER_BRANCH, 4);
|
|
||||||
|
|
||||||
ctx.tick_delay = 10.0;
|
|
||||||
ctx.mode = LIBRG_MODE_SERVER;
|
|
||||||
ctx.world_size = zpl_vec3f(FLT_MAX, FLT_MAX, FLT_MAX);
|
|
||||||
ctx.min_branch_size = zpl_vec3f(-1, -1, -1);
|
|
||||||
ctx.max_entities = 60000;
|
|
||||||
ctx.max_connections = 1200;
|
|
||||||
ctx.user_data = this;
|
|
||||||
|
|
||||||
librg_init(&ctx);
|
|
||||||
|
|
||||||
librg_event_add(&ctx, LIBRG_CONNECTION_REQUEST, on_connect_request);
|
|
||||||
librg_event_add(&ctx, LIBRG_CONNECTION_ACCEPT, on_connect_accepted);
|
|
||||||
librg_event_add(&ctx, LIBRG_CONNECTION_REFUSE, on_connect_refused);
|
|
||||||
librg_event_add(&ctx, LIBRG_CONNECTION_DISCONNECT, on_connect_disconnect);
|
|
||||||
librg_event_add(&ctx, LIBRG_CLIENT_STREAMER_UPDATE, on_update);
|
|
||||||
|
|
||||||
librg_event_add(&ctx, LIBRG_ENTITY_CREATE, on_entity_create);
|
|
||||||
librg_event_add(&ctx, LIBRG_ENTITY_UPDATE, on_entity_update);
|
|
||||||
librg_event_add(&ctx, LIBRG_ENTITY_REMOVE, on_entity_remove);
|
|
||||||
|
|
||||||
librg_network_add(&ctx, MessageType::Hit, OnHit);
|
|
||||||
librg_network_add(&ctx, MessageType::FireWeapon, OnFireWeapon);
|
|
||||||
librg_network_add(&ctx, MessageType::SpawnEntity, OnSpawnEntity);
|
|
||||||
librg_network_add(&ctx, MessageType::SyncEntity, OnSyncEntity);
|
|
||||||
librg_network_add(&ctx, MessageType::SpawnBuilding, OnSpawnBuilding);
|
|
||||||
librg_network_add(&ctx, MessageType::RemoveBuilding, OnRemoveBuilding);
|
|
||||||
librg_network_add(&ctx, MessageType::Speak, OnSpeak);
|
|
||||||
|
|
||||||
librg_log("\
|
|
||||||
F4MP Copyright (C) 2020 Hyunsung Go\n\
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY.\n\
|
|
||||||
This is free software, and you are welcome to redistribute it\n\
|
|
||||||
under certain conditions; Read LICENSE.txt for full details.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Server()
|
|
||||||
{
|
|
||||||
librg_network_stop(&ctx);
|
|
||||||
librg_free(&ctx);
|
|
||||||
|
|
||||||
// just in case..
|
|
||||||
if (instance == this)
|
|
||||||
{
|
|
||||||
instance = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
librg_network_start(&ctx, librg_address{ port, const_cast<char*>(address.c_str()) });
|
|
||||||
|
|
||||||
librg_log(" Server started. Listening on %s:%d\n\n", address.c_str(), port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Tick()
|
|
||||||
{
|
|
||||||
librg_tick(&ctx);
|
|
||||||
zpl_sleep_ms(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
librg_ctx* GetContext()
|
|
||||||
{
|
|
||||||
return &ctx;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
#include "api.h"
|
|
||||||
|
|
||||||
#define GEN_DATA_READWRITE(TYPE) \
|
|
||||||
EXPORT TYPE ZPL_JOIN2(data_r,TYPE)(struct librg_data *data){ return ZPL_JOIN2(librg_data_r,TYPE)(data); } \
|
|
||||||
EXPORT void ZPL_JOIN2(data_w,TYPE)(struct librg_data *data, TYPE value){ ZPL_JOIN2(librg_data_w,TYPE)(data, value); } \
|
|
||||||
EXPORT TYPE ZPL_JOIN3(data_r,TYPE,_at)(struct librg_data *data, isize position){ return ZPL_JOIN3(librg_data_r,TYPE,_at)(data, position); } \
|
|
||||||
EXPORT void ZPL_JOIN3(data_w,TYPE,_at)(struct librg_data *data, TYPE value, isize position){ ZPL_JOIN3(librg_data_w,TYPE,_at)(data, value, position); }
|
|
||||||
|
|
||||||
EXPORT f4mp::Server* server_create(const char* address, i32 port)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new f4mp::Server(address, port);
|
|
||||||
}
|
|
||||||
catch (const std::exception&)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void server_destroy(f4mp::Server* server)
|
|
||||||
{
|
|
||||||
delete server;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void server_start(f4mp::Server* server)
|
|
||||||
{
|
|
||||||
server->Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT librg_ctx* server_get_ctx(f4mp::Server* server)
|
|
||||||
{
|
|
||||||
return server->GetContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void server_tick(f4mp::Server* server)
|
|
||||||
{
|
|
||||||
server->Tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
GEN_DATA_READWRITE(i8);
|
|
||||||
GEN_DATA_READWRITE(u8);
|
|
||||||
GEN_DATA_READWRITE(i16);
|
|
||||||
GEN_DATA_READWRITE(u16);
|
|
||||||
GEN_DATA_READWRITE(i32);
|
|
||||||
GEN_DATA_READWRITE(u32);
|
|
||||||
GEN_DATA_READWRITE(i64);
|
|
||||||
GEN_DATA_READWRITE(u64);
|
|
||||||
GEN_DATA_READWRITE(f32);
|
|
||||||
GEN_DATA_READWRITE(f64);
|
|
||||||
GEN_DATA_READWRITE(b8);
|
|
||||||
GEN_DATA_READWRITE(b16);
|
|
||||||
GEN_DATA_READWRITE(b32);
|
|
||||||
|
|
||||||
EXPORT void event_add(f4mp::Server* server, u64 id, librg_event_cb* callback)
|
|
||||||
{
|
|
||||||
librg_event_add(server->GetContext(), id, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void network_add(f4mp::Server* server, u16 id, librg_message_cb* callback)
|
|
||||||
{
|
|
||||||
librg_network_add(server->GetContext(), id, callback);
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Server.h"
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
|
|
||||||
#define EXPORT extern "C" __declspec(dllexport)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define EXPORT
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</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">
|
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
|
||||||
<ProjectGuid>{F7829BAB-3A87-4637-91A2-FE95D1650579}</ProjectGuid>
|
|
||||||
<RootNamespace>f4mpserver</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<IncludePath>$(SolutionDir)\f4mp\;$(IncludePath)</IncludePath>
|
|
||||||
<OutDir>$(ProjectDir)\scripts\bin\</OutDir>
|
|
||||||
<TargetName>f4mp</TargetName>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<IncludePath>$(SolutionDir)\f4mp\;$(IncludePath)</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBRG_SHARED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)\thirdparty\enet\include;$(SolutionDir)\thirdparty\zpl\code;$(SolutionDir)\thirdparty\librg\include</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)\thirdparty\enet\include;$(SolutionDir)\thirdparty\zpl\code;$(SolutionDir)\thirdparty\librg\include</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\f4mp\common.cpp" />
|
|
||||||
<ClCompile Include="api.cpp" />
|
|
||||||
<ClCompile Include="Character.cpp" />
|
|
||||||
<ClCompile Include="Entity.cpp" />
|
|
||||||
<ClCompile Include="main.cpp" />
|
|
||||||
<ClCompile Include="NPC.cpp" />
|
|
||||||
<ClCompile Include="Player.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="api.h" />
|
|
||||||
<ClInclude Include="Character.h" />
|
|
||||||
<ClInclude Include="Entity.h" />
|
|
||||||
<ClInclude Include="NPC.h" />
|
|
||||||
<ClInclude Include="Player.h" />
|
|
||||||
<ClInclude Include="Server.h" />
|
|
||||||
<ClInclude Include="server_common.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="소스 파일">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="헤더 파일">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="리소스 파일">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="main.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Entity.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Player.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="NPC.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\f4mp\common.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="Character.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="api.cpp">
|
|
||||||
<Filter>소스 파일</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="Server.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Entity.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="server_common.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Player.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="NPC.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Character.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="api.h">
|
|
||||||
<Filter>헤더 파일</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup />
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
#define LIBRG_IMPLEMENTATION
|
|
||||||
//#define LIBRG_DISABLE_FEATURE_ENTITY_VISIBILITY
|
|
||||||
|
|
||||||
#include "Server.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
f4mp::Server* f4mp::Server::instance = nullptr;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
const std::string configFilePath = "server_config.txt";
|
|
||||||
|
|
||||||
std::string address;
|
|
||||||
i32 port = 7779;
|
|
||||||
|
|
||||||
std::ifstream config(configFilePath);
|
|
||||||
if (config)
|
|
||||||
{
|
|
||||||
config >> address;
|
|
||||||
config >> port;
|
|
||||||
config.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "address? ";
|
|
||||||
std::cin >> address;
|
|
||||||
|
|
||||||
std::ofstream file(configFilePath);
|
|
||||||
file << address << std::endl << port;
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
f4mp::Server* server = new f4mp::Server(address, port);
|
|
||||||
|
|
||||||
server->Start();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
server->Tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
from .server import Server
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
import os
|
|
||||||
import ctypes
|
|
||||||
from ctypes import CFUNCTYPE, c_char_p, c_uint32, c_void_p, c_uint64
|
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
dll = ctypes.cdll.LoadLibrary(os.path.join(BASE_DIR, "bin/f4mp.dll"))
|
|
||||||
|
|
||||||
|
|
||||||
class Message(ctypes.Structure):
|
|
||||||
_fields_ = [
|
|
||||||
("id", c_uint32),
|
|
||||||
("ctx", c_void_p),
|
|
||||||
("data", c_void_p),
|
|
||||||
|
|
||||||
("peer", c_void_p),
|
|
||||||
("packet", c_void_p),
|
|
||||||
|
|
||||||
("user_data", c_void_p),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Event(ctypes.Structure):
|
|
||||||
_fields_ = [
|
|
||||||
("id", c_uint32),
|
|
||||||
("ctx", c_void_p),
|
|
||||||
("data", c_void_p),
|
|
||||||
("entity", c_void_p),
|
|
||||||
|
|
||||||
("peer", c_void_p),
|
|
||||||
|
|
||||||
("flags", c_uint64),
|
|
||||||
("user_data", c_void_p),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Task:
|
|
||||||
def __init__(self, e_type, event):
|
|
||||||
self.type = e_type
|
|
||||||
self.event = Event(event)
|
|
||||||
|
|
||||||
|
|
||||||
class CallbackEnum:
|
|
||||||
LIBRG_CONNECTION_INIT = 0
|
|
||||||
LIBRG_CONNECTION_REQUEST = 1
|
|
||||||
LIBRG_CONNECTION_REFUSE = 2
|
|
||||||
LIBRG_CONNECTION_ACCEPT = 3
|
|
||||||
LIBRG_CONNECTION_DISCONNECT = 4
|
|
||||||
LIBRG_CONNECTION_TIMEOUT = 5
|
|
||||||
LIBRG_CONNECTION_TIMESYNC = 6
|
|
||||||
|
|
||||||
LIBRG_ENTITY_CREATE = 7
|
|
||||||
LIBRG_ENTITY_UPDATE = 8
|
|
||||||
LIBRG_ENTITY_REMOVE = 9
|
|
||||||
LIBRG_CLIENT_STREAMER_ADD = 10
|
|
||||||
LIBRG_CLIENT_STREAMER_REMOVE = 11
|
|
||||||
LIBRG_CLIENT_STREAMER_UPDATE = 12
|
|
||||||
|
|
||||||
LIBRG_EVENT_LAST = 13
|
|
||||||
|
|
||||||
Hit = LIBRG_EVENT_LAST + 1
|
|
||||||
FireWeapon = LIBRG_EVENT_LAST + 2
|
|
||||||
SpawnEntity = LIBRG_EVENT_LAST + 3
|
|
||||||
SyncEntity = LIBRG_EVENT_LAST + 4
|
|
||||||
SpawnBuilding = LIBRG_EVENT_LAST + 5
|
|
||||||
RemoveBuilding = LIBRG_EVENT_LAST + 6
|
|
||||||
Speak = LIBRG_EVENT_LAST + 7
|
|
||||||
|
|
||||||
dict = {
|
|
||||||
"on_connection_request": LIBRG_CONNECTION_REQUEST,
|
|
||||||
"on_connection_accepted": LIBRG_CONNECTION_ACCEPT,
|
|
||||||
"on_connection_refused": LIBRG_CONNECTION_REFUSE,
|
|
||||||
"on_disconnect": LIBRG_CONNECTION_DISCONNECT,
|
|
||||||
"on_entity_create": LIBRG_ENTITY_CREATE,
|
|
||||||
"on_entity_delete": LIBRG_ENTITY_REMOVE,
|
|
||||||
"on_entity_update": LIBRG_ENTITY_UPDATE,
|
|
||||||
"on_client_update": LIBRG_CLIENT_STREAMER_UPDATE
|
|
||||||
}
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
|
||||||
return self.dict[item]
|
|
||||||
|
|
||||||
|
|
||||||
class Callbacks:
|
|
||||||
def __init__(self, server):
|
|
||||||
self.server = server
|
|
||||||
self.instance = server.instance
|
|
||||||
self.callback_enum = CallbackEnum()
|
|
||||||
|
|
||||||
for func_name, enum in self.callback_enum.dict.items():
|
|
||||||
func = CFUNCTYPE(None, c_void_p)(getattr(self, func_name))
|
|
||||||
self.server.call_map[func_name] = set()
|
|
||||||
Interface.register_event(self.instance, enum, func)
|
|
||||||
|
|
||||||
def on_connection_request(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_connection_request", event))
|
|
||||||
|
|
||||||
def on_connection_accepted(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_connection_accepted", event))
|
|
||||||
|
|
||||||
def on_connection_refused(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_connection_refused", event))
|
|
||||||
|
|
||||||
def on_disconnect(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_disconnect", event))
|
|
||||||
|
|
||||||
def on_entity_create(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_entity_create", event))
|
|
||||||
|
|
||||||
def on_entity_delete(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_entity_delete", event))
|
|
||||||
|
|
||||||
def on_entity_update(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_entity_update", event))
|
|
||||||
|
|
||||||
def on_client_update(self, event):
|
|
||||||
self.server.task_queue.append(Task("on_client_update", event))
|
|
||||||
|
|
||||||
|
|
||||||
class Interface:
|
|
||||||
"""F4MP DLL Interface"""
|
|
||||||
dll.server_create.restype = c_void_p
|
|
||||||
dll.server_create.argtypes = c_char_p, c_uint32
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def server_create(address: str, port: int) -> c_void_p:
|
|
||||||
"""Creates a server
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
address(str): The bind address for the server
|
|
||||||
port(int): The port the server will listen on
|
|
||||||
Note:
|
|
||||||
The port
|
|
||||||
"""
|
|
||||||
return c_void_p(dll.server_create(address.encode(), port))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def server_start(instance: c_void_p) -> None:
|
|
||||||
dll.server_start(instance)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def server_destroy(instance: c_void_p) -> None:
|
|
||||||
"""Destroys the server"""
|
|
||||||
dll.server_destroy(instance)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def server_tick(instance: c_void_p) -> None:
|
|
||||||
dll.server_tick(instance)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def register_event(server: c_void_p, enum: int, func):
|
|
||||||
dll.event_add(server, enum, func)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def register_net(server: c_void_p, enum: int, func):
|
|
||||||
dll.network_add(server, enum, func)
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
import asyncio
|
|
||||||
from F4MP import f4mp
|
|
||||||
|
|
||||||
Interface = f4mp.Interface
|
|
||||||
|
|
||||||
|
|
||||||
class Server:
|
|
||||||
def __init__(self, address: str, port: int):
|
|
||||||
self.instance = Interface.server_create(address, port)
|
|
||||||
self.address = address
|
|
||||||
self.port = port
|
|
||||||
self.loop = asyncio.get_event_loop()
|
|
||||||
self.task_queue = []
|
|
||||||
self.call_map = {}
|
|
||||||
self.callbacks = f4mp.Callbacks(self)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
Interface.server_destroy(self.instance)
|
|
||||||
|
|
||||||
def listener(self, name=None):
|
|
||||||
def decorator(func):
|
|
||||||
self.call_map[name or func.__name__].add(func)
|
|
||||||
return func
|
|
||||||
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
def start(self, tps=20):
|
|
||||||
Interface.server_start(self.instance)
|
|
||||||
self.loop_tasks(tps)
|
|
||||||
|
|
||||||
def loop_tasks(self, tps):
|
|
||||||
import time
|
|
||||||
period = 1 / tps
|
|
||||||
while True:
|
|
||||||
start = time.time()
|
|
||||||
for task in self.task_queue:
|
|
||||||
for func in self.call_map[task.type]:
|
|
||||||
func(task.event)
|
|
||||||
Interface.server_tick(self.instance)
|
|
||||||
time.sleep(period - max(time.time() - start, 0))
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
from F4MP import Server
|
|
||||||
|
|
||||||
my_server = Server("127.0.0.1", 7779)
|
|
||||||
|
|
||||||
|
|
||||||
@my_server.listener()
|
|
||||||
def on_connection_request(event):
|
|
||||||
print("Connection")
|
|
||||||
|
|
||||||
|
|
||||||
my_server.start()
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.29613.14
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4se_loader", "f4se_loader\f4se_loader.vcxproj", "{4229A810-8CB3-4C31-A0F5-8E73D89C0379}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common_vc11", "..\common\common_vc11.vcxproj", "{D4C128A1-73DC-4941-A453-CE55AF239BA8}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4se", "f4se\f4se.vcxproj", "{A236F69D-8FF9-4491-AC5F-45BF49448BBE}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4se_common", "f4se_common\f4se_common.vcxproj", "{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4se_steam_loader", "f4se_steam_loader\f4se_steam_loader.vcxproj", "{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4se_loader_common", "f4se_loader_common\f4se_loader_common.vcxproj", "{BE858737-949E-48CF-ADF9-079389049B57}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6} = {20C6411C-596F-4B85-BE4E-8BC91F59D8A6}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4mp", "f4mp\f4mp.vcxproj", "{F021FA50-A159-46F9-8455-B079C458E5AF}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "f4mp_server", "f4mp_server\f4mp_server.vcxproj", "{F7829BAB-3A87-4637-91A2-FE95D1650579}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Release|x64.Build.0 = Release|x64
|
|
||||||
{4229A810-8CB3-4C31-A0F5-8E73D89C0379}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Release|x64.Build.0 = Release|x64
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{D4C128A1-73DC-4941-A453-CE55AF239BA8}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Release|x64.Build.0 = Release|x64
|
|
||||||
{A236F69D-8FF9-4491-AC5F-45BF49448BBE}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Release|x64.Build.0 = Release|x64
|
|
||||||
{20C6411C-596F-4B85-BE4E-8BC91F59D8A6}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Release|x64.Build.0 = Release|x64
|
|
||||||
{B13F31AC-C86C-47FF-B900-EDA1F6EC6C84}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Release|x64.Build.0 = Release|x64
|
|
||||||
{BE858737-949E-48CF-ADF9-079389049B57}.Release|x86.ActiveCfg = Release|x64
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Release|x64.Build.0 = Release|x64
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{F021FA50-A159-46F9-8455-B079C458E5AF}.Release|x86.Build.0 = Release|Win32
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Release|x64.Build.0 = Release|x64
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{F7829BAB-3A87-4637-91A2-FE95D1650579}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {5BBC760F-C0DF-4F62-8684-297A1BEC30CB}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
22
f4mp_originalcode/thirdparty/enet/LICENSE
vendored
22
f4mp_originalcode/thirdparty/enet/LICENSE
vendored
|
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2002-2016 Lee Salzman
|
|
||||||
Copyright (c) 2017-2018 Vladyslav Hrytsenko, Dominik Madarász
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
5906
f4mp_originalcode/thirdparty/enet/include/enet.h
vendored
5906
f4mp_originalcode/thirdparty/enet/include/enet.h
vendored
File diff suppressed because it is too large
Load diff
201
f4mp_originalcode/thirdparty/librg/LICENSE
vendored
201
f4mp_originalcode/thirdparty/librg/LICENSE
vendored
|
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
3383
f4mp_originalcode/thirdparty/librg/include/librg.h
vendored
3383
f4mp_originalcode/thirdparty/librg/include/librg.h
vendored
File diff suppressed because it is too large
Load diff
231
f4mp_originalcode/thirdparty/zpl/LICENSE
vendored
231
f4mp_originalcode/thirdparty/zpl/LICENSE
vendored
|
|
@ -1,231 +0,0 @@
|
||||||
This Software is dual licensed under the following licenses:
|
|
||||||
|
|
||||||
Unlicense
|
|
||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
distribute this software, either in source code form or as a compiled
|
|
||||||
binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
means.
|
|
||||||
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
of this software dedicate any and all copyright interest in the
|
|
||||||
software to the public domain. We make this dedication for the benefit
|
|
||||||
of the public at large and to the detriment of our heirs and
|
|
||||||
successors. We intend this dedication to be an overt act of
|
|
||||||
relinquishment in perpetuity of all present and future rights to this
|
|
||||||
software under copyright law.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
For more information, please refer to <http://unlicense.org/>
|
|
||||||
|
|
||||||
Apache 2.0
|
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
*.h linguist-language=C
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_HASHING
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
char buf[] = "Hello World";
|
|
||||||
zpl_u8 *enc = zpl_base64_encode(zpl_heap(), buf, zpl_strlen((const char*)buf));
|
|
||||||
zpl_u8 *dec = zpl_base64_decode(zpl_heap(), enc, zpl_strlen((const char*)enc));
|
|
||||||
|
|
||||||
ZPL_ASSERT_NOT_NULL(enc);
|
|
||||||
ZPL_ASSERT_NOT_NULL(dec);
|
|
||||||
|
|
||||||
ZPL_ASSERT_MSG((!zpl_strcmp((const char*)buf, (const char*)dec)), "%s == %s\n", buf, dec);
|
|
||||||
|
|
||||||
zpl_printf("Output:\n%s is %s\n", enc, dec);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NO_MATH_H
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_THREADING
|
|
||||||
#define ZPL_ENABLE_COROUTINES
|
|
||||||
#define ZPL_ENABLE_JOBS
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
zpl_global zpl_mutex test__print;
|
|
||||||
void printf_safe(const char *fmt, ...);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
zpl_u32 x;
|
|
||||||
} some_data;
|
|
||||||
|
|
||||||
// this is our meat of co-routine subsystem
|
|
||||||
void send_req(zpl_co *co) {
|
|
||||||
some_data *d = cast(some_data*)co->data;
|
|
||||||
|
|
||||||
printf_safe("step 1: %d\n", d->x);
|
|
||||||
|
|
||||||
zpl_sleep_ms(500);
|
|
||||||
|
|
||||||
// wait until main thread resumes the execution
|
|
||||||
zpl_co_yield(co);
|
|
||||||
|
|
||||||
some_data *r = cast(some_data*)co->data;
|
|
||||||
printf_safe("step 2: no data, we pass some back\n");
|
|
||||||
|
|
||||||
r->x = 21;
|
|
||||||
|
|
||||||
printf_safe("step 2: guest val %d\n", r->x);
|
|
||||||
|
|
||||||
zpl_co_yield(co);
|
|
||||||
|
|
||||||
zpl_sleep_ms(500);
|
|
||||||
|
|
||||||
d = cast(some_data*)co->data;
|
|
||||||
|
|
||||||
printf_safe("step 3: %d\n", d->x);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main (void) {
|
|
||||||
zpl_mutex_init(&test__print);
|
|
||||||
|
|
||||||
// initialize the co-routine subsystem with 4 threads
|
|
||||||
zpl_co_init(zpl_heap(), 4);
|
|
||||||
|
|
||||||
// form a new co-routine (be aware of its lifetime)
|
|
||||||
zpl_co w1;
|
|
||||||
zpl_co_make(&w1, send_req);
|
|
||||||
|
|
||||||
// create our data
|
|
||||||
some_data d = {42};
|
|
||||||
some_data r = {0};
|
|
||||||
some_data d2 = {0};
|
|
||||||
|
|
||||||
// step 1 - start a co-routine, pass data
|
|
||||||
printf_safe("resume step 1\n");
|
|
||||||
zpl_co_resume(&w1, cast(void*)&d);
|
|
||||||
|
|
||||||
do {} while (!zpl_co_waiting(&w1));
|
|
||||||
|
|
||||||
// step 2 - resume its execution, read data back
|
|
||||||
printf_safe("resume step 2\n");
|
|
||||||
zpl_co_resume(&w1, cast(void*)&r);
|
|
||||||
|
|
||||||
do {} while (!zpl_co_waiting(&w1));
|
|
||||||
|
|
||||||
// step 3 - resume its execution again, pass data
|
|
||||||
printf_safe("resume step 3\n");
|
|
||||||
zpl_co_resume(&w1, cast(void*)&d2);
|
|
||||||
|
|
||||||
do {} while (!zpl_co_waiting(&w1));
|
|
||||||
|
|
||||||
d2.x = r.x * 3;
|
|
||||||
printf_safe("r:%d,d:%d,d2:%d\n", r.x, d.x, d2.x);
|
|
||||||
|
|
||||||
// wait until co-routine finishes its execution
|
|
||||||
do {} while(!zpl_co_finished(&w1));
|
|
||||||
|
|
||||||
printf_safe("we're done here!\n");
|
|
||||||
zpl_co_destroy();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void printf_safe(const char *fmt, ...) {
|
|
||||||
zpl_mutex_lock(&test__print);
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
zpl_printf_va(fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
zpl_mutex_unlock(&test__print);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
#define BUF_LEN 4096
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// This demo requires you to have the following packages: "fortune" and "cowsay".
|
|
||||||
// You should find these in your distro repositories, or
|
|
||||||
// at source ports sites.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
char buf[BUF_LEN] = {0};
|
|
||||||
zpl_string text = NULL;
|
|
||||||
|
|
||||||
zpl_system_command("fortune | cowsay", BUF_LEN, buf);
|
|
||||||
text = zpl_system_command_str("fortune | cowsay", zpl_heap());
|
|
||||||
zpl_printf("Output:\n %s\n\n%s", buf, text);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
zpl_path_mkdir("./tempdir/", 0733);
|
|
||||||
zpl_path_mkdir("./tempdir/subdir", 0755);
|
|
||||||
|
|
||||||
if (zpl_path_mkdir("./tempdir/", 0733) == ZPL_FILE_ERROR_EXISTS) {
|
|
||||||
zpl_printf("error: directory already exist\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zpl_path_rmdir("./tempdir") == ZPL_FILE_ERROR_NOT_EMPTY) {
|
|
||||||
zpl_printf("error: directory is not empty\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ZPL_ASSERT(zpl_path_rmdir("./tempdir/subdir") == ZPL_FILE_ERROR_NONE);
|
|
||||||
ZPL_ASSERT(zpl_path_rmdir("./tempdir/") == ZPL_FILE_ERROR_NONE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
zpl_string files;
|
|
||||||
files = zpl_path_dirlist(zpl_heap(), "../misc", true);
|
|
||||||
|
|
||||||
char *p=strtok(files, "\n");
|
|
||||||
while (p) {
|
|
||||||
printf("%s\n", p);
|
|
||||||
p=strtok(NULL, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_string_free(files);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
char const* get_type(u8 type) {
|
|
||||||
switch (type) {
|
|
||||||
case ZPL_DIR_TYPE_FILE:
|
|
||||||
return "file";
|
|
||||||
case ZPL_DIR_TYPE_FOLDER:
|
|
||||||
return "folder";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
zpl_dir_info test={0};
|
|
||||||
zpl_dirinfo_init(&test, "misc");
|
|
||||||
|
|
||||||
for (int i=0; i<zpl_array_count(test.entries); ++i) {
|
|
||||||
zpl_dir_entry *e = test.entries + i;
|
|
||||||
printf("entry [%s]: %s\n", get_type(e->type), e->filename);
|
|
||||||
|
|
||||||
if (e->type != ZPL_DIR_TYPE_FOLDER) continue;
|
|
||||||
|
|
||||||
zpl_dirinfo_step(e);
|
|
||||||
|
|
||||||
if (e->dir_info) {
|
|
||||||
for (int j=0; j<zpl_array_count(e->dir_info->entries); ++j) {
|
|
||||||
printf("-- subentry [%s]: %s\n", get_type(e->dir_info->entries[j].type), e->dir_info->entries[j].filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_dirinfo_free(&test);
|
|
||||||
printf("Done!\n");
|
|
||||||
|
|
||||||
zpl_file foo = {0};
|
|
||||||
zpl_file_open(&foo, "code/zpl.h");
|
|
||||||
zpl_file_dirinfo_refresh(&foo);
|
|
||||||
if (foo.dir) {
|
|
||||||
for (int j=0; j<zpl_array_count(foo.dir->dir_info->entries); ++j) {
|
|
||||||
printf("-- file entry: %s\n", foo.dir->dir_info->entries[j].filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zpl_file_close(&foo);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
zpl_string filelst;
|
|
||||||
filelst = zpl_path_dirlist(zpl_heap_allocator(), "$HOME/", true);
|
|
||||||
|
|
||||||
char **files=zpl_str_split_lines(zpl_heap_allocator(), filelst, false);
|
|
||||||
|
|
||||||
for (i32 i=0; i<zpl_array_count(files); ++i) {
|
|
||||||
printf("%s\n", files[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_string_free(filelst);
|
|
||||||
zpl_array_free(files);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#define ZPL_IMPL
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
zpl_set_env("ZPLTMP", "Hello World");
|
|
||||||
|
|
||||||
const char *foo = zpl_get_env("ZPLTMP");
|
|
||||||
zpl_printf("%s\n", foo);
|
|
||||||
zpl_mfree((char *)foo);
|
|
||||||
|
|
||||||
const char *foo2 = zpl_get_env_buf("ZPLTMP");
|
|
||||||
zpl_printf("%s\n", foo2);
|
|
||||||
|
|
||||||
zpl_string bar = zpl_get_env_str("ZPLTMP");
|
|
||||||
zpl_printf("%s\n", bar);
|
|
||||||
zpl_string_free(bar);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_EVENT
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long a,b,c;
|
|
||||||
} test_e1;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TEST_E1,
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_e1_v1(zpl_event_data evt) {
|
|
||||||
ZPL_EVENT_CAST(test_e1, data);
|
|
||||||
zpl_printf("a: %lu b: %lu c: %lu\n", data->a, data->b, data->c);
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_e1_v2(zpl_event_data evt) {
|
|
||||||
ZPL_EVENT_CAST(test_e1, data);
|
|
||||||
zpl_printf("a -- %lu b -- %lu c -- %lu\n", data->a, data->b, data->c);
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_e1_v3(zpl_event_data evt) {
|
|
||||||
ZPL_EVENT_CAST(test_e1, data);
|
|
||||||
zpl_printf("a> %lu b> %lu c> %lu\n", data->a, data->b, data->c);
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
zpl_event_pool events;
|
|
||||||
zpl_event_init(&events, zpl_heap_allocator());
|
|
||||||
|
|
||||||
zpl_event_add(&events, TEST_E1, test_e1_v1); // 0
|
|
||||||
zpl_event_add(&events, TEST_E1, test_e1_v2); // 1
|
|
||||||
zpl_event_add(&events, TEST_E1, test_e1_v3); // 2
|
|
||||||
|
|
||||||
test_e1 cb_data = {1, 2, 3};
|
|
||||||
zpl_event_trigger(&events, TEST_E1, &cb_data);
|
|
||||||
|
|
||||||
zpl_event_remove(&events, TEST_E1, 1);
|
|
||||||
zpl_printf("After deletion of ID 1\n");
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Prints 0,2
|
|
||||||
zpl_event_trigger(&events, TEST_E1, &cb_data);
|
|
||||||
zpl_event_destroy(&events);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Hash table type and function declaration, call: ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE)
|
|
||||||
// Hash table function definitions, call: ZPL_TABLE_DEFINE(NAME, FUNC, VALUE)
|
|
||||||
//
|
|
||||||
// PREFIX - a prefix for function prototypes e.g. extern, static, etc.
|
|
||||||
// NAME - Name of the Hash Table
|
|
||||||
// FUNC - the name will prefix function names
|
|
||||||
// VALUE - the type of the value to be stored
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Declare user structure
|
|
||||||
typedef struct user {
|
|
||||||
zpl_string name;
|
|
||||||
i64 score;
|
|
||||||
} user;
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Declare hash table of type user
|
|
||||||
ZPL_TABLE_DECLARE(extern, userbl, tbl_user_, user);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Define hash table functions
|
|
||||||
// Place exactly in __ONE__ source file!
|
|
||||||
ZPL_TABLE_DEFINE(userbl, tbl_user_, user);
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void) {
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create new hash table
|
|
||||||
userbl users;
|
|
||||||
tbl_user_init(&users, zpl_heap_allocator());
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create hash key
|
|
||||||
u64 key = 0x29;
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create new user
|
|
||||||
user user1;
|
|
||||||
user1.name = zpl_string_make(zpl_heap_allocator(), "John Doe");
|
|
||||||
user1.score = 2674;
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Add user to the hash table
|
|
||||||
tbl_user_set(&users, key, user1);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create another user
|
|
||||||
user user2;
|
|
||||||
user2.name = zpl_string_make(zpl_heap_allocator(), "Steve L.");
|
|
||||||
user2.score = 303312;
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Add user to the hash table
|
|
||||||
tbl_user_set(&users, key+0xDEADBEEF, user2);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Retrieve the first user
|
|
||||||
user user3 = *tbl_user_get(&users, key);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Make sure the user is identical to the first user
|
|
||||||
ZPL_ASSERT(user3.score == user1.score);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Release resources
|
|
||||||
zpl_string_free(user1.name);
|
|
||||||
zpl_string_free(user2.name);
|
|
||||||
|
|
||||||
tbl_user_destroy(&users);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_THREADING
|
|
||||||
#define ZPL_ENABLE_JOBS
|
|
||||||
#include <zpl.h>
|
|
||||||
#define TEST_ENQUEUE_JOB 0.8
|
|
||||||
|
|
||||||
zpl_mutex print_mut;
|
|
||||||
|
|
||||||
void calc_nums(void* data) {
|
|
||||||
zpl_unused(data);
|
|
||||||
i64 nums=0;
|
|
||||||
zpl_random rnd={0};
|
|
||||||
zpl_random_init(&rnd);
|
|
||||||
|
|
||||||
for (int i=0; i<100; ++i) {
|
|
||||||
nums+=(zpl_random_gen_u64(&rnd) & 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
//zpl_sleep_ms(50*zpl_random_range_i64(&rnd, 2, 8));
|
|
||||||
|
|
||||||
zpl_mutex_lock(&print_mut);
|
|
||||||
zpl_printf("Result is: %ld\n", (long)nums);
|
|
||||||
zpl_mutex_unlock(&print_mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
zpl_random rng={0};
|
|
||||||
zpl_thread_pool p={0};
|
|
||||||
zpl_jobs_init(&p, zpl_heap(), 2);
|
|
||||||
zpl_random_init(&rng);
|
|
||||||
zpl_mutex_init(&print_mut);
|
|
||||||
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
|
|
||||||
f64 time=zpl_time_now();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
f64 now=zpl_time_now();
|
|
||||||
f64 dt =now-time;
|
|
||||||
if (dt > TEST_ENQUEUE_JOB) {
|
|
||||||
time=now;
|
|
||||||
zpl_jobs_enqueue(&p, calc_nums, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_jobs_process(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_JSON
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
zpl_file_contents fc;
|
|
||||||
fc = zpl_file_read_contents(zpl_heap(), true, "misc/data/test.json5");
|
|
||||||
|
|
||||||
zpl_json_object root = {0};
|
|
||||||
|
|
||||||
u8 err;
|
|
||||||
zpl_json_parse(&root, fc.size, (char *)fc.data, zpl_heap_allocator(), true, &err);
|
|
||||||
|
|
||||||
zpl_json_object *replace = NULL;
|
|
||||||
replace = zpl_json_find(&root, "replace_me", false);
|
|
||||||
|
|
||||||
if (replace != NULL)
|
|
||||||
{
|
|
||||||
zpl_printf("Field was found! Current value: %ld\nReplacing with an array!\n", (long)replace->integer);
|
|
||||||
|
|
||||||
replace->type = ZPL_JSON_TYPE_ARRAY;
|
|
||||||
zpl_array_init(replace->nodes, replace->backing);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
zpl_json_object *o = zpl_json_add(replace, NULL, ZPL_JSON_TYPE_INTEGER);
|
|
||||||
|
|
||||||
if (o) {
|
|
||||||
o->integer = (i64)i+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
replace->name = "i_am_replaced ";
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_json_object *first = zpl_json_add_at(&root, 0, "first", ZPL_JSON_TYPE_STRING);
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first->string = "I am first!";
|
|
||||||
first->assign_style = ZPL_JSON_ASSIGN_STYLE_EQUALS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
zpl_printf("Error code: %d\n", err);
|
|
||||||
|
|
||||||
zpl_json_write(zpl_file_get_standard(ZPL_FILE_STANDARD_OUTPUT), &root, 0);
|
|
||||||
|
|
||||||
zpl_json_free(&root);
|
|
||||||
|
|
||||||
zpl_file_free_contents(&fc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
//
|
|
||||||
// Recommends presence of jeopardy.json file, which can be received at: https://www.reddit.com/r/datasets/comments/1uyd0t/200000_jeopardy_questions_in_a_json_file/
|
|
||||||
//
|
|
||||||
// Stats on i7-4790k with jeopardy.json file
|
|
||||||
// Parsing - ~160 ms
|
|
||||||
// Parsing with strip_comments enabled - ~255 ms
|
|
||||||
//
|
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_JSON
|
|
||||||
#define ZPL_ENABLE_OPTS
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
zpl_opts opts={0};
|
|
||||||
|
|
||||||
zpl_opts_init(&opts, zpl_heap(), argv[0]);
|
|
||||||
|
|
||||||
zpl_opts_add(&opts, "f", "file", "input file name.", ZPL_OPTS_STRING);
|
|
||||||
zpl_opts_add(&opts, "s", "strip-comments", "strip comments from JSON file (recommended).", ZPL_OPTS_FLAG);
|
|
||||||
|
|
||||||
zpl_opts_positional_add(&opts, "file");
|
|
||||||
|
|
||||||
b32 ok = zpl_opts_compile(&opts, argc, argv);
|
|
||||||
|
|
||||||
char *filename = NULL;
|
|
||||||
b32 strip_comments = false;
|
|
||||||
|
|
||||||
if (ok && zpl_opts_positionals_filled(&opts))
|
|
||||||
{
|
|
||||||
filename = zpl_opts_string(&opts, "file", NULL);
|
|
||||||
strip_comments = zpl_opts_has_arg(&opts, "strip-comments");
|
|
||||||
|
|
||||||
if (filename == NULL)
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
zpl_printf("Filename: %s\n", filename);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bad:
|
|
||||||
zpl_opts_print_errors(&opts);
|
|
||||||
zpl_opts_print_help(&opts);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_file_contents fc = zpl_file_read_contents(zpl_heap(), true, filename);
|
|
||||||
|
|
||||||
zpl_printf("Parsing JSON5 file!\n");
|
|
||||||
|
|
||||||
zpl_json_object root = {0};
|
|
||||||
|
|
||||||
u8 err;
|
|
||||||
f64 time = zpl_time_now();
|
|
||||||
zpl_json_parse(&root, fc.size, (char *)fc.data, zpl_heap(), strip_comments, &err);
|
|
||||||
f64 delta = zpl_time_now() - time;
|
|
||||||
|
|
||||||
if (err == ZPL_JSON_ERROR_OBJECT_OR_SOURCE_WAS_NULL)
|
|
||||||
{
|
|
||||||
zpl_printf("File not found!\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_printf("Delta: %fms\nNo. of nodes: %td\nError code: %d\nFile size: %td bytes\n", delta*1000, zpl_array_count(root.nodes), err, fc.size);
|
|
||||||
|
|
||||||
zpl_json_free(&root);
|
|
||||||
zpl_file_free_contents(&fc);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_JSON
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
zpl_json_object root = {0};
|
|
||||||
root.cfg_mode = 1;
|
|
||||||
zpl_json_init_node(&root, zpl_heap(), "<root>" /* unused for root object */, ZPL_JSON_TYPE_OBJECT);
|
|
||||||
|
|
||||||
zpl_random rng={0};
|
|
||||||
zpl_random_init(&rng);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 16000000; i++)
|
|
||||||
{
|
|
||||||
zpl_json_object *o = zpl_json_add(&root, zpl_string_sprintf_buf(zpl_heap(), "field%lld\t", i), ZPL_JSON_TYPE_INTEGER);
|
|
||||||
|
|
||||||
if (o) {
|
|
||||||
o->name_style = ZPL_JSON_NAME_STYLE_NO_QUOTES;
|
|
||||||
o->assign_style = ZPL_JSON_ASSIGN_STYLE_LINE;
|
|
||||||
o->delim_style = ZPL_JSON_DELIM_STYLE_NEWLINE;
|
|
||||||
|
|
||||||
o->integer = zpl_random_gen_u64(&rng) & i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_json_write(zpl_file_get_standard(ZPL_FILE_STANDARD_OUTPUT), &root, 0);
|
|
||||||
zpl_json_free(&root);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
zpl_list s, *head, *cursor;
|
|
||||||
zpl_list_init(&s, "it is optional to call init: ");
|
|
||||||
head = cursor = &s;
|
|
||||||
|
|
||||||
// since we can construct an element implicitly this way
|
|
||||||
// the second field gets overwritten once we add it to a list.
|
|
||||||
zpl_list a = {"hello"};
|
|
||||||
cursor = zpl_list_add(cursor, &a);
|
|
||||||
|
|
||||||
zpl_list b = {"world"};
|
|
||||||
cursor = zpl_list_add(cursor, &b);
|
|
||||||
|
|
||||||
zpl_list c = {"!!! OK"};
|
|
||||||
cursor = zpl_list_add(cursor, &c);
|
|
||||||
|
|
||||||
for (zpl_list *l=head; l; l=l->next) {
|
|
||||||
zpl_printf("%s ", cast(char *)l->ptr);
|
|
||||||
}
|
|
||||||
zpl_printf("\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_MATH
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
zpl_vec3 myvec = zpl_vec3f(10.0f, 5.0f, 0.0f);
|
|
||||||
|
|
||||||
myvec *= 5.0f;
|
|
||||||
|
|
||||||
ZPL_ASSERT(myvec.x == 50.0f);
|
|
||||||
ZPL_ASSERT(myvec.y == 25.0f);
|
|
||||||
ZPL_ASSERT(myvec.z == 0.0f);
|
|
||||||
|
|
||||||
zpl_printf("result vec: %f %f %f\n", myvec.x, myvec.y, myvec.z);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_OPTS
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
zpl_opts opts={0};
|
|
||||||
|
|
||||||
zpl_opts_init(&opts, zpl_heap(), argv[0]);
|
|
||||||
|
|
||||||
zpl_opts_add(&opts, "?", "help", "the HELP section", ZPL_OPTS_FLAG);
|
|
||||||
zpl_opts_add(&opts, "f", "foo", "the test *foo* entry.", ZPL_OPTS_STRING);
|
|
||||||
zpl_opts_add(&opts, "p", "pi", "PI Value Redefined !!!", ZPL_OPTS_FLOAT);
|
|
||||||
zpl_opts_add(&opts, "4", "4pay", "hmmmm", ZPL_OPTS_INT);
|
|
||||||
zpl_opts_add(&opts, "E", "enablegfx", "Enables HD resource pack", ZPL_OPTS_FLAG);
|
|
||||||
|
|
||||||
zpl_opts_positional_add(&opts, "4pay");
|
|
||||||
|
|
||||||
b32 ok=zpl_opts_compile(&opts, argc, argv);
|
|
||||||
|
|
||||||
if (ok && zpl_opts_positionals_filled(&opts)) {
|
|
||||||
|
|
||||||
b32 help=zpl_opts_has_arg(&opts, "help");
|
|
||||||
if (help) {
|
|
||||||
zpl_opts_print_help(&opts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
zpl_string foo=zpl_opts_string(&opts, "foo", "WRONG!");
|
|
||||||
f64 some_num=zpl_opts_real(&opts, "pi", 0.0);
|
|
||||||
i32 right=(i32)zpl_opts_integer(&opts, "4pay", 42);
|
|
||||||
zpl_printf("The arg is %s\nPI value is: %f\nright: %d?\n", foo, some_num,
|
|
||||||
right);
|
|
||||||
|
|
||||||
b32 gfx=zpl_opts_has_arg(&opts, "enablegfx");
|
|
||||||
if (gfx) {
|
|
||||||
zpl_printf("You wanted HD graphics? Here:\n\n");
|
|
||||||
for (int i=0; i<5; ++i) {
|
|
||||||
zpl_printf("iiiii\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
zpl_opts_print_errors(&opts);
|
|
||||||
zpl_opts_print_help(&opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void) {
|
|
||||||
|
|
||||||
#define ARRAY_SIZE 4096*8
|
|
||||||
// NOTE(ZaKlaus): Define a storage for our numbers and the temporary buffer.
|
|
||||||
u32 nums[ARRAY_SIZE] = {0};
|
|
||||||
u32 temp[ARRAY_SIZE] = {0};
|
|
||||||
zpl_f64_cmp(0);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Initialize random seed.
|
|
||||||
// and generate random values.
|
|
||||||
zpl_random r; zpl_random_init(&r);
|
|
||||||
for (int i = 0; i < ARRAY_SIZE; ++i) {
|
|
||||||
nums[i] = zpl_random_gen_u32_unique(&r);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Print these values out
|
|
||||||
zpl_printf("First 30 numbers...\nBefore: ");
|
|
||||||
for (int i = 0; i < 90; ++i) {
|
|
||||||
zpl_printf("%d, ", nums[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Use radix sort on our numbers and print them out again.
|
|
||||||
zpl_radix_sort_u32(nums, temp, ARRAY_SIZE);
|
|
||||||
|
|
||||||
zpl_printf("\n\nAfter: ");
|
|
||||||
for (int i = 0; i < 90; ++i) {
|
|
||||||
zpl_printf("%d, ", nums[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_REGEX
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
|
|
||||||
zpl_re re={0};
|
|
||||||
|
|
||||||
char const* pat = "(//<<([\\w._]+)>>)";
|
|
||||||
|
|
||||||
u32 err = zpl_re_compile(&re, zpl_heap(), pat, zpl_strlen(pat));
|
|
||||||
if (err) {
|
|
||||||
zpl_printf("Regex pattern is invalid! Error code: %d\n", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_printf("Regex pattern was compiled!\n");
|
|
||||||
|
|
||||||
char const* str = "//<<buffer.c>> aaa //<<hello.c>>\n aa//<<aaa.c>>//<<test.c>>";
|
|
||||||
|
|
||||||
zpl_array_make(zpl_re_capture, captures, zpl_heap());
|
|
||||||
|
|
||||||
zpl_re_match_all(&re, str, zpl_strlen(str), 2, &captures);
|
|
||||||
|
|
||||||
for (isize i=0; i < zpl_array_count(captures); i++)
|
|
||||||
{
|
|
||||||
zpl_printf("Group %ld: %.*s\n", i, (i32)captures[i].len, captures[i].str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
ZPL_RING_DECLARE(u32);
|
|
||||||
ZPL_RING_DEFINE(u32);
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
zpl_ring_u32 pad={0};
|
|
||||||
zpl_ring_u32_init(&pad, zpl_heap(), 3);
|
|
||||||
zpl_ring_u32_append(&pad, 1);
|
|
||||||
zpl_ring_u32_append(&pad, 2);
|
|
||||||
zpl_ring_u32_append(&pad, 3);
|
|
||||||
|
|
||||||
while (!zpl_ring_u32_empty(&pad)) {
|
|
||||||
zpl_printf("Result is %d\n", *zpl_ring_u32_get(&pad));
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_ring_u32_free(&pad);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include "zpl.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void) {
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create stack memory
|
|
||||||
zpl_stack_memory stack = {0};
|
|
||||||
zpl_stack_memory_init(&stack, zpl_heap_allocator(), 2);
|
|
||||||
|
|
||||||
zpl_allocator stack_alloc = zpl_stack_allocator(&stack);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Create array container
|
|
||||||
zpl_array(u32) arr;
|
|
||||||
zpl_array_init(arr, stack_alloc);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Push 5 elements
|
|
||||||
for (i32 i = 0; i < 5; ++i) {
|
|
||||||
zpl_array_append(arr, i*2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): List them
|
|
||||||
zpl_printf("Before removal:\n");
|
|
||||||
for (i32 i = 0; i < 5; ++i) {
|
|
||||||
zpl_printf("Value: %d\n", arr[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Pop 2 values
|
|
||||||
zpl_array_pop(arr);
|
|
||||||
zpl_array_pop(arr);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): List them again
|
|
||||||
zpl_printf("\nAfter removal:\n");
|
|
||||||
for (i32 i = 0; i < 3; ++i) {
|
|
||||||
zpl_printf("Value: %d\n", arr[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Clear the array out
|
|
||||||
zpl_array_clear(arr);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Release used resources
|
|
||||||
zpl_stack_memory_free(&stack);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
char const* foo = "hello world";
|
|
||||||
|
|
||||||
//NOTE: length of a string + 1 extra byte for null terminator.
|
|
||||||
isize len = strlen(foo) + 1;
|
|
||||||
|
|
||||||
char *bar = zpl_strdup(zpl_heap(), (char *)foo, len);
|
|
||||||
zpl_printf("%s == %s\n", foo, bar);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#define ZPL_ENABLE_TIMER
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
zpl_global u8 counter = 0;
|
|
||||||
|
|
||||||
void test1_cb(void *user_data) {
|
|
||||||
(void)user_data;
|
|
||||||
zpl_printf("Hello, Sailor!\n");
|
|
||||||
|
|
||||||
if (counter == 10) {
|
|
||||||
zpl_printf("The second timer is done, press ^C to terminate the process.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void test2_cb(void *user_data) {
|
|
||||||
(void)user_data;
|
|
||||||
zpl_printf("This has been called %d/10 times!\n", ++counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
|
|
||||||
zpl_timer_pool timers;
|
|
||||||
zpl_array_init(timers, zpl_heap_allocator());
|
|
||||||
|
|
||||||
zpl_timer *t1 = zpl_timer_add(timers);
|
|
||||||
zpl_timer_set(t1, 4, -1, test1_cb);
|
|
||||||
zpl_timer_start(t1, 0);
|
|
||||||
|
|
||||||
zpl_timer *t2 = zpl_timer_add(timers);
|
|
||||||
zpl_timer_set(t2, 1, 10, test2_cb);
|
|
||||||
zpl_timer_start(t2, 2);
|
|
||||||
|
|
||||||
zpl_timer *t3 = zpl_timer_add(timers);
|
|
||||||
zpl_timer_set(t3, 1, 10, test2_cb);
|
|
||||||
zpl_timer_start(t3, 2);
|
|
||||||
zpl_timer_stop(t3); // NOTE(ZaKlaus): This won't be fired!
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
zpl_timer_update(timers);
|
|
||||||
}
|
|
||||||
|
|
||||||
zpl_array_free(timers);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#define ZPL_IMPLEMENTATION
|
|
||||||
#define ZPL_NANO
|
|
||||||
#include <zpl.h>
|
|
||||||
|
|
||||||
void easy_print(i64 *nums, isize cnt) {
|
|
||||||
zpl_printf("Numbers:\n");
|
|
||||||
for (isize i = 0; i < cnt; ++i) {
|
|
||||||
zpl_when (&nums[i], i64*, number) {
|
|
||||||
zpl_printf("%ld, ", (long)*number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zpl_printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
|
|
||||||
zpl_random rng = {0};
|
|
||||||
zpl_random_init(&rng);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Initialize our buffer
|
|
||||||
zpl_buffer(i64) numbers = 0;
|
|
||||||
zpl_buffer_init(numbers, zpl_heap_allocator(), zpl_size_of(i64)*20);
|
|
||||||
|
|
||||||
for (isize i = 0; i < 20; ++i) {
|
|
||||||
numbers[i] = zpl_random_range_i64(&rng, 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
easy_print(numbers, 20);
|
|
||||||
|
|
||||||
// NOTE(ZaKlaus): Perform checks
|
|
||||||
for (isize i = 0; i < 20; ++i) {
|
|
||||||
if (i == 19) continue;
|
|
||||||
zpl_when (&numbers[i], i64*, number) {
|
|
||||||
*number = *number + *(number+1);;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
easy_print(numbers, 20);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
#include "tester_framework.h"
|
|
||||||
|
|
||||||
#if defined(__GCC__) || defined(__GNUC__) || defined(__clang__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wattributes"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-value"
|
|
||||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
||||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
||||||
#pragma GCC diagnostic ignored "-Wmissing-braces"
|
|
||||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4201)
|
|
||||||
#pragma warning(disable : 4127) // Conditional expression is constant
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TEST CATEGORIES */
|
|
||||||
#include "unit/json.h"
|
|
||||||
#include "unit/print.h"
|
|
||||||
|
|
||||||
#define MODULE_LIST \
|
|
||||||
X(json5_parser) \
|
|
||||||
X(print)
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
int err = 0, cnt = 0;
|
|
||||||
zpl_printf("ZPL Automated tests\n");
|
|
||||||
|
|
||||||
#define X(name) cnt++;
|
|
||||||
MODULE_LIST
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
zpl_printf("Modules to be tested: %d\n", cnt);
|
|
||||||
|
|
||||||
#define X(name) err += ZPL_JOIN2(module__,name)();
|
|
||||||
MODULE_LIST
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
zpl_printf("--------------------------------------\n");
|
|
||||||
zpl_printf("MODULES: %d total, %d failed, %d passed\n", _g_modules, _g_modules_err, _g_modules - _g_modules_err);
|
|
||||||
zpl_printf("TESTS: %d total, %d failed, %d passed\n", _g_total, _g_errors, _g_total - _g_errors);
|
|
||||||
|
|
||||||
return -err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(ZPL_COMPILER_MSVC)
|
|
||||||
#pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__GCC__) || defined(__GNUC__) || defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
#define ZPL_IMPL
|
|
||||||
#include <zpl.h>
|
|
||||||
static int _g_modules = 0;
|
|
||||||
static int _g_modules_err = 0;
|
|
||||||
static int _g_total = 0;
|
|
||||||
static int _g_errors = 0;
|
|
||||||
|
|
||||||
#define MODULE(name, scope) \
|
|
||||||
int ZPL_JOIN2(module__,name)() { \
|
|
||||||
zpl_printf("--------------------------------------\n"); \
|
|
||||||
zpl_printf(" MODULE: %s\n", #name); \
|
|
||||||
fflush(stdout); \
|
|
||||||
_g_modules++; \
|
|
||||||
int _total = 0; \
|
|
||||||
int _errors = 0; \
|
|
||||||
int _lasterr = 0; \
|
|
||||||
char *_errstr = 0; \
|
|
||||||
scope; \
|
|
||||||
fflush(stdout); \
|
|
||||||
zpl_printf(" Results: %d total, %d failed, %d passed\n", _total, _errors, _total - _errors); \
|
|
||||||
_g_total += _total; \
|
|
||||||
_g_errors += _errors; \
|
|
||||||
if (_errors) _g_modules_err++; \
|
|
||||||
return (_errors); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IT(desc, scope) \
|
|
||||||
_lasterr = 0; \
|
|
||||||
_errstr = ""; \
|
|
||||||
_total += 1; \
|
|
||||||
do scope while(0); \
|
|
||||||
_errors += _lasterr; \
|
|
||||||
printf(" TEST: %-80s: %s%s\n", desc, (_lasterr) ? "\x1B[31mFAIL\x1B[0m" : "\x1B[32mPASS\x1B[0m", _errstr);
|
|
||||||
|
|
||||||
#define FAIL(a, b) { _errstr = zpl_bprintf("\n Reason: %s:%d %s %s:%d\n", #a, (int)a, (a == b)?"==":"!=", #b, b); _lasterr = 1; break; }
|
|
||||||
#define STRFAIL(a, b) { _errstr = zpl_bprintf("\n Reason: %s:%s %s %s:%s\n", #a, (char *)a, (!strcmp(a,b))?"==":"!=", #b, b); _lasterr = 1; break; }
|
|
||||||
#define EQUALS(a, b) if (a != b) { FAIL(a, b); }
|
|
||||||
#define STREQUALS(a, b) if (!!strcmp(a,b)) { STRFAIL(a, b); }
|
|
||||||
#define STRNEQUALS(a, b) if (!strcmp(a,b)) { STRFAIL(a, b); }
|
|
||||||
#define NEQUALS(a, b) if (a == b) { FAIL(a, b); }
|
|
||||||
#define LESSER(a, b) if (a >= b) { FAIL(a, b); }
|
|
||||||
#define GREATER(a, b) if (a <=b) { FAIL(a, b); }
|
|
||||||
#define LESSEREQ(a, b) if (a < b) { FAIL(a, b); }
|
|
||||||
#define GREATEREQ(a, b) if (a > b) { FAIL(a, b); }
|
|
||||||
|
|
@ -1,242 +0,0 @@
|
||||||
#define __PARSE(comments) \
|
|
||||||
zpl_json_object r={0}; \
|
|
||||||
zpl_json_parse(&r, zpl_strlen(t), (char *const)t, zpl_heap(), comments, &err);
|
|
||||||
|
|
||||||
MODULE(json5_parser, {
|
|
||||||
zpl_u8 err = 0;
|
|
||||||
IT("parses empty JSON5 object", {
|
|
||||||
const char *t = "{}";
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, 0);
|
|
||||||
EQUALS(zpl_array_count(r.nodes), 0);
|
|
||||||
EQUALS(r.type, ZPL_JSON_TYPE_OBJECT);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses empty JSON5 array", {
|
|
||||||
const char *t = " [ ]";
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, 0);
|
|
||||||
EQUALS(r.type, ZPL_JSON_TYPE_ARRAY);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("fails to parse broken JSON5 array", {
|
|
||||||
const char *t = "[ }";
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_INVALID_VALUE);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("fails to parse broken JSON5 object", {
|
|
||||||
const char *t = "{ \t]";
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_INVALID_VALUE);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("fails to parse invalid data", {
|
|
||||||
const char *t = "{{jsdljsdksd{}}{]][{}";
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_INVALID_VALUE);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses commented JSON5 object", {
|
|
||||||
// const char *t = "{/* TEST CODE */ \"a\": 123 }";
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), "{/* TEST CODE */ \"a\": 123 }");
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
NEQUALS(zpl_array_count(r.nodes), 0);
|
|
||||||
EQUALS(r.nodes[0].type, ZPL_JSON_TYPE_INTEGER);
|
|
||||||
EQUALS(r.nodes[0].integer, 123);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
zpl_string_free(t);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses commented JSON5 array", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), "[/* TEST CODE */ 123 ]");
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
NEQUALS(zpl_array_count(r.nodes), 0);
|
|
||||||
EQUALS(r.nodes[0].type, ZPL_JSON_TYPE_INTEGER);
|
|
||||||
EQUALS(r.nodes[0].integer, 123);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
zpl_string_free(t);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses JSON array of multiple values", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), "[ 123, 456, `hello` ]");
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
EQUALS(zpl_array_count(r.nodes), 3);
|
|
||||||
EQUALS(r.nodes[0].integer, 123);
|
|
||||||
EQUALS(r.nodes[1].integer, 456);
|
|
||||||
STREQUALS(r.nodes[2].string, "hello");
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
zpl_string_free(t);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses commented JSON5 document", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), ZPL_MULTILINE(\
|
|
||||||
{
|
|
||||||
$api: "opengl",
|
|
||||||
name: "Diffuse shader",
|
|
||||||
version: "150",
|
|
||||||
type: "fragment",
|
|
||||||
// These are shader uniforms
|
|
||||||
uniforms: [
|
|
||||||
{ name: 'l_pos', type: 'vec3'},
|
|
||||||
{ name: 'l_mat', type: 'mat4'},
|
|
||||||
],
|
|
||||||
_meta: "0 0 -34 2.34 123 2.34e-4",
|
|
||||||
|
|
||||||
/* GLSL shader code */
|
|
||||||
code: `
|
|
||||||
uniform vec3 l_pos;
|
|
||||||
uniform mat4 l_mat;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
}));
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
EQUALS(zpl_array_count(r.nodes), 7);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses nested array", {
|
|
||||||
const char *t = ZPL_MULTILINE(\
|
|
||||||
[
|
|
||||||
[
|
|
||||||
[
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses nested array inside of an object", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), ZPL_MULTILINE(\
|
|
||||||
{ "foo": [
|
|
||||||
[
|
|
||||||
[
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]}));
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses keywords", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), ZPL_MULTILINE(\
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
Infinity,
|
|
||||||
-Infinity,
|
|
||||||
NaN,
|
|
||||||
-NaN
|
|
||||||
]));
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses empty object as a field", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), ZPL_MULTILINE(\
|
|
||||||
{
|
|
||||||
"foo": {}
|
|
||||||
}));
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses numbers with scientific notation", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), ZPL_MULTILINE(\
|
|
||||||
{
|
|
||||||
"foo": 1.e-2,
|
|
||||||
"bar": 42.23e4,
|
|
||||||
"baz": .032
|
|
||||||
}));
|
|
||||||
__PARSE(true);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
EQUALS(r.nodes[0].base, 1);
|
|
||||||
EQUALS(r.nodes[0].exp, 2);
|
|
||||||
EQUALS(r.nodes[0].exp_neg, true);
|
|
||||||
|
|
||||||
EQUALS(r.nodes[1].base, 42);
|
|
||||||
EQUALS(r.nodes[1].base2, 23);
|
|
||||||
EQUALS(r.nodes[1].base2_offset, 0);
|
|
||||||
EQUALS(r.nodes[1].exp, 4);
|
|
||||||
|
|
||||||
EQUALS(r.nodes[2].base2, 32);
|
|
||||||
EQUALS(r.nodes[2].base2_offset, 1);
|
|
||||||
EQUALS(r.nodes[2].lead_digit, false);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses minified JSON array", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), "[{\"Name\":\"ATLAS0.png\",\"Width\":256,\"Height\":128,\"Images\":[{\"Name\":\"4\",\"X\":0,\"Y\":0,\"Width\":40,\"Height\":27,\"FrameX\":0,\"FrameY\":0,\"FrameW\":40,\"FrameH\":27},{\"Name\":\"0\",\"X\":41,\"Y\":0,\"Width\":40,\"Height\":27,\"FrameX\":0,\"FrameY\":0,\"FrameW\":40,\"FrameH\":27},{\"Name\":\"6\",\"X\":82,\"Y\":0,\"Width\":33,\"Height\":35,\"FrameX\":0,\"FrameY\":0,\"FrameW\":33,\"FrameH\":35},{\"Name\":\"2\",\"X\":0,\"Y\":28,\"Width\":33,\"Height\":35,\"FrameX\":0,\"FrameY\":0,\"FrameW\":33,\"FrameH\":35},{\"Name\":\"7\",\"X\":36,\"Y\":28,\"Width\":31,\"Height\":38,\"FrameX\":0,\"FrameY\":0,\"FrameW\":31,\"FrameH\":38},{\"Name\":\"3\",\"X\":118,\"Y\":0,\"Width\":31,\"Height\":38,\"FrameX\":0,\"FrameY\":0,\"FrameW\":31,\"FrameH\":38},{\"Name\":\"5\",\"X\":157,\"Y\":0,\"Width\":37,\"Height\":34,\"FrameX\":0,\"FrameY\":0,\"FrameW\":37,\"FrameH\":34},{\"Name\":\"1\",\"X\":118,\"Y\":32,\"Width\":37,\"Height\":34,\"FrameX\":0,\"FrameY\":0,\"FrameW\":37,\"FrameH\":34}],\"IsRotated\":true,\"IsTrimmed\":false,\"IsPremultiplied\":false}]");
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
EQUALS(zpl_array_count(r.nodes), 1);
|
|
||||||
EQUALS(zpl_array_count(r.nodes[0].nodes), 7);
|
|
||||||
EQUALS(r.nodes[0].nodes[3].type, ZPL_JSON_TYPE_ARRAY);
|
|
||||||
EQUALS(zpl_array_count(r.nodes[0].nodes[3].nodes), 8);
|
|
||||||
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
|
|
||||||
IT("parses geojson.io data", {
|
|
||||||
zpl_string t = zpl_string_make(zpl_heap(), "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[19.09149169921875,48.55786390423251],[19.172515869140625,48.55786390423251],[19.172515869140625,48.60101970261553],[19.09149169921875,48.60101970261553],[19.09149169921875,48.55786390423251]]]}},{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[19.149169921875,48.56024979174329],[16.63330078125,49.160154652338015],[18.28125,49.82380908513249],[18.720703125,49.210420445650286],[19.62158203125,48.929717630629554],[19.13818359375,48.58205840283824]]}},{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Point\",\"coordinates\":[17.962646484375,48.17341248658084]}},{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[18.4130859375,47.68388118858139],[19.951171875,47.00647991252098],[20.819091796874996,47.83159592699297],[19.237060546875,48.19904897935913],[18.380126953125,48.06706753191901],[17.633056640625,47.67648444221321],[17.764892578124996,47.21583707523794],[18.4130859375,47.68388118858139]]]}}]}");
|
|
||||||
__PARSE(false);
|
|
||||||
|
|
||||||
EQUALS(err, ZPL_JSON_ERROR_NONE);
|
|
||||||
NEQUALS(zpl_array_count(r.nodes), 0);
|
|
||||||
|
|
||||||
zpl_string_free(t);
|
|
||||||
zpl_json_free(&r);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
MODULE(print, {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
@ -1,192 +0,0 @@
|
||||||
// file: header/core/collections/array.h
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Dynamic Array (POD Types)
|
|
||||||
//
|
|
||||||
// zpl_array(Type) works like zpl_string or zpl_buffer where the actual type is just a pointer to the first
|
|
||||||
// element.
|
|
||||||
//
|
|
||||||
// Available Procedures for zpl_array(Type)
|
|
||||||
// zpl_array_init
|
|
||||||
// zpl_array_free
|
|
||||||
// zpl_array_set_capacity
|
|
||||||
// zpl_array_grow
|
|
||||||
// zpl_array_append
|
|
||||||
// zpl_array_appendv
|
|
||||||
// zpl_array_pop
|
|
||||||
// zpl_array_clear
|
|
||||||
// zpl_array_back
|
|
||||||
// zpl_array_front
|
|
||||||
// zpl_array_resize
|
|
||||||
// zpl_array_reserve
|
|
||||||
//
|
|
||||||
|
|
||||||
#if 0 // Example
|
|
||||||
void foo(void) {
|
|
||||||
zpl_isize i;
|
|
||||||
int test_values[] = {4, 2, 1, 7};
|
|
||||||
zpl_allocator a = zpl_heap_allocator();
|
|
||||||
zpl_array(int) items;
|
|
||||||
|
|
||||||
zpl_array_init(items, a);
|
|
||||||
|
|
||||||
zpl_array_append(items, 1);
|
|
||||||
zpl_array_append(items, 4);
|
|
||||||
zpl_array_append(items, 9);
|
|
||||||
zpl_array_append(items, 16);
|
|
||||||
|
|
||||||
items[1] = 3; // Manually set value
|
|
||||||
// NOTE: No array bounds checking
|
|
||||||
|
|
||||||
for (i = 0; i < items.count; i++)
|
|
||||||
zpl_printf("%d\n", items[i]);
|
|
||||||
// 1
|
|
||||||
// 3
|
|
||||||
// 9
|
|
||||||
// 16
|
|
||||||
|
|
||||||
zpl_array_clear(items);
|
|
||||||
|
|
||||||
zpl_array_appendv(items, test_values, zpl_count_of(test_values));
|
|
||||||
for (i = 0; i < items.count; i++)
|
|
||||||
zpl_printf("%d\n", items[i]);
|
|
||||||
// 4
|
|
||||||
// 2
|
|
||||||
// 1
|
|
||||||
// 7
|
|
||||||
|
|
||||||
zpl_array_free(items);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ZPL_EDITOR
|
|
||||||
#include <zpl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ZPL_BEGIN_C_DECLS
|
|
||||||
|
|
||||||
typedef struct zpl_array_header {
|
|
||||||
char *data;
|
|
||||||
zpl_isize count;
|
|
||||||
zpl_isize capacity;
|
|
||||||
zpl_allocator allocator;
|
|
||||||
} zpl_array_header;
|
|
||||||
|
|
||||||
#define zpl_array(Type) Type *
|
|
||||||
|
|
||||||
#define zpl_array_make(Type, Name, allocator) Type *Name; zpl_array_init(Name, allocator)
|
|
||||||
|
|
||||||
#ifndef ZPL_ARRAY_GROW_FORMULA
|
|
||||||
#define ZPL_ARRAY_GROW_FORMULA(x) (2 * (x) + 8)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ZPL_STATIC_ASSERT(ZPL_ARRAY_GROW_FORMULA(0) > 0, "ZPL_ARRAY_GROW_FORMULA(0) <= 0");
|
|
||||||
|
|
||||||
#define ZPL_ARRAY_HEADER(x) (cast(zpl_array_header *)(x) - 1)
|
|
||||||
#define zpl_array_allocator(x) (ZPL_ARRAY_HEADER(x)->allocator)
|
|
||||||
#define zpl_array_count(x) (ZPL_ARRAY_HEADER(x)->count)
|
|
||||||
#define zpl_array_capacity(x) (ZPL_ARRAY_HEADER(x)->capacity)
|
|
||||||
#define zpl_array_end(x) (x + (zpl_array_count(x) - 1))
|
|
||||||
|
|
||||||
#define zpl_array_init_reserve(x, allocator_, cap) \
|
|
||||||
do { \
|
|
||||||
void **zpl__array_ = cast(void **) & (x); \
|
|
||||||
zpl_array_header *zpl__ah = \
|
|
||||||
cast(zpl_array_header *) zpl_alloc(allocator_, zpl_size_of(zpl_array_header) + zpl_size_of(*(x)) * (cap)); \
|
|
||||||
zpl__ah->allocator = allocator_; \
|
|
||||||
zpl__ah->count = 0; \
|
|
||||||
zpl__ah->data = (char *)x; \
|
|
||||||
zpl__ah->capacity = cap; \
|
|
||||||
*zpl__array_ = cast(void *)(zpl__ah + 1); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// NOTE: Give it an initial default capacity
|
|
||||||
#define zpl_array_init(x, allocator) zpl_array_init_reserve(x, allocator, ZPL_ARRAY_GROW_FORMULA(0))
|
|
||||||
|
|
||||||
#define zpl_array_free(x) \
|
|
||||||
do { \
|
|
||||||
zpl_array_header *zpl__ah = ZPL_ARRAY_HEADER(x); \
|
|
||||||
zpl_free(zpl__ah->allocator, zpl__ah); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_set_capacity(x, capacity) \
|
|
||||||
do { \
|
|
||||||
if (x) { \
|
|
||||||
void **zpl__array_ = cast(void **) & (x); \
|
|
||||||
*zpl__array_ = zpl__array_set_capacity((x), (capacity), zpl_size_of(*(x))); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// NOTE: Do not use the thing below directly, use the macro
|
|
||||||
ZPL_DEF void *zpl__array_set_capacity(void *array, zpl_isize capacity, zpl_isize element_size);
|
|
||||||
|
|
||||||
#define zpl_array_grow(x, min_capacity) \
|
|
||||||
do { \
|
|
||||||
zpl_isize new_capacity = ZPL_ARRAY_GROW_FORMULA(zpl_array_capacity(x)); \
|
|
||||||
if (new_capacity < (min_capacity)) new_capacity = (min_capacity); \
|
|
||||||
zpl_array_set_capacity(x, new_capacity); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_append(x, item) \
|
|
||||||
do { \
|
|
||||||
if (zpl_array_capacity(x) < zpl_array_count(x) + 1) zpl_array_grow(x, 0); \
|
|
||||||
(x)[zpl_array_count(x)++] = (item); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_append_at(x, item, ind) \
|
|
||||||
do { \
|
|
||||||
zpl_array_header *zpl__ah = ZPL_ARRAY_HEADER(x); \
|
|
||||||
if (ind == zpl__ah->count) { zpl_array_append(x, item); break; } \
|
|
||||||
if (zpl_array_capacity(x) < zpl_array_count(x) + 1) zpl_array_grow(x, 0); \
|
|
||||||
zpl_memmove(&(x)[ind + 1], (x + ind), zpl_size_of(x[0]) * (zpl__ah->count - ind)); \
|
|
||||||
x[ind] = item; \
|
|
||||||
zpl__ah->count++; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_appendv(x, items, item_count) \
|
|
||||||
do { \
|
|
||||||
zpl_array_header *zpl__ah = ZPL_ARRAY_HEADER(x); \
|
|
||||||
ZPL_ASSERT(zpl_size_of((items)[0]) == zpl_size_of((x)[0])); \
|
|
||||||
if (zpl__ah->capacity < zpl__ah->count + (item_count)) zpl_array_grow(x, zpl__ah->count + (item_count)); \
|
|
||||||
zpl_memcopy(&(x)[zpl__ah->count], (items), zpl_size_of((x)[0]) * (item_count)); \
|
|
||||||
zpl__ah->count += (item_count); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_remove_at(x, index) \
|
|
||||||
do { \
|
|
||||||
zpl_array_header *zpl__ah = ZPL_ARRAY_HEADER(x); \
|
|
||||||
ZPL_ASSERT(index < zpl__ah->count); \
|
|
||||||
zpl_memmove(x + index, x + index + 1, zpl_size_of(x[0]) * (zpl__ah->count - index)); \
|
|
||||||
--zpl__ah->count; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_copy_init(y, x) \
|
|
||||||
do { \
|
|
||||||
zpl_array_init_reserve(y, zpl_array_allocator(x), zpl_array_capacity(x)); \
|
|
||||||
zpl_memcopy(y, x, zpl_array_capacity(x) * zpl_size_of(*x)); \
|
|
||||||
zpl_array_count(y) = zpl_array_count(x); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_pop(x) \
|
|
||||||
do { \
|
|
||||||
ZPL_ASSERT(ZPL_ARRAY_HEADER(x)->count > 0); \
|
|
||||||
ZPL_ARRAY_HEADER(x)->count--; \
|
|
||||||
} while (0)
|
|
||||||
#define zpl_array_back(x) x[ZPL_ARRAY_HEADER(x)->count - 1]
|
|
||||||
#define zpl_array_front(x) x[0]
|
|
||||||
#define zpl_array_clear(x) \
|
|
||||||
do { ZPL_ARRAY_HEADER(x)->count = 0; } while (0)
|
|
||||||
|
|
||||||
#define zpl_array_resize(x, new_count) \
|
|
||||||
do { \
|
|
||||||
if (ZPL_ARRAY_HEADER(x)->capacity < (new_count)) zpl_array_grow(x, (new_count)); \
|
|
||||||
ZPL_ARRAY_HEADER(x)->count = (new_count); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_array_reserve(x, new_capacity) \
|
|
||||||
do { \
|
|
||||||
if (ZPL_ARRAY_HEADER(x)->capacity < (new_capacity)) zpl_array_set_capacity(x, new_capacity); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
ZPL_END_C_DECLS
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
// file: header/core/collections/buffer.h
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Fixed Capacity Buffer (POD Types)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// zpl_buffer(Type) works like zpl_string or zpl_array where the actual type is just a pointer to the first
|
|
||||||
// element.
|
|
||||||
//
|
|
||||||
// Available Procedures for zpl_buffer(Type)
|
|
||||||
// zpl_buffer_init
|
|
||||||
// zpl_buffer_free
|
|
||||||
// zpl_buffer_append
|
|
||||||
// zpl_buffer_appendv
|
|
||||||
// zpl_buffer_pop
|
|
||||||
// zpl_buffer_clear
|
|
||||||
|
|
||||||
#ifdef ZPL_EDITOR
|
|
||||||
#include <zpl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ZPL_BEGIN_C_DECLS
|
|
||||||
|
|
||||||
typedef struct zpl_buffer_header {
|
|
||||||
zpl_allocator backing;
|
|
||||||
zpl_isize count;
|
|
||||||
zpl_isize capacity;
|
|
||||||
} zpl_buffer_header;
|
|
||||||
|
|
||||||
#define zpl_buffer(Type) Type *
|
|
||||||
|
|
||||||
#define zpl_buffer_make(Type, Name, allocator, cap) Type *Name; zpl_buffer_init(Name, allocator, cap)
|
|
||||||
|
|
||||||
#define ZPL_BUFFER_HEADER(x) (cast(zpl_buffer_header *)(x) - 1)
|
|
||||||
#define zpl_buffer_count(x) (ZPL_BUFFER_HEADER(x)->count)
|
|
||||||
#define zpl_buffer_capacity(x) (ZPL_BUFFER_HEADER(x)->capacity)
|
|
||||||
#define zpl_buffer_end(x) (x + (zpl_buffer_count(x) - 1))
|
|
||||||
|
|
||||||
#define zpl_buffer_init(x, allocator, cap) \
|
|
||||||
do { \
|
|
||||||
void **nx = cast(void **) & (x); \
|
|
||||||
zpl_buffer_header *zpl__bh = \
|
|
||||||
cast(zpl_buffer_header *) zpl_alloc((allocator), sizeof(zpl_buffer_header) + (cap)*zpl_size_of(*(x))); \
|
|
||||||
zpl__bh->backing = allocator; \
|
|
||||||
zpl__bh->count = 0; \
|
|
||||||
zpl__bh->capacity = cap; \
|
|
||||||
*nx = cast(void *)(zpl__bh + 1); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// DEPRECATED(zpl_buffer_free): Use zpl_buffer_free2 instead
|
|
||||||
#define zpl_buffer_free(x, allocator) (zpl_free(allocator, ZPL_BUFFER_HEADER(x)))
|
|
||||||
#define zpl_buffer_free2(x) (zpl_free(ZPL_BUFFER_HEADER(x)->backing, ZPL_BUFFER_HEADER(x)))
|
|
||||||
|
|
||||||
#define zpl_buffer_append(x, item) \
|
|
||||||
do { (x)[zpl_buffer_count(x)++] = (item); } while (0)
|
|
||||||
|
|
||||||
#define zpl_buffer_appendv(x, items, item_count) \
|
|
||||||
do { \
|
|
||||||
ZPL_ASSERT(zpl_size_of(*(items)) == zpl_size_of(*(x))); \
|
|
||||||
ZPL_ASSERT(zpl_buffer_count(x) + item_count <= zpl_buffer_capacity(x)); \
|
|
||||||
zpl_memcopy(&(x)[zpl_buffer_count(x)], (items), zpl_size_of(*(x)) * (item_count)); \
|
|
||||||
zpl_buffer_count(x) += (item_count); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_buffer_copy_init(y, x) \
|
|
||||||
do { \
|
|
||||||
zpl_buffer_init_reserve(y, zpl_buffer_allocator(x), zpl_buffer_capacity(x)); \
|
|
||||||
zpl_memcopy(y, x, zpl_buffer_capacity(x) * zpl_size_of(*x)); \
|
|
||||||
zpl_buffer_count(y) = zpl_buffer_count(x); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define zpl_buffer_pop(x) \
|
|
||||||
do { \
|
|
||||||
ZPL_ASSERT(zpl_buffer_count(x) > 0); \
|
|
||||||
zpl_buffer_count(x)--; \
|
|
||||||
} while (0)
|
|
||||||
#define zpl_buffer_clear(x) \
|
|
||||||
do { zpl_buffer_count(x) = 0; } while (0)
|
|
||||||
|
|
||||||
ZPL_END_C_DECLS
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
// file: header/core/collections/hashtable.h
|
|
||||||
|
|
||||||
/** @file hashtable.c
|
|
||||||
@brief Instantiated hash table
|
|
||||||
@defgroup hashtable Instantiated hash table
|
|
||||||
|
|
||||||
@n
|
|
||||||
@n This is an attempt to implement a templated hash table
|
|
||||||
@n NOTE: The key is always a zpl_u64 for simplicity and you will _probably_ _never_ need anything bigger.
|
|
||||||
@n
|
|
||||||
@n Hash table type and function declaration, call: ZPL_TABLE_DECLARE(PREFIX, NAME, N, VALUE)
|
|
||||||
@n Hash table function definitions, call: ZPL_TABLE_DEFINE(NAME, N, VALUE)
|
|
||||||
@n
|
|
||||||
@n PREFIX - a prefix for function prototypes e.g. extern, static, etc.
|
|
||||||
@n NAME - Name of the Hash Table
|
|
||||||
@n FUNC - the name will prefix function names
|
|
||||||
@n VALUE - the type of the value to be stored
|
|
||||||
@n
|
|
||||||
@n tablename_init(NAME * h, zpl_allocator a);
|
|
||||||
@n tablename_destroy(NAME * h);
|
|
||||||
@n tablename_get(NAME * h, zpl_u64 key);
|
|
||||||
@n tablename_set(NAME * h, zpl_u64 key, VALUE value);
|
|
||||||
@n tablename_grow(NAME * h);
|
|
||||||
@n tablename_rehash(NAME * h, zpl_isize new_count);
|
|
||||||
@n tablename_remove(NAME * h, zpl_u64 key);
|
|
||||||
|
|
||||||
@{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef ZPL_EDITOR
|
|
||||||
#include <zpl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ZPL_BEGIN_C_DECLS
|
|
||||||
|
|
||||||
typedef struct zpl_hash_table_find_result {
|
|
||||||
zpl_isize hash_index;
|
|
||||||
zpl_isize entry_prev;
|
|
||||||
zpl_isize entry_index;
|
|
||||||
} zpl_hash_table_find_result;
|
|
||||||
|
|
||||||
#define ZPL_TABLE(PREFIX, NAME, FUNC, VALUE) \
|
|
||||||
ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE); \
|
|
||||||
ZPL_TABLE_DEFINE(NAME, FUNC, VALUE);
|
|
||||||
|
|
||||||
#define ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE) \
|
|
||||||
typedef struct ZPL_JOIN2(NAME, Entry) { \
|
|
||||||
zpl_u64 key; \
|
|
||||||
zpl_isize next; \
|
|
||||||
VALUE value; \
|
|
||||||
} ZPL_JOIN2(NAME, Entry); \
|
|
||||||
\
|
|
||||||
typedef struct NAME { \
|
|
||||||
zpl_array(zpl_isize) hashes; \
|
|
||||||
zpl_array(ZPL_JOIN2(NAME, Entry)) entries; \
|
|
||||||
} NAME; \
|
|
||||||
\
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a); \
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, destroy)(NAME * h); \
|
|
||||||
PREFIX VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key); \
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value); \
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, grow)(NAME * h); \
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count); \
|
|
||||||
PREFIX void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key);
|
|
||||||
|
|
||||||
#define ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) \
|
|
||||||
void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a) { \
|
|
||||||
zpl_array_init(h->hashes, a); \
|
|
||||||
zpl_array_init(h->entries, a); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ZPL_JOIN2(FUNC, destroy)(NAME * h) { \
|
|
||||||
if (h->entries) zpl_array_free(h->entries); \
|
|
||||||
if (h->hashes) zpl_array_free(h->hashes); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
zpl_internal zpl_isize ZPL_JOIN2(FUNC, _add_entry)(NAME * h, zpl_u64 key) { \
|
|
||||||
zpl_isize index; \
|
|
||||||
ZPL_JOIN2(NAME, Entry) e = { 0 }; \
|
|
||||||
e.key = key; \
|
|
||||||
e.next = -1; \
|
|
||||||
index = zpl_array_count(h->entries); \
|
|
||||||
zpl_array_append(h->entries, e); \
|
|
||||||
return index; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
zpl_internal zpl_hash_table_find_result ZPL_JOIN2(FUNC, _find)(NAME * h, zpl_u64 key) { \
|
|
||||||
zpl_hash_table_find_result r = { -1, -1, -1 }; \
|
|
||||||
if (zpl_array_count(h->hashes) > 0) { \
|
|
||||||
r.hash_index = key % zpl_array_count(h->hashes); \
|
|
||||||
r.entry_index = h->hashes[r.hash_index]; \
|
|
||||||
while (r.entry_index >= 0) { \
|
|
||||||
if (h->entries[r.entry_index].key == key) return r; \
|
|
||||||
r.entry_prev = r.entry_index; \
|
|
||||||
r.entry_index = h->entries[r.entry_index].next; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return r; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
zpl_internal zpl_b32 ZPL_JOIN2(FUNC, _full)(NAME * h) { \
|
|
||||||
return 0.75f * zpl_array_count(h->hashes) < zpl_array_count(h->entries); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ZPL_JOIN2(FUNC, grow)(NAME * h) { \
|
|
||||||
zpl_isize new_count = ZPL_ARRAY_GROW_FORMULA(zpl_array_count(h->entries)); \
|
|
||||||
ZPL_JOIN2(FUNC, rehash)(h, new_count); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count) { \
|
|
||||||
zpl_isize i, j; \
|
|
||||||
NAME nh = { 0 }; \
|
|
||||||
ZPL_JOIN2(FUNC, init)(&nh, zpl_array_allocator(h->hashes)); \
|
|
||||||
zpl_array_resize(nh.hashes, new_count); \
|
|
||||||
zpl_array_reserve(nh.entries, zpl_array_count(h->entries)); \
|
|
||||||
for (i = 0; i < new_count; i++) nh.hashes[i] = -1; \
|
|
||||||
for (i = 0; i < zpl_array_count(h->entries); i++) { \
|
|
||||||
ZPL_JOIN2(NAME, Entry) * e; \
|
|
||||||
zpl_hash_table_find_result fr; \
|
|
||||||
if (zpl_array_count(nh.hashes) == 0) ZPL_JOIN2(FUNC, grow)(&nh); \
|
|
||||||
e = &h->entries[i]; \
|
|
||||||
fr = ZPL_JOIN2(FUNC, _find)(&nh, e->key); \
|
|
||||||
j = ZPL_JOIN2(FUNC, _add_entry)(&nh, e->key); \
|
|
||||||
if (fr.entry_prev < 0) \
|
|
||||||
nh.hashes[fr.hash_index] = j; \
|
|
||||||
else \
|
|
||||||
nh.entries[fr.entry_prev].next = j; \
|
|
||||||
nh.entries[j].next = fr.entry_index; \
|
|
||||||
nh.entries[j].value = e->value; \
|
|
||||||
} \
|
|
||||||
ZPL_JOIN2(FUNC, destroy)(h); \
|
|
||||||
h->hashes = nh.hashes; \
|
|
||||||
h->entries = nh.entries; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key) { \
|
|
||||||
zpl_isize index = ZPL_JOIN2(FUNC, _find)(h, key).entry_index; \
|
|
||||||
if (index >= 0) return &h->entries[index].value; \
|
|
||||||
return NULL; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key) { \
|
|
||||||
zpl_hash_table_find_result fr = ZPL_JOIN2(FUNC, _find)(h, key); \
|
|
||||||
if (fr.entry_index >= 0) { \
|
|
||||||
if (fr.entry_prev >= 0) { \
|
|
||||||
h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; \
|
|
||||||
} else { \
|
|
||||||
h->hashes[fr.hash_index] = fr.entry_index; \
|
|
||||||
} \
|
|
||||||
zpl_array_remove_at(h->entries, fr.entry_index); \
|
|
||||||
} \
|
|
||||||
ZPL_JOIN2(FUNC, rehash)(h, zpl_array_count(h->entries)); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value) { \
|
|
||||||
zpl_isize index; \
|
|
||||||
zpl_hash_table_find_result fr; \
|
|
||||||
if (zpl_array_count(h->hashes) == 0) ZPL_JOIN2(FUNC, grow)(h); \
|
|
||||||
fr = ZPL_JOIN2(FUNC, _find)(h, key); \
|
|
||||||
if (fr.entry_index >= 0) { \
|
|
||||||
index = fr.entry_index; \
|
|
||||||
} else { \
|
|
||||||
index = ZPL_JOIN2(FUNC, _add_entry)(h, key); \
|
|
||||||
if (fr.entry_prev >= 0) { \
|
|
||||||
h->entries[fr.entry_prev].next = index; \
|
|
||||||
} else { \
|
|
||||||
h->hashes[fr.hash_index] = index; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
h->entries[index].value = value; \
|
|
||||||
if (ZPL_JOIN2(FUNC, _full)(h)) ZPL_JOIN2(FUNC, grow)(h); \
|
|
||||||
}\
|
|
||||||
|
|
||||||
//! @}
|
|
||||||
|
|
||||||
ZPL_END_C_DECLS
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue