Aggiungere i file di progetto.

This commit is contained in:
AlessandroCH 2025-03-07 20:49:49 +01:00
commit f0855b9589
214 changed files with 270213 additions and 0 deletions

82
.editorconfig Normal file
View File

@ -0,0 +1,82 @@
[*.cs]
# IDE0090: Use 'new(...)'
dotnet_diagnostic.IDE0090.severity = none
csharp_indent_labels = one_less_than_current
csharp_space_around_binary_operators = before_and_after
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_primary_constructors = true:suggestion
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
[*.{cs,vb}]
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_prefer_collection_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
[*.{cs,vb}]
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

37
.github/workflows/nightly.yml vendored Normal file
View File

@ -0,0 +1,37 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: Nightly
on:
workflow_dispatch:
schedule:
# This runs every day at midnight: https://crontab.guru/#0_0_*_*_*
- cron: "0 0 * * *"
jobs:
build:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
include:
- os: windows-latest
build: Campofinale-${{github.ref_name}}-Windows
- os: ubuntu-latest
build: Campofinale-${{github.ref_name}}-Linux
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.build }}
path: Campofinale/bin/Release/net8.0

36
.github/workflows/stable.yml vendored Normal file
View File

@ -0,0 +1,36 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: Stable
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
include:
- os: windows-latest
build: Campofinale-${{github.ref_name}}-Windows
- os: ubuntu-latest
build: Campofinale-${{github.ref_name}}-Linux
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.build }}
path: Campofinale/bin/Release/net8.0

366
.gitignore vendored Normal file
View File

@ -0,0 +1,366 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
decrypter/
endfield-cbt2-dumps/

View File

@ -0,0 +1,901 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AnalysisLevel>6.0</AnalysisLevel>
<Platforms>AnyCPU;ARM32</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.25.0" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.59.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Protobuf Include="*.proto" ProtoRoot="." GrpcServices="None" />
</ItemGroup>
<ItemGroup>
<None Remove="AbilityActionCreateGadget.proto" />
<None Remove="AbilityActionSummon.proto" />
<None Remove="AbilityAppliedAbility.proto" />
<None Remove="AbilityArgument.proto" />
<None Remove="AbilityBornType.proto" />
<None Remove="AbilityGadgetInfo.proto" />
<None Remove="AbilityInvocationFailNotify.proto" />
<None Remove="AbilityInvocationsNotify.proto" />
<None Remove="AbilityInvokeEntry.proto" />
<None Remove="AbilityMetaAddAbility.proto" />
<None Remove="AbilityMetaModifierChange.proto" />
<None Remove="AbilityMetaSetAbilityTrigger.proto" />
<None Remove="AbilityMetaSetModifierApplyEntityId.proto" />
<None Remove="AbilityMixinAvatarSteerByCamera.proto" />
<None Remove="AbilityMixinElementShield.proto" />
<None Remove="AbilityMixinEmpty.proto" />
<None Remove="AbilityResetReason.proto" />
<None Remove="AbilityScalarType.proto" />
<None Remove="AbilityString.proto" />
<None Remove="AddQuestContentProgressReq.proto" />
<None Remove="AddSeenMonsterNotify.proto" />
<None Remove="AllSeenMonsterNotify.proto" />
<None Remove="AnimatorParameterValueInfo.proto" />
<None Remove="AREA_TYPE.proto" />
<None Remove="AREA_UNLOCK_INFO.proto" />
<None Remove="AttackHitEffectResult.proto" />
<None Remove="ATTR_INFO.proto" />
<None Remove="AuthkeySignType.proto" />
<None Remove="AuthRequest.proto" />
<None Remove="AuthResponse.proto" />
<None Remove="AvatarAddNotify.proto" />
<None Remove="AvatarCardChangeRsp.proto" />
<None Remove="AvatarChangeElementTypeRsp.proto" />
<None Remove="AvatarDelNotify.proto" />
<None Remove="AvatarDieAnimationEndRsp.proto" />
<None Remove="AvatarEnterSceneInfo.proto" />
<None Remove="AvatarFightPropNotify.proto" />
<None Remove="AvatarInfo.proto" />
<None Remove="AvatarPromoteReq.proto" />
<None Remove="AvatarPropChangeReasonNotify.proto" />
<None Remove="AvatarSkillDepotChangeNotify.proto" />
<None Remove="AvatarSkillInfoNotify.proto" />
<None Remove="AvatarTeam.proto" />
<None Remove="AvatarUnlockTalentNotify.proto" />
<None Remove="AvatarUpgradeRsp.proto" />
<None Remove="BackMyWorldRsp.proto" />
<None Remove="BATTLE_INFO.proto" />
<None Remove="BigTalentPointConvertReq.proto" />
<None Remove="BITSET_DATA.proto" />
<None Remove="BLOC_INFO.proto" />
<None Remove="BuffAddNotify.proto" />
<None Remove="BuyGoodsReq.proto" />
<None Remove="CellInfo.proto" />
<None Remove="ChangeAvatarReq.proto" />
<None Remove="ChangeGameTimeReq.proto" />
<None Remove="ChangHpReason.proto" />
<None Remove="ChapterStateNotify.proto" />
<None Remove="CHAR_INFO.proto" />
<None Remove="CHAR_TEAM_INFO.proto" />
<None Remove="CHAR_TEAM_MEMBER_INFO.proto" />
<None Remove="ChooseCurAvatarTeamReq.proto" />
<None Remove="CityInfo.proto" />
<None Remove="ClientAbilityInitFinishNotify.proto" />
<None Remove="ClientGadgetInfo.proto" />
<None Remove="ClientPauseNotify.proto" />
<None Remove="ClientReconnectReason.proto" />
<None Remove="ClientTransmitReq.proto" />
<None Remove="ClientTriggerEventNotify.proto" />
<None Remove="CLIENT_PLATFORM_TYPE.proto" />
<None Remove="CmdAbilityReflection.proto" />
<None Remove="CmdFightReflection.proto" />
<None Remove="cmdids.csv" />
<None Remove="CmdItemReflection.proto" />
<None Remove="CmdMiscReflection.proto" />
<None Remove="CmdNpcReflection.proto" />
<None Remove="CmdPropertyReflection.proto" />
<None Remove="CmdSceneReflection.proto" />
<None Remove="CmdSkillReflection.proto" />
<None Remove="Component.proto" />
<None Remove="ComponentBoxConveyor.proto" />
<None Remove="ComponentBoxRouter.proto" />
<None Remove="ComponentCache.proto" />
<None Remove="ComponentCollector.proto" />
<None Remove="ComponentInventory.proto" />
<None Remove="ComponentMap.proto" />
<None Remove="ComponentProducer.proto" />
<None Remove="ComponentSelector.proto" />
<None Remove="ComponentTransform.proto" />
<None Remove="ComponentType.proto" />
<None Remove="CompoundDataNotify.proto" />
<None Remove="ContextArchive.proto" />
<None Remove="ContextBlackboard.proto" />
<None Remove="ContextBrief.proto" />
<None Remove="ContextStatus.proto" />
<None Remove="CookDataNotify.proto" />
<None Remove="CookRecipeData.proto" />
<None Remove="COST_ITEM_LIST_DEF.proto" />
<None Remove="CreateEntityInfo.proto" />
<None Remove="CreateReason.proto" />
<None Remove="CSD_FACTORY_INTERACTIVE_PARAM.proto" />
<None Remove="CSD_FACTORY_OBSERVER_PAYLOAD_OP_CHECKOUT_CHARACTER_WORK.proto" />
<None Remove="CSD_FACTORY_OBSERVER_PAYLOAD_OP_CHECKOUT_OUTSIDE_RESOURCE.proto" />
<None Remove="CSD_FACTORY_OBSERVER_PAYLOAD_OP_CHECKOUT_POWER_CONNECTION_MAP.proto" />
<None Remove="CSD_FACTORY_OBSERVER_PAYLOAD_OP_CHECKOUT_RELATION_BOARD.proto" />
<None Remove="CSD_FACTORY_OP_ADD_CONNECTION.proto" />
<None Remove="CSD_FACTORY_OP_CACHE_TRANSPORT_ENABLE.proto" />
<None Remove="CSD_FACTORY_OP_CACHE_TRANSPORT_TRANSFER.proto" />
<None Remove="CSD_FACTORY_OP_DEL_CONNECTION.proto" />
<None Remove="CSD_FACTORY_OP_DISMANTLE.proto" />
<None Remove="CSD_FACTORY_OP_DISMANTLE_BOX_CONVEYOR.proto" />
<None Remove="CSD_FACTORY_OP_ENABLE_NODE.proto" />
<None Remove="CSD_FACTORY_OP_GRID_BOX_INNER_MOVE.proto" />
<None Remove="CSD_FACTORY_OP_GRID_BOX_INNER_SPLIT.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_BAG_TO_CACHE.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_BAG_TO_GRID_BOX.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_CACHE_TO_BAG.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_CACHE_TO_CACHE.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_CACHE_TO_DEPOT.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_CONVEYOR_TO_BAG.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_DEPOT_TO_CACHE.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_DEPOT_TO_GRID_BOX.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_GRID_BOX_TO_BAG.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_ITEM_GRID_BOX_TO_DEPOT.proto" />
<None Remove="CSD_FACTORY_OP_MOVE_NODE.proto" />
<None Remove="CSD_FACTORY_OP_PLACE.proto" />
<None Remove="CSD_FACTORY_OP_PLACE_BOX_CONVEYOR.proto" />
<None Remove="CSD_FACTORY_OP_SET_COLLECT_TARGET.proto" />
<None Remove="CSD_FACTORY_OP_SET_SELECT_TARGET.proto" />
<None Remove="CSD_FACTORY_OP_SET_TRAVEL_POLE_DEFAULT_NEXT.proto" />
<None Remove="CSD_FACTORY_OP_USE_HEAL_TOWER_POINT.proto" />
<None Remove="CSD_SP_INTERACTIVE_DOODAD_COMMON_BREAK.proto" />
<None Remove="CSD_SP_INTERACTIVE_DOODAD_COMMON_PICK.proto" />
<None Remove="CSHead.proto" />
<None Remove="CS_ACCEPT_MISSION.proto" />
<None Remove="CS_ACHIEVE_COMPLETE.proto" />
<None Remove="CS_ACHIEVE_TAKE_REWARD.proto" />
<None Remove="CS_BITSET_ADD.proto" />
<None Remove="CS_BITSET_REMOVE.proto" />
<None Remove="CS_BITSET_REMOVE_ALL.proto" />
<None Remove="CS_BLOC_SHOP_BUY.proto" />
<None Remove="CS_CHAR_BAG_SET_CURR_TEAM_INDEX.proto" />
<None Remove="CS_CHAR_BAG_SET_TEAM.proto" />
<None Remove="CS_CHAR_BAG_SET_TEAM_LEADER.proto" />
<None Remove="CS_CHAR_BAG_SET_TEAM_NAME.proto" />
<None Remove="CS_CHAR_BREAK.proto" />
<None Remove="CS_CHAR_LEVEL_UP.proto" />
<None Remove="CS_CHAR_SET_BATTLE_INFO.proto" />
<None Remove="CS_CHAR_SET_NORMAL_SKILL.proto" />
<None Remove="CS_CHAR_SET_TEAM_SKILL.proto" />
<None Remove="CS_CHAR_SKILL_LEVEL_UP.proto" />
<None Remove="CS_COMPLETE_GUIDE_GROUP.proto" />
<None Remove="CS_COMPLETE_GUIDE_GROUP_KEY_STEP.proto" />
<None Remove="CS_CREATE_ROLE.proto" />
<None Remove="CS_DELETE_ALL_MAIL.proto" />
<None Remove="CS_DELETE_MAIL.proto" />
<None Remove="CS_DUNGEON_RECOVER_AP.proto" />
<None Remove="CS_DUNGEON_REWARD.proto" />
<None Remove="CS_ENTER_DUNGEON.proto" />
<None Remove="CS_ENTER_SCENE.proto" />
<None Remove="CS_EQUIP_PUTOFF.proto" />
<None Remove="CS_EQUIP_PUTON.proto" />
<None Remove="CS_FACTORY_CHARACTER_WORK_PUNCH_IN.proto" />
<None Remove="CS_FACTORY_CHARACTER_WORK_PUNCH_OUT.proto" />
<None Remove="CS_FACTORY_HS_FB.proto" />
<None Remove="CS_FACTORY_HS_INOUT.proto" />
<None Remove="CS_FACTORY_MANUALLY_WORK_APPEND.proto" />
<None Remove="CS_FACTORY_MANUALLY_WORK_CANCEL.proto" />
<None Remove="CS_FACTORY_MANUALLY_WORK_PAUSE.proto" />
<None Remove="CS_FACTORY_MANUALLY_WORK_RESUME.proto" />
<None Remove="CS_FACTORY_MANUFACTURE_CANCEL.proto" />
<None Remove="CS_FACTORY_MANUFACTURE_SETTLE.proto" />
<None Remove="CS_FACTORY_MANUFACTURE_START.proto" />
<None Remove="CS_FACTORY_OBSERVER_OP.proto" />
<None Remove="CS_FACTORY_OP.proto" />
<None Remove="CS_FACTORY_PROCESSOR_MAKE_EQUIP.proto" />
<None Remove="CS_FACTORY_PROCESSOR_MAKE_GEM.proto" />
<None Remove="CS_FACTORY_PROCESSOR_MAKE_ITEM.proto" />
<None Remove="CS_FACTORY_PROCESSOR_MARK_UNLOCK_FORMULA_READ.proto" />
<None Remove="CS_FACTORY_PROCESSOR_RECAST_GEM.proto" />
<None Remove="CS_FACTORY_QUICKBAR_MOVE_ONE.proto" />
<None Remove="CS_FACTORY_QUICKBAR_SET_ONE.proto" />
<None Remove="CS_FACTORY_RECYCLER_COMMIT_MATERIAL.proto" />
<None Remove="CS_FACTORY_RECYCLER_FETCH_PRODUCT.proto" />
<None Remove="CS_FACTORY_REPAIR_BUILDING.proto" />
<None Remove="CS_FACTORY_SOIL_CANCEL.proto" />
<None Remove="CS_FACTORY_SOIL_HARVEST.proto" />
<None Remove="CS_FACTORY_SOIL_PLANT.proto" />
<None Remove="CS_FACTORY_STATISTIC_REQUIRE.proto" />
<None Remove="CS_FACTORY_STATISTIC_SET_BOOKMARK_ITEM_IDS.proto" />
<None Remove="CS_FACTORY_STT_UNLOCK_NODE.proto" />
<None Remove="CS_FACTORY_TRADE_CASH_ORDER.proto" />
<None Remove="CS_FACTORY_TRADE_DELETE_ORDER.proto" />
<None Remove="CS_FACTORY_TRADE_SET_CONTRACT.proto" />
<None Remove="CS_FACTORY_WORKSHOP_MAKE.proto" />
<None Remove="CS_FAIL_MISSION.proto" />
<None Remove="CS_FINISH_DIALOG.proto" />
<None Remove="CS_FLUSH_SYNC.proto" />
<None Remove="CS_GET_ALL_MAIL_ATTACHMENT.proto" />
<None Remove="CS_GET_MAIL.proto" />
<None Remove="CS_GET_MAIL_ATTACHMENT.proto" />
<None Remove="CS_GM_COMMAND.proto" />
<None Remove="CS_ITEM_BAG_BAG_TO_FACTORY_DEPOT.proto" />
<None Remove="CS_ITEM_BAG_DESTROY_IN_BAG.proto" />
<None Remove="CS_ITEM_BAG_DESTROY_IN_DEPOT.proto" />
<None Remove="CS_ITEM_BAG_FACTORY_DEPOT_TO_BAG.proto" />
<None Remove="CS_ITEM_BAG_FACTORY_DEPOT_TO_BAG_GRID.proto" />
<None Remove="CS_ITEM_BAG_MOVE_IN_BAG.proto" />
<None Remove="CS_ITEM_BAG_SET_ITEM_LOCK.proto" />
<None Remove="CS_ITEM_BAG_SET_QUICK_BAR.proto" />
<None Remove="CS_ITEM_BAG_SET_QUICK_BAR_POS.proto" />
<None Remove="CS_ITEM_BAG_SPLIT_IN_BAG.proto" />
<None Remove="CS_ITEM_BAG_TIDY_IN_BAG.proto" />
<None Remove="CS_ITEM_BAG_USE_ITEM.proto" />
<None Remove="CS_LEAVE_DUNGEON.proto" />
<None Remove="CS_LOGIN.proto" />
<None Remove="CS_LOGOUT.proto" />
<None Remove="CS_MAIL_DEF.proto" />
<None Remove="CS_MARK_WIKI_READ.proto" />
<None Remove="CS_MERGE_MSG.proto" />
<None Remove="CS_MOVE_OBJECT_MOVE.proto" />
<None Remove="CS_PING.proto" />
<None Remove="CS_PRTS_MARK_READ.proto" />
<None Remove="CS_PRTS_MARK_TERMINAL_READ.proto" />
<None Remove="CS_READ_MAIL.proto" />
<None Remove="CS_RED_DOT_READ_FORMULA.proto" />
<None Remove="CS_REMOVE_ITEM_NEW_TAGS.proto" />
<None Remove="CS_RESTART_DUNGEON.proto" />
<None Remove="CS_ROLL_BLOC_MISSION.proto" />
<None Remove="CS_SCENE_COMMIT_LEVEL_SCRIPT_CACHE_STEP.proto" />
<None Remove="CS_SCENE_CREATE_ENTITY.proto" />
<None Remove="CS_SCENE_DESTROY_ENTITY.proto" />
<None Remove="CS_SCENE_INTERACTIVE_EVENT_TRIGGER.proto" />
<None Remove="CS_SCENE_INTERACT_SP_INTERACTIVE.proto" />
<None Remove="CS_SCENE_INTERACT_TREE.proto" />
<None Remove="CS_SCENE_KILL_CHAR.proto" />
<None Remove="CS_SCENE_KILL_MONSTER.proto" />
<None Remove="CS_SCENE_LEVEL_SCRIPT_EVENT_TRIGGER.proto" />
<None Remove="CS_SCENE_LOAD_FINISH.proto" />
<None Remove="CS_SCENE_MAP_MARK_CREATE.proto" />
<None Remove="CS_SCENE_MAP_MARK_UPDATE_STATE.proto" />
<None Remove="CS_SCENE_MOVE_STATE_SET.proto" />
<None Remove="CS_SCENE_QUERY_ENTITY_EXIST.proto" />
<None Remove="CS_SCENE_QUERY_INTERACTIVE_PROPERTY.proto" />
<None Remove="CS_SCENE_REPATRIATE.proto" />
<None Remove="CS_SCENE_RESET_ENTITY.proto" />
<None Remove="CS_SCENE_RESET_LEVEL_SCRIPT.proto" />
<None Remove="CS_SCENE_REST.proto" />
<None Remove="CS_SCENE_REVIVAL.proto" />
<None Remove="CS_SCENE_SET_BATTLE.proto" />
<None Remove="CS_SCENE_SET_CHECK_POINT.proto" />
<None Remove="CS_SCENE_SET_LAST_RECORD_CAMPID.proto" />
<None Remove="CS_SCENE_SET_LEVEL_SCRIPT_ACTIVE.proto" />
<None Remove="CS_SCENE_SET_REPATRIATE_POINT.proto" />
<None Remove="CS_SCENE_SET_SAFE_ZONE.proto" />
<None Remove="CS_SCENE_SET_TRACK_POINT.proto" />
<None Remove="CS_SCENE_SET_VAR.proto" />
<None Remove="CS_SCENE_SPAWN_INTERACTIVE.proto" />
<None Remove="CS_SCENE_SPAWN_MONSTER.proto" />
<None Remove="CS_SCENE_SUBMIT_ETHER.proto" />
<None Remove="CS_SCENE_SUBMIT_ITEM.proto" />
<None Remove="CS_SCENE_TELEPORT.proto" />
<None Remove="CS_SCENE_UPDATE_INTERACTIVE_PROPERTY.proto" />
<None Remove="CS_SCENE_UPDATE_LEVEL_SCRIPT_PROPERTY.proto" />
<None Remove="CS_STOP_TRACKING_MISSION.proto" />
<None Remove="CS_TRACK_MISSION.proto" />
<None Remove="CS_UNLOCK_WIKI.proto" />
<None Remove="CS_UPDATE_QUEST_OBJECTIVE.proto" />
<None Remove="CS_WEAPON_ADD_EXP.proto" />
<None Remove="CS_WEAPON_ATTACH_GEM.proto" />
<None Remove="CS_WEAPON_BREAKTHROUGH.proto" />
<None Remove="CS_WEAPON_DETACH_GEM.proto" />
<None Remove="CS_WEAPON_PUTON.proto" />
<None Remove="CS_WIKI_PIN.proto" />
<None Remove="CutSceneEndNotify.proto" />
<None Remove="DataResVersionNotify.proto" />
<None Remove="DefineReflection.proto" />
<None Remove="DelMailRsp.proto" />
<None Remove="DIALOG.proto" />
<None Remove="Direction.proto" />
<None Remove="DISCOUNT_INFO.proto" />
<None Remove="DropHintNotify.proto" />
<None Remove="DropItemRsp.proto" />
<None Remove="DropSubfieldRsp.proto" />
<None Remove="DungeonChallengeBeginNotify.proto" />
<None Remove="DungeonDataNotify.proto" />
<None Remove="DungeonDieOptionReq.proto" />
<None Remove="DungeonEntryInfo.proto" />
<None Remove="DungeonEntryInfoRsp.proto" />
<None Remove="DungeonPlayerDieNotify.proto" />
<None Remove="DungeonPlayerDieRsp.proto" />
<None Remove="DungeonShowReminderNotify.proto" />
<None Remove="DungeonWayPointActivateRsp.proto" />
<None Remove="DYNAMIC_PARAMETER.proto" />
<None Remove="EditorReflection.proto" />
<None Remove="EncryptType.proto" />
<None Remove="ENetReason.proto" />
<None Remove="EnterSceneDoneRsp.proto" />
<None Remove="EnterSceneReadyReq.proto" />
<None Remove="EnterSceneWeatherAreaNotify.proto" />
<None Remove="EnterType.proto" />
<None Remove="EnterWorldAreaRsp.proto" />
<None Remove="EntityFightPropChangeReasonNotify.proto" />
<None Remove="EntityFightPropUpdateNotify.proto" />
<None Remove="EntityForceSyncRsp.proto" />
<None Remove="EntityMoveFailInfo.proto" />
<None Remove="EntityPropNotify.proto" />
<None Remove="ENTITY_INFO.proto" />
<None Remove="ENTITY_OP_TYPE.proto" />
<None Remove="ENV_TYPE.proto" />
<None Remove="EquipParam.proto" />
<None Remove="EQUIP_ATTR.proto" />
<None Remove="EQUIP_DATA.proto" />
<None Remove="Event.proto" />
<None Remove="EventComponentChg.proto" />
<None Remove="EventLayoutChg.proto" />
<None Remove="EventPrepared.proto" />
<None Remove="EventRelationChg.proto" />
<None Remove="EventTriggerType.proto" />
<None Remove="EventType.proto" />
<None Remove="EvtAnimatorParameterNotify.proto" />
<None Remove="EvtAvatarEnterFocusNotify.proto" />
<None Remove="EvtAvatarUpdateFocusNotify.proto" />
<None Remove="EvtBulletDeactiveNotify.proto" />
<None Remove="EvtBulletMoveNotify.proto" />
<None Remove="EvtCreateGadgetNotify.proto" />
<None Remove="EvtDoSkillSuccNotify.proto" />
<None Remove="EvtEntityStartDieEndNotify.proto" />
<None Remove="EvtFaceToEntityNotify.proto" />
<None Remove="EvtSetAttackTargetNotify.proto" />
<None Remove="ExecuteGadgetLuaRsp.proto" />
<None Remove="ExecuteGroupTriggerRsp.proto" />
<None Remove="ExitTransPointRegionNotify.proto" />
<None Remove="E_USE_ITEM_RESULT.proto" />
<None Remove="FACTORY_OP_RET_CODE.proto" />
<None Remove="FACTORY_OP_TYPE.proto" />
<None Remove="FACTORY_SOIL_HARVEST_TYPE.proto" />
<None Remove="FinishedParentQuestUpdateNotify.proto" />
<None Remove="Formula.proto" />
<None Remove="ForwardType.proto" />
<None Remove="GadgetInteractReq.proto" />
<None Remove="GadgetStateNotify.proto" />
<None Remove="GEM_DATA.proto" />
<None Remove="GENDER.proto" />
<None Remove="GetAllMailReq.proto" />
<None Remove="GetAuthkeyReq.proto" />
<None Remove="GetCompoundDataReq.proto" />
<None Remove="GetMailItemReq.proto" />
<None Remove="GetOnlinePlayerListReq.proto" />
<None Remove="GetPlayerTokenReq.proto" />
<None Remove="GetQuestTalkHistoryReq.proto" />
<None Remove="GetSceneAreaReq.proto" />
<None Remove="GetSceneNpcPostionReq.proto" />
<None Remove="GetScenePointReq.proto" />
<None Remove="GetShopReq.proto" />
<None Remove="GmTalkReq.proto" />
<None Remove="GrantRewardNotify.proto" />
<None Remove="GUIDE_GROUP_INFO.proto" />
<None Remove="Header.proto" />
<None Remove="HitColliderType.proto" />
<None Remove="HostPlayerNotify.proto" />
<None Remove="InterOpType.proto" />
<None Remove="ItemAddHintNotify.proto" />
<None Remove="ItemBox.proto" />
<None Remove="ItemCdGroupTimeNotify.proto" />
<None Remove="ItemParam.proto" />
<None Remove="ItemUnit.proto" />
<None Remove="ITEM_BUNDLE.proto" />
<None Remove="ITEM_INFO.proto" />
<None Remove="ITEM_INST.proto" />
<None Remove="ITEM_INST_EMPTY.proto" />
<None Remove="ITEM_INST_LOCK_INFO.proto" />
<None Remove="JoinPlayerSceneReq.proto" />
<None Remove="KeepAliveNotify.proto" />
<None Remove="LayoutShape.proto" />
<None Remove="LeaveSceneReq.proto" />
<None Remove="LEAVE_OBJECT_INFO.proto" />
<None Remove="LevelupCityReq.proto" />
<None Remove="LEVEL_SCRIPT_INFO.proto" />
<None Remove="LogBoolParam.proto" />
<None Remove="LogCutsceneNotify.proto" />
<None Remove="LogDoubleParam.proto" />
<None Remove="LogFloatParam.proto" />
<None Remove="LogIntParam.proto" />
<None Remove="LogLevel.proto" />
<None Remove="LogMessage.proto" />
<None Remove="LogMessageResponse.proto" />
<None Remove="LogStringParam.proto" />
<None Remove="LogTalkNotify.proto" />
<None Remove="MailData.proto" />
<None Remove="MAIL_CONTENT.proto" />
<None Remove="MapInfo.proto" />
<None Remove="Material.proto" />
<None Remove="MeshArea.proto" />
<None Remove="MeshAreaBitmap.proto" />
<None Remove="MessageType.proto" />
<None Remove="MISSION.proto" />
<None Remove="MISSION_STATE.proto" />
<None Remove="ModifierAction.proto" />
<None Remove="MONEY_INFO.proto" />
<None Remove="MonsterAlertChangeNotify.proto" />
<None Remove="MonsterForceAiNotify.proto" />
<None Remove="MonsterSummonTagNotify.proto" />
<None Remove="MotionState.proto" />
<None Remove="MOTION_INFO.proto" />
<None Remove="MOTION_STATE.proto" />
<None Remove="MOVE_OBJECT_MOVE_INFO.proto" />
<None Remove="Node.proto" />
<None Remove="NodeType.proto" />
<None Remove="NpcPostionInfo.proto" />
<None Remove="NpcTalkReq.proto" />
<None Remove="NpcTalkState.proto" />
<None Remove="NpcTalkType.proto" />
<None Remove="OBJECTIVE_VALUE_OP.proto" />
<None Remove="OnlinePlayerState.proto" />
<None Remove="OpenStateUpdateNotify.proto" />
<None Remove="Operate.proto" />
<None Remove="OperatePayloadAddNewArea.proto" />
<None Remove="OperatePayloadDismantle.proto" />
<None Remove="OperatePayloadPlace.proto" />
<None Remove="OperatePayloadPlaceConveyor.proto" />
<None Remove="OperatePayloadPutInItemsToCache.proto" />
<None Remove="OperatePayloadSetCollectTarget.proto" />
<None Remove="OperatePayloadSetEventEnable.proto" />
<None Remove="OperatePayloadSetUnloaderSelect.proto" />
<None Remove="OperatePayloadTakeOutItemsFromCache.proto" />
<None Remove="OperateRetCode.proto" />
<None Remove="OperateReturn.proto" />
<None Remove="OperateReturnPlace.proto" />
<None Remove="OperateReturnPlaceConveyor.proto" />
<None Remove="OperateReturnPutInItemsToCache.proto" />
<None Remove="OperateReturnTakeOutItemsFromCache.proto" />
<None Remove="OperateType.proto" />
<None Remove="ParamList.proto" />
<None Remove="ParentQuestRandomInfo.proto" />
<None Remove="PersonalSceneJumpRsp.proto" />
<None Remove="PingRsp.proto" />
<None Remove="PlatformChangeRouteNotify.proto" />
<None Remove="PlatformStartRouteNotify.proto" />
<None Remove="PlayerCompoundMaterialReq.proto" />
<None Remove="PlayerCookReq.proto" />
<None Remove="PlayerDataNotify.proto" />
<None Remove="PlayerDieType.proto" />
<None Remove="PlayerEnterDungeonRsp.proto" />
<None Remove="PlayerEnterSceneNotify.proto" />
<None Remove="PlayerLocationInfo.proto" />
<None Remove="PlayerLoginRsp.proto" />
<None Remove="PlayerLogoutReq.proto" />
<None Remove="PlayerPropChangeNotify.proto" />
<None Remove="PlayerPropNotify.proto" />
<None Remove="PlayerQuitDungeonRsp.proto" />
<None Remove="PlayerRandomCookRsp.proto" />
<None Remove="PlayerSetLanguageRsp.proto" />
<None Remove="PlayerSetPauseRsp.proto" />
<None Remove="PlayerTimeNotify.proto" />
<None Remove="PropValue.proto" />
<None Remove="QueryCurrRegionHttpRsp.proto" />
<None Remove="Quest.proto" />
<None Remove="QuestCreateEntityRsp.proto" />
<None Remove="QuestDestroyEntityReq.proto" />
<None Remove="QuestListNotify.proto" />
<None Remove="QUEST_OBJECTIVE.proto" />
<None Remove="QUEST_OBJECTIVE_DETAIL.proto" />
<None Remove="QUEST_STATE.proto" />
<None Remove="ReadMailNotify.proto" />
<None Remove="RefreshBackgroundAvatarRsp.proto" />
<None Remove="RegionSimpleInfo.proto" />
<None Remove="Reliquary.proto" />
<None Remove="ReliquaryPromoteRsp.proto" />
<None Remove="ReliquaryUpgradeRsp.proto" />
<None Remove="REMOVE_ITEM_NEW_DATA.proto" />
<None Remove="ResponseStatus.proto" />
<None Remove="Reward.proto" />
<None Remove="REWARD_ITEM.proto" />
<None Remove="ROLE_BASE_INFO.proto" />
<None Remove="SCD_FACTORY_CHARACTER_WORK_CHARACTER.proto" />
<None Remove="SCD_FACTORY_HS_BB.proto" />
<None Remove="SCD_FACTORY_HS_BB_POWER.proto" />
<None Remove="SCD_FACTORY_HS_CE.proto" />
<None Remove="SCD_FACTORY_HS_CE_EventType.proto" />
<None Remove="SCD_FACTORY_HS_CT.proto" />
<None Remove="SCD_FACTORY_HS_FB.proto" />
<None Remove="SCD_FACTORY_HS_FB_BOX_BRIDGE.proto" />
<None Remove="SCD_FACTORY_HS_FB_BOX_ROUTER_M1.proto" />
<None Remove="SCD_FACTORY_HS_FB_BURN_POWER.proto" />
<None Remove="SCD_FACTORY_HS_FB_CACHE.proto" />
<None Remove="SCD_FACTORY_HS_FB_CACHE_TRANSPORT.proto" />
<None Remove="SCD_FACTORY_HS_FB_COLLECTOR.proto" />
<None Remove="SCD_FACTORY_HS_FB_GRID_BOX.proto" />
<None Remove="SCD_FACTORY_HS_FB_HEAL_TOWER.proto" />
<None Remove="SCD_FACTORY_HS_FB_PRODUCER.proto" />
<None Remove="SCD_FACTORY_MANUFACTURE.proto" />
<None Remove="SCD_FACTORY_MANUFACTURE_MACHINE.proto" />
<None Remove="SCD_FACTORY_MODIFY_REGION.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_CHARACTER_WORK.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_CHARACTER_WORK_CHARACTER.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_OUTSIDE_RESOURCE.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_OUTSIDE_RESOURCE_NODE_USE.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_POWER_CONNECTION_MAP.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_POWER_CONNECTION_MAP_CONNECTION.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_POWER_CONNECTION_MAP_NODE_ELEM.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_RELATION_BOARD.proto" />
<None Remove="SCD_FACTORY_OBSERVER_PAYLOAD_RET_CHECKOUT_RELATION_BOARD_CONVEYOR_ELEM.proto" />
<None Remove="SCD_FACTORY_OP_RET_ADD_CONNECTION.proto" />
<None Remove="SCD_FACTORY_OP_RET_CACHE_TRANSPORT_ENABLE.proto" />
<None Remove="SCD_FACTORY_OP_RET_CACHE_TRANSPORT_TRANSFER.proto" />
<None Remove="SCD_FACTORY_OP_RET_DEL_CONNECTION.proto" />
<None Remove="SCD_FACTORY_OP_RET_DISMANTLE.proto" />
<None Remove="SCD_FACTORY_OP_RET_DISMANTLE_BOX_CONVEYOR.proto" />
<None Remove="SCD_FACTORY_OP_RET_ENABLE_NODE.proto" />
<None Remove="SCD_FACTORY_OP_RET_GRID_BOX_INNER_MOVE.proto" />
<None Remove="SCD_FACTORY_OP_RET_GRID_BOX_INNER_SPLIT.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_BAG_TO_CACHE.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_BAG_TO_GRID_BOX.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_CACHE_TO_BAG.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_CACHE_TO_CACHE.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_CACHE_TO_DEPOT.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_CONVEYOR_TO_BAG.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_DEPOT_TO_CACHE.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_DEPOT_TO_GRID_BOX.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_GRID_BOX_TO_BAG.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_ITEM_GRID_BOX_TO_DEPOT.proto" />
<None Remove="SCD_FACTORY_OP_RET_MOVE_NODE.proto" />
<None Remove="SCD_FACTORY_OP_RET_PLACE.proto" />
<None Remove="SCD_FACTORY_OP_RET_PLACE_BOX_CONVEYOR.proto" />
<None Remove="SCD_FACTORY_OP_RET_SET_COLLECT_TARGET.proto" />
<None Remove="SCD_FACTORY_OP_RET_SET_SELECT_TARGET.proto" />
<None Remove="SCD_FACTORY_OP_RET_SET_TRAVEL_POLE_DEFAULT_NEXT.proto" />
<None Remove="SCD_FACTORY_OP_RET_USE_HEAL_TOWER_POINT.proto" />
<None Remove="SCD_FACTORY_PROCESSOR.proto" />
<None Remove="SCD_FACTORY_PROCESSOR_MACHINE.proto" />
<None Remove="SCD_FACTORY_RECT_INT.proto" />
<None Remove="SCD_FACTORY_RECYCLER.proto" />
<None Remove="SCD_FACTORY_RECYCLER_MACHINE.proto" />
<None Remove="SCD_FACTORY_REPAIR.proto" />
<None Remove="SCD_FACTORY_REPAIR_BUILDING.proto" />
<None Remove="SCD_FACTORY_SKILL_BOARD_MACHINE.proto" />
<None Remove="SCD_FACTORY_SOIL.proto" />
<None Remove="SCD_FACTORY_SOIL_MACHINE.proto" />
<None Remove="SCD_FACTORY_STATISTIC_LASTDAY.proto" />
<None Remove="SCD_FACTORY_STATISTIC_LASTDAY_DAY.proto" />
<None Remove="SCD_FACTORY_STATISTIC_OPTION.proto" />
<None Remove="SCD_FACTORY_STATISTIC_OTHER.proto" />
<None Remove="SCD_FACTORY_STATISTIC_RECORD.proto" />
<None Remove="SCD_FACTORY_STT_NODE.proto" />
<None Remove="SCD_FACTORY_SUB_PORT.proto" />
<None Remove="SCD_FACTORY_SYNC_BLACKBOARD.proto" />
<None Remove="SCD_FACTORY_SYNC_BLACKBOARD_POWER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_BOX_BRIDGE.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_BOX_CONVEYOR.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_BOX_ROUTER_M1.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_BURN_POWER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_BUS_LOADER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_CACHE.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_CACHE_TRANSPORT.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_COLLECTOR.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_GRID_BOX.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_HEAL_TOWER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_INVENTORY.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_POWER_POLE.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_POWER_SAVE.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_PRODUCER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_SELECTOR.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_STABLE_POWER.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_SUB_PORT.proto" />
<None Remove="SCD_FACTORY_SYNC_COMPONENT_TRAVEL_POLE.proto" />
<None Remove="SCD_FACTORY_SYNC_DYNAMIC_PROPERTY.proto" />
<None Remove="SCD_FACTORY_SYNC_DYNAMIC_PROPERTY_VALUE.proto" />
<None Remove="SCD_FACTORY_SYNC_FORMULA_MAN.proto" />
<None Remove="SCD_FACTORY_SYNC_INTERACTIVE_OBJECT.proto" />
<None Remove="SCD_FACTORY_SYNC_ITEM.proto" />
<None Remove="SCD_FACTORY_SYNC_MANUALLY_WORK.proto" />
<None Remove="SCD_FACTORY_SYNC_MANUALLY_WORK_UNIT.proto" />
<None Remove="SCD_FACTORY_SYNC_MESH.proto" />
<None Remove="SCD_FACTORY_SYNC_NODE.proto" />
<None Remove="SCD_FACTORY_SYNC_QUICKBAR.proto" />
<None Remove="SCD_FACTORY_SYNC_REGION.proto" />
<None Remove="SCD_FACTORY_SYNC_SCENE.proto" />
<None Remove="SCD_FACTORY_SYNC_SCENE_BANDWIDTH.proto" />
<None Remove="SCD_FACTORY_SYNC_SCENE_CONNECTION.proto" />
<None Remove="SCD_FACTORY_SYNC_SCENE_CONNECTION_PORT.proto" />
<None Remove="SCD_FACTORY_SYNC_STT.proto" />
<None Remove="SCD_FACTORY_SYNC_TRANSFORM.proto" />
<None Remove="SCD_FACTORY_TRADE.proto" />
<None Remove="SCD_FACTORY_TRADE_MACHINE.proto" />
<None Remove="SCD_FACTORY_TRADE_ORDER.proto" />
<None Remove="SCD_FACTORY_VECTOR2_INT.proto" />
<None Remove="SCD_FACTORY_WORKSHOP.proto" />
<None Remove="SCD_FACTORY_WORKSHOP_MACHINE.proto" />
<None Remove="SCD_ITEM_BAG.proto" />
<None Remove="SCD_ITEM_BAG_MODIFY.proto" />
<None Remove="SCD_ITEM_DEPOT.proto" />
<None Remove="SCD_ITEM_DEPOT_MODIFY.proto" />
<None Remove="SCD_ITEM_GRID.proto" />
<None Remove="SCD_ITEM_USE_BLACKBOARD.proto" />
<None Remove="SceneAreaExploreNotify.proto" />
<None Remove="SceneAreaWeatherNotify.proto" />
<None Remove="SceneAvatarStaminaStepReq.proto" />
<None Remove="SceneCreateEntityReq.proto" />
<None Remove="SceneDestroyEntityReq.proto" />
<None Remove="SceneEntitiesMovesNotify.proto" />
<None Remove="SceneEntitiesMovesRsp.proto" />
<None Remove="SceneEntityAppearNotify.proto" />
<None Remove="SceneEntityDrownReq.proto" />
<None Remove="SceneEntityInfo.proto" />
<None Remove="SceneEntityMoveReq.proto" />
<None Remove="SceneForceLockNotify.proto" />
<None Remove="SceneGadgetInfo.proto" />
<None Remove="SceneGetAreaExplorePercentRsp.proto" />
<None Remove="SceneInitFinishRsp.proto" />
<None Remove="SceneKickPlayerReq.proto" />
<None Remove="SceneMonsterInfo.proto" />
<None Remove="ScenePlayerInfo.proto" />
<None Remove="ScenePlayerLocationNotify.proto" />
<None Remove="ScenePointUnlockNotify.proto" />
<None Remove="SceneRouteChangeInfo.proto" />
<None Remove="SceneSurfaceMaterial.proto" />
<None Remove="SceneTransToPointReq.proto" />
<None Remove="SceneWeaponInfo.proto" />
<None Remove="SCENE_CHARACTER.proto" />
<None Remove="SCENE_COLLECTION.proto" />
<None Remove="SCENE_IMPL_DUNGEON.proto" />
<None Remove="SCENE_IMPL_EMPTY.proto" />
<None Remove="SCENE_INTERACTIVE.proto" />
<None Remove="SCENE_MAP_MARK.proto" />
<None Remove="SCENE_MONSTER.proto" />
<None Remove="SCENE_NPC.proto" />
<None Remove="SCENE_OBJECT_COMMON_INFO.proto" />
<None Remove="SCENE_OBJECT_DETAIL_CONTAINER.proto" />
<None Remove="SCENE_SPAWN_INTERACTIVE_TYPE.proto" />
<None Remove="SCENE_SPAWN_MONSTER_TYPE.proto" />
<None Remove="SCENE_SUMMON.proto" />
<None Remove="SCENE_TRACK_POINT.proto" />
<None Remove="SC_ACCEPT_GUIDE_GROUP.proto" />
<None Remove="SC_ACHIEVE_COMPLETE.proto" />
<None Remove="SC_BITSET_ADD.proto" />
<None Remove="SC_BITSET_REMOVE.proto" />
<None Remove="SC_BITSET_REMOVE_ALL.proto" />
<None Remove="SC_BLOC_COMPLETED_MISSION_NUM_UPDATE.proto" />
<None Remove="SC_BLOC_SHOP_BUY.proto" />
<None Remove="SC_BLOC_SYNC_LEVEL.proto" />
<None Remove="SC_CHAR_BAG_ADD_CHAR.proto" />
<None Remove="SC_CHAR_BAG_SET_CURR_TEAM_INDEX.proto" />
<None Remove="SC_CHAR_BAG_SET_MAX_TEAM_MEMBER_COUNT.proto" />
<None Remove="SC_CHAR_BAG_SET_TEAM.proto" />
<None Remove="SC_CHAR_BAG_SET_TEAM_LEADER.proto" />
<None Remove="SC_CHAR_BAG_SET_TEAM_NAME.proto" />
<None Remove="SC_CHAR_BREAK.proto" />
<None Remove="SC_CHAR_GAIN_EXP_TOAST.proto" />
<None Remove="SC_CHAR_LEVEL_UP.proto" />
<None Remove="SC_CHAR_SET_NORMAL_SKILL.proto" />
<None Remove="SC_CHAR_SET_TEAM_SKILL.proto" />
<None Remove="SC_CHAR_SKILL_LEVEL_UP.proto" />
<None Remove="SC_CHAR_SYNC_LEVEL_EXP.proto" />
<None Remove="SC_CHAR_SYNC_STATUS.proto" />
<None Remove="SC_CHAR_UNLOCK_SKILL.proto" />
<None Remove="SC_COMPLETE_GUIDE_GROUP.proto" />
<None Remove="SC_COMPLETE_GUIDE_GROUP_KEY_STEP.proto" />
<None Remove="SC_DEL_MAIL_NOTIFY.proto" />
<None Remove="SC_DUNGEON_REWARD.proto" />
<None Remove="SC_ENTER_DUNGEON.proto" />
<None Remove="SC_ENTER_SCENE_NOTIFY.proto" />
<None Remove="SC_EQUIP_PUTOFF.proto" />
<None Remove="SC_EQUIP_PUTON.proto" />
<None Remove="SC_FACTORY_COMMON_RET.proto" />
<None Remove="SC_FACTORY_HS.proto" />
<None Remove="SC_FACTORY_HS_SYNC.proto" />
<None Remove="SC_FACTORY_MANUALLY_WORK_CANCEL.proto" />
<None Remove="SC_FACTORY_MANUFACTURE_CANCEL.proto" />
<None Remove="SC_FACTORY_MANUFACTURE_SETTLE.proto" />
<None Remove="SC_FACTORY_MANUFACTURE_START.proto" />
<None Remove="SC_FACTORY_MODIFY.proto" />
<None Remove="SC_FACTORY_MODIFY_CHARACTER_WORK.proto" />
<None Remove="SC_FACTORY_MODIFY_CONTEXT.proto" />
<None Remove="SC_FACTORY_MODIFY_FORMULA_MAN.proto" />
<None Remove="SC_FACTORY_MODIFY_MANUALLY_WORK.proto" />
<None Remove="SC_FACTORY_MODIFY_MANUFACTURE.proto" />
<None Remove="SC_FACTORY_MODIFY_PROCESSOR.proto" />
<None Remove="SC_FACTORY_MODIFY_QUICKBAR.proto" />
<None Remove="SC_FACTORY_MODIFY_RECYCLER.proto" />
<None Remove="SC_FACTORY_MODIFY_REGION_COMPONENTS.proto" />
<None Remove="SC_FACTORY_MODIFY_REGION_NODES.proto" />
<None Remove="SC_FACTORY_MODIFY_REGION_SCENE.proto" />
<None Remove="SC_FACTORY_MODIFY_REPAIR.proto" />
<None Remove="SC_FACTORY_MODIFY_SKILL_BOARD.proto" />
<None Remove="SC_FACTORY_MODIFY_SOIL.proto" />
<None Remove="SC_FACTORY_MODIFY_STATISTIC.proto" />
<None Remove="SC_FACTORY_MODIFY_STT.proto" />
<None Remove="SC_FACTORY_MODIFY_TRADE.proto" />
<None Remove="SC_FACTORY_MODIFY_VISIBLE_FORMULA.proto" />
<None Remove="SC_FACTORY_MODIFY_WORKSHOP.proto" />
<None Remove="SC_FACTORY_NOTIFY.proto" />
<None Remove="SC_FACTORY_OBSERVER_RET.proto" />
<None Remove="SC_FACTORY_OP_RET.proto" />
<None Remove="SC_FACTORY_PROCESSOR_RET.proto" />
<None Remove="SC_FACTORY_RECYCLER_COMMIT_MATERIAL.proto" />
<None Remove="SC_FACTORY_RECYCLER_FETCH_PRODUCT.proto" />
<None Remove="SC_FACTORY_SOIL_CANCEL.proto" />
<None Remove="SC_FACTORY_SOIL_HARVEST.proto" />
<None Remove="SC_FACTORY_SOIL_PLANT.proto" />
<None Remove="SC_FACTORY_STATISTIC_REQUIRE.proto" />
<None Remove="SC_FACTORY_SYNC.proto" />
<None Remove="SC_FACTORY_SYNC_CHARACTER_WORK.proto" />
<None Remove="SC_FACTORY_SYNC_CONTEXT.proto" />
<None Remove="SC_FACTORY_SYNC_REGION_NODES.proto" />
<None Remove="SC_FACTORY_SYNC_SKILL_BOARD.proto" />
<None Remove="SC_FACTORY_SYNC_STATISTIC.proto" />
<None Remove="SC_FACTORY_TRADE_CASH_ORDER.proto" />
<None Remove="SC_FINISH_DIALOG.proto" />
<None Remove="SC_FLUSH_SYNC.proto" />
<None Remove="SC_GET_MAIL.proto" />
<None Remove="SC_GET_MAIL_ATTACHMENT.proto" />
<None Remove="SC_GM_COMMAND.proto" />
<None Remove="SC_ITEM_BAG_BAG_TO_FACTORY_DEPOT.proto" />
<None Remove="SC_ITEM_BAG_SET_ITEM_LOCK.proto" />
<None Remove="SC_ITEM_BAG_SET_QUICK_BAR.proto" />
<None Remove="SC_ITEM_BAG_SET_QUICK_BAR_POS.proto" />
<None Remove="SC_ITEM_BAG_SYNC.proto" />
<None Remove="SC_ITEM_BAG_SYNC_MODIFY.proto" />
<None Remove="SC_ITEM_BAG_SYNC_QUICK_BAR.proto" />
<None Remove="SC_ITEM_BAG_USE_ITEM.proto" />
<None Remove="SC_LEAVE_DUNGEON.proto" />
<None Remove="SC_LEAVE_SCENE_NOTIFY.proto" />
<None Remove="SC_LOGIN.proto" />
<None Remove="SC_MISSION_DELETED.proto" />
<None Remove="SC_MISSION_FAILED.proto" />
<None Remove="SC_MISSION_STATE_UPDATE.proto" />
<None Remove="SC_MOVE_OBJECT_MOVE.proto" />
<None Remove="SC_NEW_MAIL_NOTIFY.proto" />
<None Remove="SC_NEW_NOTICE_NOTIFY.proto" />
<None Remove="SC_NTF_CODE.proto" />
<None Remove="SC_NTF_ERROR_CODE.proto" />
<None Remove="SC_OBJECT_ENTER_VIEW.proto" />
<None Remove="SC_OBJECT_LEAVE_VIEW.proto" />
<None Remove="SC_PING.proto" />
<None Remove="SC_QUEST_FAILED.proto" />
<None Remove="SC_QUEST_OBJECTIVES_UPDATE.proto" />
<None Remove="SC_QUEST_STATE_UPDATE.proto" />
<None Remove="SC_READ_MAIL.proto" />
<None Remove="SC_RECONNECT_FULL.proto" />
<None Remove="SC_RECONNECT_INCR.proto" />
<None Remove="SC_REMOVE_ITEM_NEW_TAGS.proto" />
<None Remove="SC_RESTART_DUNGEON.proto" />
<None Remove="SC_REWARD_DROP_MONEY_TOAST.proto" />
<None Remove="SC_REWARD_TOAST_BEGIN.proto" />
<None Remove="SC_REWARD_TOAST_END.proto" />
<None Remove="SC_REWARD_TO_SCENE_BEGIN.proto" />
<None Remove="SC_REWARD_TO_SCENE_END.proto" />
<None Remove="SC_ROLL_BLOC_MISSION.proto" />
<None Remove="SC_SCENE_COLLECTION_MODIFY.proto" />
<None Remove="SC_SCENE_COLLECTION_SYNC.proto" />
<None Remove="SC_SCENE_CREATE_ENTITY.proto" />
<None Remove="SC_SCENE_DESTROY_ENTITY.proto" />
<None Remove="SC_SCENE_INTERACTIVE_EVENT_TRIGGER.proto" />
<None Remove="SC_SCENE_LEVEL_SCRIPT_EVENT_TRIGGER.proto" />
<None Remove="SC_SCENE_LEVEL_SCRIPT_RESET_BEGIN.proto" />
<None Remove="SC_SCENE_LEVEL_SCRIPT_RESET_END.proto" />
<None Remove="SC_SCENE_LEVEL_SCRIPT_STATE_NOTIFY.proto" />
<None Remove="SC_SCENE_MAP_MARK_MODIFY.proto" />
<None Remove="SC_SCENE_MAP_MARK_SYNC.proto" />
<None Remove="SC_SCENE_QUERY_ENTITY_EXIST.proto" />
<None Remove="SC_SCENE_QUERY_INTERACTIVE_PROPERTY.proto" />
<None Remove="SC_SCENE_RESET_ENTITY.proto" />
<None Remove="SC_SCENE_REVIVAL.proto" />
<None Remove="SC_SCENE_REVIVAL_MODE_MODIFY.proto" />
<None Remove="SC_SCENE_SET_BATTLE.proto" />
<None Remove="SC_SCENE_SET_LAST_RECORD_CAMPID.proto" />
<None Remove="SC_SCENE_SET_SAFE_ZONE.proto" />
<None Remove="SC_SCENE_SET_TRACK_POINT.proto" />
<None Remove="SC_SCENE_SET_VAR.proto" />
<None Remove="SC_SCENE_SUBMIT_ETHER.proto" />
<None Remove="SC_SCENE_SUBMIT_ITEM.proto" />
<None Remove="SC_SCENE_TELEPORT.proto" />
<None Remove="SC_SCENE_UNLOCK_AREA.proto" />
<None Remove="SC_SCENE_UPDATE_INTERACTIVE_PROPERTY.proto" />
<None Remove="SC_SCENE_UPDATE_LEVEL_SCRIPT_PROPERTY.proto" />
<None Remove="SC_SELF_SCENE_INFO.proto" />
<None Remove="SC_START_DUNGEON_CHALLENGE.proto" />
<None Remove="SC_SYNC_ALL_BITSET.proto" />
<None Remove="SC_SYNC_ALL_BLOC.proto" />
<None Remove="SC_SYNC_ALL_DIALOG.proto" />
<None Remove="SC_SYNC_ALL_GUIDE.proto" />
<None Remove="SC_SYNC_ALL_MAIL.proto" />
<None Remove="SC_SYNC_ALL_MISSION.proto" />
<None Remove="SC_SYNC_ALL_ROLE_SCENE.proto" />
<None Remove="SC_SYNC_ALL_UNLOCK.proto" />
<None Remove="SC_SYNC_ATTR.proto" />
<None Remove="SC_SYNC_BASE_DATA.proto" />
<None Remove="SC_SYNC_BLOC_MISSION_INFO.proto" />
<None Remove="SC_SYNC_CHAR_BAG_INFO.proto" />
<None Remove="SC_SYNC_DUNGEON_CHALLENGE_STATUS.proto" />
<None Remove="SC_SYNC_DUNGEON_PASS_STATUS.proto" />
<None Remove="SC_SYNC_EXTRA_ATTACHMENT_ITEM.proto" />
<None Remove="SC_SYNC_FULL_DUNGEON_STATUS.proto" />
<None Remove="SC_SYNC_GAME_MODE.proto" />
<None Remove="SC_SYNC_STAMINA.proto" />
<None Remove="SC_SYNC_STATISTIC.proto" />
<None Remove="SC_SYNC_WALLET.proto" />
<None Remove="SC_SYNC_WIKI_PIN.proto" />
<None Remove="SC_TRACK_MISSION_CHANGE.proto" />
<None Remove="SC_UNLOCK_SYSTEM.proto" />
<None Remove="SC_WALLET_SYNC_MONEY.proto" />
<None Remove="SC_WEAPON_ADD_EXP.proto" />
<None Remove="SC_WEAPON_ATTACH_GEM.proto" />
<None Remove="SC_WEAPON_BREAKTHROUGH.proto" />
<None Remove="SC_WEAPON_DETACH_GEM.proto" />
<None Remove="SC_WEAPON_PUTON.proto" />
<None Remove="SDComponentBoxConveyor.proto" />
<None Remove="SDComponentBoxRouter.proto" />
<None Remove="SDComponentBus.proto" />
<None Remove="SDComponentBusLoader.proto" />
<None Remove="SDComponentBusUnloader.proto" />
<None Remove="SDComponentCache.proto" />
<None Remove="SDComponentCollector.proto" />
<None Remove="SDComponentFormulaMan.proto" />
<None Remove="SDComponentProducer.proto" />
<None Remove="SDComponentSelector.proto" />
<None Remove="SDNodeBoxConveyor.proto" />
<None Remove="SDNodeBoxRouter.proto" />
<None Remove="SDNodeBus.proto" />
<None Remove="SDNodeBusLoader.proto" />
<None Remove="SDNodeBusUnloader.proto" />
<None Remove="SDNodeCollector.proto" />
<None Remove="SDNodeProducer.proto" />
<None Remove="SDShape.proto" />
<None Remove="SDTemplate.proto" />
<None Remove="SealBattleEndNotify.proto" />
<None Remove="SealBattleType.proto" />
<None Remove="SeeMonsterRsp.proto" />
<None Remove="SelectWorktopOptionRsp.proto" />
<None Remove="SEND_MAIL_DEF.proto" />
<None Remove="ServerLogNotify.proto" />
<None Remove="ServerTimeNotify.proto" />
<None Remove="SetOpenStateReq.proto" />
<None Remove="SetPlayerBornDataReq.proto" />
<None Remove="SetPlayerNameReq.proto" />
<None Remove="SetPlayerPropReq.proto" />
<None Remove="SetSceneWeatherAreaReq.proto" />
<None Remove="SetUpAvatarTeamReq.proto" />
<None Remove="ShapeType.proto" />
<None Remove="Shop.proto" />
<None Remove="SHOP_INFO.proto" />
<None Remove="ShowMessageNotify.proto" />
<None Remove="SKILL_INFO.proto" />
<None Remove="SKILL_LEVEL_INFO.proto" />
<None Remove="SpringUseRsp.proto" />
<None Remove="SP_INTERACTIVE_OP_TYPE.proto" />
<None Remove="STATISTIC_RECORD.proto" />
<None Remove="StoreItemChangeNotify.proto" />
<None Remove="StoreType.proto" />
<None Remove="SUBMIT_ITEM.proto" />
<None Remove="SUBMIT_SOURCE_PARAM_INTERACTIVE.proto" />
<None Remove="SUBMIT_SOURCE_PARAM_MISSION.proto" />
<None Remove="SUBMIT_SOURCE_TYPE.proto" />
<None Remove="SubPort.proto" />
<None Remove="SvrMsgId.proto" />
<None Remove="TakeCompoundOutputRsp.proto" />
<None Remove="TakeoffEquipRsp.proto" />
<None Remove="TransmitReason.proto" />
<None Remove="TriggerCreateGadgetToEquipPartNotify.proto" />
<None Remove="UnlockAvatarTalentRsp.proto" />
<None Remove="UnlockTransPointRsp.proto" />
<None Remove="UseItemReq.proto" />
<None Remove="Vector.proto" />
<None Remove="Vector2.proto" />
<None Remove="Version.proto" />
<None Remove="VisionType.proto" />
<None Remove="WeaponAwakenReq.proto" />
<None Remove="WeaponPromoteReq.proto" />
<None Remove="WeaponUpgradeReq.proto" />
<None Remove="WEAPON_DATA.proto" />
<None Remove="WearEquipReq.proto" />
<None Remove="WeatherInfo.proto" />
<None Remove="WIKI_PIN_ENUM.proto" />
<None Remove="WorktopOptionNotify.proto" />
<None Remove="WorldPlayerReviveReq.proto" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,329 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Protocol
{
public enum CsMsgId : int
{
CsMessageBegin = 0,
CsLogin = 1,
CsCreateRole = 2,
CsLogout = 3,
CsGmCommand = 4,
CsPing = 5,
CsFlushSync = 6,
CsSetName = 7,
CsSetGender = 8,
CsCheckName = 9,
CsCheckSensitive = 10,
CsAchieveBegin = 20,
CsAchieveComplete = 21,
CsAchieveTakeReward = 22,
CsAchieveEnd = 29,
CsCharBagBegin = 30,
CsCharBagTeamBegin = 31,
CsCharBagSetTeam = 32,
CsCharBagSetCurrTeamIndex = 33,
CsCharBagSetTeamName = 34,
CsCharBagSetTeamLeader = 35,
CsCharBagTeamChangeFinish = 36,
CsCharBagTeamEnd = 37,
CsCharBagEnd = 39,
CsCharBegin = 40,
CsCharLevelUp = 41,
CsCharSetNormalSkill = 43,
CsCharSkillLevelUp = 45,
CsCharSetTeamSkill = 46,
CsCharPotentialUnlock = 47,
CsCharEnd = 49,
CsEquipBegin = 50,
CsEquipPuton = 51,
CsEquipPutoff = 52,
CsEquipMedicineModify = 53,
CsEquipRecycle = 54,
CsEquipEnhance = 55,
CsEquipProduce = 57,
CsEquipEnd = 59,
CsSceneBegin = 80,
CsEnterScene = 81,
CsMoveObjectMove = 82,
CsSceneSetLastRecordCampid = 83,
CsSceneInteractiveEventTrigger = 84,
CsSceneSetVar = 85,
CsSceneRest = 86,
CsSceneLoadFinish = 88,
CsSceneSetSafeZone = 95,
CsSceneQueryEntityExist = 96,
CsSceneQueryInteractiveProperty = 97,
CsSceneSetTrackPoint = 99,
CsSceneInteractTree = 100,
CsSceneStaticMapMarkUpdate = 101,
CsSceneTeleport = 103,
CsSceneMoveStateSet = 104,
CsSceneSubmitItem = 105,
CsSceneSubmitEther = 106,
CsSceneSetLevelScriptActive = 107,
CsSceneLevelScriptEventTrigger = 109,
CsSceneCommitLevelScriptCacheStep = 110,
CsSceneRepatriate = 115,
CsSceneInteractSpInteractive = 116,
CsSceneSetLastSafeZone = 117,
CsSceneSetBattle = 118,
CsSceneRevival = 119,
CsSceneSetLevelScriptStart = 120,
CsSceneMonsterSpawnerBeginWave = 121,
CsSceneSpawnSummon = 122,
CsSceneLeavePlane = 123,
CsSceneGradeModify = 124,
CsSceneUpdateScriptTaskProgress = 125,
CsSceneTeleportFinish = 126,
CsSceneSetStorySafeZone = 127,
CsSceneSubmitRecycle = 128,
CsSceneEnd = 199,
CsFactoryBegin = 200,
CsFactorySttUnlockNode = 201,
CsFactorySttUnlockLayer = 202,
CsFactoryManuallyWorkExec = 211,
CsFactoryProductManualUnlock = 212,
CsFactoryQuickbarSetOne = 215,
CsFactoryQuickbarMoveOne = 216,
CsFactorySoilReclaim = 217,
CsFactorySoilWater = 218,
CsFactorySoilCancel = 219,
CsFactorySoilHarvest = 220,
CsFactorySoilFarmlandLevelUp = 221,
CsFactoryHubWorkshopMake = 222,
CsFactoryHubTransportRouteSet = 223,
CsFactoryHubTransportRouteReset = 224,
CsFactoryHubTransportRouteRestart = 225,
CsFactoryHsFb = 232,
CsFactoryStatisticSetBookmarkItemIds = 234,
CsFactoryStatisticRequire = 235,
CsFactoryPinSet = 236,
CsFactoryOp = 251,
CsFactoryObserverOp = 268,
CsFactoryEnd = 269,
CsWeaponBegin = 270,
CsWeaponPuton = 271,
CsWeaponBreakthrough = 273,
CsWeaponAddExp = 274,
CsWeaponAttachGem = 275,
CsWeaponDetachGem = 276,
CsWeaponRefineUpgrade = 277,
CsWeaponEnd = 279,
CsWikiBegin = 290,
CsUnlockWiki = 291,
CsMarkWikiRead = 292,
CsWikiEnd = 299,
CsMissionBegin = 310,
CsFailMission = 311,
CsTrackMission = 313,
CsStopTrackingMission = 314,
CsUpdateQuestObjective = 315,
CsAcceptMission = 316,
CsRollBlocMission = 317,
CsMissionEventTrigger = 318,
CsMissionClientTriggerDone = 319,
CsSetNewMissionTagDone = 320,
CsMissionEnd = 329,
CsGuideBegin = 330,
CsCompleteGuideGroupKeyStep = 331,
CsCompleteGuideGroup = 332,
CsGuideEnd = 339,
CsDialogBegin = 340,
CsFinishDialog = 341,
CsDialogEnd = 349,
CsBlocBegin = 350,
CsBlocTakeLevelReward = 351,
CsBlocShopBuy = 352,
CsBlocEnd = 360,
CsDungeonBegin = 370,
CsEnterDungeon = 371,
CsRestartDungeon = 372,
CsLeaveDungeon = 373,
CsDungeonRecoverAp = 375,
CsDungeonTouchEntrance = 377,
CsDungeonEnd = 378,
CsEnterTrainDungeon = 379,
CsGameMechanicsBegin = 380,
CsGameMechanicsReqActive = 381,
CsGameMechanicsReqReward = 382,
CsGameMechanicsNtfInstPrepareFinish = 383,
CsGameMechanicsEnd = 399,
CsMailBegin = 400,
CsGetMail = 401,
CsReadMail = 402,
CsDeleteMail = 403,
CsDeleteAllMail = 404,
CsGetMailAttachment = 405,
CsGetAllMailAttachment = 406,
CsMarkStarMail = 407,
CsMailEnd = 419,
CsRedDotBegin = 430,
CsRemoveItemNewTags = 431,
CsRedDotReadFormula = 432,
CsRedDotReadCharDoc = 433,
CsRedDotReadCharVoice = 434,
CsRedDotReadEquipFormula = 435,
CsRedDotEnd = 440,
CsPrtsBegin = 441,
CsPrtsMarkRead = 442,
CsPrtsMarkTerminalRead = 443,
CsPrtsRichContentRead = 444,
CsPrtsFinishInvestigate = 445,
CsPrtsEnd = 449,
CsBitsetBegin = 480,
CsBitsetAdd = 481,
CsBitsetRemove = 482,
CsBitsetRemoveAll = 483,
CsBitsetEnd = 499,
CsMergeMsg = 500,
CsPayBegin = 510,
CsCreateOrder = 511,
CsPayEnd = 529,
CsFriendBegin = 530,
CsFriendRequestSubmit = 531,
CsFriendRequestReject = 532,
CsFriendRequestAccept = 533,
CsFriendDelete = 534,
CsFriendSearchName = 535,
CsFriendRequestListSync = 536,
CsFriendListSync = 537,
CsFriendEnd = 570,
CsWalletBegin = 600,
CsMoneyChange = 601,
CsWalletEnd = 630,
CsGameVarBegin = 631,
CsUpdateClientGameVar = 632,
CsGameVarEnd = 640,
CsMiniGameBegin = 641,
CsCompleteMiniGame = 642,
CsMiniGameEnd = 650,
CsRpgDungeonBegin = 651,
CsRpgDungeonBuy = 652,
CsRpgDungeonSell = 653,
CsRpgDungeonEquipPuton = 654,
CsRpgDungeonEquipPutoff = 655,
CsRpgDungeonPickLvAbility = 656,
CsRpgDungeonTimeStop = 657,
CsRpgDungeonAbilityChange = 658,
CsRpgDungeonEnd = 700,
CsGemBegin = 801,
CsGemRecast = 802,
CsGemEnd = 820,
CsSnsBegin = 701,
CsSnsGetList = 702,
CsSnsMomentOption = 703,
CsSnsChatDialogOption = 704,
CsSnsMomentRead = 705,
CsSnsFinishDialog = 706,
CsSnsReadDialog = 707,
CsSnsEnd = 730,
CsSpaceshipBegin = 751,
CsSpaceshipBuildRoom = 752,
CsSpaceshipLevelUpRoom = 753,
CsSpaceshipStationChar = 754,
CsSpaceshipStationCharChangeWorkState = 755,
CsSpaceshipPresentGiftToChar = 756,
CsSpaceshipRecvGiftFromChar = 757,
CsSpaceshipManufacturingBegin = 771,
CsSpaceshipManufacturingStationStart = 772,
CsSpaceshipManufacturingStationCollect = 775,
CsSpaceshipManufacturingStationCancel = 776,
CsSpaceshipManufacturingStationChangeOrder = 777,
CsSpaceshipManufacturingEnd = 785,
CsSpaceshipGrowCabinBegin = 786,
CsSpaceshipGrowCabinBreed = 787,
CsSpaceshipGrowCabinSow = 788,
CsSpaceshipGrowCabinHarvest = 789,
CsSpaceshipGrowCabinCancel = 790,
CsSpaceshipGrowCabinClearPreviewRecipe = 791,
CsSpaceshipGrowCabinEnd = 799,
CsSpaceshipEnd = 800,
CsTdBegin = 821,
CsTdGetTdList = 822,
CsTdStart = 823,
CsTdLeave = 825,
CsTdBuyBuilding = 826,
CsTdPickDropItem = 827,
CsTdDropExpired = 828,
CsTdEnd = 899,
CsBuffBegin = 900,
CsBattleOp = 901,
CsDevClearBattleInfo = 902,
CsBuffEnd = 950,
CsSkillBegin = 960,
CsCastSkill = 961,
CsCastSkillEnd = 962,
CsCastSkillEffect = 963,
CsSkillEnd = 999,
CsItemBagBegin = 1000,
CsItemBagTidyInBag = 1001,
CsItemBagMoveInBag = 1002,
CsItemBagSplitInBag = 1003,
CsItemBagFactoryDepotToBag = 1004,
CsItemBagBagToFactoryDepot = 1005,
CsItemBagFactoryDepotToBagGrid = 1006,
CsItemBagUseItem = 1007,
CsItemBagSetQuickBar = 1008,
CsItemBagSetQuickBarPos = 1009,
CsItemBagSetItemLock = 1010,
CsItemBagAbandonInBag = 1011,
CsItemBagDestroyInDepot = 1012,
CsItemBagDestroyInFactoryDepot = 1013,
CsItemBagDumpBottleInBag = 1014,
CsItemBagDumpBottleInFactoryDepot = 1015,
CsItemBagTakeoutLostAndFound = 1031,
CsItemBagUseItemCase = 1032,
CsItemBagChgSpaceshipChapter = 1033,
CsItemBagEnd = 1049,
CsSettlementBegin = 1050,
CsSettlementSelectRequire = 1051,
CsSettlementSetOfficer = 1052,
CsSettlementSetSubmitMode = 1053,
CsSettlementSubmitRequire = 1054,
CsSettlementEnd = 1099,
CsShopBegin = 1100,
CsShopBuy = 1111,
CsShopSwapMoney = 1112,
CsShopEnd = 1149,
CsAdventureBegin = 1150,
CsAdventureTakeRewardAll = 1151,
CsAdventureEnd = 1179,
CsAdventureBookBegin = 1250,
CsTakeAllAdventureTaskReward = 1251,
CsTakeAdventureTaskReward = 1252,
CsTakeAdventureBookStageReward = 1253,
CsAdventureBookEnd = 1299,
CsTalentBegin = 1300,
CsCharUnlockTalentNode = 1301,
CsTalentEnd = 1329,
CsRacingDungeonBegin = 1330,
CsRacingDungeonBattlePassReceiveReward = 1332,
CsRacingDungeonGetBattlePass = 1333,
CsRacingDungeonGetAchievement = 1334,
CsRacingDungeonAchievementReceiveReward = 1335,
CsRacingDungeonLeave = 1336,
CsRacingDungeonUpdateBattleInfo = 1337,
CsRacingDungeonEnd = 1400,
CsTrialCharacterBegin = 1401,
CsUseTrialCharacterEquipMedicine = 1402,
CsTrialCharacterEnd = 1403,
CsGachaBegin = 1431,
CsGachaSinglePullReq = 1432,
CsGachaTenPullReq = 1433,
CsGachaEnd = 1450,
CsGameTimeFreezeBegin = 1451,
CsGameTimeFreezeStartReq = 1452,
CsGameTimeFreezeEndReq = 1453,
CsGameTimeFreezeEnd = 1460,
CsActivityBegin = 1461,
CsDailyCheckin = 1471,
CsActivityEnd = 1510,
CsMessageEnd = 4095,
}
}

View File

@ -0,0 +1,401 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Protocol
{
public enum ScMsgId : int
{
ScMessageBegin = 0,
ScLogin = 1,
ScSyncBaseData = 2,
ScNtfErrorCode = 3,
ScGmCommand = 4,
ScPing = 5,
ScReconnectIncr = 6,
ScReconnectFull = 7,
ScFlushSync = 8,
ScNtfCode = 9,
ScSetName = 10,
ScSetGender = 11,
ScCheckName = 12,
ScCheckSensitive = 13,
ScSyncFullDataEnd = 14,//
ScAchieveComplete = 15,
ScSyncAllRoleScene = 20,//
ScObjectEnterView = 21,
ScObjectLeaveView = 22,
ScMoveObjectMove = 23,
ScEnterSceneNotify = 24,
ScSelfSceneInfo = 25,
ScLeaveSceneNotify = 26,
ScSceneSetLastRecordCampid = 27,
ScSceneUpdateInteractiveProperty = 28,
ScSceneSetVar = 29,
ScSceneRevival = 30,
ScSceneCreateEntity = 31,
ScSceneDestroyEntity = 32,
ScSceneSetSafeZone = 35,
ScSceneQueryEntityExist = 36,
ScSceneLevelScriptStateNotify = 37,
ScSceneQueryInteractiveProperty = 38,
ScSceneUnlockArea = 39,
ScSceneSetTrackPoint = 40,
ScSceneCollectionSync = 42, //
ScSceneCollectionModify = 43,
ScSceneMapMarkSync = 44,//
ScSceneStaticMapMarkModify = 45,
ScSceneTeleport = 46,
ScSceneSubmitItem = 47,
ScSceneSubmitEther = 48,
ScSceneUpdateLevelScriptProperty = 49,
ScSceneResetEntity = 50,
ScSceneLevelScriptResetBegin = 51,
ScSceneLevelScriptResetEnd = 52,
ScSceneSetBattle = 53,
ScSceneLevelScriptEventTrigger = 55,
ScSceneInteractiveEventTrigger = 56,
ScSceneTriggerClientLevelScriptEvent = 57,
ScSceneTriggerClientInteractiveEvent = 58,
ScSceneCrossSceneStatus = 59,
ScSceneDropCreate = 800,
ScSceneDropDelete = 801,
ScSceneDropModify = 802,
ScSceneGradeChangeNotify = 803,
ScSeamlessSceneDestroyNotify = 804,
ScSceneMonsterSpawnerStart = 805,
ScSceneMonsterSpawnerStop = 806,
ScSceneMonsterSpawnerComplete = 807,
ScSceneMonsterSpawnerBeginWave = 808,
ScSceneMonsterSpawnerWaveComplete = 809,
ScSceneMonsterSpawnerObjectDataBegin = 811,
ScSceneMonsterSpawnerObjectDataEnd = 812,
ScSceneLevelScriptTaskStateUpdate = 813,
ScSceneClientIdInfo = 814,
ScSceneLevelScriptTaskProgressUpdate = 815,
ScSceneLevelScriptTaskStartFinish = 816,
ScSceneInteractSpInteractive = 817,
ScSceneUpdateInteractiveMeta = 818,
ScSceneGradeModify = 819,
ScSceneSetStorySafeZone = 820,
ScSceneRepatriate = 821,
ScSceneSubmitRecycle = 822,
ScSceneLevelScriptSetDone = 823,
ScSyncCharBagInfo = 60,//
ScCharBagAddChar = 61,
ScCharBagSetTeam = 62,
ScCharBagSetCurrTeamIndex = 63,
ScCharBagSetTeamName = 64,
ScCharBagSetTeamLeader = 65,
ScCharBagSetMaxTeamMemberCount = 66,
ScCharBagTeamLeaderNotMatchNtf = 67,
ScCharBagDelChar = 68,
ScCharBagAddCharWithConversionNotify = 69,
ScSyncWallet = 70,//
ScWalletSyncMoney = 71,
ScCharSkillInfos = 78,
ScCharPotentialUnlock = 79,
ScCharLevelUp = 80,
ScCharSyncLevelExp = 82,
ScCharSetNormalSkill = 83,
ScCharSkillLevelUp = 84,
ScCharUnlockSkill = 85,
ScCharGainExpToast = 86,
ScCharSyncStatus = 87,
ScCharSetTeamSkill = 89,
ScEquipPuton = 90,
ScEquipPutoff = 91,
ScEquipMedicineModify = 92,
ScEquipRecycle = 93,
ScEquipEnhance = 94,
ScEquipProduce = 96,
ScSyncAllMission = 110,//
ScQuestStateUpdate = 111,
ScMissionStateUpdate = 112,
ScQuestFailed = 113,
ScMissionFailed = 114,
ScTrackMissionChange = 115,
ScQuestObjectivesUpdate = 116,
ScMissionDeleted = 117,
ScRollBlocMission = 120,
ScSyncBlocMissionInfo = 121,//
ScBlocCompletedMissionNumUpdate = 122,
ScQuestRollback = 123,
ScUpdateMissionProperty = 124,
ScSceneTriggerClientMissionEvent = 125,
ScMissionEventTrigger = 126,
ScDailyMissionInfoUpdate = 127,
ScSyncAllDialog = 130,//
ScFinishDialog = 131,
ScSyncAllGuide = 140,//
ScCompleteGuideGroupKeyStep = 141,
ScCompleteGuideGroup = 142,
ScAcceptGuideGroup = 143,
ScSyncAttr = 150,
ScSyncAllUnlock = 160,//
ScUnlockSystem = 161,
ScSyncAllBitset = 165,//
ScBitsetAdd = 166,
ScBitsetRemove = 167,
ScBitsetRemoveAll = 168,
ScFactorySync = 200,//
ScFactoryModifyFormulaMan = 201,
ScFactoryModifyStt = 202,
ScFactoryModifyVisibleFormula = 203,
ScFactoryModifyFormulaMode = 204,
ScFactorySyncOfflineInfo = 205,//
ScFactorySyncScope = 210,//
ScFactoryReleaseScope = 211,
ScFactoryModifyScope = 212,
ScFactoryModifyQuickbar = 213,
ScFactoryManuallyWorkExec = 214,
ScFactoryProductManualUnlock = 215,
ScFactoryModifySoil = 216,
ScFactorySoilReclaim = 217,
ScFactorySoilWater = 218,
ScFactorySoilCancel = 219,
ScFactorySoilHarvest = 220,
ScFactorySyncChapter = 221,//
ScFactoryModifyChapterNodes = 222,
ScFactoryModifyChapterComponents = 223,
ScFactoryModifyChapterScene = 224,
ScFactoryModifyChapterBlackboard = 225,
ScFactoryModifyChapterPinBoard = 226,
ScFactoryModifyChapterMap = 227,
ScFactoryHs = 231,
ScFactoryHsSync = 232,//
ScFactorySyncStatistic = 241,
ScFactoryModifyStatistic = 242,
ScFactoryStatisticRequire = 243,
ScFactoryHubWorkshopMake = 244,
ScFactoryHubTransportRouteModify = 245,
ScFactoryModifyStatisticBookmark = 246,
ScFactoryOpRet = 251,
ScFactoryObserverRet = 259,
ScWeaponPuton = 260,
ScWeaponBreakthrough = 262,
ScWeaponAddExp = 263,
ScWeaponAttachGem = 264,
ScWeaponDetachGem = 265,
ScWeaponRefineUpgrade = 266,
ScRewardToastBegin = 270,
ScRewardToastEnd = 271,
ScRewardDropMoneyToast = 272,
ScRewardToSceneBegin = 273,
ScRewardToSceneEnd = 274,
ScRewardDropSpItemToast = 275,
ScSyncAllBloc = 280,//
ScBlocSyncLevel = 281,
ScBlocTakeLevelReward = 282,
ScBlocShopBuy = 283,
ScDungeonBegin = 300,
ScEnterDungeon = 301,
ScRestartDungeon = 302,
ScLeaveDungeon = 303,
ScSyncStamina = 304,
ScSyncFullDungeonStatus = 306,
ScDungeonEnd = 359,
ScSyncAllMail = 400,//
ScGetMail = 401,
ScReadMail = 402,
ScGetMailAttachment = 403,
ScDelMailNotify = 404,
ScNewMailNotify = 405,
ScMarkStarMail = 406,
ScSyncGameMode = 430,
ScRemoveItemNewTags = 440,
ScSyncAllWiki = 470,
ScSyncAllStat = 500,
ScSyncStat = 501,
ScNewNoticeNotify = 600,
ScCreateOrder = 650,
ScOrderMsg = 651,
ScFriendBegin = 700,
ScFriendRequestSubmit = 701,
ScFriendRequestReject = 702,
ScFriendRequestAccept = 703,
ScFriendDelete = 704,
ScFriendSearchName = 705,
ScFriendRequestListSync = 706,
ScFriendListSync = 707,
ScFriendRequestAddNotify = 708,
ScFriendAddNotify = 709,
ScFriendEnd = 750,
ScUpdateGameVar = 901,
ScSyncAllGameVar = 902,//
ScUpdateMiniGame = 913,
ScSyncAllMiniGame = 914,//
ScCompleteMiniGame = 915,
ScRpgDungeonBegin = 950,
ScRpgDungeonBuy = 951,
ScRpgDungeonSell = 952,
ScRpgDungeonEquipPuton = 953,
ScRpgDungeonEquipPutoff = 954,
ScSyncRpgEquipColumn = 955,
ScSyncRpgDungeonBuffList = 956,
ScSyncRpgTeamLevel = 957,
ScSyncRpgLevelUp = 958,
ScRpgDungeonPickLvAbility = 959,
ScSyncRpgDungeonTimeInfo = 960,
ScSyncRpgDungeonAbility = 961,
ScRpgDungeonEnd = 999,
ScItemBagCommonSync = 1000,//
ScItemBagCommonModify = 1001,
ScItemBagScopeSync = 1002,//
ScItemBagScopeModify = 1003,
ScItemBagUseItem = 1004,
ScItemBagSetQuickBar = 1005,
ScItemBagSetQuickBarPos = 1006,
ScItemBagSetItemLock = 1007,
ScItemBagAbandonInBag = 1008,
ScItemBagBagToFactoryDepot = 1009,
ScItemBagTakeoutLostAndFound = 1031,
ScItemBagGotItemToast = 1032,
ScItemBagTrialCharDepotModify = 1033,
ScItemBagTrialCharDepotClear = 1034,
ScItemBagUseItemCase = 1035,
ScItemBagChgSpaceshipChapter = 1036,
ScItemBagEnd = 1049,
ScAddBuff = 1100,
ScRemoveBuff = 1101,
ScTriggerBuff = 1102,
ScClearBuffs = 1103,
ScCastSkill = 1160,
ScSyncHp = 1161,
ScSyncPoise = 1162,
ScSyncUltimateSpCellCnt = 1163,
ScSpawnEnemy = 1170,
ScSpawnSummon = 1171,
ScEntityPropertyChange = 1172,
ScBattleDebugInfo = 1173,
ScBattleGenerationChange = 1174,
ScAttachServerSkill = 1175,
ScDetachServerSkill = 1176,
ScAddServerBuff = 1177,
ScRemoveServerBuff = 1178,
ScSpaceshipSync = 1200,//
ScSpaceshipModifyRoom = 1201,
ScSpaceshipModifyChar = 1202,
ScSpaceshipPresentCharInfo = 1203,
ScSpaceshipCharFavorabilityChange = 1204,
ScSpaceshipRecvGiftFromChar = 1205,
ScSpaceshipPresentGiftToChar = 1206,
ScSpaceshipSyncRoomLevelUp = 1207,
ScSpaceshipSyncCharSkill = 1208,
ScSpaceshipSyncRoomStation = 1209,
ScSpaceshipManufacturingStationSync = 1210,
ScSpaceshipManufacturingStationStart = 1211,
ScSpaceshipManufacturingStationCancel = 1212,
ScSpaceshipManufacturingStationCollect = 1213,
ScSpaceshipModifyGrowCabin = 1214,
ScSpaceshipGrowCabinBreed = 1215,
ScSpaceshipGrowCabinSow = 1216,
ScSpaceshipGrowCabinHarvest = 1217,
ScSpaceshipGrowCabinCancel = 1218,
ScSpaceshipReportCharWorkModify = 1219,
ScSpaceshipReportOutputModify = 1220,
ScGameMechanicsBegin = 1250,
ScGameMechanicsSync = 1251,//
ScGameMechanicsSyncUnlockCondition = 1252,
ScGameMechanicsModifyRecords = 1253,
ScGameMechanicsSyncChallengeStart = 1254,
ScGameMechanicsSyncChallengeComplete = 1255,
ScGameMechanicsSyncCompletionReward = 1256,
ScGameMechanicsSyncEnterGameInst = 1257,
ScGameMechanicsSyncLeaveGameInst = 1258,
ScGameMechanicsSyncRestartGameInst = 1259,
ScGameMechanicsModifyInstTimeFreeze = 1260,
ScGameMechanicsEnd = 1299,
ScSnsBegin = 1300,
ScSnsGetMomentList = 1301,
ScSnsGetChatList = 1302,
ScSyncSnsAddDialog = 1303,
ScSnsMomentOption = 1304,
ScSyncSnsDialogModify = 1305,
ScSyncSnsAddMoment = 1306,
ScSnsMomentRead = 1307,
ScSnsReadDialog = 1308,
ScSyncSnsChatModify = 1309,
ScSnsEnd = 1330,
ScSettlementBegin = 1331,
ScSettlementSyncAll = 1332,//
ScSettlementSyncModify = 1333,
ScSettlementFinishRequires = 1334,
ScSettlementSetOfficer = 1335,
ScSettlementSelectRequire = 1336,
ScSettlementSetSubmitMode = 1337,
ScSettlementEnd = 1350,
ScShopBegin = 1351,
ScShopSync = 1352,//
ScShopSyncShopGroupCondition = 1353,
ScShopModifyShop = 1354,
ScShopSyncShopCondition = 1355,
ScShopSyncGoodsCondition = 1356,
ScShopModifyFrequencyLimit = 1357,
ScShopDeleteFrequencyLimit = 1358,
ScShopBuyResp = 1359,
ScShopSwapMoney = 1360,
ScShopEnd = 1370,
ScTdBegin = 1371,
ScTdGetTdList = 1372,
ScTdStart = 1373,
ScTdLeave = 1374,
ScSyncTdSettlement = 1375,
ScSyncTdFullStatus = 1376,
ScSyncTdDropItem = 1378,
ScTdPickDropItem = 1379,
ScTdBuyBuilding = 1380,
ScTdEnd = 1400,
ScAdventureBegin = 1401,
ScAdventureLevelModify = 1402,
ScAdventureSyncAll = 1403,//
ScAdventureEnd = 1430,
ScGemRecast = 1431,
ScGemEnd = 1440,
ScResetDailyAdventureTask = 1441,
ScDailyActivationModify = 1443,
ScAdventureTaskModify = 1444,
ScAdventureBookSync = 1445,//
ScAdventureBookStageModify = 1447,
ScTalentBegin = 1490,
ScCharUnlockTalentNode = 1491,
ScTalentEnd = 1529,
ScRacingDungeonBegin = 1530,
ScSyncRacingDungeonPassedLevel = 1531,
ScRacingDungeonEnter = 1532,
ScSyncRacingDungeonSettlement = 1533,
ScSyncRacingDungeonReconnect = 1534,
ScRacingDungeonBattlePassReceiveReward = 1535,
ScRacingDungeonGetBattlePass = 1536,
ScRacingDungeonGetAchievement = 1537,
ScRacingDungeonAchievementReceiveReward = 1538,
ScSyncRacingDungeonBuffModify = 1539,
ScSyncRacingDungeonAchievementModify = 1540,
ScSyncRacingTimerPause = 1541,
ScSyncRacingDungeonCompleteRoom = 1542,
ScSyncRacingDungeonCountdownEvent = 1543,
ScRacingDungeonEnd = 1600,
ScCharBagSetTempTeam = 1601,
ScCharBagRemoveTrialCharacter = 1602,
ScTrialCharacterEquipMedicineModify = 1603,
ScGachaBegin = 1610,
ScGachaSync = 1611,//
ScGachaModifyPoolInfo = 1612,
ScGachaSyncPullResult = 1613,
ScGachaModifyPoolRoleData = 1614,
ScGachaEnd = 1640,
ScGameTimeFreezeBegin = 1641,
ScGameTimeFreezeStartRsp = 1642,
ScGameTimeFreezeEndRsp = 1643,
ScGameTimeFreezeEnd = 1650,
ScActivityBegin = 1651,
ScActivitySync = 1652,//
ScActivityModify = 1653,
ScDailyCheckin = 1661,
ScActivityEnd = 1690,
ScMessageEnd = 4095,
}
}

53
Campofinale.sln Normal file
View File

@ -0,0 +1,53 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34902.65
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Campofinale", "Campofinale\Campofinale.csproj", "{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}"
ProjectSection(ProjectDependencies) = postProject
{96C85239-92E8-4D22-B6BD-DD997C36C3E0} = {96C85239-92E8-4D22-B6BD-DD997C36C3E0}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Campofinale.Protocol", "Campofinale.Protocol\Campofinale.Protocol.csproj", "{96C85239-92E8-4D22-B6BD-DD997C36C3E0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM32 = Debug|ARM32
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM32 = Release|ARM32
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|ARM32.ActiveCfg = Debug|ARM32
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|ARM32.Build.0 = Debug|ARM32
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|x86.ActiveCfg = Debug|x86
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Debug|x86.Build.0 = Debug|x86
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|Any CPU.Build.0 = Release|Any CPU
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|ARM32.ActiveCfg = Release|ARM32
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|ARM32.Build.0 = Release|ARM32
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|x86.ActiveCfg = Release|x86
{7338AADD-EFA7-407A-B2BE-AAE1560E2E8A}.Release|x86.Build.0 = Release|x86
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|ARM32.ActiveCfg = Debug|ARM32
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|ARM32.Build.0 = Debug|ARM32
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|x86.ActiveCfg = Debug|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Debug|x86.Build.0 = Debug|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|Any CPU.Build.0 = Release|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|ARM32.ActiveCfg = Release|ARM32
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|ARM32.Build.0 = Release|ARM32
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|x86.ActiveCfg = Release|Any CPU
{96C85239-92E8-4D22-B6BD-DD997C36C3E0}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {63C48BE1-779C-4539-ADBF-5E4C44354730}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,424 @@
{
"FormulaMan": {
"Unlocked": [
"component_mc_1",
"power_station_1",
"seedcollector_1",
"filling_powder_mc_1",
"handwork_anglem_flower2_1",
"handwork_plant_moss_powder_1",
"handwork_plant_moss_spc_powder_2",
"planter_1",
"handwork_bottled_rec_hp_2",
"furnance_1",
"handwork_corp2_flower2_1",
"handwork_bottled_food_1",
"tools_assebling_mc_1",
"handwork_bottled_insec1_1",
"handwork_plant_moss_powder_2",
"battle_frost_1",
"handwork_ebs_flower1_1",
"handwork_bottled_flower2spc_1",
"handwork_bottled_rec_hp_1",
"handwork_angles_flower2_1",
"miner_1",
"handwork_bottled_flower1spc_1",
"handwork_plant_moss_spc_powder_1",
"battle_cannon_1",
"handwork_port_soil_bbflower_1",
"winder_1",
"unloader_1",
"handwork_bottled_flower1spc_2",
"miner_3",
"shaper_1",
"handwork_port_soil_moss_1",
"handwork_ebm_flower1_1",
"battle_medic_1",
"travel_pole_1",
"miner_2",
"handwork_port_soil_sp_1",
"storager_1",
"handwork_bottled_insec2_1",
"battle_laser_1",
"power_diffuser_1",
"power_pole_2",
"handwork_corp1_flower1_1",
"thickener_1",
"travel_pole_2",
"handwork_animal_angles_1",
"loader_1",
"grinder_1",
"handwork_port_soil_moss_2",
"battle_turret_1",
"handwork_port_soil_sp_2"
],
"Visible": [
"handwork_plant_moss_powder_1",
"winder_equip_script_1",
"handwork_bottled_flower2spc_1",
"loader_1",
"planter_plant_moss_1_1",
"grinder_plant_moss_powder_2_1",
"winder_1",
"thickener_plant_moss_enr_powder_2_1",
"planter_plant_bbflower_1",
"winder_equip_script_3",
"tools_proc_bomb_1_1",
"shaper_1",
"grinder_plant_moss_powder_1_1",
"filling_bottled_rec_hp_3_1",
"travel_pole_1",
"grinder_plant_bbflower_powder_1_1",
"tools_proc_battery_2_1",
"tools_proc_battery_3_1",
"handwork_bottled_insec2_1",
"handwork_angles_flower2_1",
"handwork_bottled_insec1_1",
"handwork_port_soil_bbflower_1",
"component_glass_cmpt_1",
"thickener_originium_enr_powder_1",
"component_mc_1",
"grinder_crystal_powder_1",
"handwork_bottled_flower1spc_1",
"handwork_plant_moss_powder_2",
"grinder_quartz_powder_1",
"furnance_crystal_enr_powder_1",
"component_glass_enr_cmpt_1",
"handwork_ebs_flower1_1",
"battle_frost_1",
"thickener_iron_enr_powder_1",
"handwork_plant_moss_spc_powder_1",
"planter_plant_moss_2_1",
"furnance_carbon_enr_1",
"furnance_quartz_enr_1",
"filling_bottled_food_3_1",
"furnance_iron_nugget_1",
"battle_cannon_1",
"handwork_port_soil_sp_2",
"shaper_glass_bottle_1",
"battle_laser_1",
"handwork_bottled_rec_hp_1",
"filling_powder_mc_1",
"handwork_bottled_rec_hp_2",
"handwork_port_soil_sp_1",
"handwork_bottled_flower1spc_2",
"thickener_plant_moss_enr_powder_1_1",
"seedcollector_plant_sp_2",
"power_station_1",
"filling_bottled_rec_hp_2_1",
"component_iron_enr_cmpt_1",
"furnance_carbon_material_1",
"furnance_iron_enr_1",
"grinder_originium_powder_1",
"thickener_carbon_enr_powder_1",
"filling_bottled_rec_hp_1_1",
"battle_medic_1",
"shaper_iron_enr_bottle_1",
"tools_proc_battery_1_1",
"seedcollector_1",
"handwork_bottled_food_1",
"grinder_iron_powder_1",
"thickener_1",
"thickener_quartz_enr_powder_1",
"handwork_corp1_flower1_1",
"handwork_port_soil_moss_1",
"travel_pole_2",
"battle_turret_1",
"miner_3",
"furnance_crystal_enr_1",
"handwork_corp2_flower2_1",
"grinder_carbon_powder_1",
"seedcollector_plant_bbflower_1",
"handwork_ebm_flower1_1",
"tools_assebling_mc_1",
"unloader_1",
"filling_bottled_food_2_1",
"storager_1",
"shaper_iron_bottle_1",
"miner_2",
"furnance_quartz_glass_1",
"handwork_anglem_flower2_1",
"handwork_port_soil_moss_2",
"planter_1",
"seedcollector_plant_sp_1",
"furnance_crystal_shell_1",
"handwork_animal_angles_1",
"handwork_plant_moss_spc_powder_2",
"shaper_glass_enr_bottle_1",
"furnance_carbon_powder_1",
"thickener_crystal_enr_powder_1",
"seedcollector_plant_moss_1_1",
"component_iron_cmpt_1",
"seedcollector_plant_moss_2_1",
"winder_equip_script_2",
"filling_bottled_food_1_1"
],
"Modes": {
"Liquid": {
"BuildingIds": [
"pump_1",
"liquid_storager_nop_1",
"liquid_cleaner_1",
"miner_4",
"squirter_1",
"liquid_storager_1",
"squirter_nop_1",
"mix_pool_1",
"v_fluid_container_1",
"dumper_nop_1",
"dumper_1"
]
}
},
"LevelUp": [
"item_animal_angles_1"
],
"ProductManual": [
"hdwk_item_plant_moss_spc_1_10",
"hdwk_item_drop_eb_m_1_1",
"hdwk_item_plant_bbflower_1_1",
"hdwk_item_drop_angle_m_1_1",
"hdwk_item_plant_tundra_insect_1_1",
"hdwk_item_plant_tundra_insect_2_10",
"hdwk_item_drop_animal_1_30",
"hdwk_item_drop_angle_s_1_1",
"hdwk_item_plant_moss_1_150",
"hdwk_item_plant_moss_2_1",
"hdwk_item_plant_tundra_insect_2_1",
"hdwk_item_plant_moss_spc_1_1",
"hdwk_item_plant_moss_2_50",
"hdwk_item_drop_eb_s_1_30",
"hdwk_item_plant_moss_spc_1_30",
"hdwk_item_plant_moss_1_1",
"hdwk_item_plant_tundra_insect_1_20",
"hdwk_item_drop_eb_s_1_1",
"hdwk_item_drop_animal_1_1",
"hdwk_item_plant_moss_1_15",
"hdwk_item_plant_sp_2_1",
"hdwk_item_plant_moss_2_30",
"hdwk_item_plant_moss_spc_2_10",
"hdwk_item_plant_sp_1_1",
"hdwk_item_plant_moss_spc_2_1",
"hdwk_item_drop_animal_1_10",
"hdwk_item_plant_moss_1_100",
"hdwk_item_drop_eb_s_1_10",
"hdwk_item_drop_angle_s_1_10"
]
},
"Stt": {
"Nodes": [
{
"Id": "tech_jinlong_1_dumper_1"
},
{
"Id": "tech_jinlong_1_filling_mode_1"
},
{
"Id": "tech_jinlong_1_liquid_storager_1"
},
{
"Id": "tech_jinlong_1_mix_1"
},
{
"Id": "tech_jinlong_1_pipe_1",
"State": 1
},
{
"Id": "tech_jinlong_1_planter_mode_1"
},
{
"Id": "tech_jinlong_1_pump_1",
"State": 1
},
{
"Id": "tech_jinlong_1_splitter_1"
},
{
"Id": "tech_jinlong_2_connector_1"
},
{
"Id": "tech_jinlong_2_converger_1"
},
{
"Id": "tech_jinlong_2_furnance_mode_1"
},
{
"Id": "tech_jinlong_2_liquid_cleaner_1"
},
{
"Id": "tech_jinlong_2_miner_4"
},
{
"Id": "tech_jinlong_2_mix_1_unlock_1"
},
{
"Id": "tech_jinlong_2_shaper_mode_1"
},
{
"Id": "tech_jinlong_2_squirter_1"
},
{
"Id": "tech_tundra_1_battle_medic_1",
"State": 1
},
{
"Id": "tech_tundra_1_battle_turret_1",
"State": 1
},
{
"Id": "tech_tundra_1_cmpt_1",
"State": 1
},
{
"Id": "tech_tundra_1_diffuser_1",
"State": 1
},
{
"Id": "tech_tundra_1_furnance_1",
"State": 1
},
{
"Id": "tech_tundra_1_grinder_1",
"State": 1
},
{
"Id": "tech_tundra_1_miner_1",
"State": 1
},
{
"Id": "tech_tundra_1_pole_1",
"State": 1
},
{
"Id": "tech_tundra_1_shaper_1",
"State": 1
},
{
"Id": "tech_tundra_1_storager_1",
"State": 1
},
{
"Id": "tech_tundra_1_winder_1",
"State": 1
},
{
"Id": "tech_tundra_2_asm_1",
"State": 1
},
{
"Id": "tech_tundra_2_battle_cannon_1",
"State": 1
},
{
"Id": "tech_tundra_2_battle_frost_1",
"State": 1
},
{
"Id": "tech_tundra_2_battle_laser_1",
"State": 1
},
{
"Id": "tech_tundra_2_belt_1",
"State": 1
},
{
"Id": "tech_tundra_2_connector_1",
"State": 1
},
{
"Id": "tech_tundra_2_field_1",
"State": 1
},
{
"Id": "tech_tundra_2_filling_1",
"State": 1
},
{
"Id": "tech_tundra_2_miner_2",
"State": 1
},
{
"Id": "tech_tundra_2_plant_1",
"State": 1
},
{
"Id": "tech_tundra_2_power_1",
"State": 1
},
{
"Id": "tech_tundra_2_splitter_1",
"State": 1
},
{
"Id": "tech_tundra_2_travel_1",
"State": 1
},
{
"Id": "tech_tundra_3_battle_cannon_2"
},
{
"Id": "tech_tundra_3_battle_laser_2"
},
{
"Id": "tech_tundra_3_battle_lightning_1"
},
{
"Id": "tech_tundra_3_battle_shockwave_1"
},
{
"Id": "tech_tundra_3_battle_sniper_1"
},
{
"Id": "tech_tundra_3_battle_turret_2"
},
{
"Id": "tech_tundra_3_converger_1",
"State": 1
},
{
"Id": "tech_tundra_3_field_2",
"State": 1
},
{
"Id": "tech_tundra_3_miner_3",
"State": 1
},
{
"Id": "tech_tundra_3_thickener_1",
"State": 1
},
{
"Id": "tech_tundra_3_travel_2",
"State": 1
}
],
"Packages": [
{
"Id": "tech_group_jinlong",
"State": 1
},
{
"Id": "tech_group_tundra",
"State": 1
}
],
"Layers": [
{
"Id": "tech_group_jinlong_liquid",
"State": 1
},
{
"Id": "tech_group_tundra_iron",
"State": 1
},
{
"Id": "tech_group_tundra_originium",
"State": 1
},
{
"Id": "tech_group_tundra_quartz",
"State": 1
}
]
}
}

View File

@ -0,0 +1,440 @@
{
"Bitset": [
{
"Type": 7,
"Value": [
"2",
"0",
"0",
"11529215046068469760",
"262164",
"0",
"4611686018494496768",
"0",
"0",
"0",
"8589934592",
"0",
"0",
"144115188075855872",
"0",
"0",
"0",
"0",
"0",
"8388608",
"4611686018439970816",
"324259173170718981",
"0",
"0",
"0",
"126",
"0",
"268435456",
"288230376151711744",
"0",
"0",
"1593149468230811650",
"100292",
"17592186044416"
]
},
{
"Type": 3,
"Value": [
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0"
]
},
{
"Type": 45,
"Value": [
"0",
"0",
"0",
"0",
"0",
"0"
]
},
{
"Type": 13,
"Value": [
"51810140172"
]
},
{
"Type": 22,
"Value": [
"637536256"
]
},
{
"Type": 30,
"Value": [
"670695769600703488",
"7849126204"
]
},
{
"Type": 9,
"Value": [
"0",
"0",
"0",
"0",
"0"
]
},
{
"Type": 23,
"Value": [
"0",
"122357090304"
]
},
{
"Type": 46,
"Value": [
"0"
]
},
{
"Type": 44,
"Value": [
"9745508118585934080",
"2531075783884815"
]
},
{
"Type": 19
},
{
"Type": 14,
"Value": [
"9223372036855169152",
"0",
"0",
"0",
"0",
"0",
"0",
"2752512",
"0",
"0"
]
},
{
"Type": 47,
"Value": [
"3196644842209280"
]
},
{
"Type": 10,
"Value": [
"140737488355328",
"1335555265063288832",
"12124253146834798728",
"16619141365993580464",
"12333486116532429"
]
},
{
"Type": 39,
"Value": [
"503839996",
"0",
"17042430230528",
"17180393728"
]
},
{
"Type": 1,
"Value": [
"2305845352252574734",
"11276608979599364",
"1193501217834139760",
"17582059550928803968",
"234189274820750654",
"0",
"6917529027708190720",
"549755813888",
"0",
"0",
"8589934592",
"0",
"0",
"7351915285449801728",
"1610619010",
"0",
"57174604644352",
"0",
"576460752303423488",
"9241324862841349840",
"13835058059188931635",
"9195049235800194943",
"8755314334957043712",
"1261617",
"0",
"5373428292625891710",
"5835082701971406914",
"6674057571101343842",
"432345564325506799",
"0",
"0",
"11392984662570696706",
"2348486468193847252",
"19791209336838"
]
},
{
"Type": 42,
"Value": [
"144405463440556032",
"17592186044928",
"2305847510373122048",
"9261652635834909185",
"1225119838280618056",
"2291382234121218",
"8320"
]
},
{
"Type": 50,
"Value": [
"51541704716",
"17179869184"
]
},
{
"Type": 32,
"Value": [
"8796093022208",
"67108864",
"8192",
"40532396646334464",
"216188176225009664",
"7585212069490720768",
"68719477760",
"1204716198856941568",
"35786910376027",
"1",
"6878201854087904",
"201535533972553728",
"562949953422484"
]
},
{
"Type": 49,
"Value": [
"1081145935319335202",
"2267743516716"
]
},
{
"Type": 11,
"Value": [
"0",
"0",
"458480242655232"
]
},
{
"Type": 12,
"Value": [
"51810140172",
"531424821771251712",
"590604267522",
"262144"
]
},
{
"Type": 31,
"Value": [
"18446673704948596736",
"10351514792732131327",
"3038669698868181091",
"14676867182063746867",
"2259954429851840863",
"14082403297860126378",
"452585"
]
},
{
"Type": 8,
"Value": [
"0",
"700314552419483648",
"6883146427956985856",
"10678850801135",
"12557541982456905728"
]
},
{
"Type": 26,
"Value": [
"1125899906842620"
]
},
{
"Type": 21,
"Value": [
"0",
"0",
"17572948988976431104",
"13107933272249661048",
"13808029682097634519",
"175"
]
},
{
"Type": 15,
"Value": [
"0"
]
},
{
"Type": 18,
"Value": [
"0",
"2200096998416",
"18375812389242293472",
"1424917274804735",
"270397203"
]
},
{
"Type": 2,
"Value": [
"90170430014915120",
"11583546498734869004",
"3910405411899142210",
"1097",
"5622463761458790540",
"6448939136",
"18302628885633695744",
"1941299076985287561",
"4165321356736086175",
"734655911615783166",
"7816980527214433829",
"18435361420267951154",
"5476799465637475382",
"2896736039472204290",
"18139821896924482577",
"16545632413779394543",
"17543135999577665520",
"160002550206265"
]
},
{
"Type": 27,
"Value": [
"21536791257814024"
]
},
{
"Type": 16,
"Value": [
"18446744073709551615",
"18446744073709551615",
"18446744073709551615",
"18446744073709551615"
]
},
{
"Type": 17,
"Value": [
"16510976"
]
},
{
"Type": 38,
"Value": [
"34628173824"
]
},
{
"Type": 5,
"Value": [
"2305845352252573710",
"11276608979599364",
"1193501217834139728",
"12970373532501415936",
"1660298764574",
"0",
"6917529027708190720",
"549755813888",
"0",
"0",
"8589934592",
"0",
"0",
"7351915285449801728",
"1610619010",
"0",
"57174604644352",
"0",
"576460752303423488",
"9241324862841349840",
"13835058059187618867",
"9195048686043332479",
"576460752303423488",
"0",
"0",
"5373428292625891710",
"5835082701971406914",
"6674057571101343842",
"432345564325506799",
"0",
"0",
"11392984662570696706",
"2348486468193847252",
"19791209336838"
]
},
{
"Type": 41,
"Value": [
"668232592512256000",
"2424840448"
]
},
{
"Type": 48,
"Value": [
"5290262761236124",
"18014462933991424"
]
},
{
"Type": 43,
"Value": [
"137438953472",
"4",
"0",
"0",
"32768"
]
},
{
"Type": 35
}
]
}

View File

@ -0,0 +1,368 @@
{
"SceneStaticMapMarkList": [
{
"Index": 251
},
{
"Index": 460
},
{
"Index": 601
},
{
"Index": 256
},
{
"Index": 459
},
{
"Index": 283
},
{
"Index": 326
},
{
"Index": 324
},
{
"Index": 350
},
{
"Index": 255
},
{
"Index": 426
},
{
"Index": 441
},
{
"Index": 345
},
{
"Index": 333
},
{
"Index": 306
},
{
"Index": 215
},
{
"Index": 264
},
{
"Index": 250
},
{
"Index": 457
},
{
"Index": 268
},
{
"Index": 605
},
{
"Index": 280
},
{
"Index": 439
},
{
"Index": 261
},
{
"Index": 246
},
{
"Index": 455
},
{
"Index": 320
},
{
"Index": 238
},
{
"Index": 435
},
{
"Index": 338
},
{
"Index": 349
},
{
"Index": 421
},
{
"Index": 218
},
{
"Index": 325
},
{
"Index": 437
},
{
"Index": 318
},
{
"Index": 265
},
{
"Index": 263
},
{
"Index": 327
},
{
"Index": 213
},
{
"Index": 419
},
{
"Index": 526
},
{
"Index": 431
},
{
"Index": 600
},
{
"Index": 305
},
{
"Index": 440
},
{
"Index": 343
},
{
"Index": 422
},
{
"Index": 254
},
{
"Index": 344
},
{
"Index": 236
},
{
"Index": 539
},
{
"Index": 347
},
{
"Index": 276
},
{
"Index": 237
},
{
"Index": 260
},
{
"Index": 436
},
{
"Index": 456
},
{
"Index": 337
},
{
"Index": 252
},
{
"Index": 220
},
{
"Index": 515
},
{
"Index": 425
},
{
"Index": 303
},
{
"Index": 536
},
{
"Index": 239
},
{
"Index": 214
},
{
"Index": 316
},
{
"Index": 428
},
{
"Index": 266
},
{
"Index": 277
},
{
"Index": 323
},
{
"Index": 430
},
{
"Index": 442
},
{
"Index": 235
},
{
"Index": 594
},
{
"Index": 595
},
{
"Index": 462
},
{
"Index": 219
},
{
"Index": 434
},
{
"Index": 322
},
{
"Index": 282
},
{
"Index": 346
},
{
"Index": 308
},
{
"Index": 212
},
{
"Index": 420
},
{
"Index": 310
},
{
"Index": 281
},
{
"Index": 329
},
{
"Index": 342
},
{
"Index": 336
},
{
"Index": 418
},
{
"Index": 249
},
{
"Index": 469
},
{
"Index": 321
},
{
"Index": 309
},
{
"Index": 438
},
{
"Index": 278
},
{
"Index": 423
},
{
"Index": 472
},
{
"Index": 253
},
{
"Index": 427
},
{
"Index": 248
},
{
"Index": 330
},
{
"Index": 351
},
{
"Index": 247
},
{
"Index": 468
},
{
"Index": 223
},
{
"Index": 245
},
{
"Index": 307
},
{
"Index": 224
},
{
"Index": 269
},
{
"Index": 416
},
{
"Index": 470
},
{
"Index": 311
},
{
"Index": 267
},
{
"Index": 319
},
{
"Index": 524
},
{
"Index": 217
},
{
"Index": 304
},
{
"Index": 262
}
],
"TrackPoint": {}
}

View File

@ -0,0 +1,81 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU;x86;ARM32</Platforms>
<StartupObject>Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Controllers\**" />
<Compile Remove="resources\binoutput\**" />
<EmbeddedResource Remove="Controllers\**" />
<EmbeddedResource Remove="resources\binoutput\**" />
<None Remove="Controllers\**" />
<None Remove="resources\binoutput\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Google.Protobuf" Version="3.27.2" />
<PackageReference Include="HttpServerLite" Version="2.1.5" />
<PackageReference Include="MongoDB.Driver" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLua" Version="1.7.3" />
<PackageReference Include="Pastel" Version="5.1.0" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="SQLiteNetExtensions" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Campofinale.Protocol\Campofinale.Protocol.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="44_ScSyncAllMission.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="53_ScFactorySync.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="92_ScSyncAllBitset.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="93_ScSceneMapMarkSync.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Data\GachaHistory\index_noplayerfound.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Data\Static\bar.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Data\Static\bg.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Data\Static\cs_bg.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Data\GachaHistory\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Data\Static\ja-jp.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Data\PlayerConsole\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ScFactorySyncChapter.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Data\PlayerConsole\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,54 @@
using Campofinale.Database;
using Campofinale.Game.Entities;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Commands
{
public static class BaseCommands
{
[Server.Command("scene", "Change scene",true)]
public static void SceneCmd(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 1) return;
int sceneNumId = int.Parse(args[0]);
target.EnterScene(sceneNumId);
CommandManager.SendMessage(sender, "Changing scene");
}
[Server.Command("target", "Set a target uid", false)]
public static void TargetCmd(Player sender, string cmd, string[] args, Player target)
{
if (sender != null)
{
CommandManager.SendMessage(sender, "This command can't be used ingame");
return;
}
if (args.Length < 1)
{
CommandManager.SendMessage(sender,"Use: /target (uid)");
return;
}
string id = args[0];
Player player = Server.clients.Find(c=>c.accountId == id);
if (player == null)
{
CommandManager.SendMessage(sender, "Only online players can be set as target");
return;
}
CommandManager.targetId = id;
CommandManager.SendMessage(sender, "Set Target player to " +id);
}
}
}

View File

@ -0,0 +1,101 @@
namespace Campofinale.Commands
{
using Pastel;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Collections.Immutable;
using System.Linq.Expressions;
using System.Reflection;
using System.Net.Sockets;
using Campofinale.Protocol;
using Campofinale.Network;
public static class CommandManager
{
private static List<Type> s_handlerTypes = new List<Type>();
public static ImmutableDictionary<string, (Server.CommandAttribute, Server.CommandAttribute.HandlerDelegate)> s_notifyReqGroup;
public static string targetId;
public static void Init()
{
var handlers = ImmutableDictionary.CreateBuilder<string, (Server.CommandAttribute, Server.CommandAttribute.HandlerDelegate)>();
foreach (var type in s_handlerTypes)
{
foreach (var method in type.GetMethods())
{
var attribute = method.GetCustomAttribute<Server.CommandAttribute> ();
if (attribute == null)
continue;
var parameterInfo = method.GetParameters();
var senderParameter = Expression.Parameter(typeof(Player));
var commandParameter = Expression.Parameter(typeof(string));
var argsParameter = Expression.Parameter(typeof(string[]));
var targetParameter = Expression.Parameter(typeof(Player));
var call = Expression.Call(method,
Expression.Convert(senderParameter, parameterInfo[0].ParameterType),
Expression.Convert(commandParameter, parameterInfo[1].ParameterType),
Expression.Convert(argsParameter, parameterInfo[2].ParameterType),
Expression.Convert(targetParameter, parameterInfo[3].ParameterType));
var lambda = Expression.Lambda<Server.CommandAttribute.HandlerDelegate>(call,senderParameter, commandParameter, argsParameter,targetParameter);
if (!handlers.TryGetKey(attribute.command, out _))
handlers.Add(attribute.command, (attribute, lambda.Compile()));
}
}
s_notifyReqGroup = handlers.ToImmutable();
}
public static void Notify(Player sender,string cmd, string[] args,Player target)
{
if (s_notifyReqGroup.TryGetValue(cmd, out var handler))
{
if (handler.Item1.requiredTarget)
{
if (target != null)
{
handler.Item2.Invoke(sender,cmd, args, target);
}
else
{
SendMessage(sender,"This command require a target player, set one with /target (uid)");
}
}
else
{
handler.Item2.Invoke(sender, cmd, args, target);
}
}
else
{
SendMessage(sender, $"Command not found");
}
}
public static void AddReqGroupHandler(Type type)
{
s_handlerTypes.Add(type);
}
public static void SendMessage(Player sender, string msg)
{
if (sender == null)
{
Logger.Print(msg);
}
else
{
//For sending to player command prompt page made by Xannix
sender.temporanyChatMessages.Add(msg);
}
}
}
}

View File

@ -0,0 +1,39 @@
using Campofinale.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandAccount
{
[Server.Command("account", "account command")]
public static void Handle(Player sender,string cmd, string[] args, Player target)
{
if (sender != null)
{
CommandManager.SendMessage(sender, "This command can't be used ingame");
return;
}
if (args.Length < 2)
{
CommandManager.SendMessage(sender, "Usage: account create|reset (username)");
return;
}
switch (args[0])
{
case "create":
DatabaseManager.db.CreateAccount(args[1]);
break;
case "reset":
CommandManager.SendMessage(sender, "Reset is not implemented yet");
break;
default:
CommandManager.SendMessage(sender, "Example: account create (username)");
break;
}
}
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Campofinale.Game.Character;
using Campofinale.Game.Inventory;
using Campofinale.Packets.Sc;
namespace Campofinale.Commands.Handlers;
public static class CommandAdd
{
[Server.Command("add", "Adds items, weapons or characters", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if(args.Length < 2)
{
CommandManager.SendMessage(sender, "Use: /add (item|weapon|char) (item/weapon/char id) (amount/lvl)");
return;
}
string message = "";
try
{
switch (args[0])
{
case "item":
Item item=target.inventoryManager.AddItem(args[1], int.Parse(args[2]));
message = $"Item {args[1]} was added to {target.nickname}";
target.Send(new PacketScItemBagScopeModify(target, item));
break;
case "weapon":
Item wep = target.inventoryManager.AddWeapon(args[1], Convert.ToUInt64(args[2]));
message = $"Weapon {args[1]} was added to {target.nickname}";
target.Send(new PacketScItemBagScopeModify(target, wep));
break;
case "char":
int lvl = int.Parse(args[2]);
if(lvl < 1 || lvl > 80)
{
CommandManager.SendMessage(sender, "Level can't be less than 1 or more than 80");
return;
}
Character character = new Character(target.roleId, args[1], lvl);
if(target.chars.Find(c => c.id == character.id) != null)
{
CommandManager.SendMessage(sender, "Character already exists");
return;
}
if(lvl <= 20) character.breakNode = "";
if(lvl > 20 && lvl <= 40) character.breakNode = "charBreak20";
if(lvl > 40 && lvl <= 60) character.breakNode = "charBreak40";
if(lvl > 60 && lvl <= 70) character.breakNode = "charBreak60";
if(lvl > 70) character.breakNode = "charBreak70";
target.chars.Add(character);
target.SaveCharacters();
message = $"Character {character.id} was added to {target.nickname}.";
CommandManager.SendMessage(sender, message);
target.Send(new PacketScCharBagAddChar(target, character));
Item weapon = target.inventoryManager.items.Find(i => i.guid == character.weaponGuid);
if(weapon!=null)target.Send(new PacketScItemBagScopeModify(target, weapon));
return;
default:
CommandManager.SendMessage(sender, "Unknown argument, use item, weapon or character");
return;
}
target.inventoryManager.Save();
CommandManager.SendMessage(sender, $"{message}.");
}
catch (Exception err)
{
CommandManager.SendMessage(sender, $"An error occurred: {err}");
}
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson;
using static Campofinale.Resource.ResourceManager;
using Newtonsoft.Json;
using Campofinale.Game.Character;
using Campofinale.Database;
using Campofinale.Game.Inventory;
namespace Campofinale.Commands.Handlers
{
public class CommandCharInfo
{
[Server.Command("charinfo", "Information about characters", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
// maybe we could use localization here
// string lang = "EN";
// Dictionary<string, string> locTable = JsonConvert.DeserializeObject<Dictionary<string, string>>(ReadJsonFile($"TableCfg/I18nTextTable_{lang}.json"));
if (args.Length < 1)
{
CommandManager.SendMessage(sender, "Use: /charinfo (id)");
CommandManager.SendMessage(sender, "\nAll characters:");
foreach (Character chara in target.chars)
{
//locTable.TryGetValue(characterTable.Values.ToList().Find(x => x.charId == chara.id).name.id, out string aName);
string aName = characterTable.Values.ToList().Find(x => x.charId == chara.id).engName;
CommandManager.SendMessage(sender, $"{aName} ({chara.id})");
}
return;
}
//locTable.TryGetValue(characterTable.Values.ToList().Find(x => x.charId == args[0]).name.id, out string name);
string name = characterTable.Values.ToList().Find(x => x.charId == args[0]).engName;
Character character = target.GetCharacter(args[0]);
Item weapon = DatabaseManager.db.LoadInventoryItems(target.roleId).Find(w => w.guid == character.weaponGuid);
string responce = @$"
// {name} ({character.id})
guid: {character.guid}
level: {character.level}
curHp: {character.curHp}
potential: {character.potential}
breakNode: {character.breakNode}
// Weapon ({weapon.id})
guid: {character.weaponGuid}
level: {weapon.level}
weapon breakThroughLvl: {weapon.breakthroughLv}
weapon potential: {weapon.refineLv}";
CommandManager.SendMessage(sender, responce);
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandClear
{
[Server.Command("clear", "clears the console", false)]
public static void Handle(Player sender,string cmd, string[] args, Player target)
{
if (sender != null)
{
CommandManager.SendMessage(sender, "This command can't be used ingame");
return;
}
Console.Clear();
Logger.Print("Console cleared");
}
}
}

View File

@ -0,0 +1,43 @@
using Campofinale.Game.Entities;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandHeal
{
[Server.Command("heal", "Revives/Heals your team characters", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
target.GetCurTeam().ForEach(chara =>
{
chara.curHp = chara.CalcAttributes()[AttributeType.MaxHp].val;
ScCharSyncStatus state = new ScCharSyncStatus()
{
Objid=chara.guid,
IsDead=chara.curHp < 1,
BattleInfo = new()
{
Hp=chara.curHp,
Ultimatesp=chara.ultimateSp
}
};
target.Send(ScMsgId.ScCharSyncStatus, state);
});
target.Send(ScMsgId.ScSceneRevival, new ScSceneRevival()
{
});
target.sceneManager.LoadCurrentTeamEntities();
target.Send(new PacketScSelfSceneInfo(target,SelfInfoReasonType.SlrReviveRest));
CommandManager.SendMessage(sender, "Healed!");
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandHelp
{
[Server.Command("help", "Show list of commands", false)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
CommandManager.SendMessage(sender, "List of possible commands: ");
foreach (var command in CommandManager.s_notifyReqGroup)
{
CommandManager.SendMessage(sender, $"/{command.Key} - {command.Value.Item1.desc} (Require Target: {command.Value.Item1.requiredTarget})");
}
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Commands.Handlers
{
public class CommandIdList
{
[Server.Command("idlist", "List of all ids", false)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 1)
{
CommandManager.SendMessage(sender, "Use: /idlist (chars|enemies|scenes)");
return;
}
switch (args[0])
{
case "chars":
CommandManager.SendMessage(sender, "Character ids:");
characterTable.Values.ToList().ForEach(c => {
CommandManager.SendMessage(sender, $"{c.charId} ({c.engName})");
});
break;
case "enemies":
CommandManager.SendMessage(sender, "Enemy ids:");
enemyTable.Values.ToList().ForEach(e => {
CommandManager.SendMessage(sender, $"{e.enemyId} (templateId: {e.templateId})");
});
break;
case "scenes":
CommandManager.SendMessage(sender, "Scene ids:");
levelDatas.ForEach(s => {
CommandManager.SendMessage(sender, $"{s.id} (id: {s.idNum})");
});
break;
default:
CommandManager.SendMessage(sender, "Category not found");
break;
}
}
}
}

View File

@ -0,0 +1,19 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandKick
{
[Server.Command("kick", "kick target", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
target.Kick(CODE.ErrKickSessionEnd, "Kicked");
CommandManager.SendMessage(sender,"Kicked " + target.accountId);
}
}
}

View File

@ -0,0 +1,157 @@
using Campofinale.Commands;
using Campofinale.Database;
using Campofinale.Packets.Sc;
using Campofinale.Resource;
namespace Campofinale.Game.Character
{
public static class CharacterManager
{
[Server.Command("level", "Update character/item level", true)]
public static void HandleLevel(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 1)
{
CommandManager.SendMessage(sender, @"Use:
/level (char_id/item_id) (level) - Update specific character/item level
/level (level) - Update all characters and items to level");
return;
}
try
{
if (args.Length == 1)
{
if (!int.TryParse(args[0], out int level))
{
CommandManager.SendMessage(sender, "Invalid level number");
return;
}
UpdateAllLevels(sender, target, level);
}
else
{
string id = args[0];
if (!int.TryParse(args[1], out int level))
{
CommandManager.SendMessage(sender, "Invalid level number");
return;
}
UpdateSingleLevel(sender, target, id, level);
}
}
catch (Exception err)
{
CommandManager.SendMessage(sender, $"An error occurred: {err}");
}
}
private static void UpdateAllLevels(Player sender, Player target, int level)
{
level = Math.Max(1, Math.Min(level, 80));
int updatedCharCount = 0;
foreach (var item in ResourceManager.itemTable)
{
if (item.Key.StartsWith("chr_"))
{
AddOrUpdateCharacter(target, item.Key, level);
updatedCharCount++;
}
}
int updatedItemCount = 0;
foreach (var item in target.inventoryManager.items)
{
if (item.id.StartsWith("wpn_"))
{
item.amount = 0;
target.Send(new PacketScItemBagScopeModify(target, item));
item.amount = 1;
item.level = (ulong)level;
target.Send(new PacketScItemBagScopeModify(target, item));
updatedItemCount++;
}
}
target.SaveCharacters();
target.inventoryManager.Save();
CommandManager.SendMessage(sender, $"Updated {updatedCharCount} characters and {updatedItemCount} weapons to level {level}");
}
private static void UpdateSingleLevel(Player sender, Player target, string id, int level)
{
level = Math.Max(1, Math.Min(level, 80));
if (id.StartsWith("chr_"))
{
if (!ResourceManager.itemTable.ContainsKey(id))
{
CommandManager.SendMessage(sender, $"Invalid character ID: {id}");
return;
}
AddOrUpdateCharacter(target, id, level);
target.SaveCharacters();
CommandManager.SendMessage(sender, $"Character {id} level updated to {level}");
}
else if (id.StartsWith("wpn_"))
{
var item = target.inventoryManager.GetItemById(id);
if (item == null)
{
CommandManager.SendMessage(sender, $"Item not found: {id}");
return;
}
item.amount = 0;
target.Send(new PacketScItemBagScopeModify(target, item));
item.amount = 1;
item.level = (ulong)level;
target.Send(new PacketScItemBagScopeModify(target, item));
target.inventoryManager.Save();
CommandManager.SendMessage(sender, $"Weapon {id} level updated to {level}");
}
else
{
CommandManager.SendMessage(sender, $"Invalid ID format: {id} (must start with 'chr_' or 'wpn_')");
}
}
private static Character AddOrUpdateCharacter(Player target, string charId, int level)
{
Character existingChar = target.chars.Find(c => c.id == charId);
if (existingChar != null)
{
existingChar.level = level;
existingChar.breakNode = GetBreakNodeByLevel(level);
target.Send(new PacketScCharBagDelChar(target, existingChar));
target.Send(new PacketScCharBagAddChar(target, existingChar));
return existingChar;
}
Character character = new Character(target.roleId, charId, level);
character.breakNode = GetBreakNodeByLevel(level);
target.chars.Add(character);
target.Send(new PacketScCharBagAddChar(target, character));
return character;
}
private static string GetBreakNodeByLevel(int level)
{
if (level <= 20) return "";
if (level <= 40) return "charBreak20";
if (level <= 60) return "charBreak40";
if (level <= 70) return "charBreak60";
return "charBreak70";
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Campofinale.Packets.Sc;
namespace Campofinale.Commands.Handlers
{
public static class CommandNickname
{
[Server.Command("nickname", "Changes nickname", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 1)
{
CommandManager.SendMessage(sender, "Use: /nickname (your new nickname)");
return;
}
for (int i=0; i < args.Length; i++)
{
args[i] = Uri.UnescapeDataString(args[i]);
}
target.nickname = string.Join(" ", args);
target.Save();
target.Send(new PacketScSetName(target, target.nickname));
CommandManager.SendMessage(sender, $"Nickname was changed to {target.nickname}");
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandPlayers
{
[Server.Command("players", "list of connected players", false)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
CommandManager.SendMessage(sender, "List of connected players:");
if (Server.clients.Count == 0) CommandManager.SendMessage(sender, "└No players on the server");
foreach (var player in Server.clients)
{
string decorator = "│";
if (player == Server.clients.Last()) decorator = "└";
CommandManager.SendMessage(sender, $"{decorator}Player: {player.nickname} | UID: {player.accountId}");
}
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Campofinale.Database;
using Campofinale.Game.Character;
using Campofinale.Packets.Sc;
namespace Campofinale.Commands.Handlers;
public static class CommandRemove
{
[Server.Command("remove", "Removes character", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if(args.Length < 1)
{
CommandManager.SendMessage(sender, "Use: /remove (char id)");
return;
}
Character character = target.chars.Find(c => c.id == args[0]);
if(character == null)
{
CommandManager.SendMessage(sender, "Character not found");
return;
}
target.chars.Remove(character);
DatabaseManager.db.DeleteCharacter(character);
target.SaveCharacters();
target.Send(new PacketScCharBagDelChar(target, character));
CommandManager.SendMessage(sender, $"Character {character.id} removed.");
}
}

View File

@ -0,0 +1,56 @@
using Campofinale.Game.Entities;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandSpawn
{
[Server.Command("spawn", "Spawn command", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 2)
{
CommandManager.SendMessage(sender, "Example: spawn (id) (level)");
return;
}
string templateId = args[0];
int level = int.Parse(args[1]);
if (level < 1)
{
CommandManager.SendMessage(sender, "Level can't be less than 1");
return;
}
switch (templateId.Split("_")[0])
{
case "eny":
if (ResourceManager.enemyTable.ContainsKey(templateId))
{
EntityMonster mon = new(templateId, level, target.roleId, target.position, target.rotation,target.curSceneNumId);
target.sceneManager.SpawnEntity(mon);
}
else
{
CommandManager.SendMessage(sender, "Monster template id not found");
}
break;
default:
CommandManager.SendMessage(sender, "Unsupported template id to spawn: " + templateId.Split("_")[0]);
break;
}
/*target.Send(ScMessageId.ScSpawnEnemy, new ScSpawnEnemy()
{
ClientKey=2,
EnemyInstIds = { info.Detail.MonsterList[0].CommonInfo.Id }
});*/
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using Campofinale.Packets.Sc;
using MongoDB.Bson;
namespace Campofinale.Commands.Handlers
{
public class CommandTeleport
{
[Server.Command("tp", "Teleports player", true)]
public static void Handle(Player sender, string cmd, string[] args, Player target)
{
if (args.Length < 3)
{
CommandManager.SendMessage(sender, "Use: /tp (x) (y) (z)\nYou can use ~ to use current player coordinate");
CommandManager.SendMessage(sender, $"\nCurrent player position: {target.position.ToJson()}");
return;
}
for (int i=0; i < args.Length; i++)
{
args[i] = Uri.UnescapeDataString(args[i]).Replace(".", ",");
}
float x, y, z;
x = args[0] == "~" ? target.position.x : float.Parse(args[0]);
y = args[1] == "~" ? target.position.y : float.Parse(args[1]);
z = args[2] == "~" ? target.position.z : float.Parse(args[2]);
Vector3f position = new Vector3f(new Vector()
{
X = x,
Y = y,
Z = z
});
target.position = position;
target.Send(new PacketScEnterSceneNotify(target, target.curSceneNumId, position));
CommandManager.SendMessage(sender, $"Player teleported to {target.position.ToJson()}");
}
}
}

View File

@ -0,0 +1,37 @@
using Campofinale.Database;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Commands.Handlers
{
public static class CommandUnlockAll
{
[Server.Command("unlockall", "Unlock all systems",true)]
public static void Handle(Player sender,string cmd, string[] args, Player target)
{
target.unlockedSystems.Clear();
target.UnlockImportantSystems();
target.maxDashEnergy = 250;
foreach (var system in target.unlockedSystems)
{
ScUnlockSystem unlocked = new()
{
UnlockSystemType = system,
};
target.Send(ScMsgId.ScUnlockSystem, unlocked);
}
foreach (int i in ResourceManager.GetAllShortIds())
{
target.bitsetManager.AddValue(BitsetType.InteractiveActive, i);
}
target.Send(new PacketScSyncAllBitset(target));
CommandManager.SendMessage(sender, "Unlocked everything");
}
}
}

71
Campofinale/ConfigFile.cs Normal file
View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale
{
public class ConfigFile
{
public MongoDatabaseSettings mongoDatabase = new();
public DispatchServerSettings dispatchServer = new();
public GameserverSettings gameServer = new();
public ServerOptions serverOptions = new();
public LogSettings logOptions = new();
}
public struct ServerOptions
{
public int defaultSceneNumId = 98;
public int maxPlayers = 20;
public ServerOptions()
{
}
/* public struct WelcomeMail
{
}*/
}
public struct LogSettings
{
public bool packets;
public bool debugPrint=false;
public LogSettings()
{
}
}
public struct GameserverSettings
{
public string bindAddress = "127.0.0.1";
public int bindPort = 30000;
public string accessAddress = "127.0.0.1";
public int accessPort = 30000;
public GameserverSettings()
{
}
}
public struct DispatchServerSettings
{
public string bindAddress = "127.0.0.1";
public int bindPort = 5000;
public string accessAddress = "127.0.0.1";
public int accessPort = 5000;
public string emailFormat = "@campofinale.ps";
public DispatchServerSettings()
{
}
}
public struct MongoDatabaseSettings
{
public string uri = "mongodb://localhost:27017";
public string collection = "Campofinale";
public MongoDatabaseSettings()
{
}
}
}

View File

@ -0,0 +1,930 @@
/*
* Copyright (c) 2015, 2018 Scott Bennett
* (c) 2018-2023 Kaarlo Räihä
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
using System;
using System.IO;
using System.Threading.Tasks;
using System.Runtime.Intrinsics;
using System.Runtime.CompilerServices;
namespace BeyondTools.VFS.Crypto;
/// <summary>
/// Chosen SIMD mode
/// </summary>
public enum SimdMode
{
/// <summary>
/// Autodetect
/// </summary>
AutoDetect = 0,
/// <summary>
/// 128 bit SIMD
/// </summary>
V128,
/// <summary>
/// 256 bit SIMD
/// </summary>
V256,
/// <summary>
/// 512 bit SIMD
/// </summary>
V512,
/// <summary>
/// No SIMD
/// </summary>
None
}
/// <summary>
/// Class for ChaCha20 encryption / decryption
/// </summary>
public sealed class CSChaCha20 : IDisposable
{
/// <summary>
/// Only allowed key lenght in bytes
/// </summary>
public const int allowedKeyLength = 32;
/// <summary>
/// Only allowed nonce lenght in bytes
/// </summary>
public const int allowedNonceLength = 12;
/// <summary>
/// How many bytes are processed per loop
/// </summary>
public const int processBytesAtTime = 64;
private const int stateLength = 16;
/// <summary>
/// The ChaCha20 state (aka "context")
/// </summary>
private readonly uint[] state = new uint[stateLength];
/// <summary>
/// Determines if the objects in this class have been disposed of. Set to true by the Dispose() method.
/// </summary>
private bool isDisposed = false;
/// <summary>
/// Set up a new ChaCha20 state. The lengths of the given parameters are checked before encryption happens.
/// </summary>
/// <remarks>
/// See <a href="https://tools.ietf.org/html/rfc7539#page-10">ChaCha20 Spec Section 2.4</a> for a detailed description of the inputs.
/// </remarks>
/// <param name="key">
/// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
/// </param>
/// <param name="nonce">
/// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
/// </param>
/// <param name="counter">
/// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
/// </param>
public CSChaCha20(byte[] key, byte[] nonce, uint counter)
{
KeySetup(key);
IvSetup(nonce, counter);
}
/// <summary>
/// Set up a new ChaCha20 state. The lengths of the given parameters are checked before encryption happens.
/// </summary>
/// <remarks>
/// See <a href="https://tools.ietf.org/html/rfc7539#page-10">ChaCha20 Spec Section 2.4</a> for a detailed description of the inputs.
/// </remarks>
/// <param name="key">A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers</param>
/// <param name="nonce">A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers</param>
/// <param name="counter">A 4-byte (32-bit) block counter, treated as a 32-bit little-endian unsigned integer</param>
public CSChaCha20(ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, uint counter)
{
KeySetup(key.ToArray());
IvSetup(nonce.ToArray(), counter);
}
/// <summary>
/// The ChaCha20 state (aka "context"). Read-Only.
/// </summary>
public uint[] State
{
get
{
return state;
}
}
// These are the same constants defined in the reference implementation.
// http://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c
private static readonly byte[] sigma = "expand 32-byte k"u8.ToArray();
private static readonly byte[] tau = "expand 16-byte k"u8.ToArray();
/// <summary>
/// Set up the ChaCha state with the given key. A 32-byte key is required and enforced.
/// </summary>
/// <param name="key">
/// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
/// </param>
private void KeySetup(byte[] key)
{
if (key == null)
{
throw new ArgumentNullException("Key is null");
}
if (key.Length != allowedKeyLength)
{
throw new ArgumentException($"Key length must be {allowedKeyLength}. Actual: {key.Length}");
}
state[4] = Util.U8To32Little(key, 0);
state[5] = Util.U8To32Little(key, 4);
state[6] = Util.U8To32Little(key, 8);
state[7] = Util.U8To32Little(key, 12);
byte[] constants = key.Length == allowedKeyLength ? sigma : tau;
int keyIndex = key.Length - 16;
state[8] = Util.U8To32Little(key, keyIndex + 0);
state[9] = Util.U8To32Little(key, keyIndex + 4);
state[10] = Util.U8To32Little(key, keyIndex + 8);
state[11] = Util.U8To32Little(key, keyIndex + 12);
state[0] = Util.U8To32Little(constants, 0);
state[1] = Util.U8To32Little(constants, 4);
state[2] = Util.U8To32Little(constants, 8);
state[3] = Util.U8To32Little(constants, 12);
}
/// <summary>
/// Set up the ChaCha state with the given nonce (aka Initialization Vector or IV) and block counter. A 12-byte nonce and a 4-byte counter are required.
/// </summary>
/// <param name="nonce">
/// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
/// </param>
/// <param name="counter">
/// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
/// </param>
private void IvSetup(byte[] nonce, uint counter)
{
if (nonce == null)
{
// There has already been some state set up. Clear it before exiting.
Dispose();
throw new ArgumentNullException("Nonce is null");
}
if (nonce.Length != allowedNonceLength)
{
// There has already been some state set up. Clear it before exiting.
Dispose();
throw new ArgumentException($"Nonce length must be {allowedNonceLength}. Actual: {nonce.Length}");
}
state[12] = counter;
state[13] = Util.U8To32Little(nonce, 0);
state[14] = Util.U8To32Little(nonce, 4);
state[15] = Util.U8To32Little(nonce, 8);
}
private static SimdMode DetectSimdMode()
{
if (Vector512.IsHardwareAccelerated)
{
return SimdMode.V512;
}
else if (Vector256.IsHardwareAccelerated)
{
return SimdMode.V256;
}
else if (Vector128.IsHardwareAccelerated)
{
return SimdMode.V128;
}
return SimdMode.None;
}
#region Encryption methods
/// <summary>
/// Encrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="output">Output byte array, must have enough bytes</param>
/// <param name="input">Input byte array</param>
/// <param name="numBytes">Number of bytes to encrypt</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void EncryptBytes(byte[] output, byte[] input, int numBytes, SimdMode simdMode = SimdMode.AutoDetect)
{
if (output == null)
{
throw new ArgumentNullException("output", "Output cannot be null");
}
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (numBytes < 0 || numBytes > input.Length)
{
throw new ArgumentOutOfRangeException("numBytes", "The number of bytes to read must be between [0..input.Length]");
}
if (output.Length < numBytes)
{
throw new ArgumentOutOfRangeException("output", $"Output byte array should be able to take at least {numBytes}");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkBytes(output, input, numBytes, simdMode);
}
/// <summary>
/// Encrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
/// </summary>
/// <param name="output">Output stream</param>
/// <param name="input">Input stream</param>
/// <param name="howManyBytesToProcessAtTime">How many bytes to read and write at time, default is 1024</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void EncryptStream(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024, SimdMode simdMode = SimdMode.AutoDetect)
{
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkStreams(output, input, simdMode, howManyBytesToProcessAtTime);
}
/// <summary>
/// Async encrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
/// </summary>
/// <param name="output">Output stream</param>
/// <param name="input">Input stream</param>
/// <param name="howManyBytesToProcessAtTime">How many bytes to read and write at time, default is 1024</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public async Task EncryptStreamAsync(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024, SimdMode simdMode = SimdMode.AutoDetect)
{
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
await WorkStreamsAsync(output, input, simdMode, howManyBytesToProcessAtTime);
}
/// <summary>
/// Encrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="output">Output byte array, must have enough bytes</param>
/// <param name="input">Input byte array</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void EncryptBytes(byte[] output, byte[] input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (output == null)
{
throw new ArgumentNullException("output", "Output cannot be null");
}
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkBytes(output, input, input.Length, simdMode);
}
/// <summary>
/// Encrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="input">Input byte array</param>
/// <param name="numBytes">Number of bytes to encrypt</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains encrypted bytes</returns>
public byte[] EncryptBytes(byte[] input, int numBytes, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (numBytes < 0 || numBytes > input.Length)
{
throw new ArgumentOutOfRangeException("numBytes", "The number of bytes to read must be between [0..input.Length]");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] returnArray = new byte[numBytes];
WorkBytes(returnArray, input, numBytes, simdMode);
return returnArray;
}
/// <summary>
/// Encrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="input">Input byte array</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains encrypted bytes</returns>
public byte[] EncryptBytes(byte[] input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] returnArray = new byte[input.Length];
WorkBytes(returnArray, input, input.Length, simdMode);
return returnArray;
}
/// <summary>
/// Encrypt string as UTF8 byte array, returns byte array that is allocated by method.
/// </summary>
/// <remarks>Here you can NOT swap encrypt and decrypt methods, because of bytes-string transform</remarks>
/// <param name="input">Input string</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains encrypted bytes</returns>
public byte[] EncryptString(string input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(input);
byte[] returnArray = new byte[utf8Bytes.Length];
WorkBytes(returnArray, utf8Bytes, utf8Bytes.Length, simdMode);
return returnArray;
}
#endregion // Encryption methods
#region // Decryption methods
/// <summary>
/// Decrypt arbitrary-length byte array (input), writing the resulting byte array to the output buffer.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="output">Output byte array</param>
/// <param name="input">Input byte array</param>
/// <param name="numBytes">Number of bytes to decrypt</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void DecryptBytes(byte[] output, byte[] input, int numBytes, SimdMode simdMode = SimdMode.AutoDetect)
{
if (output == null)
{
throw new ArgumentNullException("output", "Output cannot be null");
}
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (numBytes < 0 || numBytes > input.Length)
{
throw new ArgumentOutOfRangeException("numBytes", "The number of bytes to read must be between [0..input.Length]");
}
if (output.Length < numBytes)
{
throw new ArgumentOutOfRangeException("output", $"Output byte array should be able to take at least {numBytes}");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkBytes(output, input, numBytes, simdMode);
}
/// <summary>
/// Decrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
/// </summary>
/// <param name="output">Output stream</param>
/// <param name="input">Input stream</param>
/// <param name="howManyBytesToProcessAtTime">How many bytes to read and write at time, default is 1024</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void DecryptStream(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024, SimdMode simdMode = SimdMode.AutoDetect)
{
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkStreams(output, input, simdMode, howManyBytesToProcessAtTime);
}
/// <summary>
/// Async decrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
/// </summary>
/// <param name="output">Output stream</param>
/// <param name="input">Input stream</param>
/// <param name="howManyBytesToProcessAtTime">How many bytes to read and write at time, default is 1024</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public async Task DecryptStreamAsync(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024, SimdMode simdMode = SimdMode.AutoDetect)
{
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
await WorkStreamsAsync(output, input, simdMode, howManyBytesToProcessAtTime);
}
/// <summary>
/// Decrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="output">Output byte array, must have enough bytes</param>
/// <param name="input">Input byte array</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
public void DecryptBytes(byte[] output, byte[] input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (output == null)
{
throw new ArgumentNullException("output", "Output cannot be null");
}
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
WorkBytes(output, input, input.Length, simdMode);
}
/// <summary>
/// Decrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="input">Input byte array</param>
/// <param name="numBytes">Number of bytes to encrypt</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains decrypted bytes</returns>
public byte[] DecryptBytes(byte[] input, int numBytes, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (numBytes < 0 || numBytes > input.Length)
{
throw new ArgumentOutOfRangeException("numBytes", "The number of bytes to read must be between [0..input.Length]");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] returnArray = new byte[numBytes];
WorkBytes(returnArray, input, numBytes, simdMode);
return returnArray;
}
/// <summary>
/// Decrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="input">Input byte array</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains decrypted bytes</returns>
public byte[] DecryptBytes(byte[] input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] returnArray = new byte[input.Length];
WorkBytes(returnArray, input, input.Length, simdMode);
return returnArray;
}
/// <summary>
/// Decrypt UTF8 byte array to string.
/// </summary>
/// <remarks>Here you can NOT swap encrypt and decrypt methods, because of bytes-string transform</remarks>
/// <param name="input">Byte array</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
/// <returns>Byte array that contains encrypted bytes</returns>
public string DecryptUTF8ByteArray(byte[] input, SimdMode simdMode = SimdMode.AutoDetect)
{
if (input == null)
{
throw new ArgumentNullException("input", "Input cannot be null");
}
if (simdMode == SimdMode.AutoDetect)
{
simdMode = DetectSimdMode();
}
byte[] tempArray = new byte[input.Length];
WorkBytes(tempArray, input, input.Length, simdMode);
return System.Text.Encoding.UTF8.GetString(tempArray);
}
#endregion // Decryption methods
private void WorkStreams(Stream output, Stream input, SimdMode simdMode, int howManyBytesToProcessAtTime = 1024)
{
int readBytes;
byte[] inputBuffer = new byte[howManyBytesToProcessAtTime];
byte[] outputBuffer = new byte[howManyBytesToProcessAtTime];
while ((readBytes = input.Read(inputBuffer, 0, howManyBytesToProcessAtTime)) > 0)
{
// Encrypt or decrypt
WorkBytes(output: outputBuffer, input: inputBuffer, numBytes: readBytes, simdMode);
// Write buffer
output.Write(outputBuffer, 0, readBytes);
}
}
private async Task WorkStreamsAsync(Stream output, Stream input, SimdMode simdMode, int howManyBytesToProcessAtTime = 1024)
{
byte[] readBytesBuffer = new byte[howManyBytesToProcessAtTime];
byte[] writeBytesBuffer = new byte[howManyBytesToProcessAtTime];
int howManyBytesWereRead = await input.ReadAsync(readBytesBuffer, 0, howManyBytesToProcessAtTime);
while (howManyBytesWereRead > 0)
{
// Encrypt or decrypt
WorkBytes(output: writeBytesBuffer, input: readBytesBuffer, numBytes: howManyBytesWereRead, simdMode);
// Write
await output.WriteAsync(writeBytesBuffer, 0, howManyBytesWereRead);
// Read more
howManyBytesWereRead = await input.ReadAsync(readBytesBuffer, 0, howManyBytesToProcessAtTime);
}
}
/// <summary>
/// Encrypt or decrypt an arbitrary-length byte array (input), writing the resulting byte array to the output buffer. The number of bytes to read from the input buffer is determined by numBytes.
/// </summary>
/// <param name="output">Output byte array</param>
/// <param name="input">Input byte array</param>
/// <param name="numBytes">How many bytes to process</param>
/// <param name="simdMode">Chosen SIMD mode (default is auto-detect)</param>
private void WorkBytes(byte[] output, byte[] input, int numBytes, SimdMode simdMode)
{
if (isDisposed)
{
throw new ObjectDisposedException("state", "The ChaCha state has been disposed");
}
uint[] x = new uint[stateLength]; // Working buffer
byte[] tmp = new byte[processBytesAtTime]; // Temporary buffer
int offset = 0;
int howManyFullLoops = numBytes / processBytesAtTime;
int tailByteCount = numBytes - howManyFullLoops * processBytesAtTime;
for (int loop = 0; loop < howManyFullLoops; loop++)
{
UpdateStateAndGenerateTemporaryBuffer(state, x, tmp);
if (simdMode == SimdMode.V512)
{
// 1 x 64 bytes
Vector512<byte> inputV = Vector512.Create(input, offset);
Vector512<byte> tmpV = Vector512.Create(tmp, 0);
Vector512<byte> outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset);
}
else if (simdMode == SimdMode.V256)
{
// 2 x 32 bytes
Vector256<byte> inputV = Vector256.Create(input, offset);
Vector256<byte> tmpV = Vector256.Create(tmp, 0);
Vector256<byte> outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset);
inputV = Vector256.Create(input, offset + 32);
tmpV = Vector256.Create(tmp, 32);
outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset + 32);
}
else if (simdMode == SimdMode.V128)
{
// 4 x 16 bytes
Vector128<byte> inputV = Vector128.Create(input, offset);
Vector128<byte> tmpV = Vector128.Create(tmp, 0);
Vector128<byte> outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset);
inputV = Vector128.Create(input, offset + 16);
tmpV = Vector128.Create(tmp, 16);
outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset + 16);
inputV = Vector128.Create(input, offset + 32);
tmpV = Vector128.Create(tmp, 32);
outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset + 32);
inputV = Vector128.Create(input, offset + 48);
tmpV = Vector128.Create(tmp, 48);
outputV = inputV ^ tmpV;
outputV.CopyTo(output, offset + 48);
}
else
{
for (int i = 0; i < processBytesAtTime; i += 4)
{
// Small unroll
int start = i + offset;
output[start] = (byte)(input[start] ^ tmp[i]);
output[start + 1] = (byte)(input[start + 1] ^ tmp[i + 1]);
output[start + 2] = (byte)(input[start + 2] ^ tmp[i + 2]);
output[start + 3] = (byte)(input[start + 3] ^ tmp[i + 3]);
}
}
offset += processBytesAtTime;
}
// In case there are some bytes left
if (tailByteCount > 0)
{
UpdateStateAndGenerateTemporaryBuffer(state, x, tmp);
for (int i = 0; i < tailByteCount; i++)
{
output[i + offset] = (byte)(input[i + offset] ^ tmp[i]);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void UpdateStateAndGenerateTemporaryBuffer(uint[] stateToModify, uint[] workingBuffer, byte[] temporaryBuffer)
{
// Copy state to working buffer
Buffer.BlockCopy(stateToModify, 0, workingBuffer, 0, stateLength * sizeof(uint));
for (int i = 0; i < 10; i++)
{
QuarterRound(workingBuffer, 0, 4, 8, 12);
QuarterRound(workingBuffer, 1, 5, 9, 13);
QuarterRound(workingBuffer, 2, 6, 10, 14);
QuarterRound(workingBuffer, 3, 7, 11, 15);
QuarterRound(workingBuffer, 0, 5, 10, 15);
QuarterRound(workingBuffer, 1, 6, 11, 12);
QuarterRound(workingBuffer, 2, 7, 8, 13);
QuarterRound(workingBuffer, 3, 4, 9, 14);
}
for (int i = 0; i < stateLength; i++)
{
Util.ToBytes(temporaryBuffer, Util.Add(workingBuffer[i], stateToModify[i]), 4 * i);
}
stateToModify[12] = Util.AddOne(stateToModify[12]);
if (stateToModify[12] <= 0)
{
/* Stopping at 2^70 bytes per nonce is the user's responsibility */
stateToModify[13] = Util.AddOne(stateToModify[13]);
}
}
/// <summary>
/// The ChaCha Quarter Round operation. It operates on four 32-bit unsigned integers within the given buffer at indices a, b, c, and d.
/// </summary>
/// <remarks>
/// The ChaCha state does not have four integer numbers: it has 16. So the quarter-round operation works on only four of them -- hence the name. Each quarter round operates on four predetermined numbers in the ChaCha state.
/// See <a href="https://tools.ietf.org/html/rfc7539#page-4">ChaCha20 Spec Sections 2.1 - 2.2</a>.
/// </remarks>
/// <param name="x">A ChaCha state (vector). Must contain 16 elements.</param>
/// <param name="a">Index of the first number</param>
/// <param name="b">Index of the second number</param>
/// <param name="c">Index of the third number</param>
/// <param name="d">Index of the fourth number</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void QuarterRound(uint[] x, uint a, uint b, uint c, uint d)
{
x[a] = Util.Add(x[a], x[b]);
x[d] = Util.Rotate(Util.XOr(x[d], x[a]), 16);
x[c] = Util.Add(x[c], x[d]);
x[b] = Util.Rotate(Util.XOr(x[b], x[c]), 12);
x[a] = Util.Add(x[a], x[b]);
x[d] = Util.Rotate(Util.XOr(x[d], x[a]), 8);
x[c] = Util.Add(x[c], x[d]);
x[b] = Util.Rotate(Util.XOr(x[b], x[c]), 7);
}
#region Destructor and Disposer
/// <summary>
/// Clear and dispose of the internal state. The finalizer is only called if Dispose() was never called on this cipher.
/// </summary>
~CSChaCha20()
{
Dispose(false);
}
/// <summary>
/// Clear and dispose of the internal state. Also request the GC not to call the finalizer, because all cleanup has been taken care of.
/// </summary>
public void Dispose()
{
Dispose(true);
/*
* The Garbage Collector does not need to invoke the finalizer because Dispose(bool) has already done all the cleanup needed.
*/
GC.SuppressFinalize(this);
}
/// <summary>
/// This method should only be invoked from Dispose() or the finalizer. This handles the actual cleanup of the resources.
/// </summary>
/// <param name="disposing">
/// Should be true if called by Dispose(); false if called by the finalizer
/// </param>
private void Dispose(bool disposing)
{
if (!isDisposed)
{
if (disposing)
{
/* Cleanup managed objects by calling their Dispose() methods */
}
/* Cleanup any unmanaged objects here */
Array.Clear(state, 0, stateLength);
}
isDisposed = true;
}
#endregion // Destructor and Disposer
}
/// <summary>
/// Utilities that are used during compression
/// </summary>
public static class Util
{
/// <summary>
/// n-bit left rotation operation (towards the high bits) for 32-bit integers.
/// </summary>
/// <param name="v"></param>
/// <param name="c"></param>
/// <returns>The result of (v LEFTSHIFT c)</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Rotate(uint v, int c)
{
unchecked
{
return v << c | v >> 32 - c;
}
}
/// <summary>
/// Unchecked integer exclusive or (XOR) operation.
/// </summary>
/// <param name="v"></param>
/// <param name="w"></param>
/// <returns>The result of (v XOR w)</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint XOr(uint v, uint w)
{
return unchecked(v ^ w);
}
/// <summary>
/// Unchecked integer addition. The ChaCha spec defines certain operations to use 32-bit unsigned integer addition modulo 2^32.
/// </summary>
/// <remarks>
/// See <a href="https://tools.ietf.org/html/rfc7539#page-4">ChaCha20 Spec Section 2.1</a>.
/// </remarks>
/// <param name="v"></param>
/// <param name="w"></param>
/// <returns>The result of (v + w) modulo 2^32</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Add(uint v, uint w)
{
return unchecked(v + w);
}
/// <summary>
/// Add 1 to the input parameter using unchecked integer addition. The ChaCha spec defines certain operations to use 32-bit unsigned integer addition modulo 2^32.
/// </summary>
/// <remarks>
/// See <a href="https://tools.ietf.org/html/rfc7539#page-4">ChaCha20 Spec Section 2.1</a>.
/// </remarks>
/// <param name="v"></param>
/// <returns>The result of (v + 1) modulo 2^32</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint AddOne(uint v)
{
return unchecked(v + 1);
}
/// <summary>
/// Convert four bytes of the input buffer into an unsigned 32-bit integer, beginning at the inputOffset.
/// </summary>
/// <param name="p"></param>
/// <param name="inputOffset"></param>
/// <returns>An unsigned 32-bit integer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint U8To32Little(byte[] p, int inputOffset)
{
unchecked
{
return p[inputOffset]
| (uint)p[inputOffset + 1] << 8
| (uint)p[inputOffset + 2] << 16
| (uint)p[inputOffset + 3] << 24;
}
}
/// <summary>
/// Serialize the input integer into the output buffer. The input integer will be split into 4 bytes and put into four sequential places in the output buffer, starting at the outputOffset.
/// </summary>
/// <param name="output"></param>
/// <param name="input"></param>
/// <param name="outputOffset"></param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToBytes(byte[] output, uint input, int outputOffset)
{
unchecked
{
output[outputOffset] = (byte)input;
output[outputOffset + 1] = (byte)(input >> 8);
output[outputOffset + 2] = (byte)(input >> 16);
output[outputOffset + 3] = (byte)(input >> 24);
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=0,initial-scale=1">
<meta name="keywords" content="">
<meta name="description" content="Player Console">
<meta property="og:type" content="website">
<meta property="og:title" content="Player Console">
<meta property="og:description" content="Player Console">
<title>Player Console</title>
<style>
* {
box-sizing: border-box;
}
html, body {
height: 100%;
margin: 0;
font-family: endfieldFont;
background-image: url("cs_bg.jpg");
background-size: cover;
display: flex;
flex-direction: column;
}
@font-face {
font-family: endfieldFont;
src: url("/ja-jp.otf");
}
.header {
padding: 30px;
margin: 0 20px 0 20px;
border-bottom: 2px solid #7a7a7a;
box-sizing: border-box;
}
.root {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 100%;
}
#console-output {
flex-grow: 1;
overflow-y: auto;
padding: 20px;
color: rgb(39, 39, 39);
}
#console-input {
display: flex;
padding: 10px;
outline: none;
}
#command-input {
flex-grow: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
outline: none;
}
#send-button {
padding: 10px 15px;
margin-left: 10px;
background-color: #fdfd1f;
color: black;
border: none;
border-radius: 4px;
cursor: pointer;
outline: none;
}
#send-button:hover {
background-color: #caca1c;
}
.message {
margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
font-family: monospace;
background-color: rgba(255, 255, 255, 0.6);
}
.user {
background-color: rgba(231, 243, 255, 0.6);
color: #1c3f95;
border-left: 5px solid #1c3f95;
}
.server {
background-color: rgba(255, 246, 224, 0.6);
color: #b8860b;
border-left: 5px solid #b8860b;
}
.error {
background-color: rgba(255, 204, 204, 0.6);
color: #a80000;
border-left: 5px solid #a80000;
}
.markdown {
white-space: pre-wrap;
font-family: inherit;
}
</style>
</head>
<body>
<div class="root">
<div class="header">//Command Prompt</div>
<div id="console-output"></div>
<div id="console-input">
<input type="text" id="command-input" placeholder="Enter command..." />
<button id="send-button">Send</button>
</div>
</div>
<script>
const consoleOutput = document.getElementById('console-output');
const commandInput = document.getElementById('command-input');
const sendButton = document.getElementById('send-button');
function renderMarkdown(text) {
// Simple markdown conversion (bold, italics, new lines)
return text
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/\n/g, '<br>');
}
function addMessage(type, text) {
const messageElement = document.createElement('div');
messageElement.classList.add('message', type);
messageElement.innerHTML = renderMarkdown(text);
consoleOutput.appendChild(messageElement);
consoleOutput.scrollTop = consoleOutput.scrollHeight;
}
async function sendCommand(command) {
if (!command.trim()) return;
addMessage('user', `**User:** ${command}`);
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
try {
const url = new URL('%dispatchip%/pcSdk/console');
url.searchParams.append('command', command);
url.searchParams.append('token', token);
const response = await fetch(url.toString(), {
method: 'GET',
});
if (!response.ok) {
throw new Error(`Server responded with status ${response.status}`);
}
const data = await response.json();
addMessage('server', `**Server:** ${data.message}`);
} catch (error) {
addMessage('error', `**Error:** ${error.message}`);
}
}
sendButton.addEventListener('click', () => {
const command = commandInput.value;
commandInput.value = '';
sendCommand(command);
});
commandInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const command = commandInput.value;
commandInput.value = '';
sendCommand(command);
}
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

View File

@ -0,0 +1,378 @@
using Campofinale.Game;
using Campofinale.Game.Character;
using Campofinale.Game.Gacha;
using Campofinale.Game.Inventory;
using Campofinale.Game.Spaceship;
using Campofinale.Resource;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Player;
using static Campofinale.Resource.ResourceManager;
using static SQLite.SQLite3;
namespace Campofinale.Database
{
public class PlayerData
{
[BsonId]
public ulong roleId;
public string accountId;
public Vector3f position;
public Vector3f rotation;
public int curSceneNumId;
public uint level = 20;
public uint xp = 0;
public string nickname = "Endministrator";
public int teamIndex = 0;
public List<Team> teams = new List<Team>();
public ulong totalGuidCount = 1;
public List<int> unlockedSystems = new();
public List<ulong> noSpawnAnymore = new();
public long maxDashEnergy = 250;
public uint curStamina;
public long nextRecoverTime;
public List<Scene> scenes = new();
public Dictionary<int, List<int>> bitsets = new();
public PlayerSafeZoneInfo savedSafeZone = new();
}
public class Account
{
public string id;
public string username;
public string token;
public string grantToken;
public static string GenerateAccountId()
{
byte[] bytes = new byte[4];
RandomNumberGenerator.Fill(bytes);
// Converte i byte in un intero positivo tra 100000000 e 999999999
int number = BitConverter.ToInt32(bytes, 0) & int.MaxValue;
number = 100000000 + (number % 900000000);
return number.ToString();
}
}
public class Database
{
private readonly IMongoDatabase _database;
public Database(string connectionString, string dbName)
{
var client = new MongoClient(connectionString);
_database = client.GetDatabase(dbName);
}
public List<Mail> LoadMails(ulong roleId)
{
return _database.GetCollection<Mail>("mails").Find(c => c.owner == roleId).ToList();
}
public List<Character> LoadCharacters(ulong roleId)
{
return _database.GetCollection<Character>("avatars").Find(c=>c.owner== roleId).ToList();
}
public List<SpaceshipChar> LoadSpaceshipChars(ulong roleId)
{
return _database.GetCollection<SpaceshipChar>("spaceship_chars").Find(c => c.owner == roleId).ToList();
}
public List<SpaceshipRoom> LoadSpaceshipRooms(ulong roleId)
{
return _database.GetCollection<SpaceshipRoom>("spaceship_rooms").Find(c => c.owner == roleId).ToList();
}
public List<Item> LoadInventoryItems(ulong roleId)
{
return _database.GetCollection<Item>("items").Find(c => c.owner == roleId).ToList();
}
public void AddGachaTransaction(GachaTransaction transaction)
{
if (transaction._id == ObjectId.Empty)
{
transaction._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<GachaTransaction>("gachas");
//These transactions never need to be changed
collection.InsertOne(transaction);
}
public List<GachaTransaction> LoadGachaTransaction(ulong roleId, string templateId)
{
return _database.GetCollection<GachaTransaction>("gachas").Find(c => c.ownerId== roleId && c.gachaTemplateId==templateId).ToList();
}
public static string GenerateToken(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
result.Append(chars[random.Next(chars.Length)]);
}
return result.ToString();
}
public void SavePlayerData(Player player)
{
PlayerData data = new()
{
accountId = player.accountId,
curSceneNumId = player.curSceneNumId,
level = player.level,
nickname = player.nickname,
position = player.position,
rotation = player.rotation,
roleId = player.roleId,
teams = player.teams,
xp = player.xp,
totalGuidCount = player.random.v,
teamIndex = player.teamIndex,
unlockedSystems = player.unlockedSystems,
maxDashEnergy = player.maxDashEnergy,
curStamina = player.curStamina,
nextRecoverTime = player.nextRecoverTime,
noSpawnAnymore = player.noSpawnAnymore,
scenes=player.sceneManager.scenes,
bitsets=player.bitsetManager.bitsets,
savedSafeZone = player.savedSaveZone
};
UpsertPlayerData(data);
}
public (string,int) CreateAccount(string username)
{
Account exist = GetAccountByUsername(username);
if (exist != null)
{
Logger.Print($"Cannot created account with username: {username} beecause it already exist.");
return ($"Cannot created account with username: {username} beecause it already exist.",1);
}
Account account = new()
{
username = username,
id = Account.GenerateAccountId(),
token= GenerateToken(22),
grantToken = GenerateToken(192)
};
UpsertAccount(account);
Logger.Print($"Account with username: {username} created with Account UID: {account.id}");
return ($"Account with username: {username} created with Account UID: {account.id}",0);
}
public void UpsertPlayerData(PlayerData player)
{
var collection = _database.GetCollection<PlayerData>("players");
var filter =
Builders<PlayerData>.Filter.Eq(p => p.roleId,player.roleId)
&
Builders<PlayerData>.Filter.Eq(p => p.accountId, player.accountId);
collection.ReplaceOne(
filter,
player,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertAccount(Account player)
{
var collection = _database.GetCollection<Account>("accounts");
var filter =
Builders<Account>.Filter.Eq(p => p.id, player.id)
&
Builders<Account>.Filter.Eq(p => p.token, player.token);
collection.ReplaceOne(
filter,
player,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertSpaceshipChar(SpaceshipChar character)
{
if (character._id == ObjectId.Empty)
{
character._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<SpaceshipChar>("spaceship_chars");
var filter =
Builders<SpaceshipChar>.Filter.Eq(c => c.id, character.id)
&
Builders<SpaceshipChar>.Filter.Eq(c => c.owner, character.owner);
var result = collection.ReplaceOne(
filter,
character,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertSpaceshipRoom(SpaceshipRoom room)
{
if (room._id == ObjectId.Empty)
{
room._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<SpaceshipRoom>("spaceship_rooms");
var filter =
Builders<SpaceshipRoom>.Filter.Eq(c => c.id, room.id)
&
Builders<SpaceshipRoom>.Filter.Eq(c => c.owner, room.owner);
var result = collection.ReplaceOne(
filter,
room,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertCharacter(Character character)
{
if (character._id == ObjectId.Empty)
{
character._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<Character>("avatars");
var filter =
Builders<Character>.Filter.Eq(c => c.guid, character.guid)
&
Builders<Character>.Filter.Eq(c => c.owner, character.owner);
var result=collection.ReplaceOne(
filter,
character,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertMail(Mail mail)
{
if (mail._id == ObjectId.Empty)
{
mail._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<Mail>("mails");
var filter =
Builders<Mail>.Filter.Eq(c => c.guid, mail.guid)
&
Builders<Mail>.Filter.Eq(c => c.owner, mail.owner);
var result = collection.ReplaceOne(
filter,
mail,
new ReplaceOptions { IsUpsert = true }
);
}
public void UpsertItem(Item item)
{
if (item._id == ObjectId.Empty)
{
item._id = ObjectId.GenerateNewId();
}
var collection = _database.GetCollection<Item>("items");
var filter =
Builders<Item>.Filter.Eq(c => c.guid, item.guid)
&
Builders<Item>.Filter.Eq(c => c.owner, item.owner);
var result = collection.ReplaceOne(
filter,
item,
new ReplaceOptions { IsUpsert = true }
);
}
public void DeleteItem(Item item)
{
var collection = _database.GetCollection<Item>("items");
var filter =
Builders<Item>.Filter.Eq(c => c.guid, item.guid)
&
Builders<Item>.Filter.Eq(c => c.owner, item.owner);
var result = collection.DeleteOne(
filter
);
}
public void DeleteCharacter(Character character)
{
var collection = _database.GetCollection<Character>("avatars");
var filter =
Builders<Character>.Filter.Eq(c => c.guid, character.guid)
&
Builders<Character>.Filter.Eq(c => c.owner, character.owner);
var result = collection.DeleteOne(
filter
);
}
public string GrantCode(Account account)
{
account.grantToken = GenerateToken(192);
UpsertAccount(account);
return account.grantToken;
}
public Account GetAccountByToken(string token)
{
try
{
return _database.GetCollection<Account>("accounts").Find(p => p.token == token).ToList().FirstOrDefault();
}
catch (Exception e)
{
Logger.PrintError("Error: " + e.Message);
return null;
}
}
public Account GetAccountByTokenGrant(string token)
{
try
{
return _database.GetCollection<Account>("accounts").Find(p => p.grantToken == token).ToList().FirstOrDefault();
}
catch (Exception e)
{
Logger.PrintError("Error: " + e.Message);
return null;
}
}
public Account GetAccountByUsername(string username)
{
try
{
return _database.GetCollection<Account>("accounts").Find(p => p.username == username).ToList().FirstOrDefault();
}
catch (Exception e)
{
Logger.PrintError("Error: "+e.Message);
return null;
}
}
public PlayerData GetPlayerById(string id)
{
try
{
return _database.GetCollection<PlayerData>("players").Find(p => p.accountId == id).ToList().FirstOrDefault();
}
catch(Exception e)
{
Logger.PrintError("Error occured while loading Player with account id: " + id+" ERROR:\n"+e.Message);
return null;
}
}
}
}

View File

@ -0,0 +1,101 @@
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson.IO;
using MongoDB.Bson;
using System.Reflection;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Database
{
public class CustomDictionarySerializer<TKey, TValue> : IBsonSerializer<Dictionary<TKey, TValue>>
{
public Type ValueType => typeof(Dictionary<TKey, TValue>);
public Dictionary<TKey, TValue> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var dictionary = new Dictionary<TKey, TValue>();
var reader = context.Reader;
reader.ReadStartDocument();
while (reader.ReadBsonType() != BsonType.EndOfDocument)
{
var key = (TKey)Convert.ChangeType(reader.ReadName(), typeof(TKey));
var value = (TValue)BsonSerializer.Deserialize<TValue>(reader);
dictionary[key] = value;
}
reader.ReadEndDocument();
return dictionary;
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary<TKey, TValue> value)
{
var writer = context.Writer;
writer.WriteStartDocument();
foreach (var kvp in value)
{
writer.WriteName(kvp.Key.ToString());
BsonSerializer.Serialize(writer, kvp.Value);
}
writer.WriteEndDocument();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
var writer = context.Writer;
writer.WriteStartDocument();
foreach (var kvp in (Dictionary < TKey, TValue > )value)
{
writer.WriteName(kvp.Key.ToString());
BsonSerializer.Serialize(writer, kvp.Value);
}
writer.WriteEndDocument();
}
object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
Deserialize(context, args);
}
public class DatabaseManager
{
public static Database db;
public static void Init()
{
BsonSerializer.RegisterSerializer(typeof(Dictionary<int, ulong>), new CustomDictionarySerializer<int, ulong>());
BsonSerializer.RegisterSerializer(typeof(Dictionary<int, List<int>>), new CustomDictionarySerializer<int, List<int>>());
RegisterSubclasses<FComponent>();
Logger.Print("Connecting to MongoDB...");
try
{
db = new Database(Server.config.mongoDatabase.uri, Server.config.mongoDatabase.collection);
Logger.Print("Connected to MongoDB database");
}
catch (Exception ex)
{
Logger.PrintError(ex.Message);
Logger.PrintError("Without initialized database the game server will crash. You can't run this server without MongoDB");
}
}
static void RegisterSubclasses<TBase>()
{
// Trova tutte le classi che ereditano da TBase
var derivedTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && typeof(TBase).IsAssignableFrom(t));
foreach (var type in derivedTypes)
{
if (!BsonClassMap.IsClassMapRegistered(type))
{
BsonClassMap.LookupClassMap(type); // Registra automaticamente il mapping BSON
}
}
}
}
}

View File

@ -0,0 +1,96 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game
{
public class BitsetManager
{
public Player player;
public Dictionary<int, List<int>> bitsets = new Dictionary<int, List<int>>();
public BitsetManager(Player player) {
this.player = player;
}
public void Load(Dictionary<int, List<int>> savedBitset)
{
if (savedBitset != null)
{
bitsets=savedBitset;
}
InitBitsets();
List<ulong> hardcodedLevelHaveBeen = new()
{
51810140172,
531424959210205184,
590604267523,
17039360
};
LongBitSet levelHaveBeen=new LongBitSet(hardcodedLevelHaveBeen.ToArray());
List<ulong> hardcodedReadActiveBlackbox = new()
{
1081145935319335202,
2267743508524
};
LongBitSet readActiveBlackbox = new LongBitSet(hardcodedReadActiveBlackbox.ToArray());
foreach (int v in levelHaveBeen.ConvertToIntValues())
{
AddValue(BitsetType.LevelHaveBeen, v);
}
foreach (int v in readActiveBlackbox.ConvertToIntValues())
{
AddValue(BitsetType.ReadActiveBlackbox, v);
}
foreach (int v in strIdNumTable.char_doc_id.dic.Values)
{
AddValue(BitsetType.CharDoc, v);
}
foreach (int v in strIdNumTable.char_voice_id.dic.Values)
{
AddValue(BitsetType.CharVoice, v);
}
foreach(int v in ResourceManager.strIdNumTable.wiki_id.dic.Values)
{
AddValue(BitsetType.Wiki, v);
}
}
public void InitBitsets()
{
foreach (BitsetType bitsetType in Enum.GetValues(typeof(BitsetType)))
{
int id=(int)bitsetType;
if (!bitsets.ContainsKey(id))
{
bitsets.Add(id, new List<int>());
}
}
}
public void AddValue(BitsetType type, int value)
{
int id = (int)type;
if (!bitsets[id].Contains(value))
{
bitsets[id].Add(value);
}
}
public void RemoveValue(BitsetType type, int value)
{
int id = (int)type;
if (bitsets[id].Contains(value))
{
bitsets[id].Remove(value);
}
}
}
}

View File

@ -0,0 +1,479 @@
using Campofinale.Game.Inventory;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using Google.Protobuf.Collections;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.IdGenerators;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using static Campofinale.Resource.ResourceManager.CharGrowthTable;
using static Campofinale.Resource.ResourceManager.WeaponUpgradeTemplateTable;
namespace Campofinale.Game.Character
{
public class Character
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
[BsonElement("templateId")]
public string id;
public ulong guid;
public ulong weaponGuid;
public int level;
public int xp;
public ulong owner;
public double curHp;
public float ultimateSp = 200;
public uint potential = 0;
public string breakNode = "charBreak20";
public List<string> passiveSkillNodes = new();
public List<string> attrNodes = new();
public List<string> factoryNodes = new();
public Dictionary<int,ulong> equipCol = new() { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 } };
public Character()
{
}
public Character(ulong owner, string id) : this(owner, id, 1)
{
}
public Dictionary<AttributeType, (double baseVal, double val)> CalcAttributes()
{
Dictionary<AttributeType, (double baseVal, double val)> attributes = new();
foreach (var item in GetAttributes())
{
attributes.Add((AttributeType)item.attrType, (item.attrValue, item.attrValue));
}
Item weapon = GetOwner().inventoryManager.items.Find(w => w.guid == weaponGuid);
if(weapon != null)
{
WeaponBasicTable wTable = ResourceManager.weaponBasicTable[weapon.id];
WeaponUpgradeTemplateTable template = ResourceManager.weaponUpgradeTemplateTable[wTable.levelTemplateId];
WeaponCurve curve=template.list.Find(c => c.weaponLv == weapon.level);
attributes[AttributeType.Atk] = (attributes[AttributeType.Atk].baseVal + curve.baseAtk, attributes[AttributeType.Atk].baseVal + curve.baseAtk);
}
//Won't be very precise but for now
foreach (var equip in equipCol)
{
Item EquipItem = GetOwner().inventoryManager.items.Find(e => e.guid == equip.Value);
if (EquipItem != null)
{
foreach (var modifier in EquipItem.GetEquipAttributeModifier())
{
switch (modifier.modifierType)
{
case ModifierType.BaseAddition:
case ModifierType.Addition:
attributes=SetValueDic(attributes, modifier.attrType, GetValueDic(attributes, modifier.attrType) + modifier.attrValue);
break;
case ModifierType.Multiplier:
case ModifierType.BaseMultiplier:
attributes=SetValueDic(attributes, modifier.attrType, GetValueDic(attributes, modifier.attrType) * 1 + modifier.attrValue);
break;
default:
break;
}
}
}
}
attributes[AttributeType.MaxHp] = (attributes[AttributeType.MaxHp].baseVal, attributes[AttributeType.MaxHp].val + attributes[AttributeType.Str].val * 10);
return attributes;
}
public double GetValueDic(Dictionary<AttributeType, (double baseVal, double val)> dic, AttributeType type)
{
if (dic.ContainsKey(type))
{
return dic[type].val;
}
return 0;
}
public Dictionary<AttributeType, (double baseVal, double val)> SetValueDic(Dictionary<AttributeType, (double baseVal, double val)> dic,AttributeType type,double value)
{
if (dic.ContainsKey(type))
{
dic[type] = (dic[type].baseVal,value);
}
else
{
dic.Add(type, (0, value));
}
return dic;
}
public void UnlockNode(string nodeId)
{
CharTalentNode nodeInfo = ResourceManager.GetTalentNode(id, nodeId);
if (nodeInfo == null) return;
//TODO remove cost items
switch (nodeInfo.nodeType)
{
case TalentNodeType.CharBreak:
breakNode = nodeId;
break;
case TalentNodeType.EquipBreak:
breakNode = nodeId;
break;
case TalentNodeType.Attr:
attrNodes.Add(nodeId);
break;
case TalentNodeType.PassiveSkill:
passiveSkillNodes.Add(nodeId);
break;
case TalentNodeType.FactorySkill:
factoryNodes.Add(nodeId);
break;
default:
Logger.PrintWarn($"Unimplemented NodeType {nodeInfo.nodeType}, not unlocked server side.");
break;
}
GetOwner().Send(new PacketScCharUnlockTalentNode(GetOwner(), this,nodeId));
}
public Character(ulong owner,string id, int level) : this()
{
this.owner = owner;
this.id = id;
this.level = level;
guid = GetOwner().random.Next();
this.weaponGuid = GetOwner().inventoryManager.AddWeapon(ResourceManager.charGrowthTable[id].defaultWeaponId, 1).guid;
this.curHp = CalcAttributes()[AttributeType.MaxHp].val;
}
public int GetSkillMaxLevel()
{
if (GetBreakStage() == 0)
{
return 1;
}else if (GetBreakStage() == 1)
{
return 3;
}
else if (GetBreakStage() == 2)
{
return 6;
}
else if (GetBreakStage() == 3)
{
return 9;
}
else if (GetBreakStage() == 4)
{
return 12;
}
else
{
return 12;
}
}
public List<ResourceManager.Attribute> GetAttributes()
{
int lev = level - 1 + GetBreakStage();
return ResourceManager.characterTable[id].attributes[lev].Attribute.attrs;
}
public Player GetOwner()
{
return Server.clients.Find(c=>c.roleId == this.owner);
}
public SceneCharacter ToSceneProto()
{
SceneCharacter proto= new SceneCharacter()
{
Level = level,
BattleInfo = new()
{
MsgGeneration = 1,
SkillList =
{
new ServerSkill()
{
Blackboard = new()
{
},
InstId=GetOwner().random.Next(),
Level=GetSkillMaxLevel(),
Source=BattleSkillSource.Default,
PotentialLv=GetSkillMaxLevel(),
SkillId=id+"_NormalSkill",
},
new ServerSkill()
{
Blackboard = new()
{
},
InstId=GetOwner().random.Next(),
Level=GetSkillMaxLevel(),
Source=BattleSkillSource.Default,
PotentialLv=GetSkillMaxLevel(),
SkillId=id+"_ComboSkill",
},
new ServerSkill()
{
Blackboard = new()
{
},
InstId=GetOwner().random.Next(),
Level=GetSkillMaxLevel(),
Source=BattleSkillSource.Default,
PotentialLv=GetSkillMaxLevel(),
SkillId=id+"_UltimateSkill",
},
new ServerSkill()
{
Blackboard = new()
{
},
InstId=GetOwner().random.Next(),
Level=GetSkillMaxLevel(),
Source=BattleSkillSource.Default,
PotentialLv=GetSkillMaxLevel(),
SkillId=id+"_NormalAttack",
}
}
},
Name = $"{ResourceManager.characterTable[id].engName}",
CommonInfo = new()
{
Hp = curHp,
Id = guid,
Position = GetOwner().position.ToProto(),
Rotation = GetOwner().rotation.ToProto(),
SceneNumId = GetOwner().curSceneNumId,
Templateid = id,
Type = (int)0,
},
Attrs =
{
}
};
foreach(var attr in CalcAttributes())
{
proto.Attrs.Add(new AttrInfo()
{
AttrType = (int)attr.Key,
BasicValue = attr.Value.baseVal,
Value = attr.Value.val
});
}
return proto;
}
public int GetBreakStage()
{
if (ResourceManager.charBreakNodeTable.ContainsKey(breakNode))
{
int breakStage = ResourceManager.charBreakNodeTable[breakNode].breakStage;
return breakStage;
}
else
{
return 0;
}
}
public bool IsEquipped(ulong equipGuid)
{
return equipCol.Values.Contains(equipGuid);
}
public Dictionary<int,ulong> GetEquipCol()
{
Dictionary<int, ulong> equips = new();
foreach(var item in equipCol)
{
if (item.Value != 0)
{
equips.Add(item.Key,item.Value);
}
}
return equips;
}
public CharInfo ToProto()
{
CharInfo info = new CharInfo()
{
Exp = xp,
Level = level,
IsDead = curHp < 1,
Objid = guid,
Templateid = id,
CharType = CharType.DefaultType,
OwnTime = 1,
NormalSkill = id + "_NormalSkill",
WeaponId = weaponGuid,
PotentialLevel = potential,
EquipCol =
{
GetEquipCol()
},
Talent = new()
{
LatestBreakNode= breakNode,
LatestPassiveSkillNodes =
{
passiveSkillNodes
},
AttrNodes =
{
attrNodes
},
LatestFactorySkillNodes =
{
factoryNodes
}
},
BattleMgrInfo = new()
{
},
BattleInfo = new()
{
Hp = curHp,
Ultimatesp= ultimateSp,
},
SkillInfo = new()
{
NormalSkill = id + "_NormalSkill",
ComboSkill = id + "_ComboSkill",
UltimateSkill = id + "_UltimateSkill",
DispNormalAttackSkill = id + "_NormalAttack",
LevelInfo =
{
new SkillLevelInfo()
{
SkillId=id+"_NormalAttack",
SkillLevel=GetSkillMaxLevel(),
SkillMaxLevel=GetSkillMaxLevel(),
SkillEnhancedLevel=GetSkillMaxLevel()
},
new SkillLevelInfo()
{
SkillId=id+"_NormalSkill",
SkillLevel=GetSkillMaxLevel(),
SkillMaxLevel=GetSkillMaxLevel(),
SkillEnhancedLevel=GetSkillMaxLevel()
},
new SkillLevelInfo()
{
SkillId=id+"_UltimateSkill",
SkillLevel=GetSkillMaxLevel(),
SkillMaxLevel=GetSkillMaxLevel(),
SkillEnhancedLevel=GetSkillMaxLevel()
},
new SkillLevelInfo()
{
SkillId=id+"_ComboSkill",
SkillLevel=GetSkillMaxLevel(),
SkillMaxLevel=GetSkillMaxLevel(),
SkillEnhancedLevel=GetSkillMaxLevel()
},
}
}
};
Item wep = GetOwner().inventoryManager.items.Find(w => w.guid == weaponGuid);
if (wep != null)
{
//TODO weapon skills
}
foreach (ulong equipGuid in equipCol.Values)
{
Item item = GetOwner().inventoryManager.items.Find(i => i.guid == equipGuid);
if (item != null)
{
string equipSuitId = ResourceManager.GetEquipSuitTableKey(item.id);
if (equipSuitId.Length > 0)
{
if (info.EquipSuit.ContainsKey(equipSuitId))
{
info.EquipSuit[equipSuitId] += 1;
}
else
{
info.EquipSuit.Add(equipSuitId, 1);
}
}
}
}
return info;
}
public (int,int,int) CalculateLevelAndGoldCost(int addedXp)
{
int gold = 0;
int curLevel = this.level;
while(addedXp >= ResourceManager.charLevelUpTable["" + curLevel].exp)
{
gold += ResourceManager.charLevelUpTable["" + curLevel].gold;
addedXp -= ResourceManager.charLevelUpTable["" + curLevel].exp;
curLevel++;
if(curLevel >= 80)
{
curLevel = 80;
}
}
return (curLevel, gold, addedXp);
}
public void LevelUp(RepeatedField<ItemInfo> items)
{
int addedXp = 0;
foreach (var item in items)
{
addedXp += ResourceManager.expItemDataMap[item.ResId].expGain * item.ResCount;
}
(int, int, int) CalculatedValues = CalculateLevelAndGoldCost(xp+addedXp);
items.Add(new ItemInfo()
{
ResId = "item_gold",
ResCount = CalculatedValues.Item2
});
if (GetOwner().inventoryManager.ConsumeItems(items))
{
this.level = CalculatedValues.Item1;
this.xp= CalculatedValues.Item3;
ScCharLevelUp levelUp = new()
{
CharObjID = guid,
};
ScCharSyncLevelExp synclevel = new()
{
Exp = xp,
CharObjID = guid,
Level = level
};
GetOwner().Send(ScMsgId.ScCharSyncLevelExp, synclevel);
GetOwner().Send(ScMsgId.ScCharLevelUp, levelUp);
GetOwner().Send(new PacketScSyncWallet(GetOwner()));
}
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Dungeons
{
public class Dungeon
{
public DungeonTable table;
public Vector3f prevPlayerPos;
public Vector3f prevPlayerRot;
public int prevPlayerSceneNumId;
public Player player;
public Dungeon()
{
}
}
}

View File

@ -0,0 +1,58 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
namespace Campofinale.Game.Entities
{
public class Entity
{
public ulong guid;
public int level;
public ulong worldOwner;
public double curHp;
public ulong levelLogicId;
public ulong belongLevelScriptId;
public int dependencyGroupId;
public ObjectType type;
public Vector3f Position=new();
public Vector3f Rotation = new();
public Vector3f BornPos=new();
public Vector3f BornRot=new();
public List<ParamKeyValue> properties=new();
public int sceneNumId;
public bool spawned = false;
public Entity()
{
}
public Entity(ulong guid, int level, ulong worldOwner,int scene)
{
this.guid = guid;
this.level = level;
this.worldOwner = worldOwner;
this.sceneNumId = scene;
}
public virtual void Damage(double dmg)
{
}
public virtual void Heal(double heal)
{
}
public virtual bool Interact(string eventName, Google.Protobuf.Collections.MapField<string, DynamicParameter> properties)
{
return false;
}
public Player GetOwner()
{
return Server.clients.Find(c => c.roleId == worldOwner);
}
}
}

View File

@ -0,0 +1,112 @@
using Campofinale.Game.Character;
using Campofinale.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Entities
{
public class EntityCharacter : Entity
{
public new double curHp
{
get
{
return GetChar().curHp;
}
}
public new Vector3f Position
{
get
{
return GetOwner().position;
}
set
{
GetOwner().position = value;
}
}
public new Vector3f Rotation
{
get
{
return GetOwner().rotation;
}
set
{
GetOwner().rotation = value;
}
}
public EntityCharacter(ulong guid, ulong worldOwner)
{
this.guid = guid;
this.worldOwner = worldOwner;
}
public override void Damage(double dmg)
{
GetChar().curHp -= dmg;
ScCharSyncStatus state = new()
{
IsDead = GetChar().curHp < 1,
Objid = guid,
BattleInfo = new()
{
Hp=curHp,
Ultimatesp=GetChar().ultimateSp,
},
};
ScEntityPropertyChange prop = new()
{
InstId=guid,
Info = new()
{
Hp=curHp,
Ultimatesp= GetChar().ultimateSp,
}
};
GetOwner().Send(ScMsgId.ScCharSyncStatus, state);
GetOwner().Send(ScMsgId.ScEntityPropertyChange, prop);
}
public override void Heal(double heal)
{
GetChar().curHp += heal;
ScCharSyncStatus state = new()
{
IsDead = GetChar().curHp < 1,
Objid = guid,
BattleInfo = new()
{
Hp = curHp,
Ultimatesp = GetChar().ultimateSp,
}
};
ScEntityPropertyChange prop = new()
{
InstId = guid,
Info = new()
{
Hp = curHp,
Ultimatesp = GetChar().ultimateSp,
}
};
GetOwner().Send(ScMsgId.ScCharSyncStatus, state);
GetOwner().Send(ScMsgId.ScEntityPropertyChange, prop);
}
public Character.Character GetChar()
{
return GetOwner().chars.Find(c => c.guid == guid);
}
}
}

View File

@ -0,0 +1,168 @@
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
namespace Campofinale.Game.Entities
{
public class EntityInteractive : Entity
{
public string templateId;
public Dictionary<InteractiveComponentType, List<ParamKeyValue>> componentProperties = new();
public EntityInteractive()
{
}
public EntityInteractive(string templateId, ulong worldOwner, Vector3f pos, Vector3f rot, int scene, ulong g=0)
{
if (g == 0)
{
this.guid = (ulong)new Random().NextInt64();
}
else
{
this.guid = g;
}
this.level = 1;
this.worldOwner = worldOwner;
this.Position = pos;
this.Rotation = rot;
this.BornPos = pos;
this.BornRot = rot;
this.templateId = templateId;
this.sceneNumId = scene;
}
public SceneInteractive ToProto()
{
SceneInteractive proto = new SceneInteractive()
{
CommonInfo = new()
{
Hp = 100,
Id = guid,
Templateid = templateId,
BelongLevelScriptId = belongLevelScriptId,
SceneNumId = sceneNumId,
Position = Position.ToProto(),
Rotation = Rotation.ToProto(),
Type = (int)5,
},
//Meta =dependencyGroupId,
BattleInfo = new()
{
},
Properties =
{
}
};
foreach (var prop in properties)
{
DynamicParameter p = prop.ToProto();
(bool, int) index = GetPropertyIndex(prop.key, proto.Properties.Keys.Count > 0 ? proto.Properties.Keys.Max() : 0);
if (p != null && index.Item1)
{
proto.Properties.Add(index.Item2, p);
}
}
foreach (var comp in componentProperties)
{
foreach (var prop in comp.Value)
{
DynamicParameter p = prop.ToProto();
(bool, int) index = GetPropertyIndex(prop.key, proto.Properties.Keys.Count > 0 ? proto.Properties.Keys.Max() : 0);
if (p != null && index.Item1)
{
proto.Properties.Add(index.Item2, p);
}
}
}
return proto;
}
public (bool,int) GetPropertyIndex(string key, int maxCur)
{
int i= maxCur;
try
{
string oriTemplateId = ResourceManager.interactiveTable.interactiveDataDict[templateId].templateId;
InteractiveData data=ResourceManager.interactiveData.Find(i=>i.id == oriTemplateId);
if(data != null)
{
return (true,data.propertyKeyToIdMap[key]);
}
return (false, maxCur + 1);
}
catch (Exception ex)
{
//Logger.PrintError(ex.Message);
return (false,maxCur+1);
}
}
public override void Damage(double dmg)
{
}
public override bool Interact(string eventName, Google.Protobuf.Collections.MapField<string, DynamicParameter> props)
{
if (eventName == "open_chest")
{
ScSceneUpdateInteractiveProperty update = new()
{
Id = guid,
SceneNumId = GetOwner().curSceneNumId,
Properties =
{
{4, new DynamicParameter()
{
RealType=3,
ValueType=3,
ValueIntList={1}
} }
}
};
GetOwner().Send(ScMsgId.ScSceneUpdateInteractiveProperty, update);
GetOwner().inventoryManager.AddRewards(properties.Find(p=>p.key== "reward_id").value.valueArray[0].valueString,Position,1);
GetOwner().sceneManager.KillEntity(guid,true,1);
GetOwner().noSpawnAnymore.Add(guid);
GetOwner().sceneManager.GetScene(sceneNumId).AddCollection("int_trchest_common", 1);
GetOwner().Send(new PacketScSceneCollectionSync(GetOwner()));
return true;
}else if(eventName == "pick_inst")
{
//TODO
}
return false;
}
public override void Heal(double heal)
{
}
}
}

View File

@ -0,0 +1,125 @@
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Entities
{
public class EntityMonster : Entity
{
public string templateId;
public EntityMonster()
{
}
public EntityMonster(string templateId, int level, ulong worldOwner, Vector3f pos, Vector3f rot, int scene, ulong g=0)
{
if (g == 0)
{
this.guid = (ulong)new Random().NextInt64();
}
else
{
this.guid = g;
}
this.level = level;
this.worldOwner = worldOwner;
this.Position = pos;
this.Rotation = rot;
this.BornPos = pos;
this.BornRot = rot;
this.templateId = templateId;
this.curHp = GetAttribValue(AttributeType.MaxHp);
this.sceneNumId=scene;
}
public double GetAttribValue(AttributeType type)
{
return GetAttributes().Find(a => a.AttrType == (int)type).Value;
}
public List<AttrInfo> GetAttributes()
{
List<AttrInfo> attrInfo = new();
EnemyTable table = ResourceManager.enemyTable[templateId];
enemyAttributeTemplateTable[table.attrTemplateId].levelDependentAttributes[level].attrs.ForEach(attr =>
{
attrInfo.Add(new AttrInfo()
{
AttrType = attr.attrType,
BasicValue = attr.attrValue,
Value = attr.attrValue
});
});
enemyAttributeTemplateTable[table.attrTemplateId].levelIndependentAttributes.attrs.ForEach(attr =>
{
attrInfo.Add(new AttrInfo()
{
AttrType = attr.attrType,
BasicValue = attr.attrValue,
Value = attr.attrValue
});
});
return attrInfo;
}
public SceneMonster ToProto()
{
SceneMonster proto = new SceneMonster()
{
Level = level,
CommonInfo = new()
{
Hp = curHp,
Id = guid,
Templateid = templateId,
BelongLevelScriptId = belongLevelScriptId,
SceneNumId = sceneNumId,
Position = Position.ToProto(),
Rotation = Rotation.ToProto(),
Type =(int) ObjectTypeIndex.Enemy,
},
Attrs =
{
GetAttributes()
},
BattleInfo = new()
{
},
};
return proto;
}
public override void Damage(double dmg)
{
curHp -= dmg;
ScEntityPropertyChange prop = new()
{
InstId = guid,
Info = new()
{
Hp = curHp,
}
};
GetOwner().Send(ScMsgId.ScEntityPropertyChange, prop);
}
public override void Heal(double heal)
{
curHp += heal;
}
}
}

View File

@ -0,0 +1,66 @@
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Entities
{
public class EntityNpc : Entity
{
public string templateId;
public EntityNpc()
{
}
public EntityNpc(string templateId, ulong worldOwner, Vector3f pos, Vector3f rot,int scene,ulong guid)
{
this.guid = (ulong)guid;
this.level = 1;
this.worldOwner = worldOwner;
this.Position = pos;
this.Rotation = rot;
this.BornPos = pos;
this.BornRot = rot;
this.templateId = templateId;
this.sceneNumId = scene;
}
public SceneNpc ToProto()
{
SceneNpc proto = new SceneNpc()
{
CommonInfo = new()
{
Hp = 100,
Id = guid,
Templateid = templateId,
BelongLevelScriptId=belongLevelScriptId,
SceneNumId =sceneNumId,
Position = Position.ToProto(),
Rotation = Rotation.ToProto(),
Type = (int)type,
},
};
return proto;
}
public override void Damage(double dmg)
{
}
public override void Heal(double heal)
{
}
}
}

View File

@ -0,0 +1,26 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentBusLoader : FComponent
{
public string lastPutinItemId = "";
public FComponentBusLoader(uint id) : base(id, FCComponentType.BusLoader)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.BusLoader = new()
{
LastPutinItemId= lastPutinItemId
};
}
}
}

View File

@ -0,0 +1,53 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentPortManager : FComponent
{
public class FPort
{
public int index = 0;
public uint ownerComId;
public uint touchComId;
public ScdFacComSubPort ToProto()
{
return new ScdFacComSubPort()
{
InBlock = false,
Index = index,
OwnerComId = ownerComId,
TouchComId = touchComId
};
}
}
public List<FPort> ports = new();
public FComponentPortManager(uint id, uint mainId) : base(id, FCComponentType.PortManager)
{
for(int i=0; i < 14; i++)
{
ports.Add(new FPort()
{
index = i,
ownerComId = mainId,
touchComId = 0
});
}
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.PortManager = new();
foreach(FPort port in ports)
{
proto.PortManager.Ports.Add(port.ToProto());
}
}
}
}

View File

@ -0,0 +1,22 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentPowerPole : FComponent
{
public FComponentPowerPole(uint id) : base(id, FCComponentType.PowerPole)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.PowerPole = new();
}
}
}

View File

@ -0,0 +1,25 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentPowerSave : FComponent
{
public FComponentPowerSave(uint id) : base(id, FCComponentType.PowerSave)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.PowerSave = new()
{
PowerSave=100000
};
}
}
}

View File

@ -0,0 +1,26 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentSelector : FComponent
{
public string selectedItemId = "";
public FComponentSelector(uint id) : base(id, FCComponentType.Selector)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.Selector = new()
{
SelectedItemId= selectedItemId
};
}
}
}

View File

@ -0,0 +1,25 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentStablePower : FComponent
{
public FComponentStablePower(uint id) : base(id, FCComponentType.StablePower)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.StablePower = new()
{
PowerGenPerSec=150
};
}
}
}

View File

@ -0,0 +1,26 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentSubHub : FComponent
{
public int level = 1;
public FComponentSubHub(uint id) : base(id, FCComponentType.SubHub)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.SubHub = new()
{
Level = level,
};
}
}
}

View File

@ -0,0 +1,22 @@
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Factory.FactoryNode;
namespace Campofinale.Game.Factory.Components
{
public class FComponentTravelPole : FComponent
{
public FComponentTravelPole(uint id) : base(id, FCComponentType.TravelPole)
{
}
public override void SetComponentInfo(ScdFacCom proto)
{
proto.TravelPole = new();
}
}
}

View File

@ -0,0 +1,459 @@
using Campofinale.Game.Factory.Components;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Factory
{
public class FactoryManager
{
public Player player;
public List<FactoryChapter> chapters = new();
public FactoryManager(Player player)
{
this.player = player;
}
public void Load()
{
//TODO Save
chapters.Add(new FactoryChapter("domain_1", player.roleId));
chapters.Add(new FactoryChapter("domain_2", player.roleId));
}
public void ExecOp(CsFactoryOp op, ulong seq)
{
FactoryChapter chapter = GetChapter(op.ChapterId);
if (chapter != null)
{
chapter.ExecOp(op, seq);
}
else
{
ScFactoryOpRet ret = new()
{
RetCode = FactoryOpRetCode.Fail,
};
player.Send(ScMsgId.ScFactoryOpRet, ret, seq);
}
}
public void Update()
{
foreach (FactoryChapter chapter in chapters)
{
chapter.Update();
}
}
public FactoryChapter GetChapter(string id)
{
return chapters.Find(c=>c.chapterId==id);
}
}
public class FactoryChapter
{
public string chapterId;
public ulong ownerId;
public List<FactoryNode> nodes=new();
public uint v = 1;
public uint compV = 0;
public void Update()
{
try
{
foreach (FactoryNode node in nodes)
{
node.Update(this);
}
}
catch (Exception e)
{
}
}
public List<FactoryNode> GetNodesInRange(Vector3f pos,float range)
{
return nodes.FindAll(n => n.position.Distance(pos) <= range);
}
public void ExecOp(CsFactoryOp op, ulong seq)
{
switch (op.OpType)
{
case FactoryOpType.Place:
CreateNode(op.Place, seq);
break;
default:
break;
}
}
public uint nextCompV()
{
compV++;
return compV;
}
private void CreateNode(CsdFactoryOpPlace place, ulong seq)
{
v++;
uint nodeId = v;
FactoryBuildingTable table = ResourceManager.factoryBuildingTable[place.TemplateId];
FactoryNode node = new()
{
nodeId = nodeId,
templateId = place.TemplateId,
mapId = place.MapId,
nodeType = table.GetNodeType(),
position = new Vector3f(place.Position),
direction = new Vector3f(place.Direction),
guid = GetOwner().random.NextRand()
};
node.InitComponents(this);
nodes.Add(node);
ScFactoryModifyChapterNodes edit = new()
{
ChapterId = chapterId,
Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
};
GetOwner().Send(new PacketScFactorySyncChapter(GetOwner(), chapterId));
edit.Nodes.Add(node.ToProto());
Logger.Print(Newtonsoft.Json.JsonConvert.SerializeObject(edit, Newtonsoft.Json.Formatting.Indented));
GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, edit);
GetOwner().Send(new PacketScFactoryOpRet(GetOwner(), node.nodeId,FactoryOpType.Place),seq);
}
public FactoryChapter(string chapterId,ulong ownerId)
{
this.ownerId = ownerId;
this.chapterId = chapterId;
FactoryNode node = new()
{
nodeId = v,
templateId= "__inventory__",
nodeType=FCNodeType.Inventory,
mapId=0,
deactive=true,
guid = GetOwner().random.NextRand()
};
node.InitComponents(this);
nodes.Add(node);
}
public Player GetOwner()
{
return Server.clients.Find(c => c.roleId == ownerId);
}
}
public class FactoryNode
{
public uint nodeId;
public FCNodeType nodeType;
public string templateId;
public Vector3f position=new();
public Vector3f direction = new();
public string instKey="";
public bool deactive = false;
public int mapId;
public bool forcePowerOn = false;
public List<FComponent> components = new();
[BsonIgnore]
public bool powered = false;
[BsonIgnore]
public uint connectedPowerNode = 0;
public ulong guid;
public void Update(FactoryChapter chapter)
{
if(!templateId.Contains("hub"))
if (GetComponent<FComponentPowerPole>() != null)
{
FactoryNode curEnergyNode = chapter.nodes.Find(n => n.nodeId == connectedPowerNode && n.position.Distance(position) <= 20 && n.InPower());
if (templateId != "power_pole_2")
{
FactoryNode energyNode = chapter.GetNodesInRange(position, 20).Find(n=>n.GetComponent< FComponentPowerPole>()!=null && n.InPower());
if (energyNode != null && curEnergyNode==null && energyNode.connectedPowerNode!=nodeId)
{
powered= true;
connectedPowerNode = energyNode.nodeId;
chapter.GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, new ScFactoryModifyChapterNodes() { Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(), Nodes = { this.ToProto()} });
}
else
{
if (curEnergyNode == null && powered==true)
{
powered = false;
connectedPowerNode = 0;
chapter.GetOwner().Send(ScMsgId.ScFactoryModifyChapterNodes, new ScFactoryModifyChapterNodes() { Tms = DateTime.UtcNow.ToUnixTimestampMilliseconds(), Nodes = { this.ToProto() } });
}
}
}
else
{
//Check near
}
}
}
public bool InPower()
{
if (forcePowerOn)
{
return true;
}
return powered;
}
public FComponent GetComponent<FComponent>() where FComponent : class
{
return components.Find(c => c is FComponent) as FComponent;
}
public FMesh GetMesh()
{
FMesh mesh = new FMesh();
if (ResourceManager.factoryBuildingTable.ContainsKey(templateId))
{
FactoryBuildingTable table = ResourceManager.factoryBuildingTable[templateId];
double centerX = position.x + table.range.width / 2.0;
double centerZ = position.z + table.range.depth / 2.0;
Vector3f p1 = new Vector3f(position.x, position.y, position.z);
Vector3f p2 = new Vector3f(
position.x + table.range.width,
position.y + table.range.height,
position.z + table.range.depth
);
p1 = RotateAroundY(p1, new Vector3f((float)centerX, position.y, (float)centerZ), direction.y);
p2 = RotateAroundY(p2, new Vector3f((float)centerX, position.y, (float)centerZ), direction.y);
mesh.points.Add(p1);
mesh.points.Add(p2);
}
return mesh;
}
private Vector3f RotateAroundY(Vector3f point, Vector3f origin, double angleDegrees)
{
double angleRadians = angleDegrees * (Math.PI / 180.0);
double cosTheta = Math.Cos(angleRadians);
double sinTheta = Math.Sin(angleRadians);
double dx = point.x - origin.x;
double dz = point.z - origin.z;
double rotatedX = origin.x + (dx * cosTheta - dz * sinTheta);
double rotatedZ = origin.z + (dx * sinTheta + dz * cosTheta);
return new Vector3f((float)rotatedX, point.y, (float)rotatedZ);
}
public ScdFacNode ToProto()
{
ScdFacNode node = new ScdFacNode()
{
InstKey = instKey,
NodeId=nodeId,
TemplateId=templateId,
StableId= GetStableId(),
IsDeactive= deactive,
Power = new()
{
InPower= InPower(),
NeedInPower=false,
},
NodeType=(int)nodeType,
Transform = new()
{
Position = position.ToProtoScd(),
Direction=direction.ToProtoScd(),
MapId=mapId,
}
};
if(templateId!="__inventory__")
{
node.Transform.Mesh = GetMesh().ToProto();
node.Transform.WorldPosition = position.ToProto();
node.Transform.WorldRotation = direction.ToProto();
node.InteractiveObject = new()
{
};
node.Flag = 0;
node.InstKey = "";
}
foreach(FComponent comp in components)
{
node.Components.Add(comp.ToProto());
node.ComponentPos.Add((int)comp.GetComPos(), comp.compId);
}
return node;
}
public uint GetStableId()
{
return 10000+nodeId;
}
public FCComponentType GetMainCompType()
{
string nodeTypeName = nodeType.ToString();
if (Enum.TryParse(nodeTypeName, out FCComponentType fromName))
{
return fromName;
}
return FCComponentType.Invalid;
}
public void InitComponents(FactoryChapter chapter)
{
switch (nodeType)
{
case FCNodeType.PowerPole:
components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
break;
case FCNodeType.PowerDiffuser:
components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
break;
case FCNodeType.TravelPole:
components.Add(new FComponentTravelPole(chapter.nextCompV()).Init());
break;
case FCNodeType.Hub:
components.Add(new FComponentSelector(chapter.nextCompV()).Init());
components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
components.Add(new FComponentPortManager(chapter.nextCompV(),GetComponent<FComponentBusLoader>().compId).Init());
forcePowerOn = true;
break;
case FCNodeType.SubHub:
components.Add(new FComponentSubHub(chapter.nextCompV()).Init());
components.Add(new FComponentSelector(chapter.nextCompV()).Init());
components.Add(new FComponentPowerPole(chapter.nextCompV()).Init());
components.Add(new FComponentPowerSave(chapter.nextCompV()).Init());
components.Add(new FComponentStablePower(chapter.nextCompV()).Init());
components.Add(new FComponentBusLoader(chapter.nextCompV()).Init());
components.Add(new FComponentPortManager(chapter.nextCompV(), GetComponent<FComponentBusLoader>().compId).Init());
forcePowerOn = true;
break;
default:
components.Add(new FComponent(chapter.nextCompV(), GetMainCompType()).Init());
break;
}
}
[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(FComponentSelector))]
public class FComponent
{
public class FCompInventory
{
public ScdFacComInventory ToProto()
{
return new ScdFacComInventory()
{
};
}
}
public uint compId;
public FCComponentType type;
public FCompInventory inventory;
public FComponent(uint id, FCComponentType t)
{
this.compId = id;
this.type = t;
}
public FCComponentPos GetComPos()
{
string compTypeName = type.ToString();
if (Enum.TryParse(compTypeName, out FCComponentPos fromName))
{
return fromName;
}
switch (type)
{
case FCComponentType.PowerPole:
return FCComponentPos.PowerPole;
}
return FCComponentPos.Invalid;
}
public ScdFacCom ToProto()
{
ScdFacCom proto = new ScdFacCom()
{
ComponentType = (int)type,
ComponentId = compId,
};
SetComponentInfo(proto);
return proto;
}
public virtual void SetComponentInfo(ScdFacCom proto)
{
if (inventory != null)
{
proto.Inventory = inventory.ToProto();
}
else if (type == FCComponentType.PowerPole)
{
proto.PowerPole = new()
{
};
}
}
public virtual FComponent Init()
{
switch (type)
{
case FCComponentType.Inventory:
inventory = new();
break;
default:
break;
}
return this;
}
}
public class FMesh
{
public FCMeshType type;
public List<Vector3f> points=new();
public ScdFacMesh ToProto()
{
ScdFacMesh m = new ScdFacMesh()
{
MeshType = (int)type
};
foreach (Vector3f p in points)
{
m.Points.Add(new ScdVec3Int()
{
X = (int)p.x,
Y = (int)p.y,
Z = (int)p.z
});
}
return m;
}
}
}
}

View File

@ -0,0 +1,262 @@
using Campofinale.Database;
using Campofinale.Protocol;
using Campofinale.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Gacha
{
public class GachaManager
{
public Player player;
internal ulong upSeqId;
const double fiftyfifty = 0.45; // 50% (make it less than real 50, because the randomness make win fifty fifty every time
private static readonly Random random = new Random();
public GachaManager(Player player)
{
this.player = player;
}
public (int fiveStarPity, int sixStarPity, GachaTransaction? lastSixStar, bool isFiftyFiftyLost) GetCurrentPity(string templateId)
{
List<GachaTransaction> transactionList = DatabaseManager.db.LoadGachaTransaction(player.roleId, templateId);
transactionList = transactionList.OrderBy(g => g.transactionTime).ToList();
int fiveStarPity = 0;
int sixStarPity = 0;
GachaTransaction? lastSixStar = null;
foreach (var transaction in transactionList)
{
if (transaction.rarity == 5)
{
fiveStarPity = 0;
sixStarPity++;
}
else if (transaction.rarity == 6)
{
fiveStarPity = 0;
sixStarPity = 0;
lastSixStar = transaction;
}
else
{
fiveStarPity++;
sixStarPity++;
}
//Logger.Print("Current calculated: " + sixStarPity);
}
bool isFiftyFiftyLost = false;
if (lastSixStar != null)
{
isFiftyFiftyLost = lastSixStar.itemId != templateId;
}
return (fiveStarPity, sixStarPity, lastSixStar, isFiftyFiftyLost);
}
public void DoGacha(string gachaId,int attempts)
{
const double prob6Star = 0.008; // 0.8%
const double prob5Star = 0.08; // 8%
(int fiveStarPity, int sixStarPity, GachaTransaction? lastSixStar, bool isFiftyFiftyLost)
PityInfo = GetCurrentPity(gachaId);
int increaseTime = 0;
int pityforcalculate = PityInfo.sixStarPity-64;
if(pityforcalculate < 1)
{
pityforcalculate = 0;
}
GachaCharPoolTable table = ResourceManager.gachaCharPoolTable[gachaId];
GachaCharPoolContentTable content = ResourceManager.gachaCharPoolContentTable[gachaId];
GachaCharPoolTypeTable type = ResourceManager.gachaCharPoolTypeTable[""+table.type];
//Sanity check
if (table==null || content == null || type==null)
{
return;
}
List<GachaCharPoolItem> fiveStars = content.list.FindAll(c => c.starLevel == 5);
List<GachaCharPoolItem> sixStars = content.list.FindAll(c => c.starLevel == 6);
List<GachaCharPoolItem> fourStars = content.list.FindAll(c => c.starLevel == 4);
List<GachaTransaction> transactions = new();
for (int i = 0; i < attempts; i++)
{
double roll = random.NextDouble();
double fifty = random.NextDouble();
double finalProb6Star = prob6Star + 0.05f * pityforcalculate;
PityInfo.fiveStarPity++;
PityInfo.sixStarPity++;
GachaTransaction transaction = null;
//Six star pull
if (roll < finalProb6Star || PityInfo.sixStarPity>=type.softGuarantee)
{
PityInfo.sixStarPity -= PityInfo.sixStarPity >= type.softGuarantee ? type.softGuarantee : PityInfo.sixStarPity;
if (table.upCharIds.Count > 0)
{
transaction = GetChar(table.upCharIds[0], PityInfo.isFiftyFiftyLost, fifty, sixStars, 6);
if (transaction.itemId != table.upCharIds[0])
{
PityInfo.isFiftyFiftyLost = true;
}
else
{
PityInfo.isFiftyFiftyLost = false;
}
}
else
{
transaction = GetChar("", PityInfo.isFiftyFiftyLost, fifty, sixStars, 6);
}
pityforcalculate = 0;
}
else if (roll < prob5Star || PityInfo.fiveStarPity >= 10)
{
PityInfo.fiveStarPity -= PityInfo.fiveStarPity >= 10 ? 10 : PityInfo.fiveStarPity;
if (table.upCharIds.Count > 1)
{
transaction = GetChar(table.upCharIds[1], false, fifty, fiveStars, 5);
}
else
{
transaction = GetChar("", false, fifty, fiveStars, 5);
}
}
else
{
transaction = GetChar("", false, fifty, fourStars, 4);
}
if(PityInfo.sixStarPity > 65)
{
pityforcalculate++;
}
transactions.Add(transaction);
}
ScGachaSyncPullResult result = new ScGachaSyncPullResult()
{
GachaPoolId = gachaId,
GachaType =table.type,
OriResultIds =
{
},
Star5GotCount = transactions.FindAll(t => t.rarity == 5).Count,
Star6GotCount = transactions.FindAll(t => t.rarity == 6).Count,
FinalResults =
{
},
UpGotCount = transactions.FindAll(t => table.upCharIds.Contains(t.itemId)).Count,
};
foreach (GachaTransaction transaction in transactions)
{
transaction.gachaTemplateId = gachaId;
bool exist = player.chars.Find(c => c.id == transaction.itemId) != null;
result.OriResultIds.Add(transaction.itemId);
result.FinalResults.Add(new ScdGachaFinalResult()
{
IsNew = !exist,
ItemId = !exist ? transaction.itemId : "item_charpotentialup_" + transaction.itemId,
RewardItemId= !exist ? transaction.itemId : "item_charpotentialup_"+ transaction.itemId,
RewardIds =
{
$"reward_{transaction.rarity}starChar_weaponCoin",
},
});
DatabaseManager.db.AddGachaTransaction(transaction);
}
player.Send(ScMsgId.ScGachaSyncPullResult, result,upSeqId);
ScGachaModifyPoolRoleData roleData = new()
{
GachaPoolId = gachaId,
GachaType = table.type,
GachaPoolCategoryRoleData = new()
{
GachaPoolType = table.type,
Star5SoftGuaranteeProgress = PityInfo.fiveStarPity,
SoftGuaranteeProgress = PityInfo.sixStarPity,
TotalPullCount = PityInfo.sixStarPity
},
GachaPoolRoleData = new()
{
GachaPoolId = gachaId,
HardGuaranteeProgress = PityInfo.sixStarPity,
SoftGuaranteeProgress = PityInfo.sixStarPity,
}
};
player.Send(ScMsgId.ScGachaModifyPoolRoleData, roleData, upSeqId);
}
public GachaTransaction GetChar(string upChar,bool guaranteed, double fifty, List<GachaCharPoolItem> items, int rarity)
{
GachaTransaction transaction = new()
{
transactionTime = DateTime.UtcNow.Ticks,
ownerId = player.roleId,
rarity = rarity,
};
if((fifty >= fiftyfifty || guaranteed) && rarity != 4 && upChar.Length >0)
{
transaction.itemId = upChar;
}
else
{
int index = random.Next(0,items.Count); // Miglior randomizzazione
// index = (int)((1 - Math.Pow(random.NextDouble(), 2)) * (items.Count - 1));
// Se vuoi evitare di prendere spesso i primi 2-3 elementi:
// index = (int)Math.Pow(random.NextDouble(), 1.5) * items.Count;
if (index > items.Count-1)
{
index = items.Count-1;
}
if(index < 0)
{
index = 0;
}
transaction.itemId = items[index].charId;
transaction.hasLost = transaction.itemId != upChar;
}
return transaction;
}
public static GachaHistoryAPI GetGachaHistoryPage(PlayerData data, string banner, int p = 1)
{
GachaHistoryAPI api = new();
int pageSize = 5;
List<GachaTransaction> transactionList = DatabaseManager.db.LoadGachaTransaction(data.roleId, banner);
transactionList = transactionList.OrderByDescending(g => g.transactionTime).ToList();
int maxPages=(int)Math.Ceiling((double)transactionList.Count / pageSize);
api.maxPages = maxPages;
api.curPage = p;
api.transactionList= transactionList.Skip((p - 1) * pageSize).Take(pageSize).ToList();
return api;
}
public class GachaHistoryAPI
{
public int maxPages = 0;
public int curPage = 0;
public List<GachaTransaction> transactionList;
}
}
}

View File

@ -0,0 +1,23 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.IdGenerators;
namespace Campofinale.Game.Gacha
{
public class GachaTransaction
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
public ulong ownerId;
public long transactionTime;
public string itemId;
public string gachaTemplateId;
public int rarity;
public bool hasLost = false;
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Game
{
public static class GameConstants
{
public static string GAME_VERSION = "0.5.28"; //CBT 2
public static string GAME_VERSION_ASSET_URL = "https://beyond.hg-cdn.com/uXUuLlNbIYmMMTlN/0.5/update/6/1/Windows/0.5.28_U1mgxrslUitdn3hb/files";//CBT 2
public static int MAX_TEAMS_NUMBER = 5; //Not used yet
public static (long, string) SERVER_UID = (99, "99"); //Not used yet, no friend chat in current Beta
}
}

View File

@ -0,0 +1,223 @@
using Campofinale.Database;
using Campofinale.Packets.Sc;
using Campofinale.Resource;
using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Game.Inventory
{
public class InventoryManager
{
public Player owner;
public List<Item> items= new List<Item>();
public int item_diamond_amt
{
get
{
if (items.Find(i => i.id == "item_diamond") == null) return 0;
return items.Find(i => i.id == "item_diamond")!.amount;
}
}
public int item_gold_amt
{
get
{
if (items.Find(i => i.id == "item_gold") == null) return 0;
return items.Find(i => i.id == "item_gold")!.amount;
}
}
public Item GetItemById(string id)
{
return items.Find(i => i.id == id);
}
public InventoryManager(Player o) {
owner = o;
}
public void AddRewards(string rewardTemplateId, Vector3f pos, int sourceType=1)
{
try
{
ScRewardToastBegin begin = new ScRewardToastBegin()
{
RewardSourceType = sourceType,
RewardToastInstId = owner.random.NextRand(),
};
ScRewardToSceneBegin begin2 = new ScRewardToSceneBegin()
{
RewardSourceType = sourceType,
SourceTemplateId = rewardTemplateId,
};
ScRewardToastEnd end = new()
{
RewardToastInstId = begin.RewardToastInstId,
};
List<RewardTable.ItemBundle> bundles = rewardTable[rewardTemplateId].itemBundles;
foreach(RewardTable.ItemBundle bundle in bundles)
{
Item item = new Item()
{
id=bundle.id
};
if (!item.InstanceType())
{
item = AddItem(bundle.id, bundle.count);
end.RewardVirtualList.Add(new RewardItem()
{
Count = bundle.count,
Id = bundle.id,
Inst=item.ToProto().Inst,
});
}
else
{
owner.sceneManager.CreateDrop(pos, bundle);
//TODO drops
}
}
owner.Send(Protocol.ScMsgId.ScRewardToastBegin, begin);
owner.Send(Protocol.ScMsgId.ScRewardToSceneBegin, begin2);
owner.Send(Protocol.ScMsgId.ScRewardToastEnd, end);
owner.Send(Protocol.ScMsgId.ScRewardToSceneEnd, new ScRewardToSceneEnd());
owner.Send(new PacketScSyncWallet(owner));
}
catch (Exception e)
{
Logger.PrintError(e.Message);
}
}
public Item AddWeapon(string id, ulong level)
{
Item item = new Item(owner.roleId, id, level);
items.Add(item);
return item;
}
public void Save()
{
foreach (Item item in items)
{
DatabaseManager.db.UpsertItem(item);
}
}
public void Load()
{
items = DatabaseManager.db.LoadInventoryItems(owner.roleId);
}
public Item AddItem(string id, int amt)
{
Item it = new()
{
id = id,
};
if(!it.InstanceType())
{
Item item = items.Find(i=>i.id == id);
if (item != null)
{
// Logger.Print(id + ": " + amt+" added to existing");
item.amount += amt;
return item;
}
else
{
// Logger.Print(id + ": " + amt + " added to new");
item = new Item(owner.roleId, id, amt);
items.Add(item);
return item;
}
}
else
{
//Logger.Print(id + ": " + amt + " added to new as instance");
Item item = new Item(owner.roleId, id, amt);
items.Add(item);
return item;
}
}
public void RemoveItem(Item item,int amt)
{
item.amount -= amt;
if(item.amount <= 0)
{
items.Remove(item);
DatabaseManager.db.DeleteItem(item);
}
this.owner.Send(new PacketScItemBagScopeModify(this.owner, item));
}
public bool ConsumeItems(MapField<string, ulong> costItemId2Count)
{
RepeatedField<ItemInfo> items = new RepeatedField<ItemInfo>();
foreach (var item in costItemId2Count)
{
items.Add(new ItemInfo()
{
ResCount=(int)item.Value,
ResId=item.Key,
});
}
return ConsumeItems(items);
}
public bool ConsumeItems(RepeatedField<ItemInfo> items)
{
bool found = true;
foreach (ItemInfo item in items)
{
Item i= GetItemById(item.ResId);
if (i != null)
{
if(i.amount < item.ResCount)
{
found = false;
break;
}
}
else
{
found = false;
break;
}
}
foreach (ItemInfo item in items)
{
Item i = GetItemById(item.ResId);
if (i != null)
{
if (i.amount >= item.ResCount)
{
RemoveItem(i,item.ResCount);
}
}
}
return found;
}
public Dictionary<uint, int> GetInventoryChapter(string chapterId)
{
Dictionary<uint, int> dir= new Dictionary<uint, int>();
List<Item> citems = items.FindAll(i=>!i.InstanceType());
foreach (Item item in citems)
{
dir.Add((uint)ResourceManager.strIdNumTable.item_id.dic[item.id], item.amount);
}
return dir;
}
}
}

View File

@ -0,0 +1,259 @@
using Campofinale.Resource;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.IdGenerators;
using static Campofinale.Resource.ResourceManager;
using Google.Protobuf.Collections;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
namespace Campofinale.Game.Inventory
{
public class Item
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
[BsonElement("templateId")]
public string id;
public ulong guid;
public int amount = 1;
public ulong owner;
public ulong level = 1;
public ulong xp;
public bool locked = false;
public ulong attachGemId;
public ulong breakthroughLv;
public ulong refineLv;
public Item() {
}
public Item(ulong owner, string id, int amt)
{
this.owner = owner;
this.id = id;
this.amount = amt;
this.level = GetDefaultLevel();
guid = GetOwner().random.Next();
}
public Item(ulong owner, string id, ulong level)
{
this.owner = owner;
this.id = id;
this.amount = 1;
this.level = level;
guid = GetOwner().random.Next();
}
public ulong GetDefaultLevel()
{
switch (ItemType)
{
case ItemValuableDepotType.Weapon:
return 1;
case ItemValuableDepotType.Equip:
return equipTable[id].minWearLv;
default:
return 0;
}
}
public List<AttributeModifier> GetEquipAttributeModifier()
{
List<AttributeModifier> modifiers = ResourceManager.equipTable[id].attrModifiers;
return modifiers;
}
public ItemValuableDepotType ItemType
{
get{
return ResourceManager.GetItemTable(id).valuableTabType;
}
}
public virtual ScdItemGrid ToProto()
{
try
{
switch (ItemType)
{
case ItemValuableDepotType.WeaponGem:
return new ScdItemGrid()
{
Count = 1,
Id = id,
Inst = new()
{
InstId = guid,
Gem = new()
{
GemId = guid,
TemplateId= ResourceManager.GetItemTemplateId(id),
WeaponId= GetOwner().inventoryManager.items.Find(i=>i.attachGemId==guid)!=null ? GetOwner().inventoryManager.items.Find(i => i.attachGemId == guid).guid: 0,
},
IsLock = locked
}
};
case ItemValuableDepotType.Weapon:
return new ScdItemGrid()
{
Count = 1,
Id = id,
Inst = new()
{
InstId = guid,
Weapon = new()
{
InstId = guid,
EquipCharId = GetOwner().chars.Find(c => c.weaponGuid == guid) != null ? GetOwner().chars.Find(c => c.weaponGuid == guid).guid : 0,
WeaponLv = level,
TemplateId = ResourceManager.GetItemTemplateId(id),
Exp = xp,
AttachGemId = attachGemId,
BreakthroughLv = breakthroughLv,
RefineLv = refineLv
},
IsLock = locked
}
};
case ItemValuableDepotType.Equip:
ScdItemGrid equip=new ScdItemGrid()
{
Count = 1,
Id = id,
Inst = new()
{
InstId = guid,
Equip = new()
{
EquipCharId = GetOwner().chars.Find(c => c.IsEquipped(guid)) != null ? GetOwner().chars.Find(c => c.IsEquipped(guid)).guid : 0,
Equipid = guid,
Templateid = ResourceManager.GetItemTemplateId(id),
},
IsLock = locked
}
};
foreach (var item in GetEquipAttributeModifier())
{
equip.Inst.Equip.Attrs.Add(new EquipAttr()
{
AttrType= (int)item.attrType,
ModifierType=(int)item.modifierType,
ModifierValue=item.attrValue,
ModifyAttributeType=item.modifyAttributeType,
});
}
return equip;
default:
return new ScdItemGrid()
{
Count = amount,
Id = id,
};
}
}
catch(Exception e)
{
return new ScdItemGrid()
{
Count = amount,
Id = id,
};
}
}
public Player GetOwner()
{
return Server.clients.Find(c => c.roleId == this.owner);
}
public (ulong, ulong, ulong) CalculateLevelAndGoldCost(ulong addedXp)
{
ulong gold = 0;
ulong curLevel = this.level;
WeaponBasicTable table = ResourceManager.weaponBasicTable[id];
WeaponUpgradeTemplateTable upgradeTable = ResourceManager.weaponUpgradeTemplateTable[table.levelTemplateId];
while (addedXp >= upgradeTable.list.Find(c=>c.weaponLv==curLevel).lvUpExp)
{
gold += upgradeTable.list.Find(c => c.weaponLv == curLevel).lvUpGold;
addedXp -= upgradeTable.list.Find(c => c.weaponLv == curLevel).lvUpExp;
curLevel++;
if (curLevel >= 80)
{
curLevel = 80;
}
}
return (curLevel, gold, addedXp);
}
public ulong GetMaterialExp(string id)
{
switch (id)
{
case "item_weapon_expcard_low":
return 200;
case "item_weapon_expcard_mid":
return 1000;
case "item_weapon_expcard_high":
return 10000;
default:
return 0;
}
}
public void LevelUp(MapField<string, ulong> costItemId2Count, RepeatedField<ulong> costWeaponIds)
{
//TODO add exp from costWeapons
ulong addedXp = 0;
foreach (var material in costItemId2Count)
{
addedXp += GetMaterialExp(material.Key) * material.Value;
}
(ulong, ulong, ulong) CalculatedValues = CalculateLevelAndGoldCost(xp + addedXp);
costItemId2Count.Add("item_gold",CalculatedValues.Item2);
if (GetOwner().inventoryManager.ConsumeItems(costItemId2Count))
{
this.level = CalculatedValues.Item1;
this.xp = CalculatedValues.Item3;
ScWeaponAddExp levelUp = new()
{
Weaponid = guid,
WeaponLv=level,
NewExp=xp,
};
GetOwner().Send(ScMsgId.ScWeaponAddExp, levelUp);
GetOwner().Send(new PacketScSyncWallet(GetOwner()));
}
}
public bool InstanceType()
{
switch (ItemType)
{
case ItemValuableDepotType.Weapon:
return true;
case ItemValuableDepotType.WeaponGem:
return true;
case ItemValuableDepotType.Equip:
return true;
case ItemValuableDepotType.SpecialItem:
return false;
case ItemValuableDepotType.MissionItem:
return true;
default:
return false;
}
}
}
}

64
Campofinale/Game/Mail.cs Normal file
View File

@ -0,0 +1,64 @@
using Campofinale.Resource;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.IdGenerators;
namespace Campofinale.Game
{
public class Mail
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
public ulong owner;
public long sendTime = 0;
public long expireTime = 0;
public ulong guid = 0;
public bool isStar = false;
public bool claimed = false;
public bool isRead = false;
public MailType mailType;
public MailSubType mailSubType;
public Mail_Content content;
//todo add rewards
public Mail() { }
public CsMailDef ToProto()
{
return new CsMailDef()
{
ExpireTime = expireTime,
MailId=guid,
IsAttachmentGot=claimed,
IsRead=isRead,
IsStar=isStar,
MailType=(int)mailType,
MailSubType=(int)mailSubType,
SendTime=sendTime,
MailContent = new()
{
Content=content.content,
SenderName=content.senderName,
Title=content.title,
TemplateId=content.templateId,
SenderIcon= "Mail/mail_endfield"
}
};
}
}
public struct Mail_Content
{
public string templateId = "";
public string title = "";
public string content = "";
public string senderName = "";
public Mail_Content() { }
}
}

View File

@ -0,0 +1,404 @@
using Campofinale.Game.Entities;
using Campofinale.Game.Inventory;
using Campofinale.Packets.Sc;
using Campofinale.Resource;
using MongoDB.Bson.Serialization.Attributes;
using SharpCompress.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
namespace Campofinale.Game
{
public class SceneManager
{
public List<Scene> scenes = new List<Scene>();
public Player player;
public List<Entity> globalEntities = new List<Entity>();
public SceneManager(Player player) {
this.player = player;
}
public void Update()
{
if (GetCurScene()!=null)
GetCurScene().UpdateShowEntities();
}
public Entity GetEntity(ulong guid)
{
Scene scene = scenes.Find(s => s.sceneNumId == player.curSceneNumId);
Entity en = globalEntities.Find(e => e.guid == guid);
if (en != null)
{
return en;
}
if (scene != null)
{
return scene.entities.Find(e => e.guid == guid);
}
return null;
}
public void LoadCurrentTeamEntities()
{
globalEntities.RemoveAll(e => e is EntityCharacter);
foreach (Character.Character chara in player.GetCurTeam())
{
EntityCharacter ch = new(chara.guid, player.roleId);
globalEntities.Add(ch);
}
}
public void LoadCurrent()
{
Scene curscene = GetCurScene();
string sceneConfigPath = curscene.info().defaultState.exportedSceneConfigPath;
foreach(Scene scene in scenes.FindAll(s => s.info().defaultState.exportedSceneConfigPath == sceneConfigPath))
{
if (scene != null)
{
scene.Load();
}
}
}
public Scene GetScene(int sceneId)
{
return scenes.Find(s=>s.sceneNumId==sceneId);
}
public Scene GetCurScene()
{
return scenes.Find(s => s.sceneNumId == player.curSceneNumId);
}
public void SpawnEntity(Entity entity)
{
Scene scene = GetCurScene();
if (scene != null)
{
scene.entities.Add(entity);
//Spawn packet
player.Send(new PacketScObjectEnterView(player,new List<Entity>{ entity }));
}
}
public void KillEntity(ulong guid, bool killClient=false, int reason=1)
{
Scene scene = GetCurScene();
if (scene != null)
{
if(GetEntity(guid) is EntityMonster)
{
EntityMonster monster = (EntityMonster)GetEntity(guid);
CreateDrop(monster.Position, new RewardTable.ItemBundle()
{
id = "item_gem_rarity_3",
count=1
});
LevelScene lv_scene = ResourceManager.GetLevelData(GetEntity(guid).sceneNumId);
LevelEnemyData d = lv_scene.levelData.enemies.Find(l => l.levelLogicId == monster.guid);
if (d != null)
{
if (!d.respawnable)
{
player.noSpawnAnymore.Add(monster.guid);
}
}
}
if (killClient)
{
ScSceneDestroyEntity destroy = new()
{
Id = guid,
Reason = reason,
SceneNumId = GetEntity(guid).sceneNumId,
};
player.Send(Protocol.ScMsgId.ScSceneDestroyEntity, destroy);
}
if (GetEntity(guid) != null)
{
if(scenes.Find(s => s.sceneNumId == GetEntity(guid).sceneNumId) != null)
{
scenes.Find(s => s.sceneNumId == GetEntity(guid).sceneNumId).entities.Remove(GetEntity(guid));
}
}
}
}
public void CreateDrop(Vector3f pos,ResourceManager.RewardTable.ItemBundle bundle)
{
ItemTable info = ResourceManager.itemTable[bundle.id];
Item item = new Item(player.roleId, info.id, bundle.count);
EntityInteractive drop = new(info.modelKey, player.roleId, pos, new Vector3f(), GetCurScene().sceneNumId)
{
type = (ObjectType)5,
curHp = 100,
properties =
{
new ParamKeyValue()
{
key="is_collected",
value = new()
{
type=ParamRealType.Bool,
valueArray=new ParamKeyValue.ParamValueAtom[1]
{
new ParamKeyValue.ParamValueAtom()
{
}
}
}
},
new ParamKeyValue()
{
key="item_id",
value = new()
{
type=ParamRealType.String,
valueArray=new ParamKeyValue.ParamValueAtom[1]
{
new ParamKeyValue.ParamValueAtom()
{
valueString=info.id,
}
}
}
},
}
};
drop.properties.Add(new ParamKeyValue()
{
key = "count",
value = new()
{
type = ParamRealType.Int,
valueArray = new ParamKeyValue.ParamValueAtom[1]
{
new ParamKeyValue.ParamValueAtom()
{
valueBit64=bundle.count
}
}
}
});
if (item.InstanceType())
{
drop.properties.Add(new ParamKeyValue()
{
key = "item_inst",
value = new()
{
type = ParamRealType.String,
valueArray = new ParamKeyValue.ParamValueAtom[1]
{
new ParamKeyValue.ParamValueAtom()
{
valueString=Newtonsoft.Json.JsonConvert.SerializeObject(item.ToProto().Inst)
}
}
}
});
}
SpawnEntity(drop);
}
public ulong GetSceneGuid(int sceneNumId)
{
return scenes.Find(s=>s.sceneNumId == sceneNumId).guid;
}
//TODO Save and get
public void Load()
{
foreach (var level in ResourceManager.levelDatas)
{
if(scenes.Find(s=>s.sceneNumId==level.idNum) == null)
scenes.Add(new Scene()
{
guid = (ulong)player.random.Next(),
ownerId=player.roleId,
sceneNumId=level.idNum,
});
}
}
public void UnloadAllByConfigPath(string sceneConfigPath)
{
foreach (Scene scene in scenes.FindAll(s => s.info().defaultState.exportedSceneConfigPath == sceneConfigPath))
{
if (scene != null)
{
scene.alreadyLoaded = false;
scene.Unload();
}
}
}
}
public class Scene
{
public ulong ownerId;
public ulong guid;
public int sceneNumId;
public Dictionary<string, int> collections = new();
[BsonIgnore,JsonIgnore]
public List<Entity> entities = new();
[BsonIgnore, JsonIgnore]
public bool alreadyLoaded = false;
public int GetCollection(string id)
{
if (collections.ContainsKey(id))
{
return collections[id];
}
return 0;
}
public void AddCollection(string id,int amt)
{
if (collections.ContainsKey(id))
{
collections[id] += amt;
}
else
{
collections.Add(id, amt);
}
}
public List<Entity> GetEntityExcludingChar()
{
return entities.FindAll(c => c is not EntityCharacter);
}
public void Unload()
{
List<ulong> guids = new();
foreach(Entity e in entities)
{
guids.Add(e.guid);
}
entities.Clear();
GetOwner().Send(new PacketScObjectLeaveView(GetOwner(), guids));
}
public LevelScene info()
{
return levelDatas.Find(l => l.idNum == sceneNumId);
}
public void Load()
{
if (info().isSeamless && alreadyLoaded) return;
alreadyLoaded = true;
Unload();
LevelScene lv_scene = ResourceManager.GetLevelData(sceneNumId);
lv_scene.levelData.interactives.ForEach(en =>
{
if (en.defaultHide || GetOwner().noSpawnAnymore.Contains(en.levelLogicId))
{
return;
}
EntityInteractive entity = new(en.entityDataIdKey, ownerId, en.position, en.rotation, sceneNumId, en.levelLogicId)
{
belongLevelScriptId=en.belongLevelScriptId,
dependencyGroupId=en.dependencyGroupId,
levelLogicId= en.levelLogicId,
type = en.entityType,
properties= en.properties,
componentProperties=en.componentProperties,
};
entities.Add(entity);
});
lv_scene.levelData.factoryRegions.ForEach(en =>
{
if (en.defaultHide || GetOwner().noSpawnAnymore.Contains(en.levelLogicId))
{
return;
}
EntityInteractive entity = new(en.entityDataIdKey, ownerId, en.position, en.rotation, sceneNumId, en.levelLogicId)
{
belongLevelScriptId = en.belongLevelScriptId,
dependencyGroupId = 0,
levelLogicId = en.levelLogicId,
type = en.entityType,
};
entities.Add(entity);
});
lv_scene.levelData.enemies.ForEach(en =>
{
if(en.defaultHide || GetOwner().noSpawnAnymore.Contains(en.levelLogicId)) return;
EntityMonster entity = new(en.entityDataIdKey,en.level,ownerId,en.position,en.rotation, sceneNumId, en.levelLogicId)
{
type=en.entityType,
belongLevelScriptId=en.belongLevelScriptId,
levelLogicId = en.levelLogicId
};
entities.Add(entity);
});
lv_scene.levelData.npcs.ForEach(en =>
{
if (en.defaultHide) return;
if (en.npcGroupId.Contains("chr")) return;
EntityNpc entity = new(en.entityDataIdKey,ownerId,en.position,en.rotation, sceneNumId, en.levelLogicId)
{
belongLevelScriptId = en.belongLevelScriptId,
levelLogicId = en.levelLogicId,
type = en.entityType,
};
entities.Add(entity);
});
/*GetEntityExcludingChar().ForEach(e =>
{
GetOwner().Send(new PacketScObjectEnterView(GetOwner(),new List<Entity>() { e}));
});*/
UpdateShowEntities();
}
public void UpdateShowEntities()
{
foreach(Entity en in GetEntityExcludingChar())
{
if (en.Position.Distance(GetOwner().position) < 200)
{
if (!en.spawned)
{
en.spawned = true;
GetOwner().Send(new PacketScObjectEnterView(GetOwner(), new List<Entity>() { en }));
}
}
else
{
if (en.spawned)
{
en.spawned = false;
GetOwner().Send(new PacketScObjectLeaveView(GetOwner(), new List<ulong>() { en.guid }));
en.Position=en.BornPos;
en.Rotation = en.Rotation;
}
}
}
}
public Player GetOwner()
{
return Server.clients.Find(c => c.roleId == ownerId);
}
}
}

View File

@ -0,0 +1,67 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using MongoDB.Bson.Serialization.IdGenerators;
using Campofinale.Resource;
namespace Campofinale.Game.Spaceship
{
public class SpaceshipChar
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
public string id;
public ulong guid;
public ulong owner;
public string stationedRoomId = "";
public float physicalStrength;
public int favorability;
public bool isWorking;
public SpaceshipChar()
{
}
public SpaceshipChar(ulong owner, string id)
{
this.owner = owner;
this.id = id;
this.guid = (ulong)new Random().NextInt64();
}
public string GetNpcId()
{
return ResourceManager.spaceShipCharBehaviourTable[id].npcId;
}
public ScdSpaceshipChar ToSpaceshipChar()
{
return new ScdSpaceshipChar()
{
CharId = id,
Favorability = favorability,
IsWorking = isWorking,
PhysicalStrength = physicalStrength,
StationedRoomId = stationedRoomId,
Skills =
{
new ScdSpaceshipCharSkill()
{
Index=1,
SkillId="spaceship_skill_acc_charmaterial_produce2_1"
},
new ScdSpaceshipCharSkill()
{
Index=0,
SkillId="spaceship_skill_acc_all_ps_recovery1_2"
}
},
};
}
}
}

View File

@ -0,0 +1,90 @@
using Campofinale.Database;
using Campofinale.Game.Inventory;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.IdGenerators;
using static Campofinale.Resource.ResourceManager;
using Campofinale.Resource;
namespace Campofinale.Game.Spaceship
{
public class SpaceshipManager
{
public Player owner;
public List<SpaceshipChar> chars=new();
public List<SpaceshipRoom> rooms = new();
public SpaceshipManager(Player o)
{
owner = o;
}
public SpaceshipChar GetChar(string id)
{
return chars.Find(c => c.id == id);
}
public void AddNewCharacter(string id)
{
if (id.Contains("endmin")) return;
SpaceshipChar chara = new(owner.roleId, id);
chars.Add(chara);
}
public void Load()
{
chars = DatabaseManager.db.LoadSpaceshipChars(owner.roleId);
rooms = DatabaseManager.db.LoadSpaceshipRooms(owner.roleId);
foreach (var chara in owner.chars)
{
SpaceshipChar c = GetChar(chara.id);
if (c == null && !chara.id.Contains("endmin"))
{
AddNewCharacter(chara.id);
}
}
if(rooms.Count < 1)
{
rooms.Add(new SpaceshipRoom(owner.roleId,"control_center"));
}
}
public void Save()
{
foreach(SpaceshipChar spaceshipChar in chars)
{
DatabaseManager.db.UpsertSpaceshipChar(spaceshipChar);
}
foreach(SpaceshipRoom room in rooms)
{
DatabaseManager.db.UpsertSpaceshipRoom(room);
}
}
public void UpdateStationedChars()
{
Dictionary<string, string> charAndRoom = new();
foreach(SpaceshipRoom room in rooms)
{
foreach (var c in room.stationedCharList)
{
charAndRoom.Add(c, room.id);
}
}
foreach(SpaceshipChar chara in chars)
{
if (charAndRoom.ContainsKey(chara.id))
{
chara.stationedRoomId = charAndRoom[chara.id];
}
else
{
chara.stationedRoomId = "";
}
}
}
}
}

View File

@ -0,0 +1,153 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
using Campofinale.Resource;
using MongoDB.Bson.Serialization.IdGenerators;
namespace Campofinale.Game.Spaceship
{
public class SpaceshipRoom
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId _id { get; set; }
public string id = "";
public int level = 1;
public List<string> stationedCharList = new();
public ulong owner;
public SpaceshipRoom()
{
}
public SpaceshipRoom(ulong owner, string id)
{
this.owner = owner;
this.id = id;
}
public bool HasCharWorking()
{
bool val = false;
foreach (string chara in stationedCharList)
{
SpaceshipChar ch = GetOwner().spaceshipManager.GetChar(chara);
if (ch != null)
{
if (ch.isWorking)
{
val = true;
}
}
}
return val;
}
public int GetType()
{
SpaceshipRoomInsTable roomInfo = ResourceManager.spaceshipRoomInsTable[id];
return roomInfo.roomType;
}
public Player GetOwner()
{
return Server.clients.Find(c => c.roleId == owner);
}
public ScdSpaceshipRoom ToRoomProto()
{
SpaceshipRoomInsTable roomInfo = ResourceManager.spaceshipRoomInsTable[id];
ScdSpaceshipRoom room = new()
{
Id = id,
Level = level,
Type = roomInfo.roomType,
HasCharWorking = HasCharWorking(),
StationedCharList =
{
stationedCharList
},
LevelUpConditionFlags =
{
{ id+"_level_"+(level+1),true}
},
LevelUpConditonValues =
{
{ id+"_level_"+(level+1),4}
},
AttrsMap =
{
{0, new ScdSpaceshipRoomAttr()
{
Value=24.8f,
TheoreticalValue=24.8f,
BaseAttrs =
{
new ScdSpaceshipRoomAttrUnit()
{
Value=20,
Source = new()
{
SourceType=1,
}
}
},
PercentAttrs =
{
new ScdSpaceshipRoomAttrUnit()
{
Value=0.24f,
Source = new()
{
CharId="chr_0004_pelica",
SkillId="spaceship_skill_acc_all_ps_recovery1_2"
}
}
}
} },
{1, new ScdSpaceshipRoomAttr()
{
Value=12,
TheoreticalValue=12,
BaseAttrs =
{
new ScdSpaceshipRoomAttrUnit()
{
Type=1,
Value=12,
Source = new()
{
SourceType=1
}
}
}
}
}
},
};
switch (roomInfo.roomType)
{
case 0:
room.ControlCenter = new()
{
};
break;
case 1:
room.ManufacturingStation = new()
{
};
break;
case 2:
room.GrowCabin = new()
{
};
break;
}
return room;
}
}
}

15
Campofinale/Game/Team.cs Normal file
View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Game
{
public class Team
{
public string name = "";
public ulong leader;
public List<ulong> members = new();
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,82 @@
using Campofinale.Commands;
using Campofinale.Commands.Handlers;
using Campofinale.Database;
using HttpServerLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Campofinale.Http
{
public class PCDispatch
{
//using as console for player
[StaticRoute(HttpServerLite.HttpMethod.GET, "/pcSdk/userInfo")]
public static async Task Info(HttpContext ctx)
{
string resp = File.ReadAllText("Data/PlayerConsole/index.html").Replace("%dispatchip%", $"http://{Server.config.dispatchServer.accessAddress}:{Server.config.dispatchServer.accessPort}");
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "text/html";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.GET, "/pcSdk/console")]
public static async Task ConsoleResponce(HttpContext ctx)
{
string cmd = ctx.Request.Query.Elements["command"].Replace("+"," ");
string token = ctx.Request.Query.Elements["token"];
string message = "";
string[] split = cmd.Split(" ");
string[] args = cmd.Split(" ").Skip(1).ToArray();
string command = split[0].ToLower();
if (token != null)
{
Account account = DatabaseManager.db.GetAccountByToken(token);
if (account != null)
{
Logger.Print(account.id);
Player player = Server.clients.Find(acc => acc.accountId == account.id);
if (player != null)
{
CommandManager.Notify(player, command, args, player);
foreach (string msg in player.temporanyChatMessages)
{
message += msg + "<br>";
}
player.temporanyChatMessages.Clear();
}
else
{
message = "You aren't connected to the server";
}
}
else
{
message = "Account not found";
}
}
else message = "Token not found";
var responseData = new
{
message = message,
};
string resp = System.Text.Json.JsonSerializer.Serialize(responseData);
ctx.Response.Headers.Add("Content-Type", "application/json");
ctx.Response.StatusCode = 200;
await ctx.Response.SendAsync(resp);
}
}
}

276
Campofinale/Http/SDK.cs Normal file
View File

@ -0,0 +1,276 @@
using Campofinale.Database;
using Campofinale.Resource;
using HttpServerLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Campofinale.Game.Gacha.GachaManager;
using static Campofinale.Http.Dispatch;
namespace Campofinale.Http
{
public class SDK
{
[StaticRoute(HttpServerLite.HttpMethod.POST, "/user/info/v1/authenticate")]
public static async Task cn_authenticate(HttpContext ctx)
{
string requestBody = ctx.Request.DataAsString;
Console.WriteLine(requestBody);
string resp = "{}";
ctx.Response.StatusCode = 200;
//ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/user/auth/v1/token_by_phone_password")]
public static async Task token_login_phone_cn(HttpContext ctx)
{
string requestBody = ctx.Request.DataAsString;
LoginJson body = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginJson>(requestBody);
Account account = DatabaseManager.db.GetAccountByUsername(body.phone);
Console.WriteLine(requestBody);
string resp = "{}";
if (account != null)
{
resp = "{\"msg\":\"OK\",\"status\":0,\"type\":\"A\",\"data\":{\"token\":\"" + account.token + "\"}}";
}
else
{
resp = "{\"msg\":\"Account not found\",\"status\":2,\"type\":\"A\"}";
}
ctx.Response.StatusCode = 200;
//ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/user/auth/v1/token_by_email_password")]
public static async Task token_login(HttpContext ctx)
{
string requestBody = ctx.Request.DataAsString;
LoginJson body = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginJson>(requestBody);
Account account = DatabaseManager.db.GetAccountByUsername(body.email.Split("@")[0]);
Console.WriteLine(requestBody);
string resp = "{}";
if (account != null)
{
resp = "{\"msg\":\"OK\",\"status\":0,\"type\":\"A\",\"data\":{\"token\":\"" + account.token + "\"}}";
}
else
{
resp = "{\"msg\":\"Account not found\",\"status\":2,\"type\":\"A\"}";
}
ctx.Response.StatusCode = 200;
//ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.GET, "/user/info/v1/basic")]
public static async Task account_info_get(HttpContext ctx)
{
string requestToken = ctx.Request.Query.Elements["token"];
Account account = DatabaseManager.db.GetAccountByToken(requestToken);
string resp = "{\"data\":{\"hgId\":\"1799321925\",\"email\":\"dispatch@endfield.ps\",\"realEmail\":\"dispatch@endfield.ps\",\"isLatestUserAgreement\":true,\"nickName\":\"Campofinale\"},\"msg\":\"OK\",\"status\":0,\"type\":1}";
if (account != null)
{
resp = "{\"data\":{\"idCardNum\": 110102200610048887,\"hgId\":\"" + account.id + "\",\"email\":\"" + account.username +Server.config.dispatchServer.emailFormat +"\",\"realEmail\":\"" + account.username + Server.config.dispatchServer.emailFormat + "\",\"isLatestUserAgreement\":true,\"nickName\":\"" + account.username + "\",\"name\":\"AAAA\"},\"msg\":\"OK\",\"status\":0,\"type\":1}";
}
else
{
resp = "{\"msg\":\"Account not found\",\"status\":2,\"type\":\"A\"}";
}
ctx.Response.StatusCode = 200;
//ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
public struct GrantData
{
public string token;
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/user/oauth2/v2/grant")]
public static async Task account_ugrant(HttpContext ctx)
{
string requestBody = ctx.Request.DataAsString;
GrantData grant = Newtonsoft.Json.JsonConvert.DeserializeObject<GrantData>(requestBody);
Account account = DatabaseManager.db.GetAccountByToken(grant.token);
string resp = "{\"msg\": \"Error\", \"status\": 2, \"type\": \"A\"}";
if (account != null)
{
resp = "{\"data\": { \"uid\": \"" + account.id + "\", \"code\": \"" + DatabaseManager.db.GrantCode(account) + "\" }, \"msg\": \"OK\", \"status\": 0, \"type\": \"A\"}";
}
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/u8/user/auth/v2/grant")]
public static async Task account_grant(HttpContext ctx)
{
string requestBody = ctx.Request.DataAsString;
GrantData grant = Newtonsoft.Json.JsonConvert.DeserializeObject<GrantData>(requestBody);
Account account = DatabaseManager.db.GetAccountByTokenGrant(grant.token);
string resp = "{\"msg\": \"Error\", \"status\": 2, \"type\": \"A\"}";
if (account != null)
{
resp = "{\"data\": { \"uid\": \"" + account.id + "\", \"code\": \"" + account.grantToken + "\" }, \"msg\": \"OK\", \"status\": 0, \"type\": \"A\"}";
}
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
public class TokenChannelData
{
public string channelToken;
}
public class ChannelTokenData
{
public string code;
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/u8/user/auth/v2/token_by_channel_token")]
public static async Task token_channel_token(HttpContext ctx)
{
try
{
string requestBody = ctx.Request.DataAsString;
Console.WriteLine(requestBody);
TokenChannelData data = Newtonsoft.Json.JsonConvert.DeserializeObject<TokenChannelData>(requestBody);
ChannelTokenData channelTokenBody = Newtonsoft.Json.JsonConvert.DeserializeObject<ChannelTokenData>(data.channelToken);
string resp = "{ \"data\": { \"token\":\"" + channelTokenBody.code + "\" }, \"msg\": \"OK\", \"status\": 0, \"type\": \"A\"}";
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
catch (Exception e)
{
Logger.PrintError(e.Message);
}
}
/*{
"appCode": "2fe67ec91610377d",
"code": "121212",
"email": "aaaa@a.cc",
"from": 0,
"password": "aaaaaaaaaaaaaa1"
}*/
public struct RegisterData
{
public string appCode;
public string code;
public string email;
public string password;
}
[StaticRoute(HttpServerLite.HttpMethod.POST, "/user/auth/v1/register")]
public static async Task register(HttpContext ctx)
{
try
{
string requestBody = ctx.Request.DataAsString;
Console.WriteLine(requestBody);
RegisterData data = Newtonsoft.Json.JsonConvert.DeserializeObject<RegisterData>(requestBody);
string username = data.email.Split("@")[0];
(string,int) msg=DatabaseManager.db.CreateAccount(username);
string resp = "";
if (msg.Item2 > 0)
{
resp = "{\"msg\": \"" + msg.Item1 + "\", \"status\": " + msg.Item2 + ", \"type\": \"\"}";
}
else
{
Account account = DatabaseManager.db.GetAccountByUsername(username);
resp = "{\"data\": { \"token\":\"" + account.token + "\" }, \"msg\": \"" + msg.Item1 + "\", \"status\": " + msg.Item2 + ", \"type\": \"\"}";
}
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/json";
await ctx.Response.SendAsync(resp);
}
catch (Exception e)
{
Logger.PrintError(e.Message);
}
}
[StaticRoute(HttpServerLite.HttpMethod.GET, "/api/gachahistory")]
public static async Task gachahistory_api(HttpContext ctx)
{
string requestId = ctx.Request.Query.Elements["id"];
string banner = ctx.Request.Query.Elements["banner"];
string page = ctx.Request.Query.Elements["page"];
PlayerData data = DatabaseManager.db.GetPlayerById(requestId);
GachaHistoryAPI transactions = new();
if (data != null)
{
transactions = GetGachaHistoryPage(data, banner, int.Parse(page));
}
else
{
transactions.transactionList = new();
}
string resp = Newtonsoft.Json.JsonConvert.SerializeObject(transactions);
ctx.Response.StatusCode = 200;
await ctx.Response.SendAsync(resp);
}
[StaticRoute(HttpServerLite.HttpMethod.GET, "/gachahistory")]
public static async Task gachahistory(HttpContext ctx)
{
string requestId = ctx.Request.Query.Elements["id"];
PlayerData data = DatabaseManager.db.GetPlayerById(requestId);
string resp = "";
if (data != null)
{
resp = File.ReadAllText("Data/GachaHistory/index.html").Replace("%dispatchip%", $"http://{Server.config.dispatchServer.accessAddress}:{Server.config.dispatchServer.accessPort}");
}
else
{
resp = File.ReadAllText("Data/GachaHistory/index_noplayerfound.html");
}
ctx.Response.StatusCode = 200;
await ctx.Response.SendAsync(resp);
}
}
}

79
Campofinale/Logger.cs Normal file
View File

@ -0,0 +1,79 @@
using Campofinale;
using Pastel;
using System;
using System.Diagnostics;
using System.IO;
using static System.Net.Mime.MediaTypeNames;
public static class Logger
{
public static Dictionary<string, string> ClassColors = new Dictionary<string, string>()
{
{"Server","03fcce" },
{"Dispatch", "0307fc" }
};
private static string GetCallingClassName()
{
StackTrace stackTrace = new StackTrace();
var frame = stackTrace.GetFrame(2);
var method = frame?.GetMethod();
return method?.DeclaringType?.Name ?? "Server";
}
public static void Print(string text)
{
string className = GetCallingClassName();
Logger.Log(text);
string prefix = "<" + "INFO".Pastel("03fcce") + $":{className.Pastel("999")}>";
Console.WriteLine($"{prefix} " + text);
}
public static void PrintError(string text)
{
string className = GetCallingClassName();
Logger.Log(text);
string prefix = "<" + "ERROR".Pastel("eb4034") + $":{className.Pastel("999")}>";
Console.WriteLine($"{prefix} " + text.Pastel("917e7e"));
}
public static void PrintWarn(string text)
{
string className = GetCallingClassName();
Logger.Log(text);
string prefix = "<" + "WARN".Pastel("ff9100") + $":{className.Pastel("999")}>";
Console.WriteLine($"{prefix} " + text);
}
public static string GetColor(string c)
{
if (ClassColors.ContainsKey(c)) return ClassColors[c];
return "999";
}
private static StreamWriter logWriter;
private static bool hideLogs;
public static void Initialize(bool hideLogs = false)
{
Logger.hideLogs = hideLogs;
logWriter = new StreamWriter("latest.log", false);
}
public static void Log(string message)
{
if (!hideLogs)
{
try
{
logWriter.WriteLine($"{DateTime.Now}: {message}");
logWriter.Flush();
}
catch(Exception e)
{
}
}
}
public static void Close()
{
logWriter.Close();
}
}

View File

@ -0,0 +1,193 @@
using Campofinale.Protocol;
using Google.Protobuf;
using Pastel;
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Campofinale.Network
{
public class Packet
{
public int cmdId;
public byte[] finishedBody;
public CSHead csHead;
public IMessage set_body;
public static void PutUInt16(byte[] buf, ushort networkValue, int offset)
{
byte[] bytes = BitConverter.GetBytes(networkValue);
Buffer.BlockCopy(bytes, 0, buf, offset, bytes.Length);
}
public static void PutUInt32(byte[] buf, uint networkValue, int offset)
{
byte[] bytes = BitConverter.GetBytes(networkValue);
Buffer.BlockCopy(bytes, 0, buf, offset, bytes.Length);
}
public static void PutUInt64(byte[] buf, ulong networkValue, int offset)
{
byte[] bytes = BitConverter.GetBytes(networkValue);
Buffer.BlockCopy(bytes, 0, buf, offset, bytes.Length);
}
public static ushort GetUInt16(byte[] buf, int index)
{
ushort networkValue = BitConverter.ToUInt16(buf, index);
return networkValue;
}
public static uint GetUInt32(byte[] buf,int index)
{
uint networkValue = BitConverter.ToUInt32(buf, index);
return (uint)IPAddress.NetworkToHostOrder((int)networkValue);
}
public static void PutByte(byte[] buf, byte networkValue, int offset)
{
byte[] bytes = new byte[1] {networkValue };
Buffer.BlockCopy(bytes, 0, buf, offset, bytes.Length);
}
public static byte GetByte(byte[] buf, int index)
{
byte networkValue = buf[index];
return networkValue;
}
public TBody DecodeBody<TBody>() where TBody : IMessage<TBody>, new()
{
return new MessageParser<TBody>(() => new()).ParseFrom(finishedBody);
}
public static void PutByteArray(byte[] destination, byte[] source, int offset)
{
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (source == null)
throw new ArgumentNullException(nameof(source));
if (offset < 0 || offset > destination.Length - source.Length)
throw new ArgumentOutOfRangeException(nameof(offset), "Offset is out of range.");
Buffer.BlockCopy(source, 0, destination, offset, source.Length);
}
public static byte[] ToByteArray(IntPtr ptr, int length)
{
if (ptr == IntPtr.Zero)
{
throw new ArgumentException("Pointer cannot be null", nameof(ptr));
}
byte[] byteArray = new byte[length];
Marshal.Copy(ptr, byteArray, 0, length);
return byteArray;
}
public static IntPtr ByteArrayToIntPtr(byte[] data)
{
if (data == null) throw new ArgumentNullException(nameof(data));
// Allocate unmanaged memory
IntPtr ptr = Marshal.AllocHGlobal(data.Length);
// Copy the byte array to the unmanaged memory
Marshal.Copy(data, 0, ptr, data.Length);
return ptr;
}
public static byte[] EncryptWithPublicKey(byte[] data, string publicKey)
{
// Crea un oggetto RSA
using (RSA rsa = RSA.Create())
{
publicKey = publicKey.Replace("-----BEGIN PUBLIC KEY-----", "");
publicKey = publicKey.Replace("\r", "");
publicKey = publicKey.Replace("\n", "");
publicKey = publicKey.Replace("-----END PUBLIC KEY-----", "");
publicKey = publicKey.Trim();
Logger.Print(publicKey);
byte[] publicKey_ = Convert.FromBase64String(publicKey);
// Importa la chiave pubblica
rsa.ImportSubjectPublicKeyInfo(publicKey_, out _);
// Crittografa i dati
return rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
}
}
public Packet SetData(ScMsgId msgId, IMessage body)
{
set_body = body;
cmdId = (int)msgId;
return this;
}
public static byte[] EncodePacket(Packet packet,ulong seq = 0, uint totalPackCount = 1, uint currentPackIndex = 0)
{
return EncodePacket(packet.cmdId,packet.set_body,seq, totalPackCount, currentPackIndex);
}
public static ulong seqNext = 1;
public static byte[] EncodePacket(int msgId, IMessage body, ulong seqNext_ = 0, uint totalPackCount=1,uint currentPackIndex=0)
{
if (seqNext_ == 0)
{
seqNext_ = seqNext;
}
seqNext++;
CSHead head = new() { Msgid = msgId,UpSeqid=seqNext_, DownSeqid= seqNext, TotalPackCount= totalPackCount, CurrentPackIndex= currentPackIndex };
int totalSerializedDataSize = 3 + head.ToByteArray().Length + body.ToByteArray().Length;
byte[] data = new byte[totalSerializedDataSize];
PutByte(data, (byte)head.ToByteArray().Length, 0);
PutUInt16(data, (ushort)body.ToByteArray().Length, 1);
PutByteArray(data, head.ToByteArray(), 3);
PutByteArray(data, body.ToByteArray(), 3+head.ToByteArray().Length);
if(Server.config.logOptions.packets && !Server.scMessageToHide.Contains((ScMsgId)msgId))
Logger.Print($"Sending packet: {((ScMsgId)msgId).ToString().Pastel(Color.LightBlue)} id: {msgId} with {data.Length} bytes");
return data;
}
public static byte[] EncodePacket(int msgId, byte[] body, ulong seqNext_ = 0, uint totalPackCount = 1, uint currentPackIndex = 0)
{
if (seqNext_ == 0)
{
seqNext_ = seqNext;
}
if(currentPackIndex==0)
{
seqNext++;
}
CSHead head = new() { Msgid = msgId, UpSeqid = seqNext_, DownSeqid = seqNext, TotalPackCount = totalPackCount, CurrentPackIndex = currentPackIndex };
int totalSerializedDataSize = 3 + head.ToByteArray().Length + body.Length;
byte[] data = new byte[totalSerializedDataSize];
PutByte(data, (byte)head.ToByteArray().Length, 0);
PutUInt16(data, (ushort)body.Length, 1);
PutByteArray(data, head.ToByteArray(), 3);
PutByteArray(data, body, 3 + head.ToByteArray().Length);
if (Server.config.logOptions.packets && !Server.scMessageToHide.Contains((ScMsgId)msgId))
Logger.Print($"Sending packet: {((ScMsgId)msgId).ToString().Pastel(Color.LightBlue)} id: {msgId} with {data.Length} bytes");
return data;
}
public static Packet Read(Player client,byte[] byteArray)
{
byte headLength = GetByte(byteArray, 0);
ushort bodyLength = GetUInt16(byteArray, 1);
byte[] csHeadBytes = new byte[headLength];
byte[] BodyBytes = new byte[bodyLength];
Array.Copy(byteArray, 3, csHeadBytes, 0, headLength);
Array.Copy(byteArray, 3+ headLength, BodyBytes, 0, bodyLength);
CSHead csHead_ = CSHead.Parser.ParseFrom(csHeadBytes);
if (Server.config.logOptions.packets)
{
Logger.Print(csHead_.ToString());
}
seqNext = csHead_.UpSeqid;
return new Packet() { csHead = csHead_, finishedBody = BodyBytes,cmdId=csHead_.Msgid };
}
}
}

View File

@ -0,0 +1,69 @@
namespace Campofinale
{
using Pastel;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Collections.Immutable;
using System.Linq.Expressions;
using System.Reflection;
using System.Net.Sockets;
using Campofinale.Protocol;
using Campofinale.Network;
internal static class NotifyManager
{
private static List<Type> s_handlerTypes = new List<Type>();
private static ImmutableDictionary<CsMsgId, (Server.HandlerAttribute, Server.HandlerAttribute.HandlerDelegate)> s_notifyReqGroup;
public static void Init()
{
var handlers = ImmutableDictionary.CreateBuilder<CsMsgId, (Server.HandlerAttribute, Server.HandlerAttribute.HandlerDelegate)>();
foreach (var type in s_handlerTypes)
{
foreach (var method in type.GetMethods())
{
var attribute = method.GetCustomAttribute<Server.HandlerAttribute>();
if (attribute == null)
continue;
var parameterInfo = method.GetParameters();
var sessionParameter = Expression.Parameter(typeof(Player));
var cmdIdParameter = Expression.Parameter(typeof(int));
var packetParameter = Expression.Parameter(typeof(Packet));
var call = Expression.Call(method,
Expression.Convert(sessionParameter, parameterInfo[0].ParameterType),
Expression.Convert(cmdIdParameter, parameterInfo[1].ParameterType),
Expression.Convert(packetParameter, parameterInfo[2].ParameterType));
var lambda = Expression.Lambda<Server.HandlerAttribute.HandlerDelegate>(call, sessionParameter, cmdIdParameter, packetParameter);
if (!handlers.TryGetKey(attribute.CmdId, out _))
handlers.Add(attribute.CmdId, (attribute, lambda.Compile()));
}
}
s_notifyReqGroup = handlers.ToImmutable();
}
public static void Notify(Player session, CsMsgId cmdId, Network.Packet packet)
{
if (s_notifyReqGroup.TryGetValue(cmdId, out var handler))
{
handler.Item2.Invoke(session, ((int)cmdId), packet);
}
else
{
if (!Server.hideLog.Contains(cmdId) && Server.config.logOptions.packets)
Logger.PrintWarn($"Can't find handler for {(Enum.GetName(typeof(CsMsgId), cmdId)).ToString().Pastel(Color.FromArgb(165, 229, 250))} ({(cmdId).ToString().Pastel(Color.FromArgb(165, 229, 250))})");
}
}
public static void AddReqGroupHandler(Type type)
{
s_handlerTypes.Add(type);
}
}
}

View File

@ -0,0 +1,191 @@
using Campofinale.Game.Character;
using Campofinale.Game.Entities;
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using MongoDB.Driver.Core.Clusters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsBattleOp
{
//TODO AbilityManager
[Server.Handler(CsMsgId.CsBattleOp)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsBattleOp req = packet.DecodeBody<CsBattleOp>();
foreach (BattleClientOpData data in req.ClientData.OpList)
{
switch (data.OpType)
{
case BattleActionOperateType.BattleOpEntityValueModify:
OnEntityValueModify(session, data);
break;
case BattleActionOperateType.BattleOpSkillStartCast:
OnSkillStartCast(session, data);
break;
case BattleActionOperateType.BattleOpSkillEndCast:
OnSkillEndCast(session, data);
break;
case BattleActionOperateType.BattleOpTriggerAction:
OnTriggerAction(session, data.TriggerActionOpData);
break;
case BattleActionOperateType.BattleOpEntityDie:
OnEntityDie(session, data.EntityDieOpData);
break;
default:
Logger.PrintWarn($"Unsupported BattleActionOperateType.{data.OpType}");
break;
}
}
}
private static void OnEntityDie(Player session, BattleEntityDieOpData data)
{
if (session.sceneManager.GetEntity(data.EntityInstId) != null)
{
if (Server.config.logOptions.debugPrint)
{
Logger.PrintWarn("Killed entity with guid: "+data.EntityInstId);
}
session.sceneManager.KillEntity(data.EntityInstId);
}
}
private static void OnTriggerAction(Player session, BattleTriggerActionOpData data)
{
switch (data.Action.ActionType)
{
case ServerBattleActionType.BattleActionDamage:
foreach(BattleDamageDetail item in data.Action.DamageAction.Details)
{
DamageEntity(session, item);
}
break;
case ServerBattleActionType.BattleActionHeal:
foreach (BattleHealActionDetail item in data.Action.HealAction.Details)
{
HealEntity(session, item);
}
break;
default:
Logger.PrintWarn($"Unsupported ServerBattleActionType.{data.Action.ActionType}");
break;
}
}
public static void HealEntity(Player session, BattleHealActionDetail detail)
{
Entity en = session.sceneManager.GetEntity(detail.TargetId);
if (en != null)
{
Logger.Print("Healing +" + detail.Value + "hp");
en.Heal(detail.Value);
}
}
public static void DamageEntity(Player session, BattleDamageDetail detail)
{
Entity en=session.sceneManager.GetEntity(detail.TargetId);
if (en != null)
{
en.Damage(detail.Value);
if (Server.config.logOptions.debugPrint)
{
Logger.PrintWarn("Damaged entity with dmg: "+detail.Value);
}
}
}
private static void OnSkillStartCast(Player session, BattleClientOpData data)
{
ulong casterId = data.OwnerId;
Character character = session.chars.Find(c => c.guid == casterId);
if (character != null)
{
ScCharSyncStatus s = new()
{
BattleInfo = new()
{
Hp = character.curHp,
Ultimatesp = character.ultimateSp
},
Objid=character.guid,
};
session.Send(ScMsgId.ScCharSyncStatus, s);
}
else
{
//Manage normal entity
}
}
private static void OnSkillEndCast(Player session, BattleClientOpData data)
{
ulong casterId = data.OwnerId;
Character character = session.chars.Find(c => c.guid == casterId);
if (character != null)
{
ScCharSyncStatus s = new()
{
BattleInfo = new()
{
Hp = character.curHp,
Ultimatesp = character.ultimateSp+1
},
Objid = character.guid,
};
session.Send(ScMsgId.ScCharSyncStatus, s);
}
else
{
//Manage normal entity
}
}
private static void OnEntityValueModify(Player session, BattleClientOpData data)
{
Logger.PrintWarn("EntityValueModify called: " + data.EntityValueModifyData.ToString());
Character character = session.chars.Find(c => c.guid == data.EntityValueModifyData.EntityInstId);
if (character != null)
{
character.curHp = data.EntityValueModifyData.Value.Hp;
ScCharSyncStatus s = new()
{
BattleInfo = new()
{
Hp = data.EntityValueModifyData.Value.Hp,
Ultimatesp = character.ultimateSp
},
Objid = character.guid,
};
session.Send(ScMsgId.ScCharSyncStatus, s);
}
else
{
//Manage normal entity
}
// data.EntityValueModifyData.
}
}
}

View File

@ -0,0 +1,34 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsBitsetAdd
{
[Server.Handler(CsMsgId.CsBitsetAdd)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsBitsetAdd req = packet.DecodeBody<CsBitsetAdd>();
foreach (var item in req.Value)
{
session.bitsetManager.AddValue((BitsetType)req.Type, (int)item);
}
session.Send(new PacketScBitsetAdd(session,req.Type,req.Value.ToList()));
}
}
}

View File

@ -0,0 +1,34 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsBitsetRemove
{
[Server.Handler(CsMsgId.CsBitsetRemove)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsBitsetRemove req = packet.DecodeBody<CsBitsetRemove>();
foreach (var item in req.Value)
{
session.bitsetManager.RemoveValue((BitsetType)req.Type, (int)item);
}
session.Send(new PacketScBitsetRemove(session,req.Type,req.Value.ToList()));
}
}
}

View File

@ -0,0 +1,36 @@
using BeyondTools.VFS.Crypto;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using static Campofinale.Resource.ResourceManager;
using static System.Net.Mime.MediaTypeNames;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharBagSetCurrTeamIndex
{
[Server.Handler(CsMsgId.CsCharBagSetCurrTeamIndex)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharBagSetCurrTeamIndex req = packet.DecodeBody<CsCharBagSetCurrTeamIndex>();
session.teamIndex = req.TeamIndex;
session.teams[session.teamIndex].leader = req.LeaderId;
session.Send(new PacketScCharBagSetCurrTeamIndex(session));
session.Send(new PacketScSelfSceneInfo(session,SelfInfoReasonType.SlrChangeTeam));
}
}
}

View File

@ -0,0 +1,40 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharBagSetTeam
{
[Server.Handler(CsMsgId.CsCharBagSetTeam)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharBagSetTeam req = packet.DecodeBody<CsCharBagSetTeam>();
session.teams[req.TeamIndex].leader=req.LeaderId;
session.teams[req.TeamIndex].members= req.CharTeam.ToList();
ScCharBagSetTeam team = new()
{
CharTeam = { req.CharTeam },
LeaderId = req.LeaderId,
ScopeName = 1,
TeamIndex = req.TeamIndex,
TeamType = CharBagTeamType.Main,
};
session.Send(ScMsgId.ScCharBagSetTeam,team);
session.Send(new PacketScSelfSceneInfo(session, Resource.SelfInfoReasonType.SlrChangeTeam));
}
}
}

View File

@ -0,0 +1,37 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharBagSetTeamLeader
{
[Server.Handler(CsMsgId.CsCharBagSetTeamLeader)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharBagSetTeamLeader req = packet.DecodeBody<CsCharBagSetTeamLeader>();
session.teams[req.TeamIndex].leader=req.Leaderid;
ScCharBagSetTeamLeader rsp = new()
{
Leaderid = req.Leaderid,
TeamIndex = req.TeamIndex,
ScopeName = 1,
TeamType = req.TeamType,
};
session.Send(ScMsgId.ScCharBagSetTeamLeader, rsp);
}
}
}

View File

@ -0,0 +1,35 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharBagSetTeamName
{
[Server.Handler(CsMsgId.CsCharBagSetTeamName)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharBagSetTeamName req = packet.DecodeBody<CsCharBagSetTeamName>();
session.teams[req.TeamIndex].name=req.TeamName;
ScCharBagSetTeamName rsp = new()
{
TeamIndex = req.TeamIndex,
TeamName = req.TeamName,
ScopeName = 1,
};
session.Send(ScMsgId.ScCharBagSetTeamName, rsp);
}
}
}

View File

@ -0,0 +1,31 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharLevelUp
{
[Server.Handler(CsMsgId.CsCharLevelUp)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharLevelUp req = packet.DecodeBody<CsCharLevelUp>();
Character character = session.chars.Find(c=>c.guid==req.CharObjID);
if(character!=null)
character.LevelUp(req.Items);
}
}
}

View File

@ -0,0 +1,42 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharPotentialUnlock
{
[Server.Handler(CsMsgId.CsCharPotentialUnlock)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharPotentialUnlock req = packet.DecodeBody<CsCharPotentialUnlock>();
Character character = session.chars.Find(c => c.guid == req.CharObjId);
if (character != null)
{
character.potential=req.Level;
//TODO consume Item ID
ScCharPotentialUnlock unlock = new()
{
CharObjId = req.CharObjId,
Level = req.Level,
};
session.Send(ScMsgId.ScCharPotentialUnlock, unlock);
}
}
}
}

View File

@ -0,0 +1,32 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsCharUnlockTalentNode
{
[Server.Handler(CsMsgId.CsCharUnlockTalentNode)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCharUnlockTalentNode req = packet.DecodeBody<CsCharUnlockTalentNode>();
Character character = session.chars.Find(c=>c.guid==req.CharObjId);
if (character != null)
{
character.UnlockNode(req.NodeId);
}
}
}
}

View File

@ -0,0 +1,27 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsEnterDungeon
{
[Server.Handler(CsMsgId.CsEnterDungeon)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsEnterDungeon req = packet.DecodeBody<CsEnterDungeon>();
session.EnterDungeon(req.DungeonId, req.RacingParam);
}
}
}

View File

@ -0,0 +1,44 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsEquipPutoff
{
[Server.Handler(CsMsgId.CsEquipPutoff)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsEquipPutoff req = packet.DecodeBody<CsEquipPutoff>();
Character toRemove = session.chars.Find(c => c.guid == req.Charid);
if (toRemove != null)
{
ScEquipPutoff put = new()
{
Charid = req.Charid,
Slotid = req.Slotid,
};
if (toRemove != null)
{
toRemove.equipCol[req.Slotid] = 0;
}
//TODO Improve all this maybe with an internal method in Character
session.Send(ScMsgId.ScEquipPutoff, put);
}
}
}
}

View File

@ -0,0 +1,47 @@
using Campofinale.Game.Character;
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsEquipPuton
{
[Server.Handler(CsMsgId.CsEquipPuton)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsEquipPuton req = packet.DecodeBody<CsEquipPuton>();
Character toEquip = session.chars.Find(c => c.guid == req.Charid);
Character toRemove = session.chars.Find(c => c.IsEquipped(req.Equipid));
if (toEquip != null)
{
ScEquipPuton put = new()
{
Charid = req.Charid,
Equipid = req.Equipid,
Slotid = req.Slotid,
};
if (toRemove != null)
{
toRemove.equipCol[req.Slotid] = toEquip.equipCol[req.Slotid];
put.PutOffCharid = toRemove.guid;
}
toEquip.equipCol[req.Slotid] = req.Equipid;
//TODO Improve all this maybe with an internal method in Character
session.Send(ScMsgId.ScEquipPuton, put);
}
}
}
}

View File

@ -0,0 +1,34 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsFactoryHsFb
{
[Server.Handler(CsMsgId.CsFactoryHsFb)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFactoryHsFb req = packet.DecodeBody<CsFactoryHsFb>();
long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
ScFactoryHs hs = new()
{
};
session.Send(ScMsgId.ScFactoryHs, hs);
}
}
}

View File

@ -0,0 +1,26 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsFactoryOp
{
[Server.Handler(CsMsgId.CsFactoryOp)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFactoryOp req = packet.DecodeBody<CsFactoryOp>();
session.factoryManager.ExecOp(req,packet.csHead.UpSeqid);
}
}
}

View File

@ -0,0 +1,33 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsFactoryStatisticRequire
{
[Server.Handler(CsMsgId.CsFactoryStatisticRequire)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFactoryStatisticRequire req = packet.DecodeBody<CsFactoryStatisticRequire>();
ScFactoryStatisticRequire rsp = new()
{
};
session.Send(ScMsgId.ScFactoryStatisticRequire, rsp);
//Logger.Print("Server: " + curtimestamp + " client: " + req.ClientTs);
}
}
}

View File

@ -0,0 +1,31 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsFinishDialog
{
[Server.Handler(CsMsgId.CsFinishDialog)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFinishDialog req = packet.DecodeBody<CsFinishDialog>();
session.Send(ScMsgId.ScFinishDialog, new ScFinishDialog()
{
DialogId=req.DialogId,
FinishNums = { req.FinishNums },
OptionIds = { req.OptionIds },
});
}
}
}

View File

@ -0,0 +1,35 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsFlushSync
{
[Server.Handler(CsMsgId.CsFlushSync)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsFlushSync req = packet.DecodeBody<CsFlushSync>();
long curtimestamp = DateTime.UtcNow.ToUnixTimestampMilliseconds();
ScFlushSync sync = new()
{
ClientTs=req.ClientTs,
ServerTs=(ulong)curtimestamp,
};
session.Send(ScMsgId.ScFlushSync, sync,packet.csHead.UpSeqid);
//Logger.Print("Server: " + curtimestamp + " client: " + req.ClientTs);
}
}
}

View File

@ -0,0 +1,138 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Campofinale.Resource;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Packets.Cs
{
public class HandleCsGachaTenPullReq
{
[Server.Handler(CsMsgId.CsGachaSinglePullReq)]
public static void HandleOnePull(Player session, CsMsgId cmdId, Packet packet)
{
CsGachaSinglePullReq req = packet.DecodeBody<CsGachaSinglePullReq>();
session.gachaManager.upSeqId = packet.csHead.UpSeqid;
session.gachaManager.DoGacha(req.GachaPoolId, 1);
}
[Server.Handler(CsMsgId.CsGachaTenPullReq)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsGachaTenPullReq req = packet.DecodeBody<CsGachaTenPullReq>();
session.gachaManager.upSeqId = packet.csHead.UpSeqid;
session.gachaManager.DoGacha(req.GachaPoolId, 10);
/* Random rng = new Random();
List<string> chars = new List<string>();
const double prob6Star = 0.008; // 0.8%
const double prob5Star = 0.08; // 8%
const double fiftyfifty = 0.50; // 50%
GachaCharPoolTable table = ResourceManager.gachaCharPoolTable[req.GachaPoolId];
GachaCharPoolContentTable content = ResourceManager.gachaCharPoolContentTable[req.GachaPoolId];
int sixstarcount = 0;
int fivestarcount = 0;
List<GachaCharPoolItem> fiveStars = content.list.FindAll(c => c.starLevel == 5);
List<GachaCharPoolItem> sixStars = content.list.FindAll(c => c.starLevel == 6);
int fiveStarGuaranteedIndex = new Random().Next(9);
for (int i=0; i < 10; i++)
{
double roll = rng.NextDouble();
double fifty = rng.NextDouble();
if (roll < prob6Star)
{
sixstarcount++;
if (table.upCharIds.Count > 0)
{
if (fifty >= fiftyfifty)
{
chars.Add(ResourceManager.characterTable[table.upCharIds[0]].charId);
}
else
{
chars.Add(sixStars[new Random().Next(sixStars.Count - 1)].charId);
}
}
else
{
chars.Add(sixStars[new Random().Next(sixStars.Count - 1)].charId);
}
}
else if (roll < prob6Star + prob5Star || fiveStarGuaranteedIndex == i)
{
fivestarcount++;
if(table.upCharIds.Count > 1)
{
if(fifty >= fiftyfifty)
{
chars.Add(ResourceManager.characterTable[table.upCharIds[1]].charId);
}
else
{
chars.Add(fiveStars[new Random().Next(fiveStars.Count - 1)].charId);
}
}
else
{
chars.Add(fiveStars[new Random().Next(fiveStars.Count-1)].charId);
}
}
else
{
chars.Add(ResourceManager.characterTable.Values.ToList().FindAll(c=>c.rarity == 4)[new Random().Next(ResourceManager.characterTable.Values.ToList().FindAll(c => c.rarity == 4).Count - 1)].charId);
}
}
ScGachaSyncPullResult result = new ScGachaSyncPullResult()
{
GachaPoolId=req.GachaPoolId,
GachaType=req.GachaType,
OriResultIds =
{
},
Star5GotCount= fivestarcount,
Star6GotCount= sixstarcount,
FinalResults =
{
},
UpGotCount= fivestarcount+ sixstarcount,
};
foreach(string ch in chars)
{
bool exist = session.chars.Find(c => c.id == ch) != null;
result.OriResultIds.Add(ch);
result.FinalResults.Add(new ScdGachaFinalResult()
{
IsNew= !exist,
ItemId=ch,
});
}
//session.Send(Packet.EncodePacket((int)CsMessageId.CsGachaTenPullReq, req));
session.Send(ScMessageId.ScGachaSyncPullResult, result); */
// session.Send(CsMessageId.CsGachaEnd, new Empty());
// session.Send(ScMessageId.ScGachaBegin, new Empty());
}
}
}

View File

@ -0,0 +1,19 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
namespace Campofinale.Packets.Cs
{
public class HandleCsGetMail
{
[Server.Handler(CsMsgId.CsGetMail)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsGetMail req = packet.DecodeBody<CsGetMail>();
session.Send(new PacketScGetMail(session));
}
}
}

View File

@ -0,0 +1,28 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsLeaveDungeon
{
[Server.Handler(CsMsgId.CsLeaveDungeon)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsLeaveDungeon req = packet.DecodeBody<CsLeaveDungeon>();
session.LeaveDungeon(req);
}
}
}

View File

@ -0,0 +1,269 @@
using BeyondTools.VFS.Crypto;
using Campofinale.Database;
using Campofinale.Game;
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
using System.Security.Cryptography;
using static Campofinale.Resource.ResourceManager;
using System.Reflection;
namespace Campofinale.Packets.Cs
{
public class HandleCsLogin
{
[Server.Handler(CsMsgId.CsCreateRole)]
public static void HandleCsCreateRole(Player session, CsMsgId cmdId, Packet packet)
{
CsCreateRole req = packet.DecodeBody<CsCreateRole>();
}
[Server.Handler(CsMsgId.CsLogin)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsLogin req = packet.DecodeBody<CsLogin>();
if(Server.clients.Count > Server.config.serverOptions.maxPlayers)
{
session.Send(ScMsgId.ScNtfErrorCode, new ScNtfErrorCode()
{
Details = "Server Full",
ErrorCode = (int)CODE.ErrCommonServerOverload,
});
session.Disconnect();
return;
}
Account account = DatabaseManager.db.GetAccountByTokenGrant(req.Token);
ScLogin rsp = new()
{
IsEnc = false,
Uid = req.Uid,
IsFirstLogin = false,
IsReconnect=false,
LastRecvUpSeqid = packet.csHead.UpSeqid,
};
byte[] encKey = GenerateRandomBytes(32);
string serverPublicKeyPem = req.ClientPublicKey.ToStringUtf8();
byte[] serverPublicKey = ConvertPemToBytes(serverPublicKeyPem);
byte[] encryptedEncKey = EncryptWithRsa(encKey, serverPublicKey);
byte[] serverEncrypNonce = GenerateRandomBytes(12);
// rsp.ServerEncrypNonce = ByteString.CopyFrom(serverEncrypNonce);
// rsp.ServerPublicKey = ByteString.CopyFrom(encryptedEncKey);
CSChaCha20 cipher = new CSChaCha20(encKey, serverEncrypNonce, 1);
if (req.ClientVersion == GameConstants.GAME_VERSION)
{
if (account == null)
{
session.Send(ScMsgId.ScNtfErrorCode, new ScNtfErrorCode()
{
Details = "Account error",
ErrorCode = (int)CODE.ErrLoginProcessLogin,
});
session.Disconnect();
return;
}
session.Load(account.id);
rsp.Uid = ""+session.accountId;
session.Send(ScMsgId.ScLogin, rsp);
}
else
{
session.Send(ScMsgId.ScNtfErrorCode, new ScNtfErrorCode()
{
Details="Unsupported client version",
ErrorCode= (int)CODE.ErrCommonClientVersionNotEqual
});
session.Disconnect();
return;
}
session.Send(new PacketScSyncBaseData(session));
ScItemBagCommonSync common = new()
{
LostAndFound = new()
{
InstList =
{
new ScdItemGrid()
{
GridIndex=0,
Count=1,
Id="item_port_power_pole_2",
Inst = new()
{
InstId=300000000000,
},
}
}
},
};
session.Send(ScMsgId.ScItemBagCommonSync, common);
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.Weapon));
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.WeaponGem));
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.Equip));
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.CommercialItem));
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.Factory));
session.Send(new PacketScItemBagScopeSync(session, ItemValuableDepotType.SpecialItem));
session.Send(new PacketScSyncAllMail(session));
session.Send(new PacketScSceneCollectionSync(session));
/*ScSyncAllMission missions = new()
{
Missions =
{
{"e0m0",
new Mission()
{
MissionId="e0m0",
MissionState=(int)MissionState.Processing,
Properties =
{
{1,new DynamicParameter()
{
ValueType=1,
RealType=1,
ValueBoolList =
{
true
}
}
},
{2,new DynamicParameter()
{
ValueType=1,
RealType=1,
ValueBoolList =
{
false
}
}
},
{3,new DynamicParameter()
{
ValueType=1,
RealType=1,
ValueBoolList =
{
false
}
}
}
}
}
}
},
TrackMissionId= "e0m0",
CurQuests =
{
{"e0m0#1", new Quest(){
QuestId="e0m0#1",
QuestState=2,
QuestObjectives =
{
}
}}
}
};*/
//session.Send(ScMessageId.ScSyncAllMission, missions);
string json1 = File.ReadAllText("44_ScSyncAllMission.json");
ScSyncAllMission m = Newtonsoft.Json.JsonConvert.DeserializeObject<ScSyncAllMission>(json1);
m.TrackMissionId = "";
session.Send(ScMsgId.ScSyncAllMission, m);
session.Send(new PacketScGachaSync(session));
ScSettlementSyncAll settlements = new ScSettlementSyncAll()
{
LastTickTime = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
};
int stid = 3;
foreach (var item in settlementBasicDataTable)
{
settlements.Settlements.Add(new Settlement()
{
Level = 1,
SettlementId = item.Value.settlementId,
RequireId = "item_plant_grass_powder_2",
Exp = 1,
Reports =
{
},
UnlockTs = DateTime.UtcNow.AddHours(1).ToUnixTimestampMilliseconds(),
AutoSubmit = false,
LastManualSubmitTime = DateTime.UtcNow.ToUnixTimestampMilliseconds(),
OfficerCharTemplateId = characterTable.Values.ToList()[stid].charId,
});
stid++;
}
session.Send(ScMsgId.ScSettlementSyncAll, settlements);
session.Send(new PacketScSyncAllRoleScene(session));
session.Send(new PacketScGameMechanicsSync(session));
session.Send(new PacketScSyncAllBloc(session));
session.Send(new PacketScSyncWallet(session));
session.Send(new PacketScSyncAllGameVar(session));
session.Send(new PacketScSyncAllUnlock(session));
session.Send(new PacketScSyncAllBitset(session));
session.Send(new PacketScSyncAllMiniGame(session));
string json = File.ReadAllText("93_ScSceneMapMarkSync.json");
ScSceneMapMarkSync chapter = Newtonsoft.Json.JsonConvert.DeserializeObject<ScSceneMapMarkSync>(json);
session.Send(ScMsgId.ScSceneMapMarkSync, chapter);
session.Send(new PacketScAdventureBookSync(session));
session.Send(new PacketScAdventureSyncAll(session));
session.Send(new PacketScFactorySync(session));
session.Send(new PacketScFactorySyncScope(session));
session.Send(new PacketScFactorySyncChapter(session, "domain_1"));
session.Send(new PacketScFactorySyncChapter(session, "domain_2"));
session.Send(new PacketScSyncCharBagInfo(session));
session.Send(new PacketScSyncAllDialog(session));
session.Send(new PacketScSpaceshipSync(session));
session.Send(new PacketScSyncFullDungeonStatus(session));
session.Send(new PacketScActivitySync(session));
session.Send(ScMsgId.ScSyncFullDataEnd, new ScSyncFullDataEnd());
session.EnterScene();
session.Initialized = true;
session.Update();
}
static byte[] GenerateRandomBytes(int length)
{
using var rng = new RNGCryptoServiceProvider();
byte[] bytes = new byte[length];
rng.GetBytes(bytes);
return bytes;
}
static byte[] ConvertPemToBytes(string pem)
{
string base64Key = pem
.Replace("-----BEGIN PUBLIC KEY-----", "")
.Replace("-----END PUBLIC KEY-----", "")
.Replace("\n", "")
.Replace("\r", "");
return Convert.FromBase64String(base64Key);
}
// Crittografare con RSA (PKCS#1)
static byte[] EncryptWithRsa(byte[] data, byte[] publicKeyBytes)
{
var rsa = RSA.Create();
rsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _);
return rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
}
}
}

View File

@ -0,0 +1,60 @@
using Campofinale.Network;
using Campofinale.Protocol;
using Google.Protobuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Campofinale.Packets.Cs
{
public class HandleCsMergeMsg
{
[Server.Handler(CsMsgId.CsMergeMsg)]
public static void Handle(Player session, CsMsgId cmdId, Packet p)
{
CsMergeMsg req = p.DecodeBody<CsMergeMsg>();
byte[] allBytes = req.Msg.ToByteArray();
while (allBytes.Length > 3) {
byte headLength = Packet.GetByte(allBytes, 0);
ushort bodyLength = Packet.GetUInt16(allBytes, 1);
byte[] head = allBytes.AsSpan().Slice(3, headLength).ToArray();
byte[] body = allBytes.AsSpan().Slice(3+ headLength, bodyLength).ToArray();
Packet packet = new()
{
finishedBody = body,
csHead = CSHead.Parser.ParseFrom(head),
cmdId = CSHead.Parser.ParseFrom(head).Msgid,
};
if (Server.config.logOptions.packets)
{
Logger.Print("CmdId: " + (CsMsgId)packet.csHead.Msgid);
Logger.Print(BitConverter.ToString(packet.finishedBody).Replace("-", string.Empty).ToLower());
}
try
{
NotifyManager.Notify(session, (CsMsgId)packet.cmdId, packet);
}
catch (Exception e)
{
Logger.PrintError("Error while notify packet: " + e.Message);
}
allBytes = allBytes.AsSpan().Slice(3 + headLength + bodyLength).ToArray();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More