Skip to content

Commit

Permalink
1.00
Browse files Browse the repository at this point in the history
- Improved EP1 support
  • Loading branch information
not_alphanine committed Jun 1, 2024
1 parent f10a744 commit f167bd9
Show file tree
Hide file tree
Showing 17 changed files with 455 additions and 340 deletions.
Binary file modified NewGamePlus.rc
Binary file not shown.
1 change: 1 addition & 0 deletions SaveDataParser.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand Down
2 changes: 1 addition & 1 deletion deps/simdjson
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ RED4EXT_C_EXPORT void RED4EXT_CALL Query(RED4ext::PluginInfo* aInfo)
{
aInfo->name = L"New Game+";
aInfo->author = L"not_alphanine";
aInfo->version = RED4EXT_SEMVER_EX(0, 9, 9, 0, 0); // Set your version here.
aInfo->version = RED4EXT_SEMVER_EX(1, 0, 0, 0, 0); // Set your version here.
aInfo->runtime = RED4EXT_RUNTIME_INDEPENDENT;
aInfo->sdk = RED4EXT_SDK_LATEST;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,59 +23,13 @@ class NativePersistencyReader : public redRTTI::native::NativeReader
virtual void ReadEnum(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aType) final
{
auto enumType = static_cast<RED4ext::CEnum*>(aType);
std::int64_t enumIndexer{};

switch (enumType->actualSize)
if (enumType->actualSize == 0)
{
case 1u:
enumIndexer = aCursor.readByte();
if (enumIndexer < enumType->valueList.size)
{
*reinterpret_cast<std::uint8_t*>(aOut) = static_cast<std::uint8_t>(enumIndexer);
}
else
{
*reinterpret_cast<std::uint8_t*>(aOut) = static_cast<std::uint8_t>(enumType->valueList.Back());
}
break;
case 2u:
enumIndexer = aCursor.readShort();
if (enumIndexer < enumType->valueList.size)
{
*reinterpret_cast<std::uint16_t*>(aOut) = static_cast<std::uint16_t>(enumIndexer);
}
else
{
*reinterpret_cast<std::uint16_t*>(aOut) = static_cast<std::uint16_t>(enumType->valueList.Back());
}
break;
case 4u:
enumIndexer = aCursor.readInt();
if (enumIndexer < enumType->valueList.size)
{
*reinterpret_cast<std::uint32_t*>(aOut) = static_cast<std::uint32_t>(enumIndexer);
}
else
{
*reinterpret_cast<std::uint32_t*>(aOut) = static_cast<std::uint32_t>(enumType->valueList.Back());
}
break;
case 8u:
enumIndexer = aCursor.readInt64();
if (enumIndexer < enumType->valueList.size)
{
*reinterpret_cast<std::uint64_t*>(aOut) = static_cast<std::uint64_t>(enumIndexer);
}
else
{
*reinterpret_cast<std::uint64_t*>(aOut) = static_cast<std::uint64_t>(enumType->valueList.Back());
}
break;
default:
throw std::runtime_error{
std::format("Enum {} has size {}", enumType->GetName().ToString(), enumType->actualSize)};
break;
PluginContext::Error("NativePersistencyReader::ReadEnum, enumType->actualSize == 0");
}

aCursor.CopyTo(aOut, enumType->actualSize);
}

virtual void ReadHandle(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aType) final
Expand Down Expand Up @@ -105,6 +59,40 @@ class NativePersistencyReader : public redRTTI::native::NativeReader
// Skip this, currently we have no need for wrefs
aCursor.readInt();
}

virtual bool TryReadHandle(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aType) noexcept final
{
const auto handleType = static_cast<Red::CRTTIHandleType*>(aType);
auto innerType = handleType->GetInnerType();

if (innerType->GetType() != Red::ERTTIType::Class)
{
PluginContext::Error(std::format("Tried to read handle of a non-class type! Typename: {}", aType->GetName().ToString()));
return false;
}

auto instance = static_cast<Red::CClass*>(innerType)->CreateInstance();
auto handle = Red::Handle<Red::ISerializable>(reinterpret_cast<Red::ISerializable*>(instance));

if (!TryReadValue(aCursor, handle.GetPtr(), innerType))
{
return false;
}

using HandleType = Red::Handle<Red::ISerializable>;

reinterpret_cast<HandleType*>(aOut)->Swap(handle);

return true;
}

virtual bool TryReadWeakHandle(FileCursor& aCursor, Red::ScriptInstance aOut,
Red::CBaseRTTIType* aType) noexcept final
{
aCursor.readInt();
return true;
}

public:
virtual void ReadClass(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aClass) final
{
Expand Down Expand Up @@ -152,5 +140,47 @@ class NativePersistencyReader : public redRTTI::native::NativeReader
PluginContext::Error(std::format("NativePersistencyReader::ReadClass, {}", e.what()));
}
}

virtual bool TryReadClass(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aClass) noexcept final
{
auto classType = static_cast<Red::CClass*>(aClass);

while (aCursor.getRemaining())
{
auto propName = aCursor.ReadCNameHash();

if (propName.IsNone())
{
break;
}

auto propTypeStr = aCursor.ReadCNameHash();
auto prop = classType->GetProperty(propName);

if (!prop)
{
PluginContext::Error(std::format("Prop {}::{} does not exist!", classType->name.ToString(), propName.ToString()));
return false;
}

if (propTypeStr != prop->type->GetName())
{
PluginContext::Error(
std::format("Prop {}::{} type mismatch, {} != {}!", classType->name.ToString(), propName.ToString(), prop->type->GetName().ToString(), propTypeStr.ToString()));
return false;
}

auto valuePtr = prop->GetValuePtr<std::remove_pointer_t<Red::ScriptInstance>>(aOut);

if (!TryReadValue(aCursor, valuePtr, prop->type))
{
PluginContext::Error(
std::format("Failed to read {}::{}", classType->name.ToString(), propName.ToString()));
return false;
}
}

return true;
}
};
} // namespace persistency::native
Original file line number Diff line number Diff line change
Expand Up @@ -115,32 +115,27 @@ class PersistencySystemNode : public NodeDataInterface
auto instance = static_cast<Red::CClass*>(type)->CreateInstance();
auto subCursor = aCursor.CreateSubCursor(classSize);

try
if (reader.TryReadClass(subCursor, instance, type))
{
reader.ReadClass(subCursor, instance, type);
}
catch (const std::exception& e)
{
// Don't do anything, pray that it doesn't crash
}
// Small optimization: instead of resizing the vector for all the persistent nodes (that we only
// use one of anyway), we only instantiate the needed one(s)
m_redClasses.emplace_back();

// Small optimization: instead of resizing the vector for all the persistent nodes (that we only use one of anyway), we only instantiate the needed one(s)
m_redClasses.emplace_back();
auto& entry = m_redClasses.back();

auto& entry = m_redClasses.back();
entry.m_classInstance.SetInstance(instance);
entry.m_className = classHash;
entry.m_id = classId;

entry.m_classInstance.SetInstance(instance);
entry.m_className = classHash;
entry.m_id = classId;

if constexpr (m_onlyDoVehicleGarage)
{
// We're done here LOL
// Seek to the end of the node so LoadNodes doesn't whine
if constexpr (m_onlyDoVehicleGarage)
{
// We're done here LOL
// Seek to the end of the node so LoadNodes doesn't whine

aCursor.seekTo(FileCursor::SeekTo::Start, node.offset + node.GetExpectedSize());
aCursor.seekTo(FileCursor::SeekTo::Start, node.offset + node.GetExpectedSize());

break;
break;
}
}
}

Expand Down
Loading

0 comments on commit f167bd9

Please sign in to comment.