Implement FlxStreamBuffer and beginnings of ConsoleCommands in unreal
This commit is contained in:
@@ -36,28 +36,28 @@ static bool SetProperty(const FString& prefix, UObject* obj, const FlxAnimationF
|
|||||||
FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data());
|
FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data());
|
||||||
FName nname(prefix + sname);
|
FName nname(prefix + sname);
|
||||||
switch (field.Type) {
|
switch (field.Type) {
|
||||||
case ElxAnimValueType::STRING: {
|
case SimpleDynamicTag::STRING: {
|
||||||
FStrProperty* fprop = FindFProperty<FStrProperty>(uclass, nname);
|
FStrProperty* fprop = FindFProperty<FStrProperty>(uclass, nname);
|
||||||
if (fprop == nullptr) return false;
|
if (fprop == nullptr) return false;
|
||||||
FString* pptr = fprop->ContainerPtrToValuePtr<FString>(obj);
|
FString* pptr = fprop->ContainerPtrToValuePtr<FString>(obj);
|
||||||
*pptr = FString(field.S.size(), (const UTF8CHAR*)field.S.data());
|
*pptr = FString(field.S.size(), (const UTF8CHAR*)field.S.data());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::NUMBER: {
|
case SimpleDynamicTag::NUMBER: {
|
||||||
FDoubleProperty* fprop = FindFProperty<FDoubleProperty>(uclass, nname);
|
FDoubleProperty* fprop = FindFProperty<FDoubleProperty>(uclass, nname);
|
||||||
if (fprop == nullptr) return false;
|
if (fprop == nullptr) return false;
|
||||||
double* pptr = fprop->ContainerPtrToValuePtr<double>(obj);
|
double* pptr = fprop->ContainerPtrToValuePtr<double>(obj);
|
||||||
*pptr = field.X;
|
*pptr = field.X;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::BOOLEAN: {
|
case SimpleDynamicTag::BOOLEAN: {
|
||||||
FBoolProperty* fprop = FindFProperty<FBoolProperty>(uclass, nname);
|
FBoolProperty* fprop = FindFProperty<FBoolProperty>(uclass, nname);
|
||||||
if (fprop == nullptr) return false;
|
if (fprop == nullptr) return false;
|
||||||
uint8* pptr = fprop->ContainerPtrToValuePtr<uint8>(obj);
|
uint8* pptr = fprop->ContainerPtrToValuePtr<uint8>(obj);
|
||||||
fprop->SetPropertyValue(pptr, (field.X == 1.0));
|
fprop->SetPropertyValue(pptr, (field.X == 1.0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::XYZ: {
|
case SimpleDynamicTag::VECTOR: {
|
||||||
FStructProperty* fprop = FindFProperty<FStructProperty>(uclass, nname);
|
FStructProperty* fprop = FindFProperty<FStructProperty>(uclass, nname);
|
||||||
if (fprop == nullptr) return false;
|
if (fprop == nullptr) return false;
|
||||||
if (fprop->Struct != TBaseStructure<FVector>::Get()) return false;
|
if (fprop->Struct != TBaseStructure<FVector>::Get()) return false;
|
||||||
@@ -84,7 +84,7 @@ bool FlxAnimationStep::Unpack(const FString& prefix, UObject* into) const {
|
|||||||
FlxAnimationField field;
|
FlxAnimationField field;
|
||||||
field.Name = "action";
|
field.Name = "action";
|
||||||
field.Persistent = false;
|
field.Persistent = false;
|
||||||
field.Type = ElxAnimValueType::STRING;
|
field.Type = SimpleDynamicTag::STRING;
|
||||||
field.S = "idle";
|
field.S = "idle";
|
||||||
ok &= SetProperty(prefix, into, field);
|
ok &= SetProperty(prefix, into, field);
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ static FlxAnimationField FindAnimationFieldLL(const FlxAnimationStep& step, std:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.Type = ElxAnimValueType::INVALID;
|
result.Type = SimpleDynamicTag::UNINITIALIZED;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,21 +122,21 @@ static FlxAnimationField FindAnimationField(const FlxAnimationStep& step, const
|
|||||||
|
|
||||||
void FlxAnimationStep::AutoUpdateXYZ(AActor *actor) const {
|
void FlxAnimationStep::AutoUpdateXYZ(AActor *actor) const {
|
||||||
FlxAnimationField xyz = FindAnimationFieldLL(*this, "xyz");
|
FlxAnimationField xyz = FindAnimationFieldLL(*this, "xyz");
|
||||||
if (xyz.Type == ElxAnimValueType::XYZ) {
|
if (xyz.Type == SimpleDynamicTag::VECTOR) {
|
||||||
actor->SetActorLocation(FVector(xyz.X, xyz.Y, xyz.Z));
|
actor->SetActorLocation(FVector(xyz.X, xyz.Y, xyz.Z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxAnimationStep::AutoUpdateFacing(AActor *actor) const {
|
void FlxAnimationStep::AutoUpdateFacing(AActor *actor) const {
|
||||||
FlxAnimationField facing = FindAnimationFieldLL(*this, "facing");
|
FlxAnimationField facing = FindAnimationFieldLL(*this, "facing");
|
||||||
if (facing.Type == ElxAnimValueType::NUMBER) {
|
if (facing.Type == SimpleDynamicTag::NUMBER) {
|
||||||
actor->SetActorRotation(FRotator(0, facing.X, 0));
|
actor->SetActorRotation(FRotator(0, facing.X, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxAnimationStep::AutoUpdatePlane(FName *planep) const {
|
void FlxAnimationStep::AutoUpdatePlane(FName *planep) const {
|
||||||
FlxAnimationField plane = FindAnimationFieldLL(*this, "plane");
|
FlxAnimationField plane = FindAnimationFieldLL(*this, "plane");
|
||||||
if (plane.Type == ElxAnimValueType::STRING) {
|
if (plane.Type == SimpleDynamicTag::STRING) {
|
||||||
FString pname(plane.S.size(), (const UTF8CHAR*)(plane.S.data()));
|
FString pname(plane.S.size(), (const UTF8CHAR*)(plane.S.data()));
|
||||||
*planep = FName(pname);
|
*planep = FName(pname);
|
||||||
}
|
}
|
||||||
@@ -152,13 +152,13 @@ bool UlxAnimationStepLibrary::AnimationStepIsIdle(const FlxAnimationStep &step)
|
|||||||
|
|
||||||
FVector UlxAnimationStepLibrary::AnimationStepGetVector(const FlxAnimationStep& step, const FString& name) {
|
FVector UlxAnimationStepLibrary::AnimationStepGetVector(const FlxAnimationStep& step, const FString& name) {
|
||||||
FlxAnimationField field = FindAnimationField(step, name);
|
FlxAnimationField field = FindAnimationField(step, name);
|
||||||
if (field.Type != ElxAnimValueType::XYZ) return FVector(0, 0, 0);
|
if (field.Type != SimpleDynamicTag::VECTOR) return FVector(0, 0, 0);
|
||||||
return FVector(field.X, field.Y, field.Z);
|
return FVector(field.X, field.Y, field.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
double UlxAnimationStepLibrary::AnimationStepGetFloat(const FlxAnimationStep& step, const FString& name) {
|
double UlxAnimationStepLibrary::AnimationStepGetFloat(const FlxAnimationStep& step, const FString& name) {
|
||||||
FlxAnimationField field = FindAnimationField(step, name);
|
FlxAnimationField field = FindAnimationField(step, name);
|
||||||
if (field.Type != ElxAnimValueType::NUMBER) return 0.0;
|
if (field.Type != SimpleDynamicTag::NUMBER) return 0.0;
|
||||||
return field.X;
|
return field.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,58 +167,44 @@ FString UlxAnimationStepLibrary::AnimationStepGetString(const FlxAnimationStep&
|
|||||||
return TEXT("idle");
|
return TEXT("idle");
|
||||||
}
|
}
|
||||||
FlxAnimationField field = FindAnimationField(step, name);
|
FlxAnimationField field = FindAnimationField(step, name);
|
||||||
if (field.Type != ElxAnimValueType::STRING) return TEXT("");
|
if (field.Type != SimpleDynamicTag::STRING) return TEXT("");
|
||||||
return FString(field.S.size(), (const UTF8CHAR*)(field.S.data()));
|
return FString(field.S.size(), (const UTF8CHAR*)(field.S.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UlxAnimationStepLibrary::AnimationStepGetBool(const FlxAnimationStep& step, const FString& name) {
|
bool UlxAnimationStepLibrary::AnimationStepGetBool(const FlxAnimationStep& step, const FString& name) {
|
||||||
FlxAnimationField field = FindAnimationField(step, name);
|
FlxAnimationField field = FindAnimationField(step, name);
|
||||||
if (field.Type != ElxAnimValueType::BOOLEAN) return false;
|
if (field.Type != SimpleDynamicTag::BOOLEAN) return false;
|
||||||
return field.X == 1.0;
|
return field.X == 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlxAnimationStepView FlxAnimQueueDecoder::ReadStep() {
|
|
||||||
FlxAnimationStepView result;
|
|
||||||
result.Hash = Decoder.read_uint64();
|
|
||||||
result.Body = Decoder.read_string_view();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 FlxAnimQueueDecoder::PeekHash() {
|
|
||||||
std::string_view rest = Decoder.GetRest();
|
|
||||||
uint64 result = Decoder.read_uint64();
|
|
||||||
Decoder.Reset(rest, false);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlxAnimationField FlxAnimationStepDecoder::ReadField() {
|
FlxAnimationField FlxAnimationStepDecoder::ReadField() {
|
||||||
FlxAnimationField result;
|
FlxAnimationField result;
|
||||||
result.Name = Decoder.read_string_view();
|
result.Name = Decoder.read_string_view();
|
||||||
result.Persistent = Decoder.read_bool();
|
result.Persistent = Decoder.read_bool();
|
||||||
result.Type = (ElxAnimValueType)Decoder.read_uint8();
|
result.Type = (SimpleDynamicTag)Decoder.read_uint8();
|
||||||
switch (result.Type) {
|
switch (result.Type) {
|
||||||
case ElxAnimValueType::STRING: {
|
case SimpleDynamicTag::STRING: {
|
||||||
result.S = Decoder.read_string_view();
|
result.S = Decoder.read_string_view();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::NUMBER: {
|
case SimpleDynamicTag::NUMBER: {
|
||||||
result.X = Decoder.read_double();
|
result.X = Decoder.read_double();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::BOOLEAN: {
|
case SimpleDynamicTag::BOOLEAN: {
|
||||||
result.X = Decoder.read_bool() ? 1.0 : 0.0;
|
result.X = Decoder.read_bool() ? 1.0 : 0.0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ElxAnimValueType::XYZ: {
|
case SimpleDynamicTag::VECTOR: {
|
||||||
result.X = Decoder.read_double();
|
result.X = Decoder.read_double();
|
||||||
result.Y = Decoder.read_double();
|
result.Y = Decoder.read_double();
|
||||||
result.Z = Decoder.read_double();
|
result.Z = Decoder.read_double();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
Decoder.set_at_eof();
|
Decoder.read_bytes(Decoder.fill());
|
||||||
result.Type = ElxAnimValueType::BOOLEAN;
|
result.Type = SimpleDynamicTag::UNINITIALIZED;
|
||||||
result.X = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,16 +225,16 @@ FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonl
|
|||||||
result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data()));
|
result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data()));
|
||||||
result.Append(field.Persistent ? TEXT("=") : TEXT(":"));
|
result.Append(field.Persistent ? TEXT("=") : TEXT(":"));
|
||||||
switch (field.Type) {
|
switch (field.Type) {
|
||||||
case ElxAnimValueType::STRING:
|
case SimpleDynamicTag::STRING:
|
||||||
result.Append(FString(field.S.size(), (const UTF8CHAR*)field.S.data()));
|
result.Append(FString(field.S.size(), (const UTF8CHAR*)field.S.data()));
|
||||||
break;
|
break;
|
||||||
case ElxAnimValueType::NUMBER:
|
case SimpleDynamicTag::NUMBER:
|
||||||
result.Appendf(TEXT("%lf"), field.X);
|
result.Appendf(TEXT("%lf"), field.X);
|
||||||
break;
|
break;
|
||||||
case ElxAnimValueType::BOOLEAN:
|
case SimpleDynamicTag::BOOLEAN:
|
||||||
result.Append((field.X) == 1.0 ? TEXT("true") : TEXT("false"));
|
result.Append((field.X) == 1.0 ? TEXT("true") : TEXT("false"));
|
||||||
break;
|
break;
|
||||||
case ElxAnimValueType::XYZ:
|
case SimpleDynamicTag::VECTOR:
|
||||||
result.Appendf(TEXT("%lf,%lf,%lf"), field.X, field.Y, field.Z);
|
result.Appendf(TEXT("%lf,%lf,%lf"), field.X, field.Y, field.Z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -256,6 +242,20 @@ FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlxAnimationStepView FlxAnimQueueDecoder::ReadStep() {
|
||||||
|
FlxAnimationStepView result;
|
||||||
|
result.Hash = Decoder.read_uint64();
|
||||||
|
result.Body = Decoder.read_string_view();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FlxAnimQueueDecoder::PeekHash() {
|
||||||
|
int64_t read_count = Decoder.total_reads();
|
||||||
|
uint64 result = Decoder.read_uint64();
|
||||||
|
Decoder.unread_to(read_count);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FlxAnimQueueDecoder::FlxAnimQueueDecoder(std::string_view queue) : Decoder(queue) {
|
FlxAnimQueueDecoder::FlxAnimQueueDecoder(std::string_view queue) : Decoder(queue) {
|
||||||
SizeLimit = Decoder.read_uint8();
|
SizeLimit = Decoder.read_uint8();
|
||||||
ActualSize = Decoder.read_uint8();
|
ActualSize = Decoder.read_uint8();
|
||||||
|
|||||||
@@ -5,20 +5,6 @@
|
|||||||
#include "Containers/Deque.h"
|
#include "Containers/Deque.h"
|
||||||
#include "AnimQueue.generated.h"
|
#include "AnimQueue.generated.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// This is copied over from Luprex source. Not ideal.
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////
|
|
||||||
|
|
||||||
enum class ElxAnimValueType {
|
|
||||||
STRING,
|
|
||||||
NUMBER,
|
|
||||||
BOOLEAN,
|
|
||||||
XYZ,
|
|
||||||
INVALID
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// An single animation step.
|
// An single animation step.
|
||||||
@@ -161,7 +147,7 @@ struct FlxAnimationStepView {
|
|||||||
struct FlxAnimationField {
|
struct FlxAnimationField {
|
||||||
std::string_view Name;
|
std::string_view Name;
|
||||||
bool Persistent;
|
bool Persistent;
|
||||||
ElxAnimValueType Type;
|
SimpleDynamicTag Type;
|
||||||
double X, Y, Z;
|
double X, Y, Z;
|
||||||
std::string_view S;
|
std::string_view S;
|
||||||
};
|
};
|
||||||
@@ -179,7 +165,7 @@ struct FlxAnimationField {
|
|||||||
|
|
||||||
class FlxAnimQueueDecoder {
|
class FlxAnimQueueDecoder {
|
||||||
private:
|
private:
|
||||||
FlxStringDecoder Decoder;
|
FlxStreamBuffer Decoder;
|
||||||
|
|
||||||
// These values are immediately read from the header.
|
// These values are immediately read from the header.
|
||||||
//
|
//
|
||||||
@@ -201,7 +187,7 @@ public:
|
|||||||
|
|
||||||
// Return true if the parser has reached the end of the string.
|
// Return true if the parser has reached the end of the string.
|
||||||
//
|
//
|
||||||
bool AtEOF() { return Decoder.at_eof(); }
|
bool AtEOF() { return Decoder.empty(); }
|
||||||
|
|
||||||
// Read one animation step.
|
// Read one animation step.
|
||||||
//
|
//
|
||||||
@@ -229,7 +215,7 @@ public:
|
|||||||
|
|
||||||
class FlxAnimationStepDecoder {
|
class FlxAnimationStepDecoder {
|
||||||
private:
|
private:
|
||||||
FlxStringDecoder Decoder;
|
FlxStreamBuffer Decoder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Initialize the FlxAnimationStepDecoder from the FlxAnimationStepView.
|
// Initialize the FlxAnimationStepDecoder from the FlxAnimationStepView.
|
||||||
@@ -238,7 +224,7 @@ public:
|
|||||||
|
|
||||||
// Return true if the parser has reached the end of the string.
|
// Return true if the parser has reached the end of the string.
|
||||||
//
|
//
|
||||||
bool AtEOF() { return Decoder.at_eof(); }
|
bool AtEOF() { return Decoder.empty(); }
|
||||||
|
|
||||||
// Read one field.
|
// Read one field.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -132,24 +132,41 @@ void AIntegrationGameModeBase::UpdateTangibles() {
|
|||||||
TangibleManager->DeleteFarawayTangibles();
|
TangibleManager->DeleteFarawayTangibles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AIntegrationGameModeBase::ExecuteDebuggingCommand(const FString &fs) {
|
||||||
|
if (fs == "\\invokeplayer") {
|
||||||
|
// FlxLockedWrapper w(LockableWrapper);
|
||||||
|
// int64 player = w.GetActor();
|
||||||
|
// w->play_invoke_player(w.Get(), player, datapk);
|
||||||
|
} else {
|
||||||
|
ConsoleOutput.AppendLine(TEXT("Unknown Command"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs)
|
void AIntegrationGameModeBase::ConsoleSendInput(const FString& fs)
|
||||||
{
|
{
|
||||||
FlxLockedWrapper w(LockableWrapper);
|
FlxLockedWrapper w(LockableWrapper);
|
||||||
if (w->engine != nullptr)
|
if (w->engine != nullptr)
|
||||||
{
|
{
|
||||||
const TCHAR* fstchar = *fs;
|
ConsoleOutput.AppendLine(FString("> ") + fs);
|
||||||
if (sizeof(TCHAR) == 2)
|
// This is a bad way to do this. The problem is that if some
|
||||||
{
|
// lua code contains '\\', we'll catch it instead of passing it
|
||||||
ConsoleOutput.AppendLine(FString("> ") + fs);
|
// through. There's no simple solution, though.
|
||||||
std::u16string_view fsview((const char16_t*)fstchar, fs.Len());
|
if (fs[0] == '\\') {
|
||||||
std::string utf8 = drvutil::utf16_to_utf8(fsview);
|
ExecuteDebuggingCommand(fs);
|
||||||
utf8 = utf8 + "\n";
|
} else {
|
||||||
w->play_recv_incoming(w.Get(), 0, utf8.size(), utf8.c_str());
|
const TCHAR* fstchar = *fs;
|
||||||
|
if (sizeof(TCHAR) == 2)
|
||||||
|
{
|
||||||
|
std::u16string_view fsview((const char16_t*)fstchar, fs.Len());
|
||||||
|
std::string utf8 = drvutil::utf16_to_utf8(fsview);
|
||||||
|
utf8 = utf8 + "\n";
|
||||||
|
w->play_recv_incoming(w.Get(), 0, utf8.size(), utf8.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AIntegrationGameModeBase::Tick(float deltaseconds)
|
void AIntegrationGameModeBase::Tick(float deltaseconds)
|
||||||
{
|
{
|
||||||
Super::Tick(deltaseconds);
|
Super::Tick(deltaseconds);
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ public:
|
|||||||
UPROPERTY(EditDefaultsOnly, Category = TangibleClasses)
|
UPROPERTY(EditDefaultsOnly, Category = TangibleClasses)
|
||||||
TSubclassOf<AActor> ClassTangibleActor;
|
TSubclassOf<AActor> ClassTangibleActor;
|
||||||
|
|
||||||
|
// Execute a debugging command, typed on the GUI.
|
||||||
|
void ExecuteDebuggingCommand(const FString &fs);
|
||||||
|
|
||||||
// Transfer console output from the Luprex engine to unreal.
|
// Transfer console output from the Luprex engine to unreal.
|
||||||
void UpdateConsoleOutput();
|
void UpdateConsoleOutput();
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,2 @@
|
|||||||
#include "StringDecoder.h"
|
#include "StringDecoder.h"
|
||||||
|
|
||||||
FlxStringDecoder::FlxStringDecoder(std::string_view s) {
|
|
||||||
Text = s.data();
|
|
||||||
Size = s.size();
|
|
||||||
ErrBeyondEOF = false;
|
|
||||||
ErrStringTooLong = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxStringDecoder::Reset(std::string_view s, bool clear) {
|
|
||||||
Text = s.data();
|
|
||||||
Size = s.size();
|
|
||||||
if (clear) {
|
|
||||||
ErrBeyondEOF = false;
|
|
||||||
ErrStringTooLong = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view FlxStringDecoder::GetRest() {
|
|
||||||
return std::string_view(Text, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view FlxStringDecoder::read_string_view() {
|
|
||||||
size_t length = read_length();
|
|
||||||
if (length > Size) {
|
|
||||||
ErrBeyondEOF = true;
|
|
||||||
return std::string_view();
|
|
||||||
}
|
|
||||||
std::string_view result(Text, length);
|
|
||||||
Text += length;
|
|
||||||
Size -= length;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxStringDecoder::set_at_eof() {
|
|
||||||
Text += Size;
|
|
||||||
Size = 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,125 +3,42 @@
|
|||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "lpx-basebuffer.hpp"
|
#include "lpx-basebuffer.hpp"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// FlxStringDecoder
|
|
||||||
//
|
|
||||||
// This class is used to decipher 8-bit strings that
|
|
||||||
// contain packed ints, strings, and other data.
|
|
||||||
// The typical example of usage is to decipher the
|
|
||||||
// serialized animation queues fed to us by Luprex.
|
|
||||||
//
|
|
||||||
// The FlxStringDecoder doesn't make a copy of the string
|
|
||||||
// you pass in, instead, it stores a pointer to it.
|
|
||||||
// So be sure not to free the string until you're
|
|
||||||
// done analyzing it.
|
|
||||||
//
|
|
||||||
// You'll note that some of the function names are
|
|
||||||
// lowercase, with underscores. That's because they're
|
|
||||||
// inherited from Luprex classes, and luprex classes
|
|
||||||
// use that naming convention. There's not any easy
|
|
||||||
// workaround for that.
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
class FlxStreamBufferCore {
|
||||||
class FlxStringDecoder : public BaseReader<FlxStringDecoder> {
|
|
||||||
private:
|
private:
|
||||||
const char* Text;
|
bool err_eof_on_read_;
|
||||||
size_t Size;
|
bool err_string_too_long_;
|
||||||
|
bool err_integer_truncated_;
|
||||||
|
protected:
|
||||||
|
|
||||||
public:
|
void *basebuffer_malloc(size_t size) { return malloc(size); }
|
||||||
// You can check and clear these error flags at will.
|
void basebuffer_free(void *p) { free(p); }
|
||||||
//
|
void clear_error_flags() { err_eof_on_read_ = err_string_too_long_ = err_integer_truncated_ = false; }
|
||||||
bool ErrBeyondEOF;
|
void raise_eof_on_read() { err_eof_on_read_ = true; }
|
||||||
bool ErrStringTooLong;
|
void raise_string_too_long() { err_string_too_long_ = true; }
|
||||||
|
void raise_integer_truncated() { err_integer_truncated_ = true; }
|
||||||
|
|
||||||
public:
|
bool get_err_eof_on_read() const { return err_eof_on_read_; }
|
||||||
// This function is required by BaseReader.
|
bool get_err_string_too_long() const { return err_string_too_long_; }
|
||||||
// It's not meant for end users.
|
bool get_err_integer_truncated() const { return err_integer_truncated_; }
|
||||||
//
|
bool any_error() const { return err_eof_on_read_ || err_string_too_long_ || err_integer_truncated_; }
|
||||||
void read_bytes_into(char* buffer, size_t size) {
|
|
||||||
if (size > Size) {
|
|
||||||
memset(buffer, 0, size);
|
|
||||||
ErrBeyondEOF = true;
|
|
||||||
set_at_eof();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(buffer, Text, size);
|
|
||||||
Text += size;
|
|
||||||
Size -= size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is required by BaseReader.
|
|
||||||
// It's not meant for end users.
|
|
||||||
//
|
|
||||||
void raise_string_too_long() {
|
|
||||||
ErrStringTooLong = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// The type returned by read_string.
|
|
||||||
//
|
|
||||||
using read_string_type = std::string;
|
|
||||||
|
|
||||||
// Initialize the string decoder with a text to analyze.
|
|
||||||
//
|
|
||||||
FlxStringDecoder(std::string_view s);
|
|
||||||
|
|
||||||
// Get the remaining text as a string_view.
|
|
||||||
//
|
|
||||||
std::string_view GetRest();
|
|
||||||
|
|
||||||
// Reinitialize with a new string_view.
|
|
||||||
//
|
|
||||||
// If clear is true, clears the error flags.
|
|
||||||
//
|
|
||||||
void Reset(std::string_view s, bool clear);
|
|
||||||
|
|
||||||
// Get the size of the remaining text.
|
|
||||||
//
|
|
||||||
size_t get_size() { return Size; }
|
|
||||||
|
|
||||||
// Return true if the remaining text is empty.
|
|
||||||
//
|
|
||||||
bool at_eof() { return Size == 0; }
|
|
||||||
|
|
||||||
// Move the cursor to EOF.
|
|
||||||
//
|
|
||||||
void set_at_eof();
|
|
||||||
|
|
||||||
|
|
||||||
// Read a string as a string_view
|
|
||||||
//
|
|
||||||
// This reads a string from the source, returning
|
|
||||||
// it as a string_view that points into the buffer.
|
|
||||||
// Naturally, if you release the buffer, the
|
|
||||||
// string_view is invalidated.
|
|
||||||
//
|
|
||||||
// This is considerably faster than read_string.
|
|
||||||
//
|
|
||||||
std::string_view read_string_view();
|
|
||||||
|
|
||||||
// Inherited Methods:
|
|
||||||
//
|
|
||||||
// The following methods are inherited from BaseReader:
|
|
||||||
//
|
|
||||||
// uint8_t read_uint8();
|
|
||||||
// uint16_t read_uint16();
|
|
||||||
// uint32_t read_uint32();
|
|
||||||
// uint64_t read_uint64();
|
|
||||||
// int8_t read_int8();
|
|
||||||
// int16_t read_int16();
|
|
||||||
// int32_t read_int32();
|
|
||||||
// int64_t read_int64();
|
|
||||||
// bool read_bool();
|
|
||||||
// char read_char();
|
|
||||||
// float read_float();
|
|
||||||
// double read_double();
|
|
||||||
// size_t read_length();
|
|
||||||
// std::string read_string_limit(uint64_t size);
|
|
||||||
// std::string read_string();
|
|
||||||
//
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FlxStreamBuffer : public BaseBuffer<FlxStreamBufferCore, std::string> {
|
||||||
|
public:
|
||||||
|
using BaseBuffer::BaseBuffer;
|
||||||
|
|
||||||
|
void write_dxyz(const FVector &xyz) {
|
||||||
|
write_double(xyz.X);
|
||||||
|
write_double(xyz.Y);
|
||||||
|
write_double(xyz.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector read_dxyz() {
|
||||||
|
double x = read_double();
|
||||||
|
double y = read_double();
|
||||||
|
double z = read_double();
|
||||||
|
return FVector(x, y, z);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user