109 Commits

Author SHA1 Message Date
Kirill e94093ac17 Add Android production release and testing builds workflows
Testing builds / test-and-build (push) Successful in 2m36s
2026-10-02 00:07:34 +03:00
Kirill c4e7302567 Add new tests and implement frame budget management
- Introduced `civilization_benchmark.gd` and `legacy_quantity_math.gd` for benchmarking and legacy quantity calculations.
- Created `test_dynamic_math.gd`, `test_frame_evolution.gd`, and `test_sparse_batches.gd` to validate mathematical operations and frame evolution logic.
- Implemented `frame_budget.gd` to manage cooperative work on the main thread, ensuring no partially calculated state is published.
- Added UID files for all new scripts to maintain unique identifiers.
2026-10-01 23:43:34 +03:00
Kirill f51eea6c0f Enhance simulation performance and accuracy by optimizing physical amount calculations and refining arithmetic operations 2026-10-01 20:30:53 +03:00
Kirill befb377774 Add new music tracks to the sound directory
- Added cosmic_unicorns.ogg
- Added funky_eldritch.ogg
- Added meditative_beings.ogg
- Added owniverse_main_theme.ogg

These tracks enhance the audio experience of the project.
2026-10-01 07:48:52 +03:00
Kirill fad862d618 Add benchmark for saved state performance
- Introduced `benchmark_saved_state.gd` to evaluate the performance of the saved state restoration process.
- Implemented JSON integer restoration to handle large integers accurately.
- Added command-line argument parsing for specifying the path to the diagnostic JSON file and optional delta seconds.
- Conducted performance tests at different speeds and logged the elapsed time for six consecutive steps.
- Created a new UID file for the benchmark script.
2026-09-30 22:46:26 +03:00
Kirill fb8a3f5658 Add exact arithmetic implementation and tests
- Introduced exact arithmetic with support for large integers and fractions in `exact.gd`, `big_integer.gd`, and `exact_value.gd`.
- Implemented a comprehensive test suite in `test_exact_math.gd` to validate arithmetic operations against expected results.
- Added a README in `math` directory to document the exact arithmetic system and its usage.
- Ensured that all arithmetic operations maintain precision without floating-point errors, using a custom representation for large numbers.
- Included methods for encoding and decoding exact values for serialization.
2026-09-30 08:08:27 +03:00
Kirill f2111a376a Add core simulation modules for owniverse mechanics
- Introduced `life_evolution.gd` to manage life evolution processes.
- Implemented `manual_production.gd` for handling production mechanics, including resource management and production steps.
- Created `object_batches.gd` to manage batches of objects, including scaling and appending batches.
- Developed `object_ledger.gd` for tracking physical amounts, available resources, and binding ownerships.
- Added `simulation_module.gd` as a base class for simulation modules, providing a weak reference to the world.
- Established `stellar_rules.gd` for managing stellar evolution and destruction mechanics.
- Introduced `universe_environment.gd` to calculate environmental parameters based on the current state of the universe.
2026-09-29 20:23:20 +03:00
Kirill da03ba11c0 Refactor Owniverse modules for quantity mathematics and entity catalog
- Introduced `quantity_math.gd` for arithmetic operations including allocation, normalization, and accumulation of quantities without scene tree dependencies.
- Created `entity_catalog.gd` to manage entity definitions, groups, and event indexes, ensuring separation from simulation state and UI.
- Implemented `item_presentation.gd` for read-only projections of simulation state, handling amounts and unlock conditions for UI elements.
- Updated `civilization_evolution.gd` and `civilization_state.gd` to utilize new quantity math functions, improving code clarity and maintainability.
- Enhanced tests in `test_quantity_catalog.gd` to validate new functionality and ensure correctness of mathematical operations.
- Revised documentation to reflect changes in module structure and functionality.
2026-09-29 19:55:20 +03:00
Kirill c2313e9163 Enhance item visibility logic and update initial energy parameter; add tests for life icon functionality 2026-09-28 22:56:40 +03:00
Kirill 2f0a3ee8d4 Warming border added 2026-09-28 22:32:52 +03:00
Kirill 15ee7833ed Add world indicators and parameters to enhance universe simulation
- new universe creation function.
2026-09-28 22:19:13 +03:00
Kirill e79f3fa362 Fix highlight visibility toggle and enhance color modulation logic 2026-09-22 23:54:13 +03:00
Kirill e87d4083e9 Refactor code structure for improved readability and maintainability 2026-09-22 23:47:59 +03:00
Kirill 5a18b41528 Refactor code structure for improved readability and maintainability 2026-09-22 23:10:09 +03:00
Kirill d6fd40969f Implement short-lived stellar event handling and optimize batch processing; add tests for new functionality 2026-09-22 22:50:54 +03:00
Kirill a3d24114a1 Add screen management to top menu and update button functionality; replace close button with back button 2026-09-21 22:32:56 +03:00
Kirill 8867da569a Refactor code structure and remove redundant sections for improved readability and maintainability 2026-09-21 21:46:43 +03:00
Kirill 1796829338 Update speed limit, enable embedded PCK format, and enhance brown dwarf production logic 2026-09-21 20:42:40 +03:00
Kirill f246efd6ad Add unit tests for action value formatting and distribution
- Implemented a new test script `test_action_values.gd` to verify the precision of fractional action amounts and the distinctiveness of adjacent values.
- Added checks to ensure that action values are correctly formatted and that the distribution of actions preserves distinct requests.
- Included validation for rendered button labels to confirm they are distinguishable.
2026-09-20 23:55:38 +03:00
Kirill f25b77b605 Implement asynchronous save manager with UI update optimizations and add tests for save functionality 2026-09-20 22:14:47 +03:00
Kirill a09e3df220 Refactor save manager validation and update state structure
- Updated the save manager to enforce a new format version (2) and improved validation checks for the save data structure.
- Enhanced the `validate_data` function to ensure all required fields are present and valid.
- Adjusted the handling of legacy saves and introduced new checks for various state fields.
- Improved number formatting in the global script for better readability of large numbers.
- Updated tests to reflect changes in the save manager and validation logic, ensuring compatibility with the new state structure.
- Added new tests for group indexing and production transactions to ensure correctness of entity management and resource production.
2026-09-20 20:56:15 +03:00
Kirill 26347fca30 Add comprehensive civilization evolution tests and enhance civilization state management
- Introduced a new test script for civilization evolution (`test_civilization_evolution.gd`) to validate the evolution mechanics, including population dynamics, ethical transitions, and war impacts.
- Updated `README.md` to include instructions for running the new civilization evolution tests.
- Modified `test_civilization_state.gd` to accommodate changes in civilization rules and ensure proper validation of ethical stages.
- Enhanced `test_descriptions.gd` to check for accurate population counters and state validation.
- Adjusted `test_life.gd` to reflect updates in life version management.
- Improved `civilization_state.gd` to include habitat budget calculations and transition management.
- Added `civilization_evolution.gd` to handle the logic for civilization evolution, including population drift, warfare, and colonization mechanics.
- Updated `owniverse.gd` and `owniverse_entity.gd` to integrate new evolution logic and ensure proper initialization of entities.
2026-09-16 19:54:47 +03:00
Kirill 5ea65a7e9b Update export presets, project version, and enhance civilization simulation rules
- Updated export path and version code in export_presets.cfg
- Changed project version in project.godot to 0.7.0
- Expanded simulation rules in simulation_rules.md to clarify resource management
- Improved testing framework in tests/README.md to include new civilization budget checks
- Added new tests for batch boundaries and civilization state transitions
- Enhanced civilization_state.gd with shared budget and transition logic
- Refactored owniverse.gd to enforce capacity during life batch initialization
2026-09-16 07:58:19 +03:00
Kirill 5f3875bc14 Add life rules and implement tests for civilization and life states
- Introduced a new file `life_rules.txt` to define life progression and degradation rules.
- Created `test_civilization_state.gd` to validate the functionality of civilization rules and ethics.
- Added `test_life.gd` to test life evolution, including initialization, batch processing, and state validation.
- Implemented `civilization_state.gd` to manage civilization ethics and space civilization detachment logic.
- Ensured all tests check for expected outcomes and validate state integrity after operations.
2026-09-15 23:05:05 +03:00
Kirill cc2700d507 Add item description and testing framework for Owniverse
- Introduced `item_description.gd` to handle item descriptions with localization support.
- Implemented a testing script `test_descriptions.gd` to validate item description rendering and localization.
- Added a new template file for Russian localization.
- Included a large package file `owniverse.0.6.29-145.pck` for game assets.
- Ensured proper memory management in tests with fixture and dispose functions.
2026-09-15 22:01:45 +03:00
Kirill 5f5cc6f894 Implement gradual evolution mechanics and simulation time handling in Owniverse.GI
- Added `blastability` property to entities for vulnerability tracking.
- Enhanced planet string parsing with validation and error handling.
- Introduced `simulation_rules.md` to document evolution mechanics and rules.
- Created tests for time progression and stellar evolution rules, ensuring correct handling of fractional years and resource production.
- Implemented `simulation_time.gd` for managing accumulated time and year processing.
- Updated tests to validate legacy save compatibility and migration to new time schema.
2026-09-15 08:27:04 +03:00
Kirill 7de65f6145 Refactor workflow and configuration files; enhance Android build process with import options, update .gitignore for entity imports, correct entity file names, and add missing import files for localization and entities. 2026-09-15 07:30:01 +03:00
Kirill 85a13eb241 Refactor save management; update validation logic in save_manager.gd and enhance action handling in actions.gd for improved data integrity and user experience 2026-09-14 07:47:21 +03:00
Kirill dea744bc30 Refactor save management; enhance save_data function with verification and plaintext copy options, and update load_data logic for improved error handling 2026-09-13 22:57:25 +03:00
Kirill c22b21a537 Refactor global.gd to update SPEED_LIMIT constant from 4 to 5
Enhance stage.gd debug output in _on_topmenu_button_pressed function for better state tracking; comment out unnecessary print statements.

Update owniverse.gd to introduce new state properties: batch_origins, distribution, and auto_resources; refactor evolute function for improved state management and batch processing.

Revise state.gd to clean up debug print statements in add function for better readability and maintainability.
2026-09-13 21:09:42 +03:00
Kirill b44f92aacf Refactor state structure; encapsulate datetime and year within a time dictionary and update related logic 2026-09-11 09:31:37 +03:00
Kirill 0162084e53 Refactor state management; update unlock logic and enhance signal bindings in scene 2026-09-01 23:53:05 +03:00
Kirill 2f4b6a98d8 Refactor production logic to use state amounts; update calculate_max_producible function to accept default desired amount 2026-09-01 21:29:07 +03:00
Kirill d90f8693c9 Update Godot core rules to version 4.7; refactor production logic and add entity batch processing 2026-08-31 23:51:07 +03:00
Kirill e870c96879 Add 'binds' key to state dictionary for enhanced state management 2026-08-30 22:31:24 +03:00
Kirill e531e7d9b6 Refactor item management and unlock logic; remove unused item update list and signal 2026-08-28 00:07:18 +03:00
Kirill 57cc023558 Implement item unlocking mechanism and refactor save functionality; update scene timer node 2026-08-27 23:04:56 +03:00
Kirill 23929e3651 Refactor owniverse state management; replace evolution class with state handling and update cycle logic 2026-08-25 00:26:31 +03:00
Kirill 829aadca2d Update version to 0.6.27 and increment version code to 143; refactor resource paths in scene files
Android / android (push) Successful in 30s
2026-08-20 22:58:24 +03:00
Kirill 30486616f8 Update version to 0.6.26 and increment version code to 142
Android / android (push) Successful in 30s
2026-08-20 22:55:01 +03:00
Kirill d9a2679af4 Replace pressed burger button image and update resource path in world.tscn 2026-08-20 22:54:42 +03:00
Kirill 4f57c37572 Update version to 0.6.25 and increment version code to 141; replace burger button image
Android / android (push) Successful in 30s
2026-08-20 22:45:22 +03:00
Kirill e4a0dd2d13 Add new spirituality trend indicator image
Android / android (push) Successful in 30s
2026-08-20 22:29:11 +03:00
Kirill 0a10cff0fa Refactor code structure for improved readability and maintainability 2026-08-20 22:28:03 +03:00
Kirill e4cf5bdad0 Add new button images for time adjustment in the top menu 2026-08-20 22:27:36 +03:00
Kirill 645751cd23 Add new button images for time adjustment in the top menu 2026-08-20 22:26:57 +03:00
Kirill b92a49821d Update version to 0.6.23 and increment version code to 139; add unique IDs to UI nodes
Android / android (push) Successful in 31s
2026-08-20 22:19:19 +03:00
Kirill 3a91528e95 Bump version to 0.6.22 and increment version code to 138
Android / android (push) Successful in 30s
2026-08-20 22:11:09 +03:00
Kirill 3c37be2a8e Add new PNG assets for time and speed UI components 2026-08-20 22:10:40 +03:00
Kirill 544b5f4f56 Add new time speed icons for UI 2026-08-20 22:10:22 +03:00
Kirill cc9de54d42 Bump version to 0.6.21 and increment version code to 137
Android / android (push) Successful in 31s
2026-08-20 21:55:23 +03:00
Kirill e76414ce17 Refactor code structure for improved readability and maintainability 2026-08-20 21:54:45 +03:00
Kirill 68c2b4f25d Refactor code structure for improved readability and maintainability 2026-08-20 21:54:32 +03:00
Kirill 78946f1bb4 Bump version to 0.6.20 and increment version code to 136
Android / android (push) Successful in 32s
2026-08-20 21:41:23 +03:00
Kirill 0d1671fe8f Update project icon reference in configuration file 2026-08-20 21:40:48 +03:00
Kirill ea35017aa0 Bump version to 0.6.19 and increment version code to 135
Android / android (push) Successful in 29s
2026-08-20 21:20:08 +03:00
Kirill 0db24fec60 Refactor background and starry sky layer scripts; move to new directory structure 2026-08-20 21:19:47 +03:00
Kirill b2a18c9c41 Refactor code structure for improved readability and maintainability 2026-08-20 21:19:30 +03:00
Kirill 16ec80929c Bump version to 0.6.18 and increment version code to 134; update Android workflow configuration
Android / android (push) Successful in 31s
2026-08-20 21:11:46 +03:00
Kirill 3536e25d52 Update version to 0.6.17 and increment version code to 133; enhance Android build workflow
Android / android (push) Successful in 27s
2026-08-20 21:05:22 +03:00
Kirill 935d249183 Bump version to 0.6.16 and update version code to 132
Android / android (push) Successful in 22s
2026-08-20 20:25:12 +03:00
Kirill 8cb01d77de Refactor Android build workflow to separate preparation and build steps 2026-08-20 20:24:30 +03:00
Kirill a446b7cb41 Update Global autoload reference in project configuration 2026-08-20 20:19:01 +03:00
Kirill 82681d27e1 Bump version to 0.6.15 and update version code to 131
Android / android (push) Failing after 17s
2026-08-20 20:11:39 +03:00
Kirill 777ec2907b Add new PNG assets for time and speed UI components 2026-08-20 20:09:14 +03:00
Kirill 8513bf0313 Add new PNG images for time and speed menu 2026-08-20 20:03:18 +03:00
Kirill a4019ed98c Add global.gd script with localization and CSV reading functionality 2026-08-20 19:55:20 +03:00
Kirill 4731489015 Refactor global scripts: remove Global.gd, add globals.gd with enhanced functionality 2026-08-20 19:54:50 +03:00
Kirill 711ace6678 Refactor autoload structure by moving Global and SaveManager scripts to the autoload directory 2026-08-20 19:53:49 +03:00
Kirill 89342dc614 Add Global and SaveManager scripts with localization and save/load functionality 2026-08-20 19:53:32 +03:00
Kirill 2459d15fc0 Bump version code to 130 and update version name to 0.6.14 in project configuration
Android / android (push) Successful in 18s
2026-08-20 19:43:43 +03:00
Kirill 3552a5e51d Update CI workflow to trigger on version tags and streamline APK upload process 2026-08-20 19:39:55 +03:00
Kirill 38b05eb4ef Remove redundant debug and check steps from CI workflow
Android / android (push) Successful in 25s
2026-08-19 23:09:53 +03:00
Kirill 735ab3774d Downgrade upload-artifact action version from v4 to v3 in CI workflow
Android / android (push) Successful in 50s
2026-08-19 23:04:17 +03:00
Kirill 43aaa6e28f Reorder APK upload step in CI workflow for clarity
Android / android (push) Failing after 29s
2026-08-19 23:02:21 +03:00
Kirill 544f5c466e Remove file type check for APK in CI workflow
Android / android (push) Successful in 26s
2026-08-19 22:49:18 +03:00
Kirill 0b80d2cdf6 Remove APK upload step from CI workflow and add APK check
Android / android (push) Failing after 27s
2026-08-19 22:47:52 +03:00
Kirill b82fe0f3d7 Disable package signing in export presets configuration
Android / android (push) Failing after 30s
2026-08-19 22:44:56 +03:00
Kirill 860168e4eb Fix resource IDs in owniverse_item.tscn for script and texture references
Android / android (push) Failing after 18s
2026-08-19 22:42:04 +03:00
Kirill 84c29ed064 Add Global.gd.uid file with unique identifier
Android / android (push) Failing after 18s
2026-08-19 22:36:02 +03:00
Kirill 14e4450679 Disable runnable option for Android export preset and remove ADB version check from CI workflow
Android / android (push) Failing after 18s
2026-08-19 22:26:44 +03:00
Kirill 15a4a2e953 Enhance Android CI workflow with verbose export and build checks
Android / android (push) Failing after 19s
2026-08-19 22:16:05 +03:00
Kirill 201284f3c2 Fix Android CI export
Android / android (push) Failing after 18s
2026-08-19 22:13:06 +03:00
Kirill 708740d757 Disable Gradle build for Android CI
Android / android (push) Failing after 14s
2026-08-19 22:11:43 +03:00
Kirill f82ccbedd9 Add Godot export check step to Android CI workflow
Android / android (push) Failing after 13s
2026-08-19 22:07:51 +03:00
Kirill 0db2fa0f96 yaml
Android / android (push) Failing after 14s
2026-08-19 22:04:32 +03:00
K 41de04c2e2 Update .gitea/workflows/android.yml
Android / android (push) Failing after 16s
2026-08-19 17:23:58 +00:00
K 5bb566351d Merge pull request 'Feature/evolution' (#1) from feature/evolution into main
Android / android (push) Failing after 39s
Reviewed-on: #1
2026-08-19 16:20:56 +00:00
Kirill 88bcf77aa9 Add Android CI 2026-08-19 19:18:39 +03:00
Kirill 4de9027d1e Refactor: improve code formatting and consistency in evolution logic 2026-08-18 22:37:38 +03:00
Kirill 044d193f8d Refactor: clean up unused code and improve variable initialization in evolution and entity management 2026-08-17 08:12:43 +03:00
Kirill d9cae38a11 Enhance production logic: add auto-producing entities and implement production calculations 2026-08-02 23:55:58 +03:00
Kirill 9d917e95ab evolution 2026-08-02 22:57:58 +03:00
Kirill 8e565e5ac0 evolution 2026-08-02 22:56:54 +03:00
Kirill 6d846ec813 Add initial implementation of StateMachine and Inventory system with SignalBus integration 2026-07-30 22:06:18 +03:00
Kirill d8a4019ce1 Refactor: restructure world entities and evolution logic; remove unused files and improve batch processing 2026-07-21 23:54:17 +03:00
Kirill f4524a7acc Refactor: update SPEED_LIMIT type, comment out signal, and enhance evolution logic 2026-07-20 00:11:44 +03:00
Kirill a81359c1e6 Refactor code structure for improved readability and maintainability 2026-07-19 15:41:44 +03:00
Kirill 2a64274322 refactor(world): optimize visuals and item definitions
Add new high-res textures for planetary systems, remove placeholder graphics and update scene tree structure in 'world.tscn
2026-07-18 15:53:31 +03:00
Kirill 5820bbc7b2 Refactor save/load functionality; improve error messages and add save data timer 2026-07-10 20:36:44 +03:00
Kirill 45cfc8c8ee Save load functionality.
Fix export path in export_presets.cfg and refactor variable names for clarity in owniverse.gd
2026-07-05 12:23:33 +03:00
Kirill b41ccdb659 page fix 2026-06-24 23:25:55 +03:00
Kirill 2d2979a1cf Refactor formatting functions and improve item production logic; update UI components for better layout and usability 2026-06-21 17:27:31 +03:00
Kirill 934d890887 Add action buttons and related functionality; refactor production logic and update entity definitions 2026-06-03 23:26:44 +03:00
Kirill c21048add3 Refactor code structure for improved readability and maintainability 2026-05-31 10:57:44 +03:00
Kirill edb5ec9dfa Refactor code structure for improved readability and maintainability 2026-05-26 23:21:44 +03:00
Kirill 3bab036cc4 Add .kilo/agent-manager.json to .gitignore for MacOS specific ignores 2026-05-17 12:24:52 +03:00
Kirill df563bf1b1 Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized existing functions. 2026-05-05 23:49:12 +03:00
Kirill fc86261a9d Add new entity and item definitions, refactor related code
- Introduced new CSV files for entities and items, defining various properties and characteristics.
- Refactored the stage.gd script to handle item selection and descriptions instead of entities.
- Updated item button script to reflect changes in item properties and signals.
- Created a new entity.gd script to define the OwniverseEntity class with initialization and parsing methods.
- Modified owniverse.gd to initialize entities from the new definitions.
- Adjusted versioning in export presets and project files to reflect recent changes.
2026-04-08 00:23:22 +03:00
485 changed files with 13896 additions and 3119 deletions
+5
View File
@@ -0,0 +1,5 @@
.godot/
export/
*.tscn
*.import
addons/
+19
View File
@@ -0,0 +1,19 @@
---
name: Godot 4.7 Core Rules
priority: high
---
Ты — senior Godot 4.7 GDScript разработчик.
- Use Godot 4.7+ API.
- Do not use Godot 3.x syntax or APIs.
- Follow the existing project architecture and coding style.
- Do not introduce unnecessary abstractions.
- Do not modify unrelated files.
- Пиши строго типизированный код (`var health: int = 100`, `: Array[Node]` и т.д.).
- Предпочитай Signals вместо проверки в _process.
- Используй @export, @export_range, @export_enum, @onready.
- Composition over deep inheritance.
- Менеджеры и автолоады выноси в отдельные singleton'ы.
+9
View File
@@ -0,0 +1,9 @@
---
name: Project Architecture
---
В этом проекте используется следующая архитектура:
- StateMachine на основе Node + signals
- Inventory использует ItemStack и SignalBus
- Все данные сохраняются через SaveManager (autoload)
- UI строится через Control + custom themes
+1
View File
@@ -0,0 +1 @@
- use spaces not tabs for indentation
+107
View File
@@ -0,0 +1,107 @@
name: Android production release
on:
push:
tags:
- "v*"
jobs:
test-build-publish:
runs-on: godot
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
lfs: true
- name: Verify tag belongs to main
run: |
git fetch origin main
git merge-base --is-ancestor "${GITHUB_SHA}" origin/main
- name: Show Godot version
run: godot --version
- name: Import project
run: |
rm -rf .godot
godot --headless --path . --editor --import --quit --verbose
- name: Run all tests
shell: bash
run: |
set -euo pipefail
mapfile -t tests < <(find tests -maxdepth 1 -type f -name 'test_*.gd' | sort)
test "${#tests[@]}" -gt 0
for test_file in "${tests[@]}"; do
echo "::group::${test_file}"
godot --headless --path . --script "res://${test_file}"
echo "::endgroup::"
done
- name: Prepare Android signing
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
test -n "${ANDROID_KEYSTORE_BASE64}"
printf '%s' "${ANDROID_KEYSTORE_BASE64}" | base64 --decode > "${RUNNER_TEMP}/release.keystore"
test -s "${RUNNER_TEMP}/release.keystore"
- name: Configure release AAB
env:
RELEASE_VERSION: ${{ github.ref_name }}
RELEASE_VERSION_CODE: ${{ github.run_number }}
run: |
python3 - <<'PY'
import os
import re
from pathlib import Path
path = Path("export_presets.cfg")
text = path.read_text()
start = text.index('[preset.1.options]')
head, android = text[:start], text[start:]
replacements = (
(r'gradle_build/use_gradle_build=false', 'gradle_build/use_gradle_build=true'),
(r'gradle_build/export_format=0', 'gradle_build/export_format=1'),
(r'package/signed=false', 'package/signed=true'),
(r'version/code=\d+', f'version/code={100000 + int(os.environ["RELEASE_VERSION_CODE"])}'),
(r'version/name="[^"]*"', f'version/name="{os.environ["RELEASE_VERSION"].removeprefix("v")}"'),
)
for pattern, replacement in replacements:
android, count = re.subn(pattern, replacement, android, count=1)
if count != 1:
raise RuntimeError(f'Expected one Android preset match for {pattern!r}, got {count}')
path.write_text(head + android)
PY
- name: Build signed Android App Bundle
env:
GODOT_ANDROID_KEYSTORE_RELEASE_USER: ${{ secrets.ANDROID_KEYSTORE_ALIAS }}
GODOT_ANDROID_KEYSTORE_RELEASE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
run: |
export GODOT_ANDROID_KEYSTORE_RELEASE_PATH="${RUNNER_TEMP}/release.keystore"
mkdir -p build
godot --headless --path . --export-release "Android" build/owniverse-${GITHUB_REF_NAME}.aab
test -s "build/owniverse-${GITHUB_REF_NAME}.aab"
ls -lh "build/owniverse-${GITHUB_REF_NAME}.aab"
- name: Publish to Google Play production
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.KIDGameProduction.Owniverse
releaseFiles: build/owniverse-${{ github.ref_name }}.aab
tracks: production
status: completed
- name: Upload release bundle
uses: actions/upload-artifact@v3
with:
name: owniverse-${{ github.ref_name }}-aab
path: build/owniverse-${{ github.ref_name }}.aab
if-no-files-found: error
retention-days: 90
+62
View File
@@ -0,0 +1,62 @@
name: Testing builds
on:
push:
branches:
- testing
jobs:
test-and-build:
runs-on: godot
steps:
- name: Checkout
uses: actions/checkout@v4
with:
lfs: true
- name: Show Godot version
run: godot --version
- name: Import project
run: |
rm -rf .godot
godot --headless --path . --editor --import --quit --verbose
- name: Run all tests
shell: bash
run: |
set -euo pipefail
mapfile -t tests < <(find tests -maxdepth 1 -type f -name 'test_*.gd' | sort)
test "${#tests[@]}" -gt 0
for test_file in "${tests[@]}"; do
echo "::group::${test_file}"
godot --headless --path . --script "res://${test_file}"
echo "::endgroup::"
done
- name: Build Android APK
run: |
mkdir -p build
godot --headless --path . --export-release "Android" build/owniverse-testing.apk
- name: Build Windows EXE
run: |
godot --headless --path . --export-release "Windows Desktop" build/owniverse-testing.exe
- name: Verify builds
run: |
test -s build/owniverse-testing.apk
test -s build/owniverse-testing.exe
ls -lh build/owniverse-testing.apk build/owniverse-testing.exe
- name: Upload testing builds
uses: actions/upload-artifact@v3
with:
name: owniverse-testing-${{ github.sha }}
path: |
build/owniverse-testing.apk
build/owniverse-testing.exe
if-no-files-found: error
retention-days: 14
+3
View File
@@ -3,6 +3,9 @@
.vscode/ .vscode/
/android/ /android/
*.import *.import
!data/*.txt.import
# MacOS specific ignores # MacOS specific ignores
.DS_Store .DS_Store
.kilo/agent-manager.json
.kilo/kilo.jsonc
-100
View File
@@ -1,100 +0,0 @@
extends Node
const SPEED_LIMIT = 4
var Settings: Dictionary = {
"filename": "save-0001",
"sound_volume": 1.0,
"language": "en",
}
# TODO getter setter for locale
var Owniverse: Dictionary = {
"datetime": {},
"sector": "",
"location": "",
"charsheet": {},
"fleet": {},
"inventory": {},
}
var Locales: Dictionary = {}
var Locale = "en"
var Entities: Dictionary = {}
var Templates: Dictionary = {}
func get_localized_item_description(entity_id: String, item: String) -> String:
if Locales[Locale].has(entity_id):
return Locales[Locale][entity_id][item]
return ""
func get_description(item_id: String, values: Array = []) -> String:
if !Templates[Locale].has(item_id):
return ""
#print(Templates[Locale])
var description: String = Templates[Locale][item_id]["text"]
var value = 0
for item in values:
description.replace("value"+str(value), str(item))
return description
func _ready() -> void:
Entities = _read_from_csv("res://Autoload/entities.csv")
Locales["en"] = _read_from_csv("res://Autoload/locale.en.csv")
Locales["ru"] = _read_from_csv("res://Autoload/locale.ru.csv")
Templates["en"] = _read_from_csv("res://Autoload/templates.en.csv")
func _read_from_csv(file_path: String) -> Dictionary:
if not FileAccess.file_exists(file_path):
printerr("File not found: " + file_path)
return {}
var file = FileAccess.open(file_path, FileAccess.READ)
if file == null:
printerr("File can not be opened:" + file_path)
return {}
var headers: PackedStringArray = []
var data: Array = []
if not file.eof_reached():
headers = PackedStringArray()
for val in file.get_csv_line("|"):
headers.append(val.strip_edges())
while not file.eof_reached():
var raw_row = file.get_csv_line("|")
if raw_row.is_empty(): # пропускаем пустые строки
continue
var trimmed_row: PackedStringArray = []
for val in raw_row:
trimmed_row.append(val.strip_edges())
data.append(trimmed_row)
file.close()
var dict_data: Dictionary = {}
for row in data:
if row.size() < 2: continue
if row.size() == headers.size():
var dict: Dictionary = {}
for i in headers.size():
dict[headers[i]] = row[i]
dict_data[row[0]] = dict
return dict_data
func _print_dict(dict_to_print: Dictionary):
for d in dict_to_print:
print(d, " → ", dict_to_print[d])
-1
View File
@@ -1 +0,0 @@
uid://5xb12usvrifm
-132
View File
@@ -1,132 +0,0 @@
Пространство|S|Resource|||||||||||||1|S||||||||
Водород|H|Resource|||||||||||||1|H||||||||
Гелий|He|Resource||||||||||||||||||||||
Металлы|Met|Resource||||||||||||||||||||||
Бурый карлик|BD|Planet|||||||||||BD:1|||||||||||
Горячий бурый карлик|HBD|Star phase 1|BD|0.1|5.00E+09|H:0.1|||S:0.5|||CBD:1|||||||||1|||
Красный карлик|RD|Star phase 1||1|4.00E+10|H:1||1|S:40|||TWD:1&H:0.13&He:0.05&Met:0.01|H:1|Star||DwStar|1x0.01|1x0.21|2x0.08|3x0.4|1|||
Оранжевый карлик|OD|Star phase 1||8|1.80E+10|H:8||1|S:36|||SRG:1|RD:1|Star||DwStar|1x0.03|2x0.34|3x0.13|3x0.4|1|||
Жёлтый карлик|YD|Star phase 1||10|9.00E+09|H:10||1|S:27|||NRG:1|OD:1|Star||DwStar|2x0.1|3x0.55|4x0.21|3x0.4|1|||
Бело-жёлтый карлик|WYD|Star phase 1||16|1.80E+09|H:16||1|S:18|||MRG:1|YD:1|Star||DwStar|3x0.3|5x0.89|5x0.34|3x0.4|1|||
Жёлтый гигант|YG|Star phase 1||50|4.50E+08|H:50||1|S:9|||LRG:1|H:15|Star||GiStar|||||2|||
Голубой гигант|BG|Star phase 1||100|9.00E+07|H:100||1|S:9|||HRG:1|H:30&YG:1|Star||GiStar|||||2|||
Сверхгигант|SG|Star phase 1||300|9.00E+06|H:300||1|S:9|||RSG:1|H:100&BG:1|Star||GiStar|||||2|||
Гипергигант|HG|Star phase 1||1000|9.00E+05|H:1000||1|S:9|||RHG:1|H:300&SG:1|Star||GiStar|||||2|||
Красный гигант|RG|Star phase 2|||||||||||RG:1|||||||||||
Малый красный гигант|SRG|Star phase 2|RG|8|2.00E+09||||S:80|||SWD:1&H:2.32&He:0.64&Met:0.08&S:12.4||Star|||||||1|||
Обычный Красный гигант|NRG|Star phase 2|RG|10|1.00E+09||||S:120.|||NWD:1&H:3.2&He:1.3&Met:0.2&S:14.3||Star|||||||1|||
Средний красный гигант|MRG|Star phase 2|RG|16|2.00E+08||||S:200|||LWD:1&H:4.96&He:3.36&Met:0.48&S:20.2||Star|||||||1|||
Большой красный гигант|LRG|Star phase 2|RG|50|5.00E+07||||S:300|||DSN^SGRB%.1||Star|||||||2|||
Огромный красный гигант|HRG|Star phase 2|RG|100|1.00E+07||||S:400.|||SN^GRB%1||Star|||||||2|||
Красный сверхгигант|RSG|Star phase 2|RG|300|1.00E+06||||S:500|||BSN^LGRB%3||Star|||||||2|||
Красный гипергигант|RHG|Star phase 2|RG|1000|1.00E+05||||S:600|||HN^HGRB%10||Star|||||||2|||
Тусклая сверхновая|DSN|Star phase 3|||1||||S:59.1|||SNS:1&H:6.5&He:13.5&Met:11&blast:2||||SNGRBB|||||2|||
Сверхновая|SN|Star phase 3|||1||||S:99.1|||LNS:1&H:8&He:50&Met:11&blast:9||||SNGRBB|||||2|||
Яркая сверхновая|BSN|Star phase 3|||1||||S:309.1|||MGT:1&H:15&He:186&Met:15&blast:305||||SNGRBB|||||2|||
Гиперновая|HN|Star phase 3|||1||||S:939.1|||BH40:1&H:30&He:560&Met:30&blast:9990||||SNGRBB|||||2|||
Малый гамма-всплеск|SGRB|Star phase 3|||1||||S:149.1|||BH25:1&H:0.5&He:10&Met:4&blast:31||||SNGRBB|||||2|||
Гамма-всплеск|GRB|Star phase 3|||1||||S:239.1|||BH30:1&H:19&He:12&Met:5&blast:136||||SNGRBB|||||2|||
Большой гамма-всплеск|LGRB|Star phase 3|||1||||S:669.1|||BH40:1&H:68&He:18&Met:9&blast:3446||||SNGRBB|||||2|||
Гипер гамма-всплеск|HGRB|Star phase 3|||1||||S:1939.1|||BH60:1&H:0&He:40&Met:10&blast:97342||||SNGRBB|||||2|||
Холодный бурый карлик|CBD|Star phase 4|BD|0.1||||||||||||||||||||
Белый карлик|WD|Star phase 4|||||||||||WD:1|||||||||||
Крошечный белый карлик|TWD|Star phase 4|WD|0.8||||||||||Star||Degen||||||||
Малый белый карлик|SWD|Star phase 4|WD|4.8||||||||||Star||Degen||||||||
Обычный белый карлик|NWD|Star phase 4|WD|5||||||||||Star||Degen||||||||
Большой белый карлик|LWD|Star phase 4|WD|6.4||||||||||Star||Degen||||||||
Нейтронная звезда|NS|Star phase 4|||||||||||NS:1|||||||||||
Малая нейтронная звезда|SNS|Star phase 4|NS|15||||||||||Star||Degen||||||||
Большая нейтронная звезда|LNS|Star phase 4|NS|18||||||||||Star||Degen||||||||
Магнетар|MGT|Star phase 4||21|||||||||MGT:1|Star||Degen||||||||
Чёрная дыра|BH|Star phase 4|||||||||||BH:1|||||||||||
Чёрная дыра 25|BH25|Star phase 4|BH|25||||||||||BH||BH||||||||
Чёрная дыра 30|BH30|Star phase 4|BH|30||||||||||BH||BH||||||||
Чёрная дыра 40|BH40|Star phase 4|BH|40||||||||||BH||BH||||||||
Чёрная дыра 60|BH60|Star phase 4|BH|60||||||||||BH||BH||||||||
СМЧД|SMBH|Star phase 4|||||||||||BH:1|||SMBH||||||||
Туманность|N|Cloud||1|1.00E+07|H:1||10|H:10|||H:1&S:10|S:1|CL||CL||||||||
Глобула|G|Cloud||11|3.00E+07|H:10&N:1||10|H:150|||H:11&S:20|N:1|CL||CL||||||||
Звёздная колыбель|STN|Cloud||211|3.00E+07|H:200&G:1||300|H:3000|0.50||H:211&S:320|G:1|CL||CL||||||||
Молекулярное облако|MC|Cloud||2011|3.00E+08|H:2000&G:1||4000|H:90000.|||H:2011&S:4020|G:1&S:1300|CL||CL||||||||
Активная звёздная колыбель|ASTN|Cloud||202011|1.00E+08|H:200000&MC:1||200000|H:2000000|0.65||H:202011&S:204020|MC:1&S:60000|CL||CL||||||||
Рассеянное звёздное скопление|SCD|Cluster|||1.00E+07||Star:1000||||||Star:300|SC||SC||||||0.10|4|C2.3
Малое звёздное скопление|SCS|Cluster|||1.00E+09||Star:10000&BH:10||||||SCD:1&Star:2000|SC||SC||||||0.20|3.6|C2.4
Среднее звёздное скопление|SCM|Cluster|||3.00E+09||Star:100000&BH:100||||||SCS:1&Star:20000|SC||SC||||||0.30|3.4|C2.5
Большое звёздное скопление|SCL|Cluster|||1.00E+10||Star:1000000&BH:1000||||||SCM:1&Star:200000|SC||SC||||||0.50|3.2|C2.6
Гигантское звёздное скопление|SCG|Cluster|||3.00E+10||Star:10000000&BH:10000||||||SCL:1&Star:2000000|SC||SC||||||0.80|3|C2.7
Карликовая эллиптическая галактика|GED|GalaxyElliptical|||1.20E+10|SMBH:10000|Star:1000000000&BH:1000000&SC:100||||||SMBH:1&SC:1|GAL||GALE||||||1.00|1.9|C2.9
Малая эллиптическая галактика|GES|GalaxyElliptical|||1.30E+10|SMBH:100000|Star:10000000000&BH:10000000&SC:1000||||||GED:1&Star:2000000000|GAL||GALE||||||1.50|1.8|C3.0
Средняя эллиптическая галактика|GEM|GalaxyElliptical|||1.50E+10|SMBH:1000000|Star:100000000000&BH:100000000&SC:10000||||||GES:1&Star:20000000000|GAL||GALE||||||2.00|1.7|C3.1
Большая эллиптическая галактика|GEL|GalaxyElliptical|||1.70E+10|SMBH:10000000|Star:1000000000000&BH:1000000000&SC:100000||||||GEM:1&Star:200000000000|GAL||GALE||||||3.00|1.6|C3.2
Гигантская эллиптическая галактика|GEG|GalaxyElliptical|||2.00E+10|SMBH:100000000|Star:10000000000000&BH:10000000000&SC:1000000||||||GEL:1&Star:2000000000000|GAL||GALE||||||4.50|1.5|C3.3
Карликовая спиральная галактика|GSD|GalaxySpiral|||2.00E+09|STN:10000&ASTN:10|GED:1|-5240200|H:2400000000|0.80||H:4112110|GED:1|GAL||GALS|||||||2.5|C2.9
Малая спиральная галактика|GSS|GalaxySpiral|||3.00E+09|STN:100000&ASTN:100|GES:1|-52402000|H:36000000000|0.80||H:41121100|GES:1|GAL||GALS|||||||2.3|C3.0
Средняя спиральная галактика|GSM|GalaxySpiral|||4.00E+09|STN:1000000&ASTN:1000|GEM:1|-524020000|H:480000000000|0.80||H:411211000|GEM:1|GAL||GALS|||||||2.2|C3.1
Большая спиральная галактика|GSL|GalaxySpiral|||6.00E+09|STN:10000000&ASTN:10000|GEL:1|-5240200000|H:7200000000000|0.80||H:4112110000|GEL:1|GAL||GALS|||||||2.1|C3.2
Гигантская спиральная галактика|GSG|GalaxySpiral|||9.00E+09|STN:100000000&ASTN:100000|GEG:1|-52402000000|H:108000000000000|0.80||H:41121100000|GEG:1|GAL||GALS|||||||2|C3.3
Группа галактик|LGG|Structures|||1.00E+10||GAL:50||||||GAL:20|LS||LS|||||||1.5|C3.4
Сверхскопление|LSC|Structures|||2.00E+10||LGG:200||||||LGG:1&GAL:100|LS||LS|||||||1.4|C3.6
Галактическая нить|LGF|Structures|||3.00E+10||LSC:100||||5||LSC:1&LGG:400|LS||LS|||||||1.3|C3.8
Великая стена|LGW|Structures|||6.00E+10||LGF:1000||||1.00E+04||LGF:1&LSC:200|LS||LS|||||||1.2|C4.1
Вселенский пузырь|LUB|Structures|||1.00E+11||LGW:1000||||1.00E+09||LGW:1&LGF:2000|LS||LS|||||||1.1|C4.4
Газовый гигант|GG|Planet|||||||||||GG:1|Planet||BPlanet||||||||
Астероиды|AB|Planet|||||||||||AB:1|Planet||BPlanet||||||||
Каменистая|RP|Planet|||||||||||RP:1|Planet||BPlanet||||||||
Обитаемая|HP|Planet|||||||||||HP:1|Planet||LPlanet||||||||
Живая|LP|Planet|||||||||||LP:1|Planet||LPlanet||||||||
Эон 1: Архей|EON1|Planet|LP||||||||||EON1:1|Planet||LPlanet||||||||
Эон 2: Протерозой|EON2|Planet|LP||||||||||EON2:1|Planet||LPlanet||||||||
Эон 3: Палеозой|EON3|Planet|LP||||||||||EON3:1|Planet||LPlanet||||||||
Эон 4: Мезозой|EON4|Planet|LP||||||||||EON4:1|Planet||LPlanet||||||||
Эон 5: Кайнозой|EON5|Planet|LP||||||||||EON5:1|Planet||LPlanet||||||||
Цивилизация типа 0|C0|Civilization|||||||||||C0:1|Planet||LPlanet||||||||
Цивилизация 0.0|C0.0|Civilization|C0||||||||||C0.0:1|Planet||LPlanet||||||||
Цивилизация 0.1|C0.1|Civilization|C0||||||||||C0.1:1|Planet||LPlanet||||||||
Цивилизация 0.2|C0.2|Civilization|C0||||||||||C0.2:1|Planet||LPlanet||||||||
Цивилизация 0.3|C0.3|Civilization|C0||||||||||C0.3:1|Planet||LPlanet||||||||
Цивилизация 0.4|C0.4|Civilization|C0||||||||||C0.4:1|Planet||LPlanet||||||||
Цивилизация 0.5|C0.5|Civilization|C0||||||||||C0.5:1|Planet||LPlanet||||||||
Цивилизация 0.6|C0.6|Civilization|C0||||||||||C0.6:1|Planet||LPlanet||||||||
Цивилизация 0.7|C0.7|Civilization|C0||||||||||C0.7:1|Planet||LPlanet||||||||
Цивилизация 0.8|C0.8|Civilization|C0||||||||||C0.8:1|Planet||LPlanet||||||||
Цивилизация 0.9|C0.9|Civilization|C0||||||||||C0.9:1|Planet||LPlanet||||||||
Цивилизация типа 1|C1|Civilization|||||||||||C1:1|Planet||LPlanet||||||||
Цивилизация 1.0|C1.0|Civilization|C1||||||||||C1.0:1|Planet||LPlanet||||||||
Цивилизация 1.1|C1.1|Civilization|C1||||||||||C1.1:1|Planet||LPlanet||||||||
Цивилизация 1.2|C1.2|Civilization|C1||||||||||C1.2:1|Planet||LPlanet||||||||
Цивилизация 1.3|C1.3|Civilization|C1||||||||||C1.3:1|Planet||LPlanet||||||||
Цивилизация 1.4|C1.4|Civilization|C1||||||||||C1.4:1|Planet||LPlanet||||||||
Цивилизация 1.5|C1.5|Civilization|C1||||||||||C1.5:1|Planet||LPlanet||||||||
Цивилизация 1.6|C1.6|Civilization|C1||||||||||C1.6:1|Planet||LPlanet||||||||
Цивилизация 1.7|C1.7|Civilization|C1||||||||||C1.7:1|Planet||LPlanet||||||||
Цивилизация 1.8|C1.8|Civilization|C1||||||||||C1.8:1|Planet||LPlanet||||||||
Цивилизация 1.9|C1.9|Civilization|C1||||||||||C1.9:1|Planet||LPlanet||||||||
Цивилизация типа 2|C2|Civilization|||||||||||C2:1|||||||||||
Цивилизация 2.0|C2.0|Civilization|C2||||||||||C2.0:1|||||||||||
Цивилизация 2.1|C2.1|Civilization|C2||||||||||C2.1:1|||||||||||
Цивилизация 2.2|C2.2|Civilization|C2||||||||||C2.2:1|||||||||||
Цивилизация 2.3|C2.3|Civilization|C2||||||||||C2.3:1|||||||||||
Цивилизация 2.4|C2.4|Civilization|C2||||||||||C2.4:1|||||||||||
Цивилизация 2.5|C2.5|Civilization|C2||||||||||C2.5:1|||||||||||
Цивилизация 2.6|C2.6|Civilization|C2||||||||||C2.6:1|||||||||||
Цивилизация 2.7|C2.7|Civilization|C2||||||||||C2.7:1|||||||||||
Цивилизация 2.8|C2.8|Civilization|C2||||||||||C2.8:1|||||||||||
Цивилизация 2.9|C2.9|Civilization|C2||||||||||C2.9:1|||||||||||
Цивилизация типа 3|C3|Civilization|||||||||||C3:1|||||||||||
Цивилизация 3.0|C3.0|Civilization|C3||||||||||C3.0:1|||||||||||
Цивилизация 3.1|C3.1|Civilization|C3||||||||||C3.1:1|||||||||||
Цивилизация 3.2|C3.2|Civilization|C3||||||||||C3.2:1|||||||||||
Цивилизация 3.3|C3.3|Civilization|C3||||||||||C3.3:1|||||||||||
Цивилизация 3.4|C3.4|Civilization|C3||||||||||C3.4:1|||||||||||
Цивилизация 3.5|C3.5|Civilization|C3||||||||||C3.5:1|||||||||||
Цивилизация 3.6|C3.6|Civilization|C3||||||||||C3.6:1|||||||||||
Цивилизация 3.7|C3.7|Civilization|C3||||||||||C3.7:1|||||||||||
Цивилизация 3.8|C3.8|Civilization|C3||||||||||C3.8:1|||||||||||
Цивилизация 3.9|C3.9|Civilization|C3||||||||||C3.9:1|||||||||||
Цивилизация типа 4|C4|Civilization|||||||||||C4:1|||||||||||
Цивилизация 4.0|C4.0|Civilization|C4||||||||||C4.0:1|||||||||||
Цивилизация 4.1|C4.1|Civilization|C4||||||||||C4.1:1|||||||||||
Цивилизация 4.2|C4.2|Civilization|C4||||||||||C4.2:1|||||||||||
Цивилизация 4.3|C4.3|Civilization|C4||||||||||C4.3:1|||||||||||
Цивилизация 4.4|C4.4|Civilization|C4||||||||||C4.4:1|||||||||||
Трансцендентная цивилизация|Ct|Civilization||||||||||||||||||||||
1 Пространство S Resource 1 S
2 Водород H Resource 1 H
3 Гелий He Resource
4 Металлы Met Resource
5 Бурый карлик BD Planet BD:1
6 Горячий бурый карлик HBD Star phase 1 BD 0.1 5.00E+09 H:0.1 S:0.5 CBD:1 1
7 Красный карлик RD Star phase 1 1 4.00E+10 H:1 1 S:40 TWD:1&H:0.13&He:0.05&Met:0.01 H:1 Star DwStar 1x0.01 1x0.21 2x0.08 3x0.4 1
8 Оранжевый карлик OD Star phase 1 8 1.80E+10 H:8 1 S:36 SRG:1 RD:1 Star DwStar 1x0.03 2x0.34 3x0.13 3x0.4 1
9 Жёлтый карлик YD Star phase 1 10 9.00E+09 H:10 1 S:27 NRG:1 OD:1 Star DwStar 2x0.1 3x0.55 4x0.21 3x0.4 1
10 Бело-жёлтый карлик WYD Star phase 1 16 1.80E+09 H:16 1 S:18 MRG:1 YD:1 Star DwStar 3x0.3 5x0.89 5x0.34 3x0.4 1
11 Жёлтый гигант YG Star phase 1 50 4.50E+08 H:50 1 S:9 LRG:1 H:15 Star GiStar 2
12 Голубой гигант BG Star phase 1 100 9.00E+07 H:100 1 S:9 HRG:1 H:30&YG:1 Star GiStar 2
13 Сверхгигант SG Star phase 1 300 9.00E+06 H:300 1 S:9 RSG:1 H:100&BG:1 Star GiStar 2
14 Гипергигант HG Star phase 1 1000 9.00E+05 H:1000 1 S:9 RHG:1 H:300&SG:1 Star GiStar 2
15 Красный гигант RG Star phase 2 RG:1
16 Малый красный гигант SRG Star phase 2 RG 8 2.00E+09 S:80 SWD:1&H:2.32&He:0.64&Met:0.08&S:12.4 Star 1
17 Обычный Красный гигант NRG Star phase 2 RG 10 1.00E+09 S:120. NWD:1&H:3.2&He:1.3&Met:0.2&S:14.3 Star 1
18 Средний красный гигант MRG Star phase 2 RG 16 2.00E+08 S:200 LWD:1&H:4.96&He:3.36&Met:0.48&S:20.2 Star 1
19 Большой красный гигант LRG Star phase 2 RG 50 5.00E+07 S:300 DSN^SGRB%.1 Star 2
20 Огромный красный гигант HRG Star phase 2 RG 100 1.00E+07 S:400. SN^GRB%1 Star 2
21 Красный сверхгигант RSG Star phase 2 RG 300 1.00E+06 S:500 BSN^LGRB%3 Star 2
22 Красный гипергигант RHG Star phase 2 RG 1000 1.00E+05 S:600 HN^HGRB%10 Star 2
23 Тусклая сверхновая DSN Star phase 3 1 S:59.1 SNS:1&H:6.5&He:13.5&Met:11&blast:2 SNGRBB 2
24 Сверхновая SN Star phase 3 1 S:99.1 LNS:1&H:8&He:50&Met:11&blast:9 SNGRBB 2
25 Яркая сверхновая BSN Star phase 3 1 S:309.1 MGT:1&H:15&He:186&Met:15&blast:305 SNGRBB 2
26 Гиперновая HN Star phase 3 1 S:939.1 BH40:1&H:30&He:560&Met:30&blast:9990 SNGRBB 2
27 Малый гамма-всплеск SGRB Star phase 3 1 S:149.1 BH25:1&H:0.5&He:10&Met:4&blast:31 SNGRBB 2
28 Гамма-всплеск GRB Star phase 3 1 S:239.1 BH30:1&H:19&He:12&Met:5&blast:136 SNGRBB 2
29 Большой гамма-всплеск LGRB Star phase 3 1 S:669.1 BH40:1&H:68&He:18&Met:9&blast:3446 SNGRBB 2
30 Гипер гамма-всплеск HGRB Star phase 3 1 S:1939.1 BH60:1&H:0&He:40&Met:10&blast:97342 SNGRBB 2
31 Холодный бурый карлик CBD Star phase 4 BD 0.1
32 Белый карлик WD Star phase 4 WD:1
33 Крошечный белый карлик TWD Star phase 4 WD 0.8 Star Degen
34 Малый белый карлик SWD Star phase 4 WD 4.8 Star Degen
35 Обычный белый карлик NWD Star phase 4 WD 5 Star Degen
36 Большой белый карлик LWD Star phase 4 WD 6.4 Star Degen
37 Нейтронная звезда NS Star phase 4 NS:1
38 Малая нейтронная звезда SNS Star phase 4 NS 15 Star Degen
39 Большая нейтронная звезда LNS Star phase 4 NS 18 Star Degen
40 Магнетар MGT Star phase 4 21 MGT:1 Star Degen
41 Чёрная дыра BH Star phase 4 BH:1
42 Чёрная дыра 25 BH25 Star phase 4 BH 25 BH BH
43 Чёрная дыра 30 BH30 Star phase 4 BH 30 BH BH
44 Чёрная дыра 40 BH40 Star phase 4 BH 40 BH BH
45 Чёрная дыра 60 BH60 Star phase 4 BH 60 BH BH
46 СМЧД SMBH Star phase 4 BH:1 SMBH
47 Туманность N Cloud 1 1.00E+07 H:1 10 H:10 H:1&S:10 S:1 CL CL
48 Глобула G Cloud 11 3.00E+07 H:10&N:1 10 H:150 H:11&S:20 N:1 CL CL
49 Звёздная колыбель STN Cloud 211 3.00E+07 H:200&G:1 300 H:3000 0.50 H:211&S:320 G:1 CL CL
50 Молекулярное облако MC Cloud 2011 3.00E+08 H:2000&G:1 4000 H:90000. H:2011&S:4020 G:1&S:1300 CL CL
51 Активная звёздная колыбель ASTN Cloud 202011 1.00E+08 H:200000&MC:1 200000 H:2000000 0.65 H:202011&S:204020 MC:1&S:60000 CL CL
52 Рассеянное звёздное скопление SCD Cluster 1.00E+07 Star:1000 Star:300 SC SC 0.10 4 C2.3
53 Малое звёздное скопление SCS Cluster 1.00E+09 Star:10000&BH:10 SCD:1&Star:2000 SC SC 0.20 3.6 C2.4
54 Среднее звёздное скопление SCM Cluster 3.00E+09 Star:100000&BH:100 SCS:1&Star:20000 SC SC 0.30 3.4 C2.5
55 Большое звёздное скопление SCL Cluster 1.00E+10 Star:1000000&BH:1000 SCM:1&Star:200000 SC SC 0.50 3.2 C2.6
56 Гигантское звёздное скопление SCG Cluster 3.00E+10 Star:10000000&BH:10000 SCL:1&Star:2000000 SC SC 0.80 3 C2.7
57 Карликовая эллиптическая галактика GED GalaxyElliptical 1.20E+10 SMBH:10000 Star:1000000000&BH:1000000&SC:100 SMBH:1&SC:1 GAL GALE 1.00 1.9 C2.9
58 Малая эллиптическая галактика GES GalaxyElliptical 1.30E+10 SMBH:100000 Star:10000000000&BH:10000000&SC:1000 GED:1&Star:2000000000 GAL GALE 1.50 1.8 C3.0
59 Средняя эллиптическая галактика GEM GalaxyElliptical 1.50E+10 SMBH:1000000 Star:100000000000&BH:100000000&SC:10000 GES:1&Star:20000000000 GAL GALE 2.00 1.7 C3.1
60 Большая эллиптическая галактика GEL GalaxyElliptical 1.70E+10 SMBH:10000000 Star:1000000000000&BH:1000000000&SC:100000 GEM:1&Star:200000000000 GAL GALE 3.00 1.6 C3.2
61 Гигантская эллиптическая галактика GEG GalaxyElliptical 2.00E+10 SMBH:100000000 Star:10000000000000&BH:10000000000&SC:1000000 GEL:1&Star:2000000000000 GAL GALE 4.50 1.5 C3.3
62 Карликовая спиральная галактика GSD GalaxySpiral 2.00E+09 STN:10000&ASTN:10 GED:1 -5240200 H:2400000000 0.80 H:4112110 GED:1 GAL GALS 2.5 C2.9
63 Малая спиральная галактика GSS GalaxySpiral 3.00E+09 STN:100000&ASTN:100 GES:1 -52402000 H:36000000000 0.80 H:41121100 GES:1 GAL GALS 2.3 C3.0
64 Средняя спиральная галактика GSM GalaxySpiral 4.00E+09 STN:1000000&ASTN:1000 GEM:1 -524020000 H:480000000000 0.80 H:411211000 GEM:1 GAL GALS 2.2 C3.1
65 Большая спиральная галактика GSL GalaxySpiral 6.00E+09 STN:10000000&ASTN:10000 GEL:1 -5240200000 H:7200000000000 0.80 H:4112110000 GEL:1 GAL GALS 2.1 C3.2
66 Гигантская спиральная галактика GSG GalaxySpiral 9.00E+09 STN:100000000&ASTN:100000 GEG:1 -52402000000 H:108000000000000 0.80 H:41121100000 GEG:1 GAL GALS 2 C3.3
67 Группа галактик LGG Structures 1.00E+10 GAL:50 GAL:20 LS LS 1.5 C3.4
68 Сверхскопление LSC Structures 2.00E+10 LGG:200 LGG:1&GAL:100 LS LS 1.4 C3.6
69 Галактическая нить LGF Structures 3.00E+10 LSC:100 5 LSC:1&LGG:400 LS LS 1.3 C3.8
70 Великая стена LGW Structures 6.00E+10 LGF:1000 1.00E+04 LGF:1&LSC:200 LS LS 1.2 C4.1
71 Вселенский пузырь LUB Structures 1.00E+11 LGW:1000 1.00E+09 LGW:1&LGF:2000 LS LS 1.1 C4.4
72 Газовый гигант GG Planet GG:1 Planet BPlanet
73 Астероиды AB Planet AB:1 Planet BPlanet
74 Каменистая RP Planet RP:1 Planet BPlanet
75 Обитаемая HP Planet HP:1 Planet LPlanet
76 Живая LP Planet LP:1 Planet LPlanet
77 Эон 1: Архей EON1 Planet LP EON1:1 Planet LPlanet
78 Эон 2: Протерозой EON2 Planet LP EON2:1 Planet LPlanet
79 Эон 3: Палеозой EON3 Planet LP EON3:1 Planet LPlanet
80 Эон 4: Мезозой EON4 Planet LP EON4:1 Planet LPlanet
81 Эон 5: Кайнозой EON5 Planet LP EON5:1 Planet LPlanet
82 Цивилизация типа 0 C0 Civilization C0:1 Planet LPlanet
83 Цивилизация 0.0 C0.0 Civilization C0 C0.0:1 Planet LPlanet
84 Цивилизация 0.1 C0.1 Civilization C0 C0.1:1 Planet LPlanet
85 Цивилизация 0.2 C0.2 Civilization C0 C0.2:1 Planet LPlanet
86 Цивилизация 0.3 C0.3 Civilization C0 C0.3:1 Planet LPlanet
87 Цивилизация 0.4 C0.4 Civilization C0 C0.4:1 Planet LPlanet
88 Цивилизация 0.5 C0.5 Civilization C0 C0.5:1 Planet LPlanet
89 Цивилизация 0.6 C0.6 Civilization C0 C0.6:1 Planet LPlanet
90 Цивилизация 0.7 C0.7 Civilization C0 C0.7:1 Planet LPlanet
91 Цивилизация 0.8 C0.8 Civilization C0 C0.8:1 Planet LPlanet
92 Цивилизация 0.9 C0.9 Civilization C0 C0.9:1 Planet LPlanet
93 Цивилизация типа 1 C1 Civilization C1:1 Planet LPlanet
94 Цивилизация 1.0 C1.0 Civilization C1 C1.0:1 Planet LPlanet
95 Цивилизация 1.1 C1.1 Civilization C1 C1.1:1 Planet LPlanet
96 Цивилизация 1.2 C1.2 Civilization C1 C1.2:1 Planet LPlanet
97 Цивилизация 1.3 C1.3 Civilization C1 C1.3:1 Planet LPlanet
98 Цивилизация 1.4 C1.4 Civilization C1 C1.4:1 Planet LPlanet
99 Цивилизация 1.5 C1.5 Civilization C1 C1.5:1 Planet LPlanet
100 Цивилизация 1.6 C1.6 Civilization C1 C1.6:1 Planet LPlanet
101 Цивилизация 1.7 C1.7 Civilization C1 C1.7:1 Planet LPlanet
102 Цивилизация 1.8 C1.8 Civilization C1 C1.8:1 Planet LPlanet
103 Цивилизация 1.9 C1.9 Civilization C1 C1.9:1 Planet LPlanet
104 Цивилизация типа 2 C2 Civilization C2:1
105 Цивилизация 2.0 C2.0 Civilization C2 C2.0:1
106 Цивилизация 2.1 C2.1 Civilization C2 C2.1:1
107 Цивилизация 2.2 C2.2 Civilization C2 C2.2:1
108 Цивилизация 2.3 C2.3 Civilization C2 C2.3:1
109 Цивилизация 2.4 C2.4 Civilization C2 C2.4:1
110 Цивилизация 2.5 C2.5 Civilization C2 C2.5:1
111 Цивилизация 2.6 C2.6 Civilization C2 C2.6:1
112 Цивилизация 2.7 C2.7 Civilization C2 C2.7:1
113 Цивилизация 2.8 C2.8 Civilization C2 C2.8:1
114 Цивилизация 2.9 C2.9 Civilization C2 C2.9:1
115 Цивилизация типа 3 C3 Civilization C3:1
116 Цивилизация 3.0 C3.0 Civilization C3 C3.0:1
117 Цивилизация 3.1 C3.1 Civilization C3 C3.1:1
118 Цивилизация 3.2 C3.2 Civilization C3 C3.2:1
119 Цивилизация 3.3 C3.3 Civilization C3 C3.3:1
120 Цивилизация 3.4 C3.4 Civilization C3 C3.4:1
121 Цивилизация 3.5 C3.5 Civilization C3 C3.5:1
122 Цивилизация 3.6 C3.6 Civilization C3 C3.6:1
123 Цивилизация 3.7 C3.7 Civilization C3 C3.7:1
124 Цивилизация 3.8 C3.8 Civilization C3 C3.8:1
125 Цивилизация 3.9 C3.9 Civilization C3 C3.9:1
126 Цивилизация типа 4 C4 Civilization C4:1
127 Цивилизация 4.0 C4.0 Civilization C4 C4.0:1
128 Цивилизация 4.1 C4.1 Civilization C4 C4.1:1
129 Цивилизация 4.2 C4.2 Civilization C4 C4.2:1
130 Цивилизация 4.3 C4.3 Civilization C4 C4.3:1
131 Цивилизация 4.4 C4.4 Civilization C4 C4.4:1
132 Трансцендентная цивилизация Ct Civilization
-69
View File
@@ -1,69 +0,0 @@
# SaveManager.gd (добавить в AutoLoad)
extends Node
# ~/Library/Application Support/Godot/app_userdata/Owniverse Adventure/savegame.cfg
const SETTING_SECTION := "Settings"
const SAVE_PATH = "user://settings.cfg"
func ch():
pass
#print(Global.Owniverse)
#print('h')
#save_data('ow1', 'test', Global.Owniverse)
#var d1: Dictionary = load_data('ow1', 'test1')
#print("d1: ", d1)
#var d2: Dictionary = load_data('ow1', 'test')
#print("d2: ", d2)
#print('d')
#print(Global.Owniverse.datetime.WEEKDAYS)
func save_data(filename: String, password: String, data: Dictionary) -> void:
filename = "user://" + filename + ".adventure"
var file := FileAccess.open_encrypted_with_pass(filename, FileAccess.WRITE, password)
if file == null:
push_error("Не удалось открыть файл для шифрованной записи")
return
file.store_var(data) # бинарно + быстрее + сериализация
file.close()
func load_data(filename: String, password: String) -> Dictionary:
filename = "user://" + filename + ".adventure"
if not FileAccess.file_exists(filename):
return {}
var file := FileAccess.open_encrypted_with_pass(filename, FileAccess.READ, password)
if file == null:
push_error("Неверный пароль или повреждённый файл")
return {}
var data:Variant = file.get_var()
file.close()
#print("data")
#print(data)
return data if data is Dictionary else {}
#region Settings
func save_settings():
var config = ConfigFile.new()
for item in Global.Settings:
config.set_value(SETTING_SECTION, item, Global.Settings[item])
config.save(SAVE_PATH)
func load_settings():
var config = ConfigFile.new()
var err = config.load(SAVE_PATH)
if err != OK:
return false
for item in Global.Settings:
Global.Settings[item] = config.get_value(SETTING_SECTION, item, Global.Settings[item])
return true
#endregion
-125
View File
@@ -1,125 +0,0 @@
id|name|image|page|row|col|sub_page
Shovelin|Shovelin|UI/0-Forces/|0|0|0|
Inflatin|Inflatin|UI/0-Forces/|0|0|1|
Temporite|Temporite|UI/0-Forces/|0|0|2|
Collisite|Collisite|UI/0-Forces/|0|0|3|
Primex|Primex|UI/0-Forces/|0|0|4|
Singularite|Singularite|UI/0-Forces/|0|1|0|
Renewin|Renewin|UI/0-Forces/|0|1|1|
Infusite|Infusite|UI/0-Forces/|0|1|2|
Frostin|Frostin|UI/0-Forces/|0|1|3|
Destellarite|Destellarite|UI/0-Forces/|0|1|4|
Rockex|Rockex|UI/0-Forces/|0|2|0|
Panspermin|Panspermin|UI/0-Forces/|0|2|1|
Gaianite|Gaianite|UI/0-Forces/|0|2|2|
Darwinite|Darwinite|UI/0-Forces/|0|2|3|
Edenex|Edenex|UI/0-Forces/|0|2|4|
Pacifin|Pacifin|UI/0-Forces/|0|3|0|
Enragein|Enragein|UI/0-Forces/|0|3|1|
Moralite|Moralite|UI/0-Forces/|0|3|2|
Discriminite|Discriminite|UI/0-Forces/|0|3|3|
Reprex|Reprex|UI/0-Forces/|0|3|4|
S|Space|UI/1-Resources/|1|0|0|
H|Hydrogen|UI/1-Resources/|1|1|0|
He|Helium|UI/1-Resources/|1|2|0|
Met|Metal|UI/1-Resources/|1|3|0|
N|Nebula|UI/2-Stars/|2|0|0|
G|Globula|UI/2-Stars/|2|0|1|
STN|StarNursery|UI/2-Stars/|2|0|2|
MC|MolecularCloud|UI/2-Stars/|2|0|3|
ASTN|ActiveStarNursery|UI/2-Stars/|2|0|4|
BD|BrownDwarf|UI/2-Stars/|2|1|0|
RD|RedDwarf|UI/2-Stars/|2|1|1|
OD|OrangeDwarf|UI/2-Stars/|2|1|2|
YD|YellowDwarf|UI/2-Stars/|2|1|3|
WYD|WhiteYellowDwarf|UI/2-Stars/|2|1|4|
RG|RedGiant|UI/2-Stars/|2|2|0|
WS|WhiteStar|UI/2-Stars/|2|2|1|
BG|BlueGiant|UI/2-Stars/|2|2|2|
SG|Supergiant|UI/2-Stars/|2|2|3|
HG|Hypergiant|UI/2-Stars/|2|2|4|
WD|WhiteDwarf|UI/2-Stars/|2|3|0|
NS|NeutronStar|UI/2-Stars/|2|3|1|
MGT|Magnetar|UI/2-Stars/|2|3|2|
BH|BlackHole|UI/2-Stars/|2|3|3|
SMBH|SupermassiveBlackHole|UI/2-Stars/|2|3|4|
SCD|StarClusterScattered|UI/3-Structures/|3|0|0|
SCS|StarClusterSmall|UI/3-Structures/|3|0|1|
SCM|StarClusterMedium|UI/3-Structures/|3|0|2|
SCL|StarClusterLarge|UI/3-Structures/|3|0|3|
SCG|StarClusterGiant|UI/3-Structures/|3|0|4|
GED|GalaxyEllipticalDwarf|UI/3-Structures/|3|1|0|
GES|GalaxyEllipticalSmall|UI/3-Structures/|3|1|1|
GEM|GalaxyEllipticalMedium|UI/3-Structures/|3|1|2|
GEL|GalaxyEllipticalLarge|UI/3-Structures/|3|1|3|
GEG|GalaxyEllipticalGiant|UI/3-Structures/|3|1|4|
GSD|GalaxySpiralDwarf|UI/3-Structures/|3|2|0|
GSS|GalaxySpiralSmall|UI/3-Structures/|3|2|1|
GSM|GalaxySpiralMedium|UI/3-Structures/|3|2|2|
GSL|GalaxySpiralLarge|UI/3-Structures/|3|2|3|
GSG|GalaxySpiralGiant|UI/3-Structures/|3|2|4|
LGG|GalacticGroup|UI/3-Structures/|3|3|0|
LSC|GalacticSupercluster|UI/3-Structures/|3|3|1|
LGF|GalacticFilament|UI/3-Structures/|3|3|2|
LGW|GalacticWall|UI/3-Structures/|3|3|3|
LUB|UniverseBubble|UI/3-Structures/|3|3|4|
GG|GasGiant|UI/4-Life/|4|0|0|
AB|AsteroidBelt|UI/4-Life/|4|0|1|
RP|RockyPlanet|UI/4-Life/|4|0|2|
HP|HabitablePlanet|UI/4-Life/|4|0|3|
LP|LivingPlanet|UI/4-Life/|4|0|4|5
C0|Civ0|UI/4-Life/|4|1|0|6
C1|Civ1|UI/4-Life/|4|1|1|7
C2|Civ2|UI/4-Life/|4|1|2|8
C3|Civ3|UI/4-Life/|4|1|3|9
C4|Civ4|UI/4-Life/|4|1|4|10
EON1|Archean|UI/4-Life/Living/|5|0|0|
EON2|Proterozoic|UI/4-Life/Living/|5|0|1|
EON3|Paleozoic|UI/4-Life/Living/|5|0|2|
EON4|Mezozoic|UI/4-Life/Living/|5|0|3|
EON5|Cenozoic|UI/4-Life/Living/|5|0|4|
C0.0|Civ0.0|UI/4-Life/Civ0/|6|0|0|
C0.1|Civ0.1|UI/4-Life/Civ0/|6|0|1|
C0.2|Civ0.2|UI/4-Life/Civ0/|6|0|2|
C0.3|Civ0.3|UI/4-Life/Civ0/|6|0|3|
C0.4|Civ0.4|UI/4-Life/Civ0/|6|0|4|
C0.5|Civ0.5|UI/4-Life/Civ0/|6|1|0|
C0.6|Civ0.6|UI/4-Life/Civ0/|6|1|1|
C0.7|Civ0.7|UI/4-Life/Civ0/|6|1|2|
C0.8|Civ0.8|UI/4-Life/Civ0/|6|1|3|
C0.9|Civ0.9|UI/4-Life/Civ0/|6|1|4|
C1.0|Civ1.0|UI/4-Life/Civ1/|7|0|0|
C1.1|Civ1.1|UI/4-Life/Civ1/|7|0|1|
C1.2|Civ1.2|UI/4-Life/Civ1/|7|0|2|
C1.3|Civ1.3|UI/4-Life/Civ1/|7|0|3|
C1.4|Civ1.4|UI/4-Life/Civ1/|7|0|4|
C1.5|Civ1.5|UI/4-Life/Civ1/|7|1|0|
C1.6|Civ1.6|UI/4-Life/Civ1/|7|1|1|
C1.7|Civ1.7|UI/4-Life/Civ1/|7|1|2|
C1.8|Civ1.8|UI/4-Life/Civ1/|7|1|3|
C1.9|Civ1.9|UI/4-Life/Civ1/|7|1|4|
C2.0|Civ2.0|UI/4-Life/Civ2/|8|0|0|
C2.1|Civ2.1|UI/4-Life/Civ2/|8|0|1|
C2.2|Civ2.2|UI/4-Life/Civ2/|8|0|2|
C2.3|Civ2.3|UI/4-Life/Civ2/|8|0|3|
C2.4|Civ2.4|UI/4-Life/Civ2/|8|0|4|
C2.5|Civ2.5|UI/4-Life/Civ2/|8|1|0|
C2.6|Civ2.6|UI/4-Life/Civ2/|8|1|1|
C2.7|Civ2.7|UI/4-Life/Civ2/|8|1|2|
C2.8|Civ2.8|UI/4-Life/Civ2/|8|1|3|
C2.9|Civ2.9|UI/4-Life/Civ2/|8|1|4|
C3.0|Civ3.0|UI/4-Life/Civ3/|9|0|0|
C3.1|Civ3.1|UI/4-Life/Civ3/|9|0|1|
C3.2|Civ3.2|UI/4-Life/Civ3/|9|0|2|
C3.3|Civ3.3|UI/4-Life/Civ3/|9|0|3|
C3.4|Civ3.4|UI/4-Life/Civ3/|9|0|4|
C3.5|Civ3.5|UI/4-Life/Civ3/|9|1|0|
C3.6|Civ3.6|UI/4-Life/Civ3/|9|1|1|
C3.7|Civ3.7|UI/4-Life/Civ3/|9|1|2|
C3.8|Civ3.8|UI/4-Life/Civ3/|9|1|3|
C3.9|Civ3.9|UI/4-Life/Civ3/|9|1|4|
C4.0|Civ4.0|UI/4-Life/Civ4/|10|0|0|
C4.1|Civ4.1|UI/4-Life/Civ4/|10|0|1|
C4.2|Civ4.2|UI/4-Life/Civ4/|10|0|2|
C4.3|Civ4.3|UI/4-Life/Civ4/|10|0|3|
C4.4|Civ4.4|UI/4-Life/Civ4/|10|0|4|
1 id name image page row col sub_page
2 Shovelin Shovelin UI/0-Forces/ 0 0 0
3 Inflatin Inflatin UI/0-Forces/ 0 0 1
4 Temporite Temporite UI/0-Forces/ 0 0 2
5 Collisite Collisite UI/0-Forces/ 0 0 3
6 Primex Primex UI/0-Forces/ 0 0 4
7 Singularite Singularite UI/0-Forces/ 0 1 0
8 Renewin Renewin UI/0-Forces/ 0 1 1
9 Infusite Infusite UI/0-Forces/ 0 1 2
10 Frostin Frostin UI/0-Forces/ 0 1 3
11 Destellarite Destellarite UI/0-Forces/ 0 1 4
12 Rockex Rockex UI/0-Forces/ 0 2 0
13 Panspermin Panspermin UI/0-Forces/ 0 2 1
14 Gaianite Gaianite UI/0-Forces/ 0 2 2
15 Darwinite Darwinite UI/0-Forces/ 0 2 3
16 Edenex Edenex UI/0-Forces/ 0 2 4
17 Pacifin Pacifin UI/0-Forces/ 0 3 0
18 Enragein Enragein UI/0-Forces/ 0 3 1
19 Moralite Moralite UI/0-Forces/ 0 3 2
20 Discriminite Discriminite UI/0-Forces/ 0 3 3
21 Reprex Reprex UI/0-Forces/ 0 3 4
22 S Space UI/1-Resources/ 1 0 0
23 H Hydrogen UI/1-Resources/ 1 1 0
24 He Helium UI/1-Resources/ 1 2 0
25 Met Metal UI/1-Resources/ 1 3 0
26 N Nebula UI/2-Stars/ 2 0 0
27 G Globula UI/2-Stars/ 2 0 1
28 STN StarNursery UI/2-Stars/ 2 0 2
29 MC MolecularCloud UI/2-Stars/ 2 0 3
30 ASTN ActiveStarNursery UI/2-Stars/ 2 0 4
31 BD BrownDwarf UI/2-Stars/ 2 1 0
32 RD RedDwarf UI/2-Stars/ 2 1 1
33 OD OrangeDwarf UI/2-Stars/ 2 1 2
34 YD YellowDwarf UI/2-Stars/ 2 1 3
35 WYD WhiteYellowDwarf UI/2-Stars/ 2 1 4
36 RG RedGiant UI/2-Stars/ 2 2 0
37 WS WhiteStar UI/2-Stars/ 2 2 1
38 BG BlueGiant UI/2-Stars/ 2 2 2
39 SG Supergiant UI/2-Stars/ 2 2 3
40 HG Hypergiant UI/2-Stars/ 2 2 4
41 WD WhiteDwarf UI/2-Stars/ 2 3 0
42 NS NeutronStar UI/2-Stars/ 2 3 1
43 MGT Magnetar UI/2-Stars/ 2 3 2
44 BH BlackHole UI/2-Stars/ 2 3 3
45 SMBH SupermassiveBlackHole UI/2-Stars/ 2 3 4
46 SCD StarClusterScattered UI/3-Structures/ 3 0 0
47 SCS StarClusterSmall UI/3-Structures/ 3 0 1
48 SCM StarClusterMedium UI/3-Structures/ 3 0 2
49 SCL StarClusterLarge UI/3-Structures/ 3 0 3
50 SCG StarClusterGiant UI/3-Structures/ 3 0 4
51 GED GalaxyEllipticalDwarf UI/3-Structures/ 3 1 0
52 GES GalaxyEllipticalSmall UI/3-Structures/ 3 1 1
53 GEM GalaxyEllipticalMedium UI/3-Structures/ 3 1 2
54 GEL GalaxyEllipticalLarge UI/3-Structures/ 3 1 3
55 GEG GalaxyEllipticalGiant UI/3-Structures/ 3 1 4
56 GSD GalaxySpiralDwarf UI/3-Structures/ 3 2 0
57 GSS GalaxySpiralSmall UI/3-Structures/ 3 2 1
58 GSM GalaxySpiralMedium UI/3-Structures/ 3 2 2
59 GSL GalaxySpiralLarge UI/3-Structures/ 3 2 3
60 GSG GalaxySpiralGiant UI/3-Structures/ 3 2 4
61 LGG GalacticGroup UI/3-Structures/ 3 3 0
62 LSC GalacticSupercluster UI/3-Structures/ 3 3 1
63 LGF GalacticFilament UI/3-Structures/ 3 3 2
64 LGW GalacticWall UI/3-Structures/ 3 3 3
65 LUB UniverseBubble UI/3-Structures/ 3 3 4
66 GG GasGiant UI/4-Life/ 4 0 0
67 AB AsteroidBelt UI/4-Life/ 4 0 1
68 RP RockyPlanet UI/4-Life/ 4 0 2
69 HP HabitablePlanet UI/4-Life/ 4 0 3
70 LP LivingPlanet UI/4-Life/ 4 0 4 5
71 C0 Civ0 UI/4-Life/ 4 1 0 6
72 C1 Civ1 UI/4-Life/ 4 1 1 7
73 C2 Civ2 UI/4-Life/ 4 1 2 8
74 C3 Civ3 UI/4-Life/ 4 1 3 9
75 C4 Civ4 UI/4-Life/ 4 1 4 10
76 EON1 Archean UI/4-Life/Living/ 5 0 0
77 EON2 Proterozoic UI/4-Life/Living/ 5 0 1
78 EON3 Paleozoic UI/4-Life/Living/ 5 0 2
79 EON4 Mezozoic UI/4-Life/Living/ 5 0 3
80 EON5 Cenozoic UI/4-Life/Living/ 5 0 4
81 C0.0 Civ0.0 UI/4-Life/Civ0/ 6 0 0
82 C0.1 Civ0.1 UI/4-Life/Civ0/ 6 0 1
83 C0.2 Civ0.2 UI/4-Life/Civ0/ 6 0 2
84 C0.3 Civ0.3 UI/4-Life/Civ0/ 6 0 3
85 C0.4 Civ0.4 UI/4-Life/Civ0/ 6 0 4
86 C0.5 Civ0.5 UI/4-Life/Civ0/ 6 1 0
87 C0.6 Civ0.6 UI/4-Life/Civ0/ 6 1 1
88 C0.7 Civ0.7 UI/4-Life/Civ0/ 6 1 2
89 C0.8 Civ0.8 UI/4-Life/Civ0/ 6 1 3
90 C0.9 Civ0.9 UI/4-Life/Civ0/ 6 1 4
91 C1.0 Civ1.0 UI/4-Life/Civ1/ 7 0 0
92 C1.1 Civ1.1 UI/4-Life/Civ1/ 7 0 1
93 C1.2 Civ1.2 UI/4-Life/Civ1/ 7 0 2
94 C1.3 Civ1.3 UI/4-Life/Civ1/ 7 0 3
95 C1.4 Civ1.4 UI/4-Life/Civ1/ 7 0 4
96 C1.5 Civ1.5 UI/4-Life/Civ1/ 7 1 0
97 C1.6 Civ1.6 UI/4-Life/Civ1/ 7 1 1
98 C1.7 Civ1.7 UI/4-Life/Civ1/ 7 1 2
99 C1.8 Civ1.8 UI/4-Life/Civ1/ 7 1 3
100 C1.9 Civ1.9 UI/4-Life/Civ1/ 7 1 4
101 C2.0 Civ2.0 UI/4-Life/Civ2/ 8 0 0
102 C2.1 Civ2.1 UI/4-Life/Civ2/ 8 0 1
103 C2.2 Civ2.2 UI/4-Life/Civ2/ 8 0 2
104 C2.3 Civ2.3 UI/4-Life/Civ2/ 8 0 3
105 C2.4 Civ2.4 UI/4-Life/Civ2/ 8 0 4
106 C2.5 Civ2.5 UI/4-Life/Civ2/ 8 1 0
107 C2.6 Civ2.6 UI/4-Life/Civ2/ 8 1 1
108 C2.7 Civ2.7 UI/4-Life/Civ2/ 8 1 2
109 C2.8 Civ2.8 UI/4-Life/Civ2/ 8 1 3
110 C2.9 Civ2.9 UI/4-Life/Civ2/ 8 1 4
111 C3.0 Civ3.0 UI/4-Life/Civ3/ 9 0 0
112 C3.1 Civ3.1 UI/4-Life/Civ3/ 9 0 1
113 C3.2 Civ3.2 UI/4-Life/Civ3/ 9 0 2
114 C3.3 Civ3.3 UI/4-Life/Civ3/ 9 0 3
115 C3.4 Civ3.4 UI/4-Life/Civ3/ 9 0 4
116 C3.5 Civ3.5 UI/4-Life/Civ3/ 9 1 0
117 C3.6 Civ3.6 UI/4-Life/Civ3/ 9 1 1
118 C3.7 Civ3.7 UI/4-Life/Civ3/ 9 1 2
119 C3.8 Civ3.8 UI/4-Life/Civ3/ 9 1 3
120 C3.9 Civ3.9 UI/4-Life/Civ3/ 9 1 4
121 C4.0 Civ4.0 UI/4-Life/Civ4/ 10 0 0
122 C4.1 Civ4.1 UI/4-Life/Civ4/ 10 0 1
123 C4.2 Civ4.2 UI/4-Life/Civ4/ 10 0 2
124 C4.3 Civ4.3 UI/4-Life/Civ4/ 10 0 3
125 C4.4 Civ4.4 UI/4-Life/Civ4/ 10 0 4
File diff suppressed because it is too large Load Diff
-240
View File
@@ -1,240 +0,0 @@
extends Control
const ITEM_BUTTON = preload("uid://d3xjfxwe3w16v")
const SPEED_TEXTURE_NAME_TEMPLATE = "res://UI/TopMenu/Time&Speed/Time%s.png"
const PAGE_COUNT = 5
const PAGE_WIDTH = 1080
const DRAG_TOLERANCE = 360
const SWIPE_DURATION: float = 2
const SWIPE_DELAY = 2000 # msec
@onready var stage_page_scroller: ScrollContainer = $StageRows/PageScroller
@onready var item_pages: Array[Control] = [
$StageRows/PageScroller/HBoxContainer/ForcePage/Forces,
$StageRows/PageScroller/HBoxContainer/ResourcePage/HBoxContainer/Resources,
$StageRows/PageScroller/HBoxContainer/StarPage/Stars,
$StageRows/PageScroller/HBoxContainer/StructurePage/Structures,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Life,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/LivingPlanet,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Civ0,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Civ1,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Civ2,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Civ3,
$StageRows/PageScroller/HBoxContainer/LifePage/Planets/Civ4
]
@onready var g_entity_descriptions: Array = [
$StageRows/PageScroller/HBoxContainer/ForcePage/Description,
$StageRows/PageScroller/HBoxContainer/ResourcePage/Description,
$StageRows/PageScroller/HBoxContainer/StarPage/Description,
$StageRows/PageScroller/HBoxContainer/StructurePage/Description,
$StageRows/PageScroller/HBoxContainer/LifePage/Description
]
@onready var date_time: Label = $StageRows/TopMenu/InfoPanel/DateTime
@onready var g_speed_icons: Array = [
$StageRows/TopMenu/InfoPanel/Speed/Speed1,
$StageRows/TopMenu/InfoPanel/Speed/Speed2,
$StageRows/TopMenu/InfoPanel/Speed/Speed3,
$StageRows/TopMenu/InfoPanel/Speed/Speed4,
$StageRows/TopMenu/InfoPanel/Speed/Speed5,
$StageRows/TopMenu/InfoPanel/Speed/Speed6,
$StageRows/TopMenu/InfoPanel/Speed/Speed7,
$StageRows/TopMenu/InfoPanel/Speed/Speed8
]
@onready var g_time_minus: TextureButton = $StageRows/TopMenu/TimeMinus
@onready var g_time_plus: TextureButton = $StageRows/TopMenu/TimePlus
var g_tween: Tween = null
var g_dragged_start: Vector2 = Vector2.ZERO
var g_scroll_start: int = 0
var g_current_page: int = 0
var g_last_scroll_updated: int = 0
var f_check_swipe: bool = false
var g_swipe_time_delta: float = 0
var g_counters: Dictionary[String, Counter] = {
"swipe": Counter.new(),
}
var ActiveEntities: Dictionary = {}
var owniverse = Owniverse.new()
func set_datetime(value: String):
date_time.text = value
func _on_indicator_pressed(indicator_name: String, page: int = 0):
_set_description(indicator_name, page)
func entity_activated(entity: OwniverseEntity) -> void:
_control_page(entity)
_set_entity_description(entity)
func _set_entity_description(entity: OwniverseEntity) -> void:
var description: String = "[b]" \
+ Global.get_localized_item_description(entity.entity_name, "label") \
+"[/b]" \
+"\n" \
+ Global.get_localized_item_description(entity.entity_name, "description")
var desc_page = clamp(entity.entity_page, 0, 4)
g_entity_descriptions[desc_page].text = description
func _set_description(item_name: String, page: int) -> void:
var description = Global.get_description(item_name + ".Name")
description += "\n"
description += Global.get_description(item_name + ".Description")
g_entity_descriptions[page].text = description
func _control_page(entity: OwniverseEntity) -> void:
if !ActiveEntities.has(entity.entity_page):
ActiveEntities[entity.entity_page] = null
var current_entity: OwniverseEntity = ActiveEntities[entity.entity_page]
if current_entity == entity:
return
ActiveEntities[entity.entity_page] = entity
if current_entity != null and current_entity.entity_page == entity.entity_page:
current_entity.set_selection(false)
entity.set_selection(true)
# subpages
if entity.sub_page != -1:
item_pages[entity.sub_page].visible = true
if current_entity == null \
or current_entity.sub_page == -1 \
or current_entity.sub_page == entity.sub_page:
return
item_pages[current_entity.sub_page].visible = false
func _init_entities() -> bool:
for e_id in Global.Entities:
var entity_properties: Dictionary = Global.Entities[e_id]
var entity: OwniverseEntity = ITEM_BUTTON.instantiate()
if !entity_properties.has("page"):
printerr("Entity `", e_id, "` has no `page` key.")
return false
var page: int = int(entity_properties.page)
item_pages[page].add_child(entity)
entity.init_button(entity_properties)
entity.entity_activated.connect(entity_activated)
return false
func _check_counters(delta: float) -> Array:
var actions: Array = []
for k in g_counters:
var cnt: Counter = g_counters[k]
if not cnt.is_active:
continue
cnt.value += delta
if cnt.value >= cnt.sec:
actions.append(k)
cnt.value = 0
cnt.is_active = false
return actions
func _do_actions(actions: Array) -> void:
for action: String in actions:
match action:
"swipe":
_swipe_to_nearest_page()
#region Swipe
func _swipe_to_nearest_page() -> void:
if stage_page_scroller.scroll_horizontal % PAGE_WIDTH == 0: return
var new_page: int = round(1.0 * stage_page_scroller.scroll_horizontal / PAGE_WIDTH)
if g_tween != null:
if g_tween.is_running():
return
g_tween = stage_page_scroller.get_tree().create_tween()
g_tween.tween_property(stage_page_scroller, "scroll_horizontal",
new_page * PAGE_WIDTH, SWIPE_DURATION).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
func _input(event: InputEvent) -> void:
if event is InputEventScreenDrag:
stage_page_scroller.scroll_horizontal = clamp(
stage_page_scroller.scroll_horizontal - PAGE_COUNT * event.screen_relative.x,
0, PAGE_WIDTH * (PAGE_COUNT - 1))
g_counters.swipe.is_active = true
g_counters.swipe.value = 0
elif event is InputEventPanGesture:
g_counters.swipe.is_active = true
g_counters.swipe.value = 0
elif event is InputEventScreenTouch:
pass
#endregion
func _ready() -> void:
_init_entities()
func _process(delta: float) -> void:
# Update date
var sdt: String = str(snapped(owniverse.add_time_delta(delta), 0.1))
set_datetime(sdt)
var actions = _check_counters(delta)
_do_actions(actions)
func _on_burger_button_pressed() -> void:
print("b")
pass # Replace with function body.
func _on_report_button_pressed() -> void:
print("r")
pass # Replace with function body.
func _change_speed(delta: int) -> void:
var speed: int = owniverse.change_speed(delta)
var ind: int = 1
for icon in g_speed_icons:
if ind <= speed:
icon.visible = true
else:
icon.visible = false
ind += 1
if speed == 1:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "x")
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "2")
elif speed == Global.SPEED_LIMIT:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(Global.SPEED_LIMIT - 1))
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "x")
else:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(speed - 1))
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(speed + 1))
func _on_topmenu_button_pressed(ButtonName) -> void:
print(ButtonName)
-1
View File
@@ -1 +0,0 @@
uid://dnshr5nb2v60a
-6
View File
@@ -1,6 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://dg15dpxiepicb"]
[ext_resource type="Texture2D" uid="uid://chxxghyul1im7" path="res://UI/Border/border-2px.png" id="1_6kaf8"]
[node name="Border" type="TextureRect"]
texture = ExtResource("1_6kaf8")
-40
View File
@@ -1,40 +0,0 @@
extends Control
class_name OwniverseEntity
signal entity_activated(entity)
const ENTITY_WIDTH = 216
const ENTITY_HEIGHT = 256
@onready var texture_button: TextureButton = $TextureButton
@onready var description: Label = $Description
@onready var selection: TextureRect = $Selection
@export var entity_name: String = ""
@export var entity_id: String = ""
@export var entity_page: int = -1
@export var sub_page: int = -1
func set_selection(flag: bool) -> void:
selection.visible = flag
func init_button(properties: Dictionary):
var image_path = "res://" + properties.image + properties.name + ".png"
texture_button.texture_normal = load(image_path)
position = Vector2i(int(properties.col) * ENTITY_WIDTH, int(properties.row) * ENTITY_HEIGHT)
entity_id = properties.id
entity_name = properties.name
entity_page = int(properties.page)
sub_page = int(properties.sub_page)
name = properties.id
set_selection(false)
#print(properties)
func _on_button_up() -> void:
set_selection(true)
entity_activated.emit(self)
#Texture_button.texture_normal = load("res://UI/0-Forces/Inflatin.png")
+144
View File
@@ -0,0 +1,144 @@
extends Node
const E = preload("res://world/owniverse/math/exact.gd")
const SPEED_LIMIT: int = 6
# Write a readable diagnostic copy next to the encrypted save. Never used for loading.
var save_plaintext_copy: bool = true
var Settings: Dictionary = {
"filename": "save-0001",
"sound_volume": 1.0,
"language": "en",
}
# TODO getter setter for locale
var Locales: Dictionary = {}
var Locale = "en"
var OwniverseEntities: Dictionary = {}
var OwniverseItems: Dictionary = {}
var Templates: Dictionary = {}
var LifeRules: Dictionary = {}
var CivilizationRules: Dictionary = {}
var batch_count: float = 40.0 # must be even not odd
func get_localized_item_description(item_id: String, item: String) -> String:
if Locales[Locale].has(item_id):
return Locales[Locale][item_id][item]
return ""
# Russian templates include the class; legacy English keys omit it.
func get_template(id: String, category: String, field: String) -> Dictionary:
var rows: Dictionary = Templates.get(Locale, {})
for key in [id + "." + category + "." + field, id + "." + field]:
if rows.has(key):
return rows[key]
return {}
func render_template(row: Dictionary, variables: Dictionary) -> String:
var result: String = str(row.get("text", ""))
for i in range(5):
var variable: String = str(row.get("value" + str(i), "")).strip_edges()
var value: String = str(variables.get(variable, "—")) if variable != "" else ""
result = result.replace("%value" + str(i) + "%", value)
return result.replace("<br>", "\n").replace("[p]", "\n")
func get_description(item_id: String, items: Array = []) -> String:
var row: Dictionary = Templates.get(Locale, {}).get(item_id, {})
var variables: Dictionary = {}
for i in mini(items.size(), 5):
variables[str(row.get("value" + str(i), ""))] = items[i]
return render_template(row, variables)
func format_number(value, digits: int = 0) -> String:
return E.grouped(value, digits)
func _ready() -> void:
CivilizationRules.clear()
for row: Dictionary in _read_from_csv("res://data/civilization_rules.txt").values():
if not CivilizationRules.has(row.stage):
CivilizationRules[row.stage] = {"home": row.home, "span": E.of(row.span), "stars": E.of(row.stars), "ethics": {},
"colonizes": row.colonizes == "1", "fights": row.fights == "1", "diplomacy": row.diplomacy == "1", "worships": row.worships == "1"}
CivilizationRules[row.stage].ethics[row.ethic] = row
var stages: Array = CivilizationRules.keys()
stages.sort()
for i in stages.size():
CivilizationRules[stages[i]].next = stages[i + 1] if i + 1 < stages.size() else "Ct"
CivilizationRules[stages[i]].previous = stages[i - 1] if i > 0 else "C0.1"
CivilizationRules[stages[i]].colony = stages[maxi(0, i - 2)]
CivilizationRules.Ct = {"home": "", "span": 0.0, "stars": 0.0, "ethics": {}, "next": "Ct", "previous": "C4.4", "colonizes": false, "fights": false, "diplomacy": false, "worships": false}
LifeRules = _read_from_csv("res://data/life_rules.txt")
OwniverseEntities = _read_from_csv("res://data/owniverse_entities.txt")
OwniverseItems = _read_from_csv("res://data/owniverse_items.txt")
Locales["en"] = _read_from_csv("res://data/locale.en.txt")
Locales["ru"] = _read_from_csv("res://data/locale.ru.txt")
Templates = OwniverseTemplate.get_data()
func _read_from_csv(file_path: String) -> Dictionary:
if not FileAccess.file_exists(file_path):
printerr("File not found: " + file_path)
return {}
var file = FileAccess.open(file_path, FileAccess.READ)
if file == null:
printerr("File can not be opened:" + file_path)
return {}
var headers: PackedStringArray = []
var data: Array = []
if not file.eof_reached():
headers = PackedStringArray()
for val in file.get_csv_line("|"):
headers.append(val.strip_edges())
while not file.eof_reached():
var raw_row = file.get_csv_line("|")
if raw_row.is_empty(): # пропускаем пустые строки
continue
var trimmed_row: PackedStringArray = []
for val in raw_row:
trimmed_row.append(val.strip_edges())
data.append(trimmed_row)
file.close()
var dict_data: Dictionary = {}
for row in data:
if row.size() < 2: continue
if row.size() == headers.size():
var dict: Dictionary = {}
for i in headers.size():
dict[headers[i]] = row[i]
dict_data[row[0]] = dict
return dict_data
func _read_folder_list(folder_name: String) -> void:
var dir := DirAccess.open(folder_name)
if dir == null: printerr("Could not open folder: ", folder_name); return
dir.list_dir_begin()
for file: String in dir.get_files():
print(" → ", file)
func _print_dict(dict_to_print: Dictionary):
for d in dict_to_print:
print(d, " → ", dict_to_print[d])
+1
View File
@@ -0,0 +1 @@
uid://dy0hrqie4ritn
+357
View File
@@ -0,0 +1,357 @@
# SaveManager.gd (добавить в AutoLoad)
extends Node
const E = preload("res://world/owniverse/math/exact.gd")
# ~/Library/Application Support/Godot/app_userdata/Owniverse Adventure/savegame.cfg
const SETTING_SECTION = "Settings"
const SAVE_PATH = "user://settings.cfg"
const FORMAT_VERSION : int = 5
const SimulationTime = preload("res://world/owniverse/simulation_time.gd")
const WorldParameters = preload("res://world/owniverse/world_parameters.gd")
const STATE_VERSION : String = SimulationTime.STATE_VERSION
var last_error: String = ""
var blocked_saves: Dictionary = {}
var save_directory: String = "user://"
signal save_completed ( filename : String , success : bool , error : String )
signal saves_drained
# Queue ownership stays on the main thread. The worker only sees its snapshot.
var _save_thread: Thread
var _active_filename: String = ""
var _pending_saves: Dictionary = {}
func _process(_delta: Variant) -> void:
if (E.ne(_save_thread, null) and (not _save_thread.is_alive())):
_finish_save()
func is_saving() -> bool:
return (E.ne(_save_thread, null) or (not _pending_saves.is_empty()))
func _snapshot(filename: String, password: String, data: Dictionary) -> Dictionary:
var payload: Dictionary = E.encode(data)
payload.format_version = FORMAT_VERSION
payload.app_version = str(ProjectSettings.get_setting("application/config/version", ""))
return {"filename": filename, "path": save_directory.path_join(E.add(filename, ".adventure")), "password": password, "payload": payload, "plaintext": Global.save_plaintext_copy, "speed_limit": Global.SPEED_LIMIT, "stages": Global.CivilizationRules.keys(), "entities": Global.OwniverseEntities.keys()}
## True means queued, not written. Completion is reported by save_completed.
func request_save(filename: String, password: String, data: Dictionary) -> bool:
if blocked_saves.has(filename):
return _fail(E.add("Save blocked to preserve an unreadable save: ", filename))
_pending_saves[filename] = _snapshot(filename, password, data)
if E.eq(_save_thread, null):
_start_save()
return true
func _start_save() -> void:
if _pending_saves.is_empty():
return
_active_filename = _pending_saves.keys()[0]
var job: Dictionary = _pending_saves[_active_filename]
_pending_saves.erase(_active_filename)
_save_thread = Thread.new()
var error: Error = _save_thread.start(_write_snapshot.bind(job))
if E.ne(error, OK):
_save_thread = null
_fail(E.add("Cannot start save worker: ", error_string(error)))
save_completed.emit(_active_filename, false, last_error)
_start_save()
if (not is_saving()): saves_drained.emit()
func _finish_save() -> void:
var error: String = _save_thread.wait_to_finish()
var filename: String = _active_filename
_save_thread = null
last_error = error
if E.ne(error, ""): push_error(error)
save_completed.emit(filename, E.eq(error, ""), error)
if E.eq(_save_thread, null): _start_save()
if (not is_saving()): saves_drained.emit()
## Used for application suspension and teardown, when frames may stop arriving.
func flush_saves() -> void:
while is_saving():
if E.eq(_save_thread, null): _start_save()
if E.ne(_save_thread, null): _finish_save()
func _exit_tree() -> void:
flush_saves()
#region Save Load routines
func _fail(message: String) -> bool:
last_error = message
push_error(message)
return false
func save_data(filename: String, password: String, data: Dictionary) -> bool:
# Synchronous compatibility API must never race an asynchronous writer.
flush_saves()
last_error = ""
if blocked_saves.has(filename):
return _fail(E.add("Save blocked to preserve an unreadable save: ", filename))
var error: String = _write_snapshot(_snapshot(filename, password, data))
return (_fail(error) if E.ne(error, "") else true)
static func _write_snapshot(job: Dictionary) -> String:
var payload: Dictionary = job.payload
var problem: String = _validate_payload(payload, job.speed_limit, job.stages, job.entities)
if E.ne(problem, ""):
return E.add("Invalid save: ", problem)
var path: String = job.path
var temporary: String = E.add(path, ".tmp")
var file = FileAccess.open_encrypted_with_pass(temporary, FileAccess.WRITE, job.password)
if E.eq(file, null):
return E.add("Cannot write encrypted save: ", temporary)
file.store_var(payload, false)
file.close()
# Check the actual encrypted file, including finalization, before replacing the old save.
var verification = FileAccess.open_encrypted_with_pass(temporary, FileAccess.READ, job.password)
if E.eq(verification, null):
return E.add("Cannot verify encrypted save: ", temporary)
var restored: Variant = verification.get_var(false)
verification.close()
if ((not (restored is Dictionary)) or E.ne(restored, payload)):
return E.add("Encrypted save verification failed: ", temporary)
if E.ne(DirAccess.rename_absolute(temporary, path), OK):
return E.add("Cannot replace encrypted save: ", path)
if job.plaintext:
var plain_path: String = E.add(path, ".json")
file = FileAccess.open(E.add(plain_path, ".tmp"), FileAccess.WRITE)
if E.eq(file, null):
return E.add("Encrypted save written, but cannot write diagnostic copy: ", plain_path)
file.store_string(E.add(JSON.stringify(payload, " ", true, true), "\n"))
file.flush()
var write_error: Error = file.get_error()
file.close()
if (E.ne(write_error, OK) or E.ne(DirAccess.rename_absolute(E.add(plain_path, ".tmp"), plain_path), OK)):
return E.add("Encrypted save written, but diagnostic copy failed: ", plain_path)
return ""
func load_data(filename: String, password: String) -> Dictionary:
flush_saves()
last_error = ""
# Plaintext is diagnostic only: never use it as a fallback.
var path: String = save_directory.path_join(E.add(filename, ".adventure"))
if (not FileAccess.file_exists(path)):
return {}
var file = FileAccess.open_encrypted_with_pass(path, FileAccess.READ, password)
if E.eq(file, null):
blocked_saves[filename] = true
_fail(E.add("Cannot decrypt save: ", path))
return {}
var data: Variant = file.get_var(false)
file.close()
# Unsupported formats are archived, never converted or overwritten.
# Returning no data lets the stage start a new, saveable session.
if ((data is Dictionary) and E.ne(data.get("format_version"), FORMAT_VERSION)):
var archive: String = E.add(path, ".incompatible.bak")
var index: int = 0
while FileAccess.file_exists(archive):
index = E.add(index, 1)
archive = E.add(E.add(path, ".incompatible.bak."), str(index))
var error: Error = DirAccess.rename_absolute(path, archive)
if E.ne(error, OK):
blocked_saves[filename] = true
_fail(E.add("Cannot archive incompatible save: ", error_string(error)))
return {}
blocked_saves.erase(filename)
push_warning(E.add(E.add("Incompatible save preserved at ", archive), "; starting a new game."))
return {}
var problem: String = validate_data(data)
if E.ne(problem, ""):
blocked_saves[filename] = true
_fail(E.add(E.add(E.add("Invalid save ", path), ": "), problem))
return {}
blocked_saves.erase(filename)
return E.decode(data)
static func _number(value: Variant, whole: bool = false, nonnegative: bool = true) -> bool:
return E.numeric(value) and E.finite(value) and (not value is float or absf(value) < 1e28) and (not whole or E.eq(value, E.floor_value(value))) and (not nonnegative or E.ge(value, 0))
static func _number_map(value: Variant, whole: bool = false, nonnegative: bool = true) -> bool:
if (not (value is Dictionary)):
return false
for key in value:
if ((not (((key is String) or (key is StringName)))) or (not _number(value[key], whole, nonnegative))):
return false
return true
static func _plain_tree(value: Variant) -> bool:
if (value is Dictionary):
for key in value:
if ((not (((key is String) or (key is StringName)))) or (not _plain_tree(value[key]))):
return false
return true
if (value is Array):
for item in value:
if (not _plain_tree(item)):
return false
return true
return ((((E.eq(value, null) or (value is String)) or (value is StringName)) or (value is bool)) or _number(value, false, false))
## Return a diagnostic path on failure; an empty string means the structure is valid.
func validate_data(data: Variant) -> String:
return _validate_payload(data, Global.SPEED_LIMIT, Global.CivilizationRules.keys(), Global.OwniverseEntities.keys())
static func _validate_payload(data: Variant, speed_limit: int, stages: Array, entities: Array) -> String:
if not E.valid_encoded(data): return "invalid exact number encoding"
data = E.decode(data)
if ((not (data is Dictionary)) or (not _plain_tree(data))):
return "save must contain plain finite values"
if (E.ne(data.get("format_version"), FORMAT_VERSION) or (not (data.get("app_version") is String))):
return "unsupported save format"
if (((not (data.get("ui") is Dictionary)) or (not E.numeric(data.ui.get("current_page")))) or E.lt(data.ui.current_page, 0)):
return "invalid ui.current_page"
if (not (data.get("state") is Dictionary)):
return "state must be a Dictionary"
var saved: Dictionary = data.state
var required = ["version", "time", "speed", "speed_in_year", "energy", "batches", "batch_origins", "binds", "amount", "distribution", "auto_resources", "auto_star_deficits", "production_remainders", "resource_remainders", "evolution_remainders", "life_remainders", "planet_remainders", "blast_remainders", "destruction_remainders", "civilization_remainders", "civilization_stats", "civilization_homes", "ethics", "stats"]
# Optional additions to the current format. Saves predating indicators keep
# their quantities and receive neutral defaults from Owniverse on load.
for field in saved:
if (not E.contains(required, field) and not E.contains(["world_parameters", "trends"], field)):
return "unsupported state structure"
if saved.has("world_parameters"):
if ((not _number_map(saved.world_parameters)) or E.ne(saved.world_parameters.size(), WorldParameters.defaults().size())):
return "invalid state.world_parameters"
for key in WorldParameters.defaults():
if ((not saved.world_parameters.has(key)) or E.lt(saved.world_parameters[key], 1)):
return E.add("invalid world parameter ", key)
if (E.contains(["Bur", "Exp", "Agg"], key) and E.gt(saved.world_parameters[key], 19)):
return E.add("invalid world scale ", key)
if saved.has("trends"):
if ((not _number_map(saved.trends)) or E.ne(saved.trends.size(), WorldParameters.TRENDS.size())):
return "invalid state.trends"
for key in WorldParameters.TRENDS:
if ((not saved.trends.has(key)) or E.ge(saved.trends[key], 1)):
return E.add("invalid trend ", key)
for field in required:
if (not saved.has(field)):
return E.add("missing state.", field)
if E.ne(saved.version, STATE_VERSION):
return "unsupported state.version"
if (((not (saved.time is Dictionary)) or (not _number(saved.time.get("datetime")))) or (not _number(saved.time.get("year")))):
return "invalid state.time"
if E.ne(saved.time.year, SimulationTime.processed_year(saved.time.datetime)):
return "invalid processed time"
if saved.time.has("tick_remainder"):
if not E.finite(saved.time.tick_remainder) or E.ge(E.absolute(saved.time.tick_remainder), 1):
return "invalid fractional tick"
if (((not _number(saved.speed, true)) or E.lt(saved.speed, 1)) or E.gt(saved.speed, speed_limit)):
return "invalid state.speed"
if ((not _number(saved.speed_in_year)) or E.ne(saved.speed_in_year, E.power(10, E.subtract(saved.speed, 1)))):
return "invalid state.speed_in_year"
if data.has("simulation"):
var checkpoint: Variant = data.simulation
if not checkpoint is Dictionary or not checkpoint.get("productions") is Array:
return "invalid simulation checkpoint"
if not _number(checkpoint.get("speed"), true) or E.lt(checkpoint.speed, 1) or E.gt(checkpoint.speed, speed_limit):
return "invalid simulation speed"
for name in ["requested_clock", "active_clock"]:
var clock: Variant = checkpoint.get(name)
if not clock is Dictionary: return "invalid simulation clock"
if clock.is_empty(): continue
if not _number(clock.get("datetime")) or not _number(clock.get("year")):
return "invalid simulation clock"
if E.lt(clock.datetime, saved.time.datetime) or E.ne(clock.year, SimulationTime.processed_year(clock.datetime)):
return "invalid simulation clock"
if not E.finite(clock.get("tick_remainder", 0)) or E.ge(E.absolute(clock.get("tick_remainder", 0)), 1):
return "invalid simulation tick"
if not checkpoint.active_clock.is_empty():
if checkpoint.requested_clock.is_empty() or E.gt(checkpoint.active_clock.datetime, checkpoint.requested_clock.datetime):
return "invalid simulation clock order"
for command in checkpoint.productions:
if not command is Dictionary or not entities.has(command.get("id")) or not command.get("resource") is bool or not _number(command.get("amount")):
return "invalid queued production"
if command.resource and command.id not in ["S", "H"]: return "invalid queued resource production"
if ((not _number(saved.energy, true)) or (not _number_map(saved.amount, true))):
return "invalid state resources"
if ((not (saved.stats is Dictionary)) or (not _number_map(saved.stats.get("total_amount"), true))):
return "invalid state.stats.total_amount"
if E.ne(saved.amount.keys(), saved.stats.total_amount.keys()):
return "amount and total_amount keys differ"
if ((not (saved.binds is Dictionary)) or (not (saved.batches is Dictionary))):
return "state.binds and state.batches must be Dictionaries"
for owner_id in saved.binds:
if ((not saved.amount.has(owner_id)) or (not _number_map(saved.binds[owner_id], true))):
return E.add("invalid state.binds.", owner_id)
for id in saved.binds[owner_id]:
if (not saved.amount.has(id)):
return E.add("unknown bound resource ", id)
for id in saved.batches:
if ((not saved.amount.has(id)) or (not (saved.batches[id] is Array))):
return E.add("invalid state.batches.", id)
for batch in saved.batches[id]:
if ((((not (batch is Dictionary)) or (not _number(batch.get("amount"), true))) or (not _number(batch.get("start_year")))) or (not _number(batch.get("end_year")))):
return E.add("invalid batch in ", id)
if E.lt(batch.end_year, batch.start_year):
return E.add("reversed batch interval in ", id)
if E.ne(batch.has("created_from"), batch.has("created_to")):
return E.add("incomplete batch creation interval in ", id)
if (batch.has("created_from") and (((((not _number(batch.created_from)) or (not _number(batch.created_to))) or E.le(batch.created_to, batch.created_from)) or E.lt(batch.start_year, batch.created_from)))):
return E.add("invalid batch creation interval in ", id)
if (batch.has("processed_until") and ((((not _number(batch.processed_until)) or E.lt(batch.processed_until, batch.start_year)) or E.gt(batch.processed_until, batch.end_year)))):
return E.add("invalid batch.processed_until in ", id)
if (batch.has("withdraw_remainder") and (((not _number(batch.withdraw_remainder)) or E.gt(batch.withdraw_remainder, batch.amount)))):
return E.add("invalid batch.withdraw_remainder in ", id)
for field in ["batch_origins", "distribution", "production_remainders", "evolution_remainders", "planet_remainders", "blast_remainders", "destruction_remainders", "life_remainders", "civilization_remainders", "civilization_stats"]:
if (not _number_map(saved[field], false, false)):
return E.add("invalid state.", field)
if ((not _number_map(saved.auto_resources, true)) or (not _number_map(saved.auto_star_deficits, false, false))):
return "invalid automatic production state"
if ((((not (saved.resource_remainders is Dictionary)) or E.ne(saved.resource_remainders.keys().size(), 2)) or (not saved.resource_remainders.has("basic"))) or (not saved.resource_remainders.has("automatic"))):
return "invalid state.resource_remainders"
for channel in ["basic", "automatic"]:
if (not _number_map(saved.resource_remainders[channel], false, false)):
return E.add("invalid state.resource_remainders.", channel)
if ((not (saved.ethics is Dictionary)) or (not (saved.civilization_homes is Dictionary))):
return "invalid civilization state"
for id in saved.ethics:
if (not E.contains(stages, id) or (not _number_map(saved.ethics[id], true))):
return E.add("invalid state.ethics.", str(id))
for ethic in saved.ethics[id]:
if not E.contains(["m", "l", "w", "d", "c", "b"], ethic):
return E.add("invalid ethic ", str(ethic))
for id in saved.civilization_homes:
if (not _number_map(saved.civilization_homes[id], true)):
return "invalid civilization homes"
return ""
#endregion
#region Settings
func save_settings():
var config = ConfigFile.new()
for item in Global.Settings:
config.set_value(SETTING_SECTION, item, Global.Settings[item])
config.save(SAVE_PATH)
func load_settings():
var config = ConfigFile.new()
var err = config.load(SAVE_PATH)
if E.ne(err, OK):
return false
for item in Global.Settings:
Global.Settings[item] = config.get_value(SETTING_SECTION, item, Global.Settings[item])
return true
#endregion
-5
View File
@@ -1,5 +0,0 @@
extends Node
func print_smth(smth: String):
pass
#print(smth)
-1
View File
@@ -1 +0,0 @@
uid://xte4iwvipeve
+259
View File
@@ -0,0 +1,259 @@
id|stage|span|home|stars|colonizes|fights|diplomacy|worships|ethic|progress|degradation|colonization|war|diplomacy_rate|worship|fall
C0.2:m|C0.2|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.1:1
C0.2:b|C0.2|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.1:1
C0.2:d|C0.2|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.1:1
C0.2:l|C0.2|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.1:1
C0.2:c|C0.2|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.1:1
C0.2:w|C0.2|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.1:1
C0.3:m|C0.3|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.2:1
C0.3:b|C0.3|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.2:1
C0.3:d|C0.3|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.2:1
C0.3:l|C0.3|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.2:1
C0.3:c|C0.3|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.2:1
C0.3:w|C0.3|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.2:1
C0.4:m|C0.4|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.3:1
C0.4:b|C0.4|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.3:1
C0.4:d|C0.4|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.3:1
C0.4:l|C0.4|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.3:1
C0.4:c|C0.4|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.3:1
C0.4:w|C0.4|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.3:1
C0.5:m|C0.5|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.4:1
C0.5:b|C0.5|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.4:1
C0.5:d|C0.5|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.4:1
C0.5:l|C0.5|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.4:1
C0.5:c|C0.5|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.4:1
C0.5:w|C0.5|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.4:1
C0.6:m|C0.6|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.5:1
C0.6:b|C0.6|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.5:1
C0.6:d|C0.6|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.5:1
C0.6:l|C0.6|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.5:1
C0.6:c|C0.6|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.5:1
C0.6:w|C0.6|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.5:1
C0.7:m|C0.7|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.6:1
C0.7:b|C0.7|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.6:1
C0.7:d|C0.7|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.6:1
C0.7:l|C0.7|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.6:1
C0.7:c|C0.7|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.6:1
C0.7:w|C0.7|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.6:1
C0.8:m|C0.8|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.7:1
C0.8:b|C0.8|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.7:1
C0.8:d|C0.8|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.7:1
C0.8:l|C0.8|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.7:1
C0.8:c|C0.8|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.7:1
C0.8:w|C0.8|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.7:1
C0.9:m|C0.9|2E+03||||||1|m|0.0084|0.01|0.0000625|0.001024||1.6|C0.8:512^C0.7:256^EON5:21^EON1:6
C0.9:b|C0.9|2E+03||||||1|b|0.01859375|0.02|0.00003125|0.0025||1|C0.8:512^C0.7:256^EON5:43^EON1:9
C0.9:d|C0.9|2E+03||||||1|d|0.0112|0.01538461538|0.0005|0.00015625||1|C0.8:512^C0.7:256^EON5:7^EON1:3
C0.9:l|C0.9|2E+03||||||1|l|0.0504|0.03571428571|0.0005|0.0025||0.5|C0.8:512^C0.7:256^EON5:60^EON1:11
C0.9:c|C0.9|2E+03||||||1|c|0.021|0.02604166667|0.004096|0.006103515625||0.8|C0.8:512^C0.7:256^EON5:252^EON1:19
C0.9:w|C0.9|2E+03||||||1|w|0.02625|0.03125|0.0005|0.016384||1.25|C0.8:512^C0.7:256^EON5:260^EON1:26
C1.0:m|C1.0|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C0.9:1024^EON5:21^EON1:6
C1.0:b|C1.0|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C0.9:1024^EON5:43^EON1:9
C1.0:d|C1.0|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C0.9:1024^EON5:7^EON1:3
C1.0:l|C1.0|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C0.9:1024^EON5:60^EON1:11
C1.0:c|C1.0|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C0.9:1024^EON5:152^EON1:19
C1.0:w|C1.0|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C0.9:1024^EON5:260^EON1:26
C1.1:m|C1.1|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.0:1024^C0.9:256^EON5:21^EON1:6
C1.1:b|C1.1|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.0:1024^C0.9:256^EON5:43^EON1:9
C1.1:d|C1.1|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.0:1024^C0.9:256^EON5:7^EON1:3
C1.1:l|C1.1|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.0:1024^C0.9:256^EON5:60^EON1:11
C1.1:c|C1.1|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.0:1024^C0.9:256^EON5:152^EON1:19
C1.1:w|C1.1|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.0:1024^C0.9:256^EON5:260^EON1:26
C1.2:m|C1.2|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.1:256^C1.0:1024^C0.9:256^EON5:21^EON1:6
C1.2:b|C1.2|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.1:256^C1.0:1024^C0.9:256^EON5:43^EON1:9
C1.2:d|C1.2|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.1:256^C1.0:1024^C0.9:256^EON5:7^EON1:3
C1.2:l|C1.2|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.1:256^C1.0:1024^C0.9:256^EON5:60^EON1:11
C1.2:c|C1.2|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.1:256^C1.0:1024^C0.9:256^EON5:152^EON1:19
C1.2:w|C1.2|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.1:256^C1.0:1024^C0.9:256^EON5:260^EON1:26
C1.3:m|C1.3|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.2:256^C1.0:1024^C0.9:64^EON5:13^EON1:13
C1.3:b|C1.3|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.2:256^C1.0:1024^C0.9:64^EON5:22^EON1:22
C1.3:d|C1.3|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.2:256^C1.0:1024^C0.9:64^EON5:5^EON1:5
C1.3:l|C1.3|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.2:256^C1.0:1024^C0.9:64^EON5:30^EON1:30
C1.3:c|C1.3|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.2:256^C1.0:1024^C0.9:64^EON5:64^EON1:64
C1.3:w|C1.3|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.2:256^C1.0:1024^C0.9:64^EON5:100^EON1:100
C1.4:m|C1.4|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.3:384^C1.0:896^EON5:6^EON1:21
C1.4:b|C1.4|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.3:384^C1.0:896^EON5:9^EON1:43
C1.4:d|C1.4|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.3:384^C1.0:896^EON5:3^EON1:7
C1.4:l|C1.4|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.3:384^C1.0:896^EON5:11^EON1:60
C1.4:c|C1.4|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.3:384^C1.0:896^EON5:19^EON1:152
C1.4:w|C1.4|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.3:384^C1.0:896^EON5:26^EON1:260
C1.5:m|C1.5|5E+03||||||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.4:512^C1.0:768^EON5:6^EON1:21
C1.5:b|C1.5|5E+03||||||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.4:512^C1.0:768^EON5:9^EON1:43
C1.5:d|C1.5|5E+03||||||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.4:512^C1.0:768^EON5:3^EON1:7
C1.5:l|C1.5|5E+03||||||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.4:512^C1.0:768^EON5:11^EON1:60
C1.5:c|C1.5|5E+03||||||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.4:512^C1.0:768^EON5:19^EON1:152
C1.5:w|C1.5|5E+03||||||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.4:512^C1.0:768^EON5:26^EON1:260
C1.6:m|C1.6|5E+03|||1|||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.5:768^C1.0:512^EON5:6^RP:21
C1.6:b|C1.6|5E+03|||1|||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.5:768^C1.0:512^EON5:9^RP:43
C1.6:d|C1.6|5E+03|||1|||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.5:768^C1.0:512^EON5:3^RP:7
C1.6:l|C1.6|5E+03|||1|||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.5:768^C1.0:512^EON5:11^RP:60
C1.6:c|C1.6|5E+03|||1|||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.5:768^C1.0:512^EON5:19^RP:152
C1.6:w|C1.6|5E+03|||1|||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.5:768^C1.0:512^EON5:26^RP:260
C1.7:m|C1.7|5E+03|||1|||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.6:896^C1.0:384^EON5:6^RP:21
C1.7:b|C1.7|5E+03|||1|||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.6:896^C1.0:384^EON5:9^RP:43
C1.7:d|C1.7|5E+03|||1|||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.6:896^C1.0:384^EON5:3^RP:7
C1.7:l|C1.7|5E+03|||1|||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.6:896^C1.0:384^EON5:11^RP:60
C1.7:c|C1.7|5E+03|||1|||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.6:896^C1.0:384^EON5:19^RP:152
C1.7:w|C1.7|5E+03|||1|||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.6:896^C1.0:384^EON5:26^RP:260
C1.8:m|C1.8|5E+03|||1|||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.7:1024^C1.0:256^EON5:6^RP:21
C1.8:b|C1.8|5E+03|||1|||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.7:1024^C1.0:256^EON5:9^RP:43
C1.8:d|C1.8|5E+03|||1|||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.7:1024^C1.0:256^EON5:3^RP:7
C1.8:l|C1.8|5E+03|||1|||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.7:1024^C1.0:256^EON5:11^RP:60
C1.8:c|C1.8|5E+03|||1|||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.7:1024^C1.0:256^EON5:19^RP:152
C1.8:w|C1.8|5E+03|||1|||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.7:1024^C1.0:256^EON5:26^RP:260
C1.9:m|C1.9|5E+03|||1|||1|m|0.009|0.01|0.0000625|0.001024||1.6|C1.8:1024^C1.0:128^EON5:6^RP:21
C1.9:b|C1.9|5E+03|||1|||1|b|0.019921875|0.02|0.00003125|0.0025||1|C1.8:1024^C1.0:128^EON5:9^RP:43
C1.9:d|C1.9|5E+03|||1|||1|d|0.012|0.01538461538|0.0005|0.00015625||1|C1.8:1024^C1.0:128^EON5:3^RP:7
C1.9:l|C1.9|5E+03|||1|||1|l|0.054|0.03571428571|0.0005|0.0025||0.5|C1.8:1024^C1.0:128^EON5:11^RP:60
C1.9:c|C1.9|5E+03|||1|||1|c|0.0225|0.02604166667|0.004096|0.006103515625||0.8|C1.8:1024^C1.0:128^EON5:19^RP:152
C1.9:w|C1.9|5E+03|||1|||1|w|0.028125|0.03125|0.0005|0.016384||1.25|C1.8:1024^C1.0:128^EON5:26^RP:260
C2.0:m|C2.0|5E+03|DwStar|1E+00|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C1.9:1024^C1.0:128^RP:28
C2.0:b|C2.0|5E+03|DwStar|1E+00|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C1.9:1024^C1.0:128^EON5:9^RP:59
C2.0:d|C2.0|5E+03|DwStar|1E+00|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C1.9:1024^C1.0:128^EON5:3^RP:8
C2.0:l|C2.0|5E+03|DwStar|1E+00|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C1.9:1024^C1.0:128^EON5:11^RP:85
C2.0:c|C2.0|5E+03|DwStar|1E+00|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C1.9:1024^C1.0:128^EON5:19^RP:235
C2.0:w|C2.0|5E+03|DwStar|1E+00|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C1.9:1024^C1.0:128^EON5:26^RP:419
C2.1:m|C2.1|5E+03|DwStar|1E+01|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.0:1
C2.1:b|C2.1|5E+03|DwStar|1E+01|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.0:1
C2.1:d|C2.1|5E+03|DwStar|1E+01|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.0:1
C2.1:l|C2.1|5E+03|DwStar|1E+01|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.0:1
C2.1:c|C2.1|5E+03|DwStar|1E+01|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.0:1
C2.1:w|C2.1|5E+03|DwStar|1E+01|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.0:1
C2.2:m|C2.2|1E+04|DwStar|1E+02|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.1:1024^C2.0:6
C2.2:b|C2.2|1E+04|DwStar|1E+02|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.1:1024^C2.0:9
C2.2:d|C2.2|1E+04|DwStar|1E+02|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.1:1024^C2.0:3
C2.2:l|C2.2|1E+04|DwStar|1E+02|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.1:1024^C2.0:11
C2.2:c|C2.2|1E+04|DwStar|1E+02|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.1:1024^C2.0:19
C2.2:w|C2.2|1E+04|DwStar|1E+02|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.1:1024^C2.0:26
C2.3:m|C2.3|2E+04|DwStar|1E+03|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.2:1024^C2.1:6
C2.3:b|C2.3|2E+04|DwStar|1E+03|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.2:1024^C2.1:9
C2.3:d|C2.3|2E+04|DwStar|1E+03|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.2:1024^C2.1:3
C2.3:l|C2.3|2E+04|DwStar|1E+03|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.2:1024^C2.1:11
C2.3:c|C2.3|2E+04|DwStar|1E+03|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.2:1024^C2.1:19
C2.3:w|C2.3|2E+04|DwStar|1E+03|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.2:1024^C2.1:26
C2.4:m|C2.4|2E+04|DwStar|1E+04|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.3:1024^C2.2:6
C2.4:b|C2.4|2E+04|DwStar|1E+04|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.3:1024^C2.2:9
C2.4:d|C2.4|2E+04|DwStar|1E+04|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.3:1024^C2.2:3
C2.4:l|C2.4|2E+04|DwStar|1E+04|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.3:1024^C2.2:11
C2.4:c|C2.4|2E+04|DwStar|1E+04|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.3:1024^C2.2:19
C2.4:w|C2.4|2E+04|DwStar|1E+04|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.3:1024^C2.2:26
C2.5:m|C2.5|3E+04|DwStar|1E+05|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.4:1024^C2.3:6
C2.5:b|C2.5|3E+04|DwStar|1E+05|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.4:1024^C2.3:9
C2.5:d|C2.5|3E+04|DwStar|1E+05|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.4:1024^C2.3:3
C2.5:l|C2.5|3E+04|DwStar|1E+05|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.4:1024^C2.3:11
C2.5:c|C2.5|3E+04|DwStar|1E+05|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.4:1024^C2.3:19
C2.5:w|C2.5|3E+04|DwStar|1E+05|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.4:1024^C2.3:26
C2.6:m|C2.6|3E+04|DwStar|1E+06|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.5:1024^C2.4:6
C2.6:b|C2.6|3E+04|DwStar|1E+06|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.5:1024^C2.4:9
C2.6:d|C2.6|3E+04|DwStar|1E+06|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.5:1024^C2.4:3
C2.6:l|C2.6|3E+04|DwStar|1E+06|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.5:1024^C2.4:11
C2.6:c|C2.6|3E+04|DwStar|1E+06|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.5:1024^C2.4:19
C2.6:w|C2.6|3E+04|DwStar|1E+06|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.5:1024^C2.4:26
C2.7:m|C2.7|4E+04|GiStar|1E+07|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.6:1024^C2.5:6
C2.7:b|C2.7|4E+04|GiStar|1E+07|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.6:1024^C2.5:9
C2.7:d|C2.7|4E+04|GiStar|1E+07|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.6:1024^C2.5:3
C2.7:l|C2.7|4E+04|GiStar|1E+07|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.6:1024^C2.5:11
C2.7:c|C2.7|4E+04|GiStar|1E+07|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.6:1024^C2.5:19
C2.7:w|C2.7|4E+04|GiStar|1E+07|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.6:1024^C2.5:26
C2.8:m|C2.8|4E+04|GiStar|1E+08|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.7:1024^C2.6:6
C2.8:b|C2.8|4E+04|GiStar|1E+08|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.7:1024^C2.6:9
C2.8:d|C2.8|4E+04|GiStar|1E+08|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.7:1024^C2.6:3
C2.8:l|C2.8|4E+04|GiStar|1E+08|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.7:1024^C2.6:11
C2.8:c|C2.8|4E+04|GiStar|1E+08|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.7:1024^C2.6:19
C2.8:w|C2.8|4E+04|GiStar|1E+08|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.7:1024^C2.6:26
C2.9:m|C2.9|5E+04|GiStar|1E+09|1|1|1|1|m|0.006|0.01|0.0005|0.00128|1|1.6|C2.8:1024^C2.7:6
C2.9:b|C2.9|5E+04|GiStar|1E+09|1|1|1|1|b|0.02125|0.015625|0.00003125|0.0025|0.64|1|C2.8:1024^C2.7:9
C2.9:d|C2.9|5E+04|GiStar|1E+09|1|1|1|1|d|0.0128|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.8:1024^C2.7:3
C2.9:l|C2.9|5E+04|GiStar|1E+09|1|1|1|1|l|0.0576|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.8:1024^C2.7:11
C2.9:c|C2.9|5E+04|GiStar|1E+09|1|1|1|1|c|0.024|0.04166666667|0.004096|0.006103515625|1|0.8|C2.8:1024^C2.7:19
C2.9:w|C2.9|5E+04|GiStar|1E+09|1|1|1|1|w|0.03|0.025|0.000256|0.03072|0.25|1.25|C2.8:1024^C2.7:26
C3.0:m|C3.0|1E+05|GiStar|1E+10|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C2.9:1024^C2.8:6
C3.0:b|C3.0|1E+05|GiStar|1E+10|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C2.9:1024^C2.8:9
C3.0:d|C3.0|1E+05|GiStar|1E+10|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C2.9:1024^C2.8:3
C3.0:l|C3.0|1E+05|GiStar|1E+10|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C2.9:1024^C2.8:11
C3.0:c|C3.0|1E+05|GiStar|1E+10|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C2.9:1024^C2.8:19
C3.0:w|C3.0|1E+05|GiStar|1E+10|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C2.9:1024^C2.8:26
C3.1:m|C3.1|1E+05|GiStar|1E+11|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.0:1024^C2.9:6
C3.1:b|C3.1|1E+05|GiStar|1E+11|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.0:1024^C2.9:9
C3.1:d|C3.1|1E+05|GiStar|1E+11|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.0:1024^C2.9:3
C3.1:l|C3.1|1E+05|GiStar|1E+11|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.0:1024^C2.9:11
C3.1:c|C3.1|1E+05|GiStar|1E+11|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.0:1024^C2.9:19
C3.1:w|C3.1|1E+05|GiStar|1E+11|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.0:1024^C2.9:26
C3.2:m|C3.2|2E+05|WD|1E+12|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.1:1024^C3.0:6
C3.2:b|C3.2|2E+05|WD|1E+12|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.1:1024^C3.0:9
C3.2:d|C3.2|2E+05|WD|1E+12|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.1:1024^C3.0:3
C3.2:l|C3.2|2E+05|WD|1E+12|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.1:1024^C3.0:11
C3.2:c|C3.2|2E+05|WD|1E+12|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.1:1024^C3.0:19
C3.2:w|C3.2|2E+05|WD|1E+12|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.1:1024^C3.0:26
C3.3:m|C3.3|3E+05|WD|1E+13|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.2:1024^C3.1:6
C3.3:b|C3.3|3E+05|WD|1E+13|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.2:1024^C3.1:9
C3.3:d|C3.3|3E+05|WD|1E+13|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.2:1024^C3.1:3
C3.3:l|C3.3|3E+05|WD|1E+13|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.2:1024^C3.1:11
C3.3:c|C3.3|3E+05|WD|1E+13|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.2:1024^C3.1:19
C3.3:w|C3.3|3E+05|WD|1E+13|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.2:1024^C3.1:26
C3.4:m|C3.4|4E+05|WD|1E+14|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.3:1024^C3.2:6
C3.4:b|C3.4|4E+05|WD|1E+14|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.3:1024^C3.2:9
C3.4:d|C3.4|4E+05|WD|1E+14|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.3:1024^C3.2:3
C3.4:l|C3.4|4E+05|WD|1E+14|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.3:1024^C3.2:11
C3.4:c|C3.4|4E+05|WD|1E+14|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.3:1024^C3.2:19
C3.4:w|C3.4|4E+05|WD|1E+14|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.3:1024^C3.2:26
C3.5:m|C3.5|5E+05|NS|1E+15|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.4:1024^C3.3:6
C3.5:b|C3.5|5E+05|NS|1E+15|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.4:1024^C3.3:9
C3.5:d|C3.5|5E+05|NS|1E+15|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.4:1024^C3.3:3
C3.5:l|C3.5|5E+05|NS|1E+15|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.4:1024^C3.3:11
C3.5:c|C3.5|5E+05|NS|1E+15|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.4:1024^C3.3:19
C3.5:w|C3.5|5E+05|NS|1E+15|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.4:1024^C3.3:26
C3.6:m|C3.6|6E+05|NS|1E+16|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.5:1024^C3.4:6
C3.6:b|C3.6|6E+05|NS|1E+16|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.5:1024^C3.4:9
C3.6:d|C3.6|6E+05|NS|1E+16|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.5:1024^C3.4:3
C3.6:l|C3.6|6E+05|NS|1E+16|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.5:1024^C3.4:11
C3.6:c|C3.6|6E+05|NS|1E+16|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.5:1024^C3.4:19
C3.6:w|C3.6|6E+05|NS|1E+16|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.5:1024^C3.4:26
C3.7:m|C3.7|7E+05|MGT|1E+17|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.6:1024^C3.5:6
C3.7:b|C3.7|7E+05|MGT|1E+17|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.6:1024^C3.5:9
C3.7:d|C3.7|7E+05|MGT|1E+17|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.6:1024^C3.5:3
C3.7:l|C3.7|7E+05|MGT|1E+17|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.6:1024^C3.5:11
C3.7:c|C3.7|7E+05|MGT|1E+17|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.6:1024^C3.5:19
C3.7:w|C3.7|7E+05|MGT|1E+17|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.6:1024^C3.5:26
C3.8:m|C3.8|8E+05|MGT|1E+18|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.7:1024^C3.6:6
C3.8:b|C3.8|8E+05|MGT|1E+18|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.7:1024^C3.6:9
C3.8:d|C3.8|8E+05|MGT|1E+18|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.7:1024^C3.6:3
C3.8:l|C3.8|8E+05|MGT|1E+18|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.7:1024^C3.6:11
C3.8:c|C3.8|8E+05|MGT|1E+18|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.7:1024^C3.6:19
C3.8:w|C3.8|8E+05|MGT|1E+18|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.7:1024^C3.6:26
C3.9:m|C3.9|9E+05|BH|1E+19|1|1|1|1|m|0.006375|0.01|0.0005|0.00128|1|1.6|C3.8:1024^C3.7:6
C3.9:b|C3.9|9E+05|BH|1E+19|1|1|1|1|b|0.022578125|0.015625|0.00003125|0.0025|0.64|1|C3.8:1024^C3.7:9
C3.9:d|C3.9|9E+05|BH|1E+19|1|1|1|1|d|0.0136|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.8:1024^C3.7:3
C3.9:l|C3.9|9E+05|BH|1E+19|1|1|1|1|l|0.0612|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.8:1024^C3.7:11
C3.9:c|C3.9|9E+05|BH|1E+19|1|1|1|1|c|0.0255|0.04166666667|0.004096|0.006103515625|1|0.8|C3.8:1024^C3.7:19
C3.9:w|C3.9|9E+05|BH|1E+19|1|1|1|1|w|0.031875|0.025|0.000256|0.03072|0.25|1.25|C3.8:1024^C3.7:26
C4.0:m|C4.0|2E+06|BH|1E+20|1|1|1|1|m|0.00675|0.01|0.0005|0.00128|1|1.6|C3.9:1024^C3.8:6
C4.0:b|C4.0|2E+06|BH|1E+20|1|1|1|1|b|0.02390625|0.015625|0.00003125|0.0025|0.64|1|C3.9:1024^C3.8:9
C4.0:d|C4.0|2E+06|BH|1E+20|1|1|1|1|d|0.0144|0.01923076923|0.0009765625|0.0003125|2.56|1|C3.9:1024^C3.8:3
C4.0:l|C4.0|2E+06|BH|1E+20|1|1|1|1|l|0.0648|0.04464285714|0.0005|0.0025|1.5625|0.5|C3.9:1024^C3.8:11
C4.0:c|C4.0|2E+06|BH|1E+20|1|1|1|1|c|0.027|0.04166666667|0.004096|0.006103515625|1|0.8|C3.9:1024^C3.8:19
C4.0:w|C4.0|2E+06|BH|1E+20|1|1|1|1|w|0.03375|0.025|0.000256|0.03072|0.25|1.25|C3.9:1024^C3.8:26
C4.1:m|C4.1|2E+06|BH|1E+21|1|1|1|1|m|0.00675|0.01|0.0005|0.00128|1|1.6|C4.0:1024^C3.9:6
C4.1:b|C4.1|2E+06|BH|1E+21|1|1|1|1|b|0.02390625|0.015625|0.00003125|0.0025|0.64|1|C4.0:1024^C3.9:9
C4.1:d|C4.1|2E+06|BH|1E+21|1|1|1|1|d|0.0144|0.01923076923|0.0009765625|0.0003125|2.56|1|C4.0:1024^C3.9:3
C4.1:l|C4.1|2E+06|BH|1E+21|1|1|1|1|l|0.0648|0.04464285714|0.0005|0.0025|1.5625|0.5|C4.0:1024^C3.9:11
C4.1:c|C4.1|2E+06|BH|1E+21|1|1|1|1|c|0.027|0.04166666667|0.004096|0.006103515625|1|0.8|C4.0:1024^C3.9:19
C4.1:w|C4.1|2E+06|BH|1E+21|1|1|1|1|w|0.03375|0.025|0.000256|0.03072|0.25|1.25|C4.0:1024^C3.9:26
C4.2:m|C4.2|4E+06|SMBH|1E+22|1|1|1|1|m|0.00675|0.01|0.0005|0.00128|1|1.6|C4.1:1024^C4.0:6
C4.2:b|C4.2|4E+06|SMBH|1E+22|1|1|1|1|b|0.02390625|0.015625|0.00003125|0.0025|0.64|1|C4.1:1024^C4.0:9
C4.2:d|C4.2|4E+06|SMBH|1E+22|1|1|1|1|d|0.0144|0.01923076923|0.0009765625|0.0003125|2.56|1|C4.1:1024^C4.0:3
C4.2:l|C4.2|4E+06|SMBH|1E+22|1|1|1|1|l|0.0648|0.04464285714|0.0005|0.0025|1.5625|0.5|C4.1:1024^C4.0:11
C4.2:c|C4.2|4E+06|SMBH|1E+22|1|1|1|1|c|0.027|0.04166666667|0.004096|0.006103515625|1|0.8|C4.1:1024^C4.0:19
C4.2:w|C4.2|4E+06|SMBH|1E+22|1|1|1|1|w|0.03375|0.025|0.000256|0.03072|0.25|1.25|C4.1:1024^C4.0:26
C4.3:m|C4.3|6E+06|SMBH|1E+23|1|1|1|1|m|0.00675|0.01|0.0005|0.00128|1|1.6|C4.2:1024^C4.1:6
C4.3:b|C4.3|6E+06|SMBH|1E+23|1|1|1|1|b|0.02390625|0.015625|0.00003125|0.0025|0.64|1|C4.2:1024^C4.1:9
C4.3:d|C4.3|6E+06|SMBH|1E+23|1|1|1|1|d|0.0144|0.01923076923|0.0009765625|0.0003125|2.56|1|C4.2:1024^C4.1:3
C4.3:l|C4.3|6E+06|SMBH|1E+23|1|1|1|1|l|0.0648|0.04464285714|0.0005|0.0025|1.5625|0.5|C4.2:1024^C4.1:11
C4.3:c|C4.3|6E+06|SMBH|1E+23|1|1|1|1|c|0.027|0.04166666667|0.004096|0.006103515625|1|0.8|C4.2:1024^C4.1:19
C4.3:w|C4.3|6E+06|SMBH|1E+23|1|1|1|1|w|0.03375|0.025|0.000256|0.03072|0.25|1.25|C4.2:1024^C4.1:26
C4.4:m|C4.4|8E+06|SMBH|1E+24|1|1|1|1|m|0.00675|0.01|0.0005|0.00128|1|1.6|C4.3:1024^C4.2:6
C4.4:b|C4.4|8E+06|SMBH|1E+24|1|1|1|1|b|0.02390625|0.015625|0.00003125|0.0025|0.64|1|C4.3:1024^C4.2:9
C4.4:d|C4.4|8E+06|SMBH|1E+24|1|1|1|1|d|0.0144|0.01923076923|0.0009765625|0.0003125|2.56|1|C4.3:1024^C4.2:3
C4.4:l|C4.4|8E+06|SMBH|1E+24|1|1|1|1|l|0.0648|0.04464285714|0.0005|0.0025|1.5625|0.5|C4.3:1024^C4.2:11
C4.4:c|C4.4|8E+06|SMBH|1E+24|1|1|1|1|c|0.027|0.04166666667|0.004096|0.006103515625|1|0.8|C4.3:1024^C4.2:19
C4.4:w|C4.4|8E+06|SMBH|1E+24|1|1|1|1|w|0.03375|0.025|0.000256|0.03072|0.25|1.25|C4.3:1024^C4.2:26
+36
View File
@@ -0,0 +1,36 @@
class_name CSVLoader
const SPLITTER = '|'
static func load(csv_text: String) -> Dictionary:
var result: Dictionary = {}
var lines := csv_text.strip_edges().split("\n")
if lines.size() < 2:
return result
var headers := lines[0].split(SPLITTER)
for i in range(1, lines.size()):
var line := lines[i].strip_edges()
if line.is_empty():
continue
var values := line.split(SPLITTER)
if values.size() != headers.size():
push_warning(
"CSV row %d has %d columns, expected %d"
% [i + 1, values.size(), headers.size()]
)
continue
var elem: Dictionary = {}
for j in range(headers.size()):
elem[headers[j].strip_edges()] = values[j].strip_edges()
result[elem[headers[0]]] = elem
return result
+1
View File
@@ -0,0 +1 @@
uid://bfe1fyutcw0cx
@@ -1,5 +1,6 @@
Version|Content:en|Content:ru Version|Content:en|Content:ru
0.5.1.|Minor fixes|Незначительные правки 0.6.12.128|Unlock|Раблокироровка
0.5.1|Minor fixes|Незначительные правки
0.5.0|WooHoo! Public release|Ура! Публичный релиз 0.5.0|WooHoo! Public release|Ура! Публичный релиз
0.4.8|Ads double forces|Реклама удваивает силы 0.4.8|Ads double forces|Реклама удваивает силы
0.4.7|Forces rebalanced|Силы перебалансированы 0.4.7|Forces rebalanced|Силы перебалансированы
+9
View File
@@ -0,0 +1,9 @@
id|span|progress|degradation|next|fall
HP|5E+06|0.00025|0.0025|EON1|RP:1
EON1|1E+07|0.00025|0.0025|EON2|HP:100^RP:1
EON2|1E+07|0.00025|0.0025|EON3|EON1:1
EON3|1E+06|0.00025|0.0025|EON4|EON2:1000^EON1:1
EON4|1E+06|0.00025|0.0025|EON5|EON3:1000^EON1:1
EON5|5E+05|0.00025|0.0025|C0.0|EON4:2000^EON1:1
C0.0|2E+03|0.0175|0.025|C0.1|EON5:1
C0.1|2E+03|0.0175|0.025|C0.2|C0.0:1
+3
View File
@@ -0,0 +1,3 @@
[remap]
importer="keep"
+3
View File
@@ -0,0 +1,3 @@
[remap]
importer="keep"
+153
View File
@@ -0,0 +1,153 @@
id|is_visible|unlock|cost|bind|mass|space|lifespan|auto|gamma|blast|life_product|voids|output|destroy_level|degradation|planets|count_as|group_as|event_group|blastability|space_bonus|civ_bonus|claim
S|1|S:0|E:1||||||||||||||||S||||
H|1|H:0|E:1||||||||||||||||H||||
He|1|He:1|||||||||||||||||||||
Met|1|Met:1|||||||||||||||||||||
BD|1|BD:1|||||||||||||||||||||
HBD|0||H:0.1||0.1||5000000000||||S:0.5||CBD:1|1|mass:0.1&H:0&HE:0&MET:0||BD||||||
RD|1|H:1|H:1||1|1|40000000000||||S:40||TWD:1&H:0.13&He:0.05&Met:0.01|1|mass:0.8&H:0.13&HE:0.05&MET:0.01|HP:1:0.01&RP:1:0.21&GG:2:0.08&AB:3:0.4||Star|DwStar||||
OD|1|RD:1|H:8||8|1|18000000000||||S:36||SRG:1|1||HP:1:0.03&RP:2:0.34&GG:3:0.13&AB:3:0.4||Star|DwStar||||
YD|1|OD:1|H:10||10|1|9000000000||||S:27||NRG:1|1||HP:2:0.1&RP:3:0.55&GG:4:0.21&AB:3:0.4||Star|DwStar||||
WYD|1|YD:1|H:16||16|1|1800000000||||S:18||MRG:1|1||HP:3:0.3&RP:5:0.89&GG:5:0.34&AB:3:0.4||Star|DwStar||||
WS|1|H:15|H:50||50|1|450000000||||S:9||LRG:1|2||||Star|GiStar||||
BG|1|H:30&WS:1|H:100||100|1|90000000||||S:9||HRG:1|2||||Star|GiStar||||
SG|1|H:100&BG:1|H:300||300|1|9000000||||S:9||RSG:1|2||||Star|GiStar||||
HG|1|H:300&SG:1|H:1000||1000|1|900000||||S:9||RHG:1|2||||Star|GiStar||||
RG|1|RG:1|||||||||||||||||||||
SRG|0||||8||2000000000||||S:80||SWD:1&H:2.32&He:0.64&Met:0.08&S:12.4|1|mass:4.8&H:2.32&HE:0.64&MET:0.08||RG|Star|||||
NRG|0||||10||1000000000||||S:120.||NWD:1&H:3.2&He:1.3&Met:0.2&S:14.3|1|mass:5&H:3.2&HE:1.3&MET:0.2||RG|Star|||||
MRG|0||||16||200000000||||S:200||LWD:1&H:4.96&He:3.36&Met:0.48&S:20.2|1|mass:6.4&H:4.96&HE:3.36&MET:0.48||RG|Star|||||
LRG|0||||50||50000000||||S:300||DSN^SGRB%0.1|2|||RG|Star|||||
HRG|0||||100||10000000||||S:400.||SN^GRB%1|2|||RG|Star|||||
RSG|0||||300||1000000||||S:500||BSN^LGRB%3|2|||RG|Star|||||
RHG|0||||1000||100000||||S:600||HN^HGRB%10|2|||RG|Star|||||
DSN|0||||||1|||2|S:59.1||SNS:1&H:6.5&He:13.5&Met:11|2|mass:15&H:6.5&HE:13.5&MET:11||||SNGRBB||||
SN|0||||||1|||9|S:99.1||LNS:1&H:8&He:50&Met:11|2|mass:18&H:8&HE:50&MET:11||||SNGRBB||||
BSN|0||||||1||.|305|S:309.1||MGT:1&H:15&He:186&Met:15|2|mass:21&H:15&HE:186&MET:15||||SNGRBB||||
HN|0||||||1|||9990|S:939.1||BH40:1&H:30&He:560&Met:30|2|mass:40&H:30&HE:560&MET:30||||SNGRBB||||
SGRB|0||||||1||0.001|31|S:149.1||BH25:1&H:0.5&He:10&Met:4|2|mass:25&H:0.5&HE:10&MET:4||||SNGRBB||||
GRB|0||||||1||0.01|136|S:239.1||BH30:1&H:19&He:12&Met:5|2|mass:30&H:19&HE:12&MET:5||||SNGRBB||||
LGRB|0||||||1||0.03|3446|S:669.1||BH40:1&H:68&He:18&Met:9|2|mass:40&H:68&HE:18&MET:9||||SNGRBB||||
HGRB|0||||||1||0.1|97342|S:1939.1||BH60:1&H:0&He:40&Met:10|2|mass:60&H:0&HE:40&MET:10||||SNGRBB||||
CBD|0||||0.1||||||||||||BD||||||
WD|1|WD:1|||||||||||||||||||||
TWD|0||||0.8||||||||||||WD|Star|Degen||||
SWD|0||||4.8||||||||||||WD|Star|Degen||||
NWD|0||||5||||||||||||WD|Star|Degen||||
LWD|0||||6.4||||||||||||WD|Star|Degen||||
NS|1|NS:1|||||||||||||||||||||
SNS|0||||15||||||||||||NS|Star|Degen||||
LNS|0||||18||||||||||||NS|Star|Degen||||
MGT|1|MGT:1|||21|||||||||||||Star|Degen||||
BH|1|BH:1|||||||||||||||||||||
BH25|0||||25||||||||||||BH|BH|BH||||
BH30|0||||30||||||||||||BH|BH|BH||||
BH40|0||||40||||||||||||BH|BH|BH||||
BH60|0||||60||||||||||||BH|BH|BH||||
SMBH|1|BH:1|||||||||||||||||SMBH||||
N|1|S:1|H:1||1|10|10000000||||H:10||H:1&S:10|||||CL|CL||||
G|1|N:1|H:10&N:1||11|10|30000000||||H:150||H:11&S:20|||||CL|CL||||
STN|1|G:1|H:200&G:1||211|300|30000000|0.5|||H:3000||H:211&S:320|||||CL|CL||||
MC|1|G:1&S:1300|H:2000&G:1||2011|4000|300000000||||H:90000.||H:2011&S:4020|||||CL|CL||||
ASTN|1|MC:1&S:60000|H:200000&MC:1||202011|200000|100000000|0.65|||H:2000000||H:202011&S:204020|||||CL|CL||||
SCD|1|Star:300||Star:1000|||10000000|||||||||||SC|SC||0.1|4|C2.3
SCS|1|SCD:1&Star:2000||Star:10000&BH:10|||1000000000|||||||||||SC|SC||0.2|3.6|C2.4
SCM|1|SCS:1&Star:20000||Star:100000&BH:100|||3000000000|||||||||||SC|SC||0.3|3.4|C2.5
SCL|1|SCM:1&Star:200000||Star:1000000&BH:1000|||10000000000|||||||||||SC|SC||0.5|3.2|C2.6
SCG|1|SCL:1&Star:2000000||Star:10000000&BH:10000|||30000000000|||||||||||SC|SC||0.8|3|C2.7
GED|1|SMBH:1&SC:1|SMBH:10000|Star:1000000000&BH:1000000&SC:100|||12000000000|||||||||||GAL|GALE||1|1.9|C2.9
GES|1|GED:1&Star:2000000000|SMBH:100000|Star:10000000000&BH:10000000&SC:1000|||13000000000|||||||||||GAL|GALE||1.5|1.8|C3.0
GEM|1|GES:1&Star:20000000000|SMBH:1000000|Star:100000000000&BH:100000000&SC:10000|||15000000000|||||||||||GAL|GALE||2|1.7|C3.1
GEL|1|GEM:1&Star:200000000000|SMBH:10000000|Star:1000000000000&BH:1000000000&SC:100000|||17000000000|||||||||||GAL|GALE||3|1.6|C3.2
GEG|1|GEL:1&Star:2000000000000|SMBH:100000000|Star:10000000000000&BH:10000000000&SC:1000000|||20000000000|||||||||||GAL|GALE||4.5|1.5|C3.3
GSD|1|GED:1|STN:10000&ASTN:10|GED:1||-5240200|2000000000|0.8|||H:2400000000||H:4112110|||||GAL|GALS|||2.5|C2.9
GSS|1|GES:1|STN:100000&ASTN:100|GES:1||-52402000|3000000000|0.8|||H:36000000000||H:41121100|||||GAL|GALS|||2.3|C3.0
GSM|1|GEM:1|STN:1000000&ASTN:1000|GEM:1||-524020000|4000000000|0.8|||H:480000000000||H:411211000|||||GAL|GALS|||2.2|C3.1
GSL|1|GEL:1|STN:10000000&ASTN:10000|GEL:1||-5240200000|6000000000|0.8|||H:7200000000000||H:4112110000|||||GAL|GALS|||2.1|C3.2
GSG|1|GEG:1|STN:100000000&ASTN:100000|GEG:1||-52402000000|9000000000|0.8|||H:108000000000000||H:41121100000|||||GAL|GALS|||2|C3.3
LGG|1|GAL:20||GAL:50|||10000000000|||||||||||LS|LS|||1.5|C3.4
LSC|1|LGG:1&GAL:100||LGG:200|||20000000000|||||||||||LS|LS|||1.4|C3.6
LGF|1|LSC:1&LGG:400||LSC:100|||30000000000|||||5||||||LS|LS|||1.3|C3.8
LGW|1|LGF:1&LSC:200||LGF:1000|||60000000000|||||10000||||||LS|LS|||1.2|C4.1
LUB|1|LGW:1&LGF:2000||LGW:1000|||100000000000|||||1000000000||||||LS|LS|||1.1|C4.4
GG|1|GG:1||||||||||||||||Planet|BPlanet||||
AB|1|AB:1||||||||||||||||Planet|BPlanet||||
RP|1|RP:1||||||||||||||||Planet|BPlanet||||
HP|1|HP:1||||||||||||||||Planet|LPlanet|1|||
LP|1|LP:1||||||||||||||||Planet|LPlanet||||
EON1|1|EON1:1|||||||||||||||LP|Planet|LPlanet|1|||
EON2|1|EON2:1|||||||||||||||LP|Planet|LPlanet|1|||
EON3|1|EON3:1|||||||||||||||LP|Planet|LPlanet|1|||
EON4|1|EON4:1|||||||||||||||LP|Planet|LPlanet|1|||
EON5|1|EON5:1|||||||||||||||LP|Planet|LPlanet|1|||
C0|1|C0:1||||||||||||||||Planet|LPlanet||||
C0.0|1|C0.0:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.1|1|C0.1:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.2|1|C0.2:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.3|1|C0.3:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.4|1|C0.4:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.5|1|C0.5:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.6|1|C0.6:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.7|1|C0.7:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.8|1|C0.8:1|||||||||||||||C0|Planet|LPlanet|1|||
C0.9|1|C0.9:1|||||||||||||||C0|Planet|LPlanet|1|||
C1|1|C1:1||||||||||||||||Planet|LPlanet||||
C1.0|1|C1.0:1|||||||||||||||C1|Planet|LPlanet|1|||
C1.1|1|C1.1:1|||||||||||||||C1|Planet|LPlanet|1|||
C1.2|1|C1.2:1|||||||||||||||C1|Planet|LPlanet|1|||
C1.3|1|C1.3:1|||||||||||||||C1|Planet|LPlanet||||
C1.4|1|C1.4:1|||||||||||||||C1|Planet|LPlanet||||
C1.5|1|C1.5:1|||||||||||||||C1|Planet|LPlanet||||
C1.6|1|C1.6:1|||||||||||||||C1|Planet|LPlanet||||
C1.7|1|C1.7:1|||||||||||||||C1|Planet|LPlanet||||
C1.8|1|C1.8:1|||||||||||||||C1|Planet|LPlanet||||
C1.9|1|C1.9:1|||||||||||||||C1|Planet|LPlanet||||
C2|1|C2:1|||||||||||||||||||||
C2.0|1|C2.0:1|||||||||||||||C2||||||
C2.1|1|C2.1:1|||||||||||||||C2||||||
C2.2|1|C2.2:1|||||||||||||||C2||||||
C2.3|1|C2.3:1|||||||||||||||C2||||||
C2.4|1|C2.4:1|||||||||||||||C2||||||
C2.5|1|C2.5:1|||||||||||||||C2||||||
C2.6|1|C2.6:1|||||||||||||||C2||||||
C2.7|1|C2.7:1|||||||||||||||C2||||||
C2.8|1|C2.8:1|||||||||||||||C2||||||
C2.9|1|C2.9:1|||||||||||||||C2||||||
C3|1|C3:1|||||||||||||||||||||
C3.0|1|C3.0:1|||||||||||||||C3||||||
C3.1|1|C3.1:1|||||||||||||||C3||||||
C3.2|1|C3.2:1|||||||||||||||C3||||||
C3.3|1|C3.3:1|||||||||||||||C3||||||
C3.4|1|C3.4:1|||||||||||||||C3||||||
C3.5|1|C3.5:1|||||||||||||||C3||||||
C3.6|1|C3.6:1|||||||||||||||C3||||||
C3.7|1|C3.7:1|||||||||||||||C3||||||
C3.8|1|C3.8:1|||||||||||||||C3||||||
C3.9|1|C3.9:1|||||||||||||||C3||||||
C4|1|C4:1|||||||||||||||||||||
C4.0|1|C4.0:1|||||||||||||||C4||||||
C4.1|1|C4.1:1|||||||||||||||C4||||||
C4.2|1|C4.2:1|||||||||||||||C4||||||
C4.3|1|C4.3:1|||||||||||||||C4||||||
C4.4|1|C4.4:1|||||||||||||||C4||||||
Ct|0||||||||||||||||||||||
fsho|1|fsho:1|||||||||||||||||||||
finf|1|finf:1|||||||||||||||||||||
ftem|1|ftem:1|||||||||||||||||||||
fcol|1|fcol:1|||||||||||||||||||||
fpri|1|fpri:1|||||||||||||||||||||
fsin|1|fsin:1|||||||||||||||||||||
fren|1|fren:1|||||||||||||||||||||
finf|1|finf:1|||||||||||||||||||||
ffro|1|ffro:1|||||||||||||||||||||
fdes|1|fdes:1|||||||||||||||||||||
froc|1|froc:1|||||||||||||||||||||
fpan|1|fpan:1|||||||||||||||||||||
fgai|1|fgai:1|||||||||||||||||||||
fdar|1|fdar:1|||||||||||||||||||||
fede|1|fede:1|||||||||||||||||||||
fpac|1|fpac:1|||||||||||||||||||||
fenr|1|fenr:1|||||||||||||||||||||
fmor|1|fmor:1|||||||||||||||||||||
fdis|1|fdis:1|||||||||||||||||||||
frep|1|frep:1|||||||||||||||||||||
+3
View File
@@ -0,0 +1,3 @@
[remap]
importer="keep"
+125
View File
@@ -0,0 +1,125 @@
id|name|image|page|row|col|sub_page
fsho|shovelin|ui/0-forces/|0|0|0|
finf|inflatin|ui/0-forces/|0|0|1|
ftem|temporite|ui/0-forces/|0|0|2|
fcol|collisite|ui/0-forces/|0|0|3|
fpri|primex|ui/0-forces/|0|0|4|
fsin|singularite|ui/0-forces/|0|1|0|
fren|renewin|ui/0-forces/|0|1|1|
finf|infusite|ui/0-forces/|0|1|2|
ffro|frostin|ui/0-forces/|0|1|3|
fdes|destellarite|ui/0-forces/|0|1|4|
froc|rockex|ui/0-forces/|0|2|0|
fpan|panspermin|ui/0-forces/|0|2|1|
fgai|gaianite|ui/0-forces/|0|2|2|
fdar|darwinite|ui/0-forces/|0|2|3|
fede|edenex|ui/0-forces/|0|2|4|
fpac|pacifin|ui/0-forces/|0|3|0|
fenr|enragein|ui/0-forces/|0|3|1|
fmor|moralite|ui/0-forces/|0|3|2|
fdis|discriminite|ui/0-forces/|0|3|3|
frep|reprex|ui/0-forces/|0|3|4|
S|space|ui/1-resources/|1|0|0|
H|hydrogen|ui/1-resources/|1|1|0|
He|helium|ui/1-resources/|1|2|0|
Met|metal|ui/1-resources/|1|3|0|
N|nebula|ui/2-stars/|2|0|0|
G|globula|ui/2-stars/|2|0|1|
STN|star_nursery|ui/2-stars/|2|0|2|
MC|molecular_cloud|ui/2-stars/|2|0|3|
ASTN|active_star_nursery|ui/2-stars/|2|0|4|
BD|brown_dwarf|ui/2-stars/|2|1|0|
RD|red_dwarf|ui/2-stars/|2|1|1|
OD|orange_dwarf|ui/2-stars/|2|1|2|
YD|yellow_dwarf|ui/2-stars/|2|1|3|
WYD|white_yellow_dwarf|ui/2-stars/|2|1|4|
RG|red_giant|ui/2-stars/|2|2|0|
WS|white_star|ui/2-stars/|2|2|1|
BG|blue_giant|ui/2-stars/|2|2|2|
SG|supergiant|ui/2-stars/|2|2|3|
HG|hypergiant|ui/2-stars/|2|2|4|
WD|white_dwarf|ui/2-stars/|2|3|0|
NS|neutron_star|ui/2-stars/|2|3|1|
MGT|magnetar|ui/2-stars/|2|3|2|
BH|black_hole|ui/2-stars/|2|3|3|
SMBH|supermassive_black_hole|ui/2-stars/|2|3|4|
SCD|star_cluster_scattered|ui/3-structures/|3|0|0|
SCS|star_cluster_small|ui/3-structures/|3|0|1|
SCM|star_cluster_medium|ui/3-structures/|3|0|2|
SCL|star_cluster_large|ui/3-structures/|3|0|3|
SCG|star_cluster_giant|ui/3-structures/|3|0|4|
GED|galaxy_elliptical_dwarf|ui/3-structures/|3|1|0|
GES|galaxy_elliptical_small|ui/3-structures/|3|1|1|
GEM|galaxy_elliptical_medium|ui/3-structures/|3|1|2|
GEL|galaxy_elliptical_large|ui/3-structures/|3|1|3|
GEG|galaxy_elliptical_giant|ui/3-structures/|3|1|4|
GSD|galaxy_spiral_dwarf|ui/3-structures/|3|2|0|
GSS|galaxy_spiral_small|ui/3-structures/|3|2|1|
GSM|galaxy_spiral_medium|ui/3-structures/|3|2|2|
GSL|galaxy_spiral_large|ui/3-structures/|3|2|3|
GSG|galaxy_spiral_giant|ui/3-structures/|3|2|4|
LGG|galactic_group|ui/3-structures/|3|3|0|
LSC|galactic_super_cluster|ui/3-structures/|3|3|1|
LGF|galactic_filament|ui/3-structures/|3|3|2|
LGW|galactic_wall|ui/3-structures/|3|3|3|
LUB|universe_bubble|ui/3-structures/|3|3|4|
GG|gas_giant|ui/4-life/|4|0|0|
AB|asteroid_belt|ui/4-life/|4|0|1|
RP|rocky_planet|ui/4-life/|4|0|2|
HP|habitable_planet|ui/4-life/|4|0|3|
LP|living_planet|ui/4-life/|4|0|4|5
C0|civ0|ui/4-life/|4|1|0|6
C1|civ1|ui/4-life/|4|1|1|7
C2|civ2|ui/4-life/|4|1|2|8
C3|civ3|ui/4-life/|4|1|3|9
C4|civ4|ui/4-life/|4|1|4|10
EON1|archean|ui/4-life/living/|5|0|0|
EON2|proterozoic|ui/4-life/living/|5|0|1|
EON3|paleozoic|ui/4-life/living/|5|0|2|
EON4|mezozoic|ui/4-life/living/|5|0|3|
EON5|cenozoic|ui/4-life/living/|5|0|4|
C0.0|civ0.0|ui/4-life/civ0/|6|0|0|
C0.1|civ0.1|ui/4-life/civ0/|6|0|1|
C0.2|civ0.2|ui/4-life/civ0/|6|0|2|
C0.3|civ0.3|ui/4-life/civ0/|6|0|3|
C0.4|civ0.4|ui/4-life/civ0/|6|0|4|
C0.5|civ0.5|ui/4-life/civ0/|6|1|0|
C0.6|civ0.6|ui/4-life/civ0/|6|1|1|
C0.7|civ0.7|ui/4-life/civ0/|6|1|2|
C0.8|civ0.8|ui/4-life/civ0/|6|1|3|
C0.9|civ0.9|ui/4-life/civ0/|6|1|4|
C1.0|civ1.0|ui/4-life/civ1/|7|0|0|
C1.1|civ1.1|ui/4-life/civ1/|7|0|1|
C1.2|civ1.2|ui/4-life/civ1/|7|0|2|
C1.3|civ1.3|ui/4-life/civ1/|7|0|3|
C1.4|civ1.4|ui/4-life/civ1/|7|0|4|
C1.5|civ1.5|ui/4-life/civ1/|7|1|0|
C1.6|civ1.6|ui/4-life/civ1/|7|1|1|
C1.7|civ1.7|ui/4-life/civ1/|7|1|2|
C1.8|civ1.8|ui/4-life/civ1/|7|1|3|
C1.9|civ1.9|ui/4-life/civ1/|7|1|4|
C2.0|civ2.0|ui/4-life/civ2/|8|0|0|
C2.1|civ2.1|ui/4-life/civ2/|8|0|1|
C2.2|civ2.2|ui/4-life/civ2/|8|0|2|
C2.3|civ2.3|ui/4-life/civ2/|8|0|3|
C2.4|civ2.4|ui/4-life/civ2/|8|0|4|
C2.5|civ2.5|ui/4-life/civ2/|8|1|0|
C2.6|civ2.6|ui/4-life/civ2/|8|1|1|
C2.7|civ2.7|ui/4-life/civ2/|8|1|2|
C2.8|civ2.8|ui/4-life/civ2/|8|1|3|
C2.9|civ2.9|ui/4-life/civ2/|8|1|4|
C3.0|civ3.0|ui/4-life/civ3/|9|0|0|
C3.1|civ3.1|ui/4-life/civ3/|9|0|1|
C3.2|civ3.2|ui/4-life/civ3/|9|0|2|
C3.3|civ3.3|ui/4-life/civ3/|9|0|3|
C3.4|civ3.4|ui/4-life/civ3/|9|0|4|
C3.5|civ3.5|ui/4-life/civ3/|9|1|0|
C3.6|civ3.6|ui/4-life/civ3/|9|1|1|
C3.7|civ3.7|ui/4-life/civ3/|9|1|2|
C3.8|civ3.8|ui/4-life/civ3/|9|1|3|
C3.9|civ3.9|ui/4-life/civ3/|9|1|4|
C4.0|civ4.0|ui/4-life/civ4/|10|0|0|
C4.1|civ4.1|ui/4-life/civ4/|10|0|1|
C4.2|civ4.2|ui/4-life/civ4/|10|0|2|
C4.3|civ4.3|ui/4-life/civ4/|10|0|3|
C4.4|civ4.4|ui/4-life/civ4/|10|0|4|
+3
View File
@@ -0,0 +1,3 @@
[remap]
importer="keep"
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
uid://cunl2sqmcj1ff
+15
View File
@@ -0,0 +1,15 @@
[gd_resource type="AudioBusLayout" format=3 uid="uid://b5g7p85k5do0m"]
[resource]
bus/1/name = &"Music"
bus/1/solo = false
bus/1/mute = false
bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/2/name = &"FX"
bus/2/solo = false
bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"
+20 -274
View File
@@ -1,14 +1,17 @@
[runnable_presets]
"Windows Desktop"="Windows Desktop"
[preset.0] [preset.0]
name="Windows Desktop" name="Windows Desktop"
platform="Windows Desktop" platform="Windows Desktop"
runnable=true
dedicated_server=false dedicated_server=false
custom_features="" custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="../../Documents/Owad/Owniverse.I/Builds/owniverse.0.6.7.exe" export_path="../../../Documents/Owad/Owniverse.I/Builds/owniverse.0.7.0-146.console.exe"
patches=PackedStringArray() patches=PackedStringArray()
patch_delta_encoding=false patch_delta_encoding=false
patch_delta_compression_level_zstd=19 patch_delta_compression_level_zstd=19
@@ -27,7 +30,7 @@ script_export_mode=2
custom_template/debug="" custom_template/debug=""
custom_template/release="" custom_template/release=""
debug/export_console_wrapper=1 debug/export_console_wrapper=1
binary_format/embed_pck=false binary_format/embed_pck=true
texture_format/s3tc_bptc=true texture_format/s3tc_bptc=true
texture_format/etc2_astc=false texture_format/etc2_astc=false
shader_baker/enabled=false shader_baker/enabled=false
@@ -74,13 +77,12 @@ Remove-Item -Recurse -Force '{temp_dir}'"
name="Android" name="Android"
platform="Android" platform="Android"
runnable=false
dedicated_server=false dedicated_server=false
custom_features="" custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter="res://autoload/*.*, *.gd, *.tscn, *.tres, *.json, *.txt, *.png, res://autoload/entitites.txt"
exclude_filter="" exclude_filter=""
export_path="../../Documents/Owad/Owniverse.I/Builds/owniverse.0.6.8-124.aab" export_path="../../Documents/Owad/Owniverse.I/Builds/owniverse.0.6.12-128.aab"
patches=PackedStringArray() patches=PackedStringArray()
patch_delta_encoding=false patch_delta_encoding=false
patch_delta_compression_level_zstd=19 patch_delta_compression_level_zstd=19
@@ -98,11 +100,11 @@ script_export_mode=2
custom_template/debug="" custom_template/debug=""
custom_template/release="" custom_template/release=""
gradle_build/use_gradle_build=true gradle_build/use_gradle_build=false
gradle_build/gradle_build_directory="" gradle_build/gradle_build_directory=""
gradle_build/android_source_template="" gradle_build/android_source_template=""
gradle_build/compress_native_libraries=true gradle_build/compress_native_libraries=false
gradle_build/export_format=1 gradle_build/export_format=0
gradle_build/min_sdk="" gradle_build/min_sdk=""
gradle_build/target_sdk="" gradle_build/target_sdk=""
gradle_build/custom_theme_attributes={} gradle_build/custom_theme_attributes={}
@@ -110,11 +112,11 @@ architectures/armeabi-v7a=false
architectures/arm64-v8a=true architectures/arm64-v8a=true
architectures/x86=false architectures/x86=false
architectures/x86_64=false architectures/x86_64=false
version/code=124 version/code=146
version/name="" version/name=""
package/unique_name="com.KIDGameProduction.Owniverse" package/unique_name="com.KIDGameProduction.Owniverse"
package/name="Owniverse" package/name="Owniverse"
package/signed=true package/signed=false
package/app_category=2 package/app_category=2
package/retain_data_on_uninstall=false package/retain_data_on_uninstall=false
package/exclude_from_recents=false package/exclude_from_recents=false
@@ -136,11 +138,12 @@ screen/support_normal=true
screen/support_large=true screen/support_large=true
screen/support_xlarge=true screen/support_xlarge=true
screen/background_color=Color(0, 0, 0, 1) screen/background_color=Color(0, 0, 0, 1)
splash_screen/disable_godot_boot_splash=false
splash_screen/icon=""
splash_screen/branding_image=""
splash_screen/background_color=Color(0, 0, 0, 1)
user_data_backup/allow=false user_data_backup/allow=false
command_line/extra_args="" command_line/extra_args=""
apk_expansion/enable=false
apk_expansion/SALT=""
apk_expansion/public_key=""
permissions/custom_permissions=PackedStringArray() permissions/custom_permissions=PackedStringArray()
permissions/access_checkin_properties=false permissions/access_checkin_properties=false
permissions/access_coarse_location=false permissions/access_coarse_location=false
@@ -295,263 +298,6 @@ permissions/write_sms=false
permissions/write_social_stream=false permissions/write_social_stream=false
permissions/write_sync_settings=false permissions/write_sync_settings=false
permissions/write_user_dictionary=false permissions/write_user_dictionary=false
apk_expansion/enable=false
[preset.2] apk_expansion/SALT=""
apk_expansion/public_key=""
name="macOS"
platform="macOS"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../../Sync/Owad/Owniverse.I/Builds/owniverse.II.20260309.dmg"
patches=PackedStringArray()
patch_delta_encoding=false
patch_delta_compression_level_zstd=19
patch_delta_min_reduction=0.1
patch_delta_include_filters="*"
patch_delta_exclude_filters=""
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.2.options]
export/distribution_type=1
binary_format/architecture="universal"
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
application/liquid_glass_icon=""
application/icon=""
application/icon_interpolation=4
application/bundle_identifier="com.KIDGameProduction.Owniverse"
application/signature=""
application/app_category="Games"
application/short_version=""
application/version=""
application/copyright=""
application/copyright_localized={}
application/min_macos_version_x86_64="10.12"
application/min_macos_version_arm64="11.00"
application/export_angle=0
display/high_res=true
shader_baker/enabled=false
application/additional_plist_content=""
xcode/platform_build="14C18"
xcode/sdk_version="13.1"
xcode/sdk_build="22C55"
xcode/sdk_name="macosx13.1"
xcode/xcode_version="1420"
xcode/xcode_build="14C18"
codesign/codesign=3
codesign/installer_identity=""
codesign/apple_team_id=""
codesign/identity=""
codesign/entitlements/custom_file=""
codesign/entitlements/allow_jit_code_execution=false
codesign/entitlements/allow_unsigned_executable_memory=false
codesign/entitlements/allow_dyld_environment_variables=false
codesign/entitlements/disable_library_validation=false
codesign/entitlements/audio_input=false
codesign/entitlements/camera=false
codesign/entitlements/location=false
codesign/entitlements/address_book=false
codesign/entitlements/calendars=false
codesign/entitlements/photos_library=false
codesign/entitlements/apple_events=false
codesign/entitlements/debugging=false
codesign/entitlements/app_sandbox/enabled=false
codesign/entitlements/app_sandbox/network_server=false
codesign/entitlements/app_sandbox/network_client=false
codesign/entitlements/app_sandbox/device_usb=false
codesign/entitlements/app_sandbox/device_bluetooth=false
codesign/entitlements/app_sandbox/files_downloads=0
codesign/entitlements/app_sandbox/files_pictures=0
codesign/entitlements/app_sandbox/files_music=0
codesign/entitlements/app_sandbox/files_movies=0
codesign/entitlements/app_sandbox/files_user_selected=0
codesign/entitlements/app_sandbox/helper_executables=[]
codesign/entitlements/additional=""
codesign/custom_options=PackedStringArray()
notarization/notarization=1
privacy/microphone_usage_description=""
privacy/microphone_usage_description_localized={}
privacy/camera_usage_description=""
privacy/camera_usage_description_localized={}
privacy/location_usage_description=""
privacy/location_usage_description_localized={}
privacy/address_book_usage_description=""
privacy/address_book_usage_description_localized={}
privacy/calendar_usage_description=""
privacy/calendar_usage_description_localized={}
privacy/photos_library_usage_description=""
privacy/photos_library_usage_description_localized={}
privacy/desktop_folder_usage_description=""
privacy/desktop_folder_usage_description_localized={}
privacy/documents_folder_usage_description=""
privacy/documents_folder_usage_description_localized={}
privacy/downloads_folder_usage_description=""
privacy/downloads_folder_usage_description_localized={}
privacy/network_volumes_usage_description=""
privacy/network_volumes_usage_description_localized={}
privacy/removable_volumes_usage_description=""
privacy/removable_volumes_usage_description_localized={}
privacy/tracking_enabled=false
privacy/tracking_domains=PackedStringArray()
privacy/collected_data/name/collected=false
privacy/collected_data/name/linked_to_user=false
privacy/collected_data/name/used_for_tracking=false
privacy/collected_data/name/collection_purposes=0
privacy/collected_data/email_address/collected=false
privacy/collected_data/email_address/linked_to_user=false
privacy/collected_data/email_address/used_for_tracking=false
privacy/collected_data/email_address/collection_purposes=0
privacy/collected_data/phone_number/collected=false
privacy/collected_data/phone_number/linked_to_user=false
privacy/collected_data/phone_number/used_for_tracking=false
privacy/collected_data/phone_number/collection_purposes=0
privacy/collected_data/physical_address/collected=false
privacy/collected_data/physical_address/linked_to_user=false
privacy/collected_data/physical_address/used_for_tracking=false
privacy/collected_data/physical_address/collection_purposes=0
privacy/collected_data/other_contact_info/collected=false
privacy/collected_data/other_contact_info/linked_to_user=false
privacy/collected_data/other_contact_info/used_for_tracking=false
privacy/collected_data/other_contact_info/collection_purposes=0
privacy/collected_data/health/collected=false
privacy/collected_data/health/linked_to_user=false
privacy/collected_data/health/used_for_tracking=false
privacy/collected_data/health/collection_purposes=0
privacy/collected_data/fitness/collected=false
privacy/collected_data/fitness/linked_to_user=false
privacy/collected_data/fitness/used_for_tracking=false
privacy/collected_data/fitness/collection_purposes=0
privacy/collected_data/payment_info/collected=false
privacy/collected_data/payment_info/linked_to_user=false
privacy/collected_data/payment_info/used_for_tracking=false
privacy/collected_data/payment_info/collection_purposes=0
privacy/collected_data/credit_info/collected=false
privacy/collected_data/credit_info/linked_to_user=false
privacy/collected_data/credit_info/used_for_tracking=false
privacy/collected_data/credit_info/collection_purposes=0
privacy/collected_data/other_financial_info/collected=false
privacy/collected_data/other_financial_info/linked_to_user=false
privacy/collected_data/other_financial_info/used_for_tracking=false
privacy/collected_data/other_financial_info/collection_purposes=0
privacy/collected_data/precise_location/collected=false
privacy/collected_data/precise_location/linked_to_user=false
privacy/collected_data/precise_location/used_for_tracking=false
privacy/collected_data/precise_location/collection_purposes=0
privacy/collected_data/coarse_location/collected=false
privacy/collected_data/coarse_location/linked_to_user=false
privacy/collected_data/coarse_location/used_for_tracking=false
privacy/collected_data/coarse_location/collection_purposes=0
privacy/collected_data/sensitive_info/collected=false
privacy/collected_data/sensitive_info/linked_to_user=false
privacy/collected_data/sensitive_info/used_for_tracking=false
privacy/collected_data/sensitive_info/collection_purposes=0
privacy/collected_data/contacts/collected=false
privacy/collected_data/contacts/linked_to_user=false
privacy/collected_data/contacts/used_for_tracking=false
privacy/collected_data/contacts/collection_purposes=0
privacy/collected_data/emails_or_text_messages/collected=false
privacy/collected_data/emails_or_text_messages/linked_to_user=false
privacy/collected_data/emails_or_text_messages/used_for_tracking=false
privacy/collected_data/emails_or_text_messages/collection_purposes=0
privacy/collected_data/photos_or_videos/collected=false
privacy/collected_data/photos_or_videos/linked_to_user=false
privacy/collected_data/photos_or_videos/used_for_tracking=false
privacy/collected_data/photos_or_videos/collection_purposes=0
privacy/collected_data/audio_data/collected=false
privacy/collected_data/audio_data/linked_to_user=false
privacy/collected_data/audio_data/used_for_tracking=false
privacy/collected_data/audio_data/collection_purposes=0
privacy/collected_data/gameplay_content/collected=false
privacy/collected_data/gameplay_content/linked_to_user=false
privacy/collected_data/gameplay_content/used_for_tracking=false
privacy/collected_data/gameplay_content/collection_purposes=0
privacy/collected_data/customer_support/collected=false
privacy/collected_data/customer_support/linked_to_user=false
privacy/collected_data/customer_support/used_for_tracking=false
privacy/collected_data/customer_support/collection_purposes=0
privacy/collected_data/other_user_content/collected=false
privacy/collected_data/other_user_content/linked_to_user=false
privacy/collected_data/other_user_content/used_for_tracking=false
privacy/collected_data/other_user_content/collection_purposes=0
privacy/collected_data/browsing_history/collected=false
privacy/collected_data/browsing_history/linked_to_user=false
privacy/collected_data/browsing_history/used_for_tracking=false
privacy/collected_data/browsing_history/collection_purposes=0
privacy/collected_data/search_history/collected=false
privacy/collected_data/search_history/linked_to_user=false
privacy/collected_data/search_history/used_for_tracking=false
privacy/collected_data/search_history/collection_purposes=0
privacy/collected_data/user_id/collected=false
privacy/collected_data/user_id/linked_to_user=false
privacy/collected_data/user_id/used_for_tracking=false
privacy/collected_data/user_id/collection_purposes=0
privacy/collected_data/device_id/collected=false
privacy/collected_data/device_id/linked_to_user=false
privacy/collected_data/device_id/used_for_tracking=false
privacy/collected_data/device_id/collection_purposes=0
privacy/collected_data/purchase_history/collected=false
privacy/collected_data/purchase_history/linked_to_user=false
privacy/collected_data/purchase_history/used_for_tracking=false
privacy/collected_data/purchase_history/collection_purposes=0
privacy/collected_data/product_interaction/collected=false
privacy/collected_data/product_interaction/linked_to_user=false
privacy/collected_data/product_interaction/used_for_tracking=false
privacy/collected_data/product_interaction/collection_purposes=0
privacy/collected_data/advertising_data/collected=false
privacy/collected_data/advertising_data/linked_to_user=false
privacy/collected_data/advertising_data/used_for_tracking=false
privacy/collected_data/advertising_data/collection_purposes=0
privacy/collected_data/other_usage_data/collected=false
privacy/collected_data/other_usage_data/linked_to_user=false
privacy/collected_data/other_usage_data/used_for_tracking=false
privacy/collected_data/other_usage_data/collection_purposes=0
privacy/collected_data/crash_data/collected=false
privacy/collected_data/crash_data/linked_to_user=false
privacy/collected_data/crash_data/used_for_tracking=false
privacy/collected_data/crash_data/collection_purposes=0
privacy/collected_data/performance_data/collected=false
privacy/collected_data/performance_data/linked_to_user=false
privacy/collected_data/performance_data/used_for_tracking=false
privacy/collected_data/performance_data/collection_purposes=0
privacy/collected_data/other_diagnostic_data/collected=false
privacy/collected_data/other_diagnostic_data/linked_to_user=false
privacy/collected_data/other_diagnostic_data/used_for_tracking=false
privacy/collected_data/other_diagnostic_data/collection_purposes=0
privacy/collected_data/environment_scanning/collected=false
privacy/collected_data/environment_scanning/linked_to_user=false
privacy/collected_data/environment_scanning/used_for_tracking=false
privacy/collected_data/environment_scanning/collection_purposes=0
privacy/collected_data/hands/collected=false
privacy/collected_data/hands/linked_to_user=false
privacy/collected_data/hands/used_for_tracking=false
privacy/collected_data/hands/collection_purposes=0
privacy/collected_data/head/collected=false
privacy/collected_data/head/linked_to_user=false
privacy/collected_data/head/used_for_tracking=false
privacy/collected_data/head/collection_purposes=0
privacy/collected_data/other_data_types/collected=false
privacy/collected_data/other_data_types/linked_to_user=false
privacy/collected_data/other_data_types/used_for_tracking=false
privacy/collected_data/other_data_types/collection_purposes=0
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
open \"{temp_dir}/{exe_name}.app\" --args {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
pkill -x -f \"{temp_dir}/{exe_name}.app/Contents/MacOS/{exe_name} {cmd_args}\"
rm -rf \"{temp_dir}\""
Binary file not shown.
+10 -8
View File
@@ -8,28 +8,30 @@
config_version=5 config_version=5
[animation] [accessibility]
compatibility/default_parent_skeleton_in_mesh_instance_3d=true general/updates_per_second=10
[application] [application]
config/name="Owniverse" config/name="Owniverse"
config/version="0.6.8" config/version="0.7.0"
run/main_scene="uid://bv384dpmvjv8o" run/main_scene="uid://bv384dpmvjv8o"
config/features=PackedStringArray("4.6", "Mobile") config/features=PackedStringArray("4.7", "Mobile")
config/icon="res://icon.svg" boot_splash/show_image=false
config/icon="uid://djiwkyk470qb2"
config/size/borderless=true
config/stretch_mode=0
[autoload] [autoload]
Global="*res://Autoload/Global.gd" Global="*uid://dy0hrqie4ritn"
SaveManager="*res://Autoload/SaveManager.gd" SaveManager="*uid://ul0srjc4gcgg"
[display] [display]
window/size/viewport_width=1080 window/size/viewport_width=1080
window/size/viewport_height=1920 window/size/viewport_height=1920
window/size/borderless=true
window/size/extend_to_title=true window/size/extend_to_title=true
window/stretch/mode="viewport" window/stretch/mode="viewport"
window/handheld/orientation=1 window/handheld/orientation=1
+208
View File
@@ -0,0 +1,208 @@
# Эволюция звёзд Owniverse.GI
Числа симуляции хранят целую часть в двух блоках int64, дробный остаток — в
float. Весь порядок E27 сохраняет целые единицы. Возраст разделён на целые
годы и дробную часть с шагом 10^-9 года; большие промежуточные произведения
распределений вычисляются через `mul_div`. Границы точности, допуск переноса
дробей и несовместимый со старым формат сохранения 4 описаны в
[документации математики](world/owniverse/math/README.md).
Механики перенесены из Owniverse.U с согласованными изменениями GI: постепенные партии, детерминированные дробные остатки, уязвимость цивилизаций до C1.2 и передача выживших планет преемнику. Баланс таблицы GI сохраняется.
## Порядок расчёта
1. Накопить игровое время; обработать новые десятые доли года.
2. Рассчитать производство существующих объектов за интервал с учётом их постепенного исчезновения; выполнить автоматическое создание звёзд и их планет.
3. Для очередного поколения определить долю заканчивающих жизнь звёзд. Применить локальное разрушение их планет до списания партий.
4. Снять целые объекты из партий, рассчитать основные и альтернативные выходы с накоплением дробей.
5. Передать выжившие планеты полученным звёздам/остаткам. Если преемников несколько, распределить по их фактическим количествам; если преемника нет — освободить. Остальные связанные объекты используют существующие правила GI.
6. Создать партии преемников. Учесть производство новорождённых за оставшуюся часть длинного шага, включая излучение короткоживущих сверхновых.
7. Применить суммарный бласт поколения; повторять обработку поколений, пока в интервале остаются переходы.
8. Пересчитать группы и опубликовать состояние.
## Автоматическое создание бурых карликов
На горячие бурые карлики `HBD` выделяется 0,1% **нового фактически произведённого автоматического водорода** за расчётный интервал. По текущей таблице автоматическую долю имеют STN (`auto = 0.5`) и ASTN (`auto = 0.65`). Обычный водород, ручные покупки и неиспользованный запас прошлых интервалов повторно в эту долю не входят.
При стоимости `c = 0.1 H` квота объектов увеличивается на `ΔQ = ΔH_auto × 0.001 / c`. Она хранится между циклами и в сохранении в `auto_star_deficits.HBD`. Доступность ограничивается автоматическим запасом и уже оплаченным топливом: `Q ≤ (auto_resources.H + HBD_fuel) / c`.
Карлики появляются по одному. Для `q = max(0, Q)` создаётся `floor(q)` объектов и ещё один с вероятностью `q - floor(q)`, с ограничением по доступному топливу. Созданное количество вычитается из Q; отрицательный остаток компенсирует досрочное появление на следующих шагах. Повторного случайного округления без нового автоматического водорода нет. Это исключение из общего детерминированного округления GI. Состояние генератора `auto_star_deficits.HBD_random` сохраняется, поэтому загрузка продолжает ту же последовательность.
Водород списывается целыми единицами авансом: `charge = ceil(max(0, count × c - HBD_fuel))`. Неиспользованный остаток `HBD_fuel += charge - count × c` сохраняется в `auto_star_deficits.HBD_fuel` и больше не входит в свободный запас или бюджет обычных звёзд. Например, 500 автоматических H позволяют создать 5 HBD, списав 1 H и оставив 0,5 H оплаченного топлива. Следующие 5 HBD используют этот остаток без повторного списания. Численность всегда целая, но не обязана быть кратной 10. При отсутствии обычных звёзд их доля остаётся в запасе, а производство HBD всё равно работает.
Новые HBD получают обычные жизненные партии. По таблице их срок — 5 миллиардов лет, затем они постепенно превращаются в холодные `CBD`. На экране оба типа суммируются в `BD`. Ручного рецепта у общего счётчика BD нет. Миграция сохранений не требуется: квота использует существующий словарь, отсутствующее значение равно нулю.
## Постепенные партии
### Короткоживущие звёздные события внутри длинного шага
Для SN, DSN, BSN, HN и GRB-событий полностью завершившиеся окна рождения не создают отдельные словари партий. Их целые количества суммируются в очередь завершений текущего расчёта; обычные партии сохраняются только для окон, срок которых ещё не закончился. Состояние этой очереди не записывается в сохранение: она полностью обрабатывается до публикации нового состояния.
Окно завершено, если `window_end + lifespan ≤ to_year`. Его доля количества рассчитывается прежним методом разности накопленных целых значений. Для производства пространства интеграл исчезновения вычитается по окнам в прежнем порядке, чтобы сохранить округление. Здесь остаётся лёгкий арифметический проход по окнам, но отсутствуют создание, копирование, сортировка и последующая обработка тысяч временных словарей.
Ресурсы, остатки звёзд и бласты от завершившейся части применяются на следующем поколении расчёта, как раньше. Поэтому сохраняются порядок передачи привязок, среда бластов и ограничения цивилизаций. Ускорение допускается только для событий группы `SNGRBB` с линейным выходом и без преемников с ненулевым сроком жизни. При изменении таблиц остальные случаи автоматически используют обычный путь. Сроки жизни и ширина окон не увеличиваются, формат сохранения не меняется.
На сохранении возраста 140,55 млн лет, при шестой скорости и шаге 1/60 секунды: максимальное временное число партий SN/GRB уменьшилось с 1668 до 2; средний расчёт кадра без отрисовки — примерно с 15 до 10 мс. За 120 шагов результаты старого и нового путей совпали по всем полям состояния. Эти значения характеризуют конкретное сохранение, а не гарантированную частоту кадров на всех устройствах.
### Общие окна рождения и эволюции
Окно рождения шириной `w = lifespan / 40` при `lifespan > 10`, иначе `w = lifespan`. Окно превращения сдвинуто на `lifespan`. При частичном списании:
```
expected = remainder + (remaining_count - remainder) * elapsed / remaining_window
converted = floor(expected)
remainder = expected - converted
```
Конец окна списывает остаток. Переход не уничтожает всю партию в начале окна. Начала и длительности сохраняют модель GI, включая годовую длительность событий SN/GRB.
## Планеты
При ручном и автоматическом создании звёзд:
```
expected = stars_created * planet_amount * planet_chance * metallicity + remainder
planets_created = floor(expected)
remainder = expected - planets_created
```
Остаток независим для каждой пары звезда/планета и сохраняется. Планеты сразу связаны со звездой. Эволюционный переход сам по себе не создаёт новую планетную систему. Шансы планет в таблице — доли, а проценты альтернативных выходов звёзд делятся на 100.
## Среда: адаптация формул Unity к состоянию GI
GI не хранит накопленные счётчики первичной материи Unity. Поэтому `stellar_environment()` вычисляет среду из текущего физического состава, включая связанные объекты, без суммирующих групп интерфейса. Это приближение для баланса GI, а не побитовое воспроизведение Unity.
- `M` — свободные и связанные H/He/Met плюс табличная масса конкретных объектов и масса SMBH.
- `V` — физическое S плюс табличный объём объектов и `voids * 1e22`.
- `Z = max(0, 0.4 * ln(100 * free_Met / M + 0.11) + 0.88)`; при `M = 0` металличность нулевая.
- `B = 65536 * f(M)`, где `f(0)=1`, `f(M)=M^0.1` при `0<M<1e10`, иначе `10`.
- `density = 1.23456e-7 * sqrt(B + M) / max(1, V)^(1/6)`.
- `blast_factor = clamp(free_S / V, 0, 1)`; при нулевом объёме `1`.
Планетные бонусы сил пока не перенесены. Параметры мира Bur/Exp/Agg имеют собственные сохраняемые шкалы и эффективные множители (см. раздел индикаторов ниже). Металличность для производства фиксируется до расходования ресурсов на звёзды. Среда бласта фиксируется для поколения до добавления его продуктов.
## Разрушение и бласты
Локальное воздействие: `ratio = dying_stars / physical_stars`, без множителя плотности.
Бласт: `hits = floor(power * blast_factor + saved_remainder)`. Распределение экспозиции между типами звёзд, имеющими планетные системы в таблице, пропорционально их физическому количеству. Для типа: `ratio = hits * star_share / physical_stars * density`.
Для каждого связанного типа планет накапливается `held_planets * min(1, ratio)`. Уничтожается целая часть, не больше существующего количества. Остатки локального воздействия и бластов раздельны. Это позволяет слабым воздействиям работать при постепенной эволюции.
Уровень 1 превращает только `blastability=1` в RP (HP, EON, цивилизации до C1.2). C1.3 и выше защищены от этого уровня. Уровень 2 уничтожает все планеты, включая защищённые цивилизации, без создания RP. Уничтоженные объекты удаляются из жизненных партий, чтобы не возникать заново.
Единственный источник мощности — поле `blast` сущности: `power = expired_count × max(0, entity.blast)`. При `blast = 0` внешнего воздействия нет. Старые вхождения `blast:N` в `output` игнорируются, включая альтернативные выходы; двойного суммирования нет. Внутренний выход `blast` остаётся событием, а не предметом. `destroy_level` независимо задаёт уровень локального разрушения у умирающего объекта; внешние бласты всегда действуют на уровне 1.
## Границы этапа
Рассчитываются агрегаты по типам, а не отдельные звёздные системы; конкретная принадлежность каждой планеты отдельной звезде не моделируется. Распределения целых объектов детерминированы. Порядок внутри длинного шага — по поколениям, поэтому нелинейное воздействие бластов и среды не обязано совпадать с серией более коротких шагов. Эволюция HP и эонов подключена ниже; эволюция цивилизаций и бонусы структур описаны ниже. Глобальная система сил остаётся отдельной механикой.
Проверки: `tests/test_time.gd`, `tests/test_stellar_rules.gd`. Сохранения игрока тестами не затрагиваются.
## Первичная жизнь: HP → EON1 → … → EON5 → C0.0
Правила хранятся в `data/life_rules.txt`, исходные сроки и коэффициенты взяты из Unity `civs.txt`. В каждой обработанной части партии:
- прогресс: `count * progress + carry_progress`;
- деградация: `count * degradation + carry_degradation`;
- остальная жизнь остаётся на прежней стадии и получает новую партию для следующей попытки.
Прогресс и деградация округляются вниз с сохранением остатков. Если оба накопленных исхода конкурируют за последнюю планету, распределяются только существующие объекты, а неиспользованный остаток переносится на следующую попытку. Деградация распределяется по весам `fall`; знаковые ошибки распределения также сохраняются.
Для всех шести стадий базовые доли за попытку — `progress=0.00025`, `degradation=0.0025`. Интервалы HP/EON1/EON2/EON3/EON4/EON5: 5 млн, 10 млн, 10 млн, 1 млн, 1 млн, 500 тыс. лет. Используются постепенные окна GI шириной `span / 40`. Случайные множители Unity не применяются. Агрессия, порядок и просвещение изменяют вероятности по формулам из раздела индикаторов ниже.
HP деградирует в RP. У эонов возможен откат к предыдущим стадиям по таблице. RP не развивается сам. C0.0 и C0.1 также развиваются: период 2000 лет, прогресс 0.0175, деградация 0.025. Переходы C0.0 → C0.1 → C0.2, откат C0.0 → EON5 и C0.1 → C0.0. Развитие C0.2 и выше подключено через этические правила. Конфликт civ_bonus устранён повторным импортом: бонусы структур совпадают с Unity. Для существующих этических цивилизаций пользователь выбрал равномерное распределение между шестью этиками с детерминированным целым остатком.
Переходы сохраняют количество планет и их хозяев, включая передачу преемнику звезды и разрушение бластом. Повторная попытка той же стадии не увеличивает статистику созданных объектов. Партии новых планет регистрируются при создании; недостающие партии старых HP/эонов — однократно при загрузке с текущим возрастом вселенной, без выдумывания их прошлого возраста. Состояние содержит `life_version=2` (версия 1 также загружается) и `life_remainders`.
Миграция версии жизни 1 → 2 добавляет только недостающие партии C0.0/C0.1, сохраняя уже существующие партии HP и эонов.
## Этические и космические цивилизации
`civilization_rules.txt` содержит 43 стадии по шесть этик из Unity. Они загружаются в `Global.CivilizationRules` и участвуют в расчёте партий. После C4.4 следует Ct: конечная стадия без новых жизненных партий.
Состояние `ethics[stage][ethic]` хранит целые количества. Для существующих цивилизаций без этик количество распределяется поровну в порядке m, l, w, d, c, b; остаток распределяется по одному в этом порядке. Существующее распределение сохраняется. При внешних потерях оно пропорционально сокращается.
Цивилизации с непустым `home` (C2.0–C4.4) освобождаются от прежних привязок без изменения общего количества. Общий механизм переходов больше не переносит планетную привязку на такого преемника. Структуры назначаются отдельно в `civilization_homes`; при возвращении к планетным стадиям цивилизации размещаются у имеющихся карликовых звёзд.
Правило среды согласовано: число космических цивилизаций ограничено звёздным ресурсом. Для стадии `i` расход ёмкости — `population[i] * max(1, Stars[i])`. Каждое семейство `Home` имеет общий бюджет для всех использующих его стадий; звёзды внутри структур также учитываются, но повторно не суммируются. SMBH учитывается по суммарной массе в эквиваленте звёзд, согласно решению пользователя.
Переход переиспользует резерв исходной стадии. При нехватке ёмкости неподдержанные переходы остаются на исходной стадии. Лимит применяется к общему механизму выходов партий и ручному созданию; расчёт прогресса C0.2+ использует тот же бюджет.
При загрузке и после эволюционных поколений избыток деградирует последовательно до поддерживаемой стадии. Приоритет получают существующие более развитые цивилизации; остаток бюджета достаётся младшим. Деградация переносит количество и этики, сокращает старые партии и регистрирует новые, не уничтожая цивилизации. C2.0 при избытке становится C1.9 и распределяется по имеющимся звёздам-карликам. Если карликов нет, C1.9 остаётся свободной — отсутствующая звезда не создаётся. Планетные стадии до C2.0 не расходуют отдельную звёздную ёмкость: у одной звезды могут быть несколько планет.
Резерв ёмкости логический: звёзды не расходуются и продолжают производить ресурсы. Общий бюджет пересчитывается из физических количеств, отдельная копия бронирований в сохранении не хранится.
### Расчёт поколения C0.2–C4.4
1. Из истёкшей части партии пропорционально выбираются представители шести этик. Для каждой этики читаются `progress` и `degradation`; целые исходы получаются с сохранением дробных остатков. Неудавшийся из-за лимита переход возвращается на исходную стадию.
2. Прогресс ведёт на следующую стадию; деградация распределяется по весам `fall` конкретной этики. Повторные попытки не увеличивают статистику созданных цивилизаций.
3. При флаге `fights` рассчитываются войны. Веса исходов — 1:2:3:3, доли прогресса победителей — 0:0.25:0.5:0.75; первый исход деградирует атакующих. Потери противников — 2:1:1.5:2 на войну. Два последних исхода дают 10 и 30 единиц побочного ущерба предыдущей стадии. Выбор участников ограничен живой популяцией, включая ещё не сработавшие партии; их партии сокращаются вместе с населением.
4. Для обычного дрейфа веса своей/противоположной/каждой другой этики равны 196/0/1. Дипломатия умножает исходные численности на `diplomacy_rate`, затем нормирует к прежней численности. Флаг дипломатии действует на остающихся на стадии. При переходе в Ct этика сохраняется без дрейфа.
5. При флаге `colonizes` создаются колонии на две стадии ниже отправителя. Цели — существующие GG, AB, RP, HP; колонизация заменяет цель и сохраняет её звёздную привязку. Веса дрейфа колонистов — 960/4/9. Исходная цивилизация не расходуется. Новая партия начинается в текущий игровой момент.
6. После применения переходов пересчитываются этики, поклонение (`Σ population × worship`), бласты и ограничения среды. Число операций зависит от числа типов и партий, а не от числа цивилизаций.
Окна исходных партий сохраняют время переходов; несколько частей одного типа обрабатываются агрегированно между минимальным и максимальным временем. Побочный ущерб неистёкшим партиям применяется в текущий момент. Все остатки округления сохраняются в `civilization_remainders`, счётчики — в `civilization_stats`.
### Структуры и периоды
Прямой `claim` задаёт структуру стадии и норму 1; каждая промежуточная стадия умножает норму на 10 до следующего `claim`. Начиная с C3.0 требуется соответствующий запас структур, общий для использующих его стадий. При потере запаса избыток деградирует. Этот бюджет действует одновременно со звёздным.
Размещение выбирает структуры в порядке убывания `civ_bonus`, начиная с соответствующего стадии `claim`. Прямое размещение ограничено числом структур; остальные разрешённые структуры при наличии дают общий бонус, как в Unity. Период новых партий равен `span / средневзвешенный civ_bonus`, для неразмещённой части множитель равен 1. Уже назначенные сроки партий не переписываются при изменении бонуса.
Ct не получает часы. Инициализация отсутствующих партий жизни выполняется при загрузке и перед продвижением симуляции. Параметры мира и тенденции описаны ниже; интерфейс применения сил в этот перенос не входит.
## Параметры мира, тенденции и индикаторы
Источник формул — Unity `OwniverseInstance`, `Life`, `LifeActions`, `Trends` и классы индикаторов. Расчёты находятся в `world_parameters.gd`; показ — в `ui/indicators/world_indicators.gd`. Шкалы обновляются каждые 0,1 реальной секунды и сразу при создании/загрузке вселенной. Подписи используют текущую локаль и шаблоны.
### Энергия и плотность
Энергия сохраняет экономику GI: запас расходуется на H/S. Заполнение индикатора — `clamp(energy / 1e14, 0, 1)`. Это не коэффициент производства Unity; дополнительное замедление производства при уменьшении запаса не вводится. В описании выводятся остаток и процент.
Плотность берётся из `stellar_environment`. Положение указателя ограничено диапазоном 0…1:
- `density ≤ 1e-5`: шкала разрыва, `(log10(max(density, 1e-7)) + 7) / 2`;
- `1e-5 < density < 0.9`: обычная шкала, `ln(density × 1e5) / ln(9e4)`;
- `density ≥ 0.9`: шкала сжатия, `(density − 0.9) × 10`.
В Unity в первой формуле было `−7`; это ошибка, не позволяющая указателю двигаться. Здесь исправлено на `+7`. Переключение шкалы меняет и заголовок/описание индикатора. Само наступление апокалипсиса индикатор не запускает.
Общая рамка `Background/WarningBorder` получает цвета Unity `WarningUI` в формате RGBA: при плотности ≤1e-5 — `C040407F`, ≤1e-6 — `DF2020BF`, ≤1e-7 — `FF0000FF`; при плотности ≥0,9 — `40A0C07F`, ≥0,97 — `20B0DFBF`, ≥1 — `00C0FFFF`. В нормальном диапазоне рамка прозрачна. Она обновляется вместе с индикаторами, не перехватывает нажатия и снимается при восстановлении плотности. Необратимая последовательность апокалипсиса Unity сюда не входит.
### Горючесть, взрывчатость и агрессия
`world_parameters` хранит Bur, Exp и Agg в диапазоне 1…19, начальное значение — 10. Эффективный множитель `M(x) = 10^((x−10)/9)`: крайние значения 0,1 и 10, нейтральное — 1.
- Bur делит срок жизни новых звёзд на `M(Bur)`. `modify_world_parameter("Bur", delta)` также пересчитывает оставшееся время существующих звёзд с коэффициентом `старый M / новый M`, сохраняя количество и остатки округления. Производство звёзд умножается на `M`, если `M ≤ 1`, иначе на `sqrt(M)`.
- Exp умножает вероятность альтернативного исхода (с ограничением до 1), мощность `entity.blast` и производство событий группы SNGRBB. Локальный `destroy_level` от него не меняется.
- Для Agg обозначим `a = M(Agg)`. Вероятность прогресса умножается на `a`, деградации — на `(1 − (1−a)/20) / Order`, войны — на `1 − (1−a)/5`, колонизации — на `1 − (1−a)/2`. Если сумма прогресса и деградации превышает 1, они пропорционально нормируются. Вероятности войны/колонизации ограничены единицей.
- Для первичной жизни дополнительный множитель прогресса — Enlightenment. Order дополнительно уменьшает потери в войнах и побочный ущерб. Начальные Enlightenment и Order равны 1.
Изменять шкалы следует через `owniverse.modify_world_parameter(key, delta)`, чтобы горючесть корректно обновляла партии. Готовых кнопок применения сил этот метод не добавляет.
### Тенденции
Пять направлений: Antitheism, Integration, Xenocide, Reconstruction, Spirituality. Участвуют космические стадии с непустым `home`; вес первой — 1, каждой следующей — вдвое больше. Для каждой тенденции:
`rate = Σ_стадий (вес стадии × Σ_этик(доля этики × вес этики))`
`прирост = rate × прошедшие игровые годы × 1e-9`.
Доли берутся на начало интервала, после проверки вместимости. Умножение на время исправляет ошибку Unity, где аргумент period не использовался. Накопление само по себе не зависит от FPS; изменение состава цивилизаций внутри крупных шагов остаётся дискретным, как остальная симуляция.
Веса этик в порядке пяти направлений:
| Этика | Антитеизм | Интеграция | Ксеноцид | Реконструкция | Духовность |
|---|---:|---:|---:|---:|---:|
| m | 0 | 2 | 2 | 0 | 6 |
| l | 6 | 1 | 1 | 2 | 0 |
| w | 2 | 0 | 6 | 0 | 2 |
| d | 0 | 6 | 0 | 1 | 3 |
| c | 1 | 3 | 3 | 3 | 0 |
| b | 3 | 0 | 0 | 6 | 1 |
При достижении 1 учитываются все целые срабатывания, дробный остаток сохраняется. Только Integration имеет последствия в исходной Unity: равновероятно выбирается Federation (+0,1 и Agg −1), Enlightenment (+0,2 и Agg −1) или Order (+0,1). Генератор сохраняет своё состояние. До 256 событий за шаг выбор выполняется по одному; для больших количеств используется нормальная аппроксимация мультиномиального распределения с сохранением точного суммарного числа событий, чтобы высокие скорости не блокировали кадр. Она может менять последовательность исходов при другом разбиении больших интервалов.
Federation сохраняется и увеличивается как в Unity, но в исходном коде не применяется к дипломатии. Дополнительное правило для него не придумано. Остальные четыре тенденции имеют счётчики срабатываний и сброс, но не последствия — так же, как в исходной реализации. Параметры и остатки тенденций сохраняются; у существующего сохранения текущего формата без этих полей используются нейтральные значения и нулевые тенденции, без изменения ресурсов или возраста.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+534
View File
@@ -0,0 +1,534 @@
extends Control
const E = preload("res://world/owniverse/math/exact.gd")
const OWNIVERSE_ITEM = preload("uid://d3xjfxwe3w16v")
const SPEED_TEXTURE_NAME_TEMPLATE = "res://ui/topmenu/time&speed/time%s.png"
const ItemDescription = preload("res://world/owniverse/item_description.gd")
const WorldIndicators = preload("res://ui/indicators/world_indicators.gd")
var world_indicators: RefCounted
var indicator_elapsed: float = 0.0
var description_targets: Dictionary = {}
var description_samples: Dictionary = {}
var description_rates: Dictionary = {}
var description_elapsed: float = 0.0
const PAGE_COUNT = 5
const RESOURCE_PAGE = 1
const PAGE_WIDTH = 1080
const DRAG_TOLERANCE = 360
const SWIPE_DURATION: float = 0.4
@onready var stage_page_scroller: ScrollContainer = $World/PageScroller
@onready var item_pages: Array[Control] = [
$World/PageScroller/HBoxContainer/ForcePage/Forces,
$World/PageScroller/HBoxContainer/ResourcePage/HBoxContainer/Resources,
$World/PageScroller/HBoxContainer/StarPage/Stars,
$World/PageScroller/HBoxContainer/StructurePage/Structures,
$World/PageScroller/HBoxContainer/LifePage/Planets/Life,
$World/PageScroller/HBoxContainer/LifePage/Planets/LivingPlanet,
$World/PageScroller/HBoxContainer/LifePage/Planets/Civ0,
$World/PageScroller/HBoxContainer/LifePage/Planets/Civ1,
$World/PageScroller/HBoxContainer/LifePage/Planets/Civ2,
$World/PageScroller/HBoxContainer/LifePage/Planets/Civ3,
$World/PageScroller/HBoxContainer/LifePage/Planets/Civ4
]
@onready var page_actions: Dictionary[int, OwniverseAction] = {
2: $World/PageScroller/HBoxContainer/StarPage/Actions,
3: $World/PageScroller/HBoxContainer/StructurePage/Actions,
}
@onready var g_item_descriptions: Array = [
$World/PageScroller/HBoxContainer/ForcePage/Description,
$World/PageScroller/HBoxContainer/ResourcePage/Description,
$World/PageScroller/HBoxContainer/StarPage/Description,
$World/PageScroller/HBoxContainer/StructurePage/Description,
$World/PageScroller/HBoxContainer/LifePage/Description
]
@onready var date_time: Label = $World/TopMenu/InfoPanel/DateTime
@onready var g_speed_icons: Array = [
$World/TopMenu/InfoPanel/Speed/Speed1,
$World/TopMenu/InfoPanel/Speed/Speed2,
$World/TopMenu/InfoPanel/Speed/Speed3,
$World/TopMenu/InfoPanel/Speed/Speed4,
$World/TopMenu/InfoPanel/Speed/Speed5,
$World/TopMenu/InfoPanel/Speed/Speed6,
$World/TopMenu/InfoPanel/Speed/Speed7,
$World/TopMenu/InfoPanel/Speed/Speed8
]
@onready var g_time_minus: TextureButton = $World/TopMenu/TimeMinus
@onready var g_time_plus: TextureButton = $World/TopMenu/TimePlus
@onready var screens: Dictionary = {
"World": $World,
"MainMenu": $MainMenu,
"Report": $Report,
"Achievements": $Achievements,
"Credits": $Credits,
}
var g_tween: Tween = null
var g_dragged_start: Vector2 = Vector2.ZERO
var g_scroll_start: int = 0
#var g_current_page: int = 0
var g_last_scroll_updated: int = 0
var f_check_swipe: bool = false
var g_swipe_time_delta: float = 0
var g_counters: Dictionary[String, Counter] = {
"swipe": Counter.new(),
}
var g_active_items: Dictionary = {}
var pending_page: int = -1
var active_actions_dirty: bool = true
var active_actions_elapsed: float = 0.0
var owniverse:Owniverse = Owniverse.new()
var owniverse_items: Dictionary[String, OwniverseItem] = {}
var locked_items: Array = []
func set_datetime(value):
# Simulation time advances in tenths of a year; displaying five decimal
# places only adds zeroes and suggests precision the simulation does not
# have.
date_time.text = Global.format_number(value, 1) if not E.eq(value, 0) else "0.0"
#region Item manipulations: update and visibility
func set_owniverse_item_value() -> void:
for item_id in owniverse.presentation.pending_amounts:
if owniverse_items.has(item_id):
owniverse_items[item_id].set_label(owniverse.presentation.pending_amounts[item_id])
owniverse.presentation.pending_amounts.clear()
#endregion
func _unlock_items():
var result: Dictionary = owniverse.presentation.unlocks(owniverse.state, owniverse.catalog, locked_items)
for item_id in result.visible:
if owniverse_items.has(item_id):
owniverse_items[item_id].set_visible(true)
locked_items = result.remaining
func _on_indicator_pressed(indicator_name: String, page: int = 0):
_set_description(indicator_name, page)
func _set_item_description(item: OwniverseItem) -> void:
var category: String = "Entity" if owniverse.catalog.entities.has(item.item_id) else "Force"
var id: String = item.item_id if category == "Entity" else item.item_name.capitalize()
var page: int = clampi(item.item_page, 0, 4)
if description_targets.get(page, {}).get("id", "") != id:
description_samples.erase(id)
description_rates.erase(id)
description_targets[page] = {"id": id, "category": category}
_refresh_descriptions()
func _set_description(item_name: String, page: int) -> void:
description_targets[page] = {"id": item_name, "category": "Indicator"}
_refresh_descriptions()
func _refresh_descriptions() -> void:
for page in description_targets:
var target: Dictionary = description_targets[page]
var label: RichTextLabel = g_item_descriptions[page]
label.bbcode_enabled = true
label.text = ItemDescription.render(owniverse, Global, target.id, target.category, description_rates.get(target.id, 0.0))
func _update_descriptions(delta: float) -> void:
description_elapsed += delta
if description_elapsed < 0.25:
return
for page in description_targets:
var id: String = description_targets[page].id
var total = ItemDescription.quantities(owniverse, id).total
description_rates[id] = E.divide(E.subtract(total, description_samples[id]), E.of(description_elapsed)) if description_samples.has(id) else 0.0
description_samples[id] = total
description_elapsed = 0.0
_refresh_descriptions()
func _control_page(item: OwniverseItem) -> void:
# TODO переписать это ↓
if !g_active_items.has(item.item_page):
g_active_items[item.item_page] = null
var current_item: OwniverseItem = g_active_items[item.item_page]
if current_item == item:
return
g_active_items[item.item_page] = item
active_actions_dirty = true
if current_item != null and current_item.item_page == item.item_page:
current_item.set_selection(false)
item.set_selection(true)
# subpages
if item.item_sub_page != -1:
item_pages[item.item_sub_page].visible = true
if current_item == null \
or current_item.item_sub_page == -1 \
or current_item.item_sub_page == item.item_sub_page:
return
item_pages[current_item.item_sub_page].visible = false
func _init_owniverse_items() -> bool:
owniverse_items = {}
for item_id in Global.OwniverseItems:
var item_props: Dictionary = Global.OwniverseItems[item_id]
var item: OwniverseItem = OWNIVERSE_ITEM.instantiate()
if !item_props.has("page"):
printerr("Item `", item_id, "` has no `page` key.")
return false
var page: int = int(item_props.page)
item_pages[page].add_child(item)
item.init_button(item_props)
item.item_activated.connect(item_activated)
owniverse_items[item_id] = item
return false
func item_activated(item: OwniverseItem) -> void:
_control_page(item)
_set_item_description(item)
if item.item_id == "S" or item.item_id == "H":
var _value = owniverse.state.amount[item.item_id]
_value = E.multiply(9, _value) if E.gt(_value, 0) else 1
owniverse.request_production(item.item_id, _value, true)
func _check_counters(delta: float) -> Array:
var actions: Array = []
for k in g_counters:
var cnt: Counter = g_counters[k]
if not cnt.is_active:
continue
cnt.value += delta
if cnt.value >= cnt.sec:
actions.append(k)
cnt.value = 0
cnt.is_active = false
return actions
#region Swipe and page
func _do_actions(actions: Array) -> void:
for action: String in actions:
match action:
"swipe":
_swipe_to_nearest_page()
func _swipe_to_nearest_page() -> void:
if stage_page_scroller.scroll_horizontal % PAGE_WIDTH == 0: return
var new_page: int = round(1.0 * stage_page_scroller.scroll_horizontal / PAGE_WIDTH)
if g_tween != null:
if g_tween.is_running():
return
g_tween = stage_page_scroller.get_tree().create_tween()
g_tween.tween_property(stage_page_scroller, "scroll_horizontal",
new_page * PAGE_WIDTH, SWIPE_DURATION).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
func _input(event: InputEvent) -> void:
if event is InputEventScreenDrag:
stage_page_scroller.scroll_horizontal = clamp(
stage_page_scroller.scroll_horizontal - PAGE_COUNT * event.screen_relative.x,
0, PAGE_WIDTH * (PAGE_COUNT - 1))
g_counters.swipe.is_active = true
g_counters.swipe.value = 0
elif event is InputEventPanGesture:
g_counters.swipe.is_active = true
g_counters.swipe.value = 0
elif event is InputEventScreenTouch:
pass
func _set_active_page_actions() -> void:
for pa in page_actions:
if !g_active_items.has(pa): continue
var item_id: String = g_active_items[pa].item_id
var entity: OwniverseEntity = owniverse.catalog.entities[item_id]
#var amount = owniverse.get_available_to_produce(item_id)
#var amount = owniverse.get_available_to_produce(entity)
var amount = owniverse.production.calculate_max_producible(entity)
#print(item_id, " : ", amount)
if item_id == "SMBH":
var preview: Callable = func(requested):
return owniverse.production.calculate_max_producible(entity, requested)
page_actions[pa].set_actions(item_id, amount, preview)
else:
page_actions[pa].set_actions(item_id, amount)
func _page_action_pressed(page_id: int, action_amount) -> void:
if !g_active_items.has(page_id):
return
var item_id: String = g_active_items[page_id].item_id
if E.gt(action_amount, 0):
owniverse.request_production(item_id, action_amount)
#endregion
func _ready() -> void:
get_tree().auto_accept_quit = false
world_indicators = WorldIndicators.new(self)
create_new_universe()
load_data()
_refresh_universe_ui()
g_counters.swipe.sec = 0.2
for pa in page_actions:
page_actions[pa].action_pressed.connect(_page_action_pressed)
page_actions[pa].page_id = pa
## Starts a fresh universe. Can be connected directly to a button's pressed signal.
## Saving continues through the normal autosave/close path.
func create_new_universe() -> void:
var previous: Owniverse = owniverse
owniverse = Owniverse.new()
var inited_result: Dictionary = init_enitities()
locked_items = inited_result.locked_items
for entity in previous.catalog.entities.values():
entity.free()
previous.free()
if is_instance_valid(g_tween):
g_tween.kill()
g_active_items.clear()
description_targets.clear()
description_samples.clear()
description_rates.clear()
description_elapsed = 0.0
active_actions_dirty = true
active_actions_elapsed = 0.0
for label in g_item_descriptions:
label.text = ""
for item in owniverse_items.values():
item.get_parent().remove_child(item)
item.queue_free()
_init_owniverse_items()
for page in range(5, item_pages.size()):
item_pages[page].visible = false
for actions in page_actions.values():
actions.set_actions("", 0.0)
pending_page = RESOURCE_PAGE
_restore_page.call_deferred()
_refresh_universe_ui()
_on_topmenu_button_pressed("World")
func _refresh_universe_ui() -> void:
owniverse.presentation.refresh(owniverse.state, owniverse.catalog)
_change_speed(0)
set_datetime(owniverse.state.time.year)
set_owniverse_item_value()
_unlock_items()
if world_indicators != null: world_indicators.update(owniverse)
func _process(delta: float) -> void:
owniverse.evolute_frame(delta, get_tree())
indicator_elapsed += delta
if indicator_elapsed >= 0.1:
indicator_elapsed = 0.0
world_indicators.update(owniverse)
_update_descriptions(delta)
set_owniverse_item_value()
set_datetime(owniverse.state.time.year)
#owniverse.cycle(delta)
#owniverse.cycle_legacy(year_delta)
var actions = _check_counters(delta)
_do_actions(actions)
# Production limits are expensive (they walk the resource ledger). Refresh
# them when selection changes and at a modest cadence instead of every
# rendered frame. The simulation itself continues to run every frame.
active_actions_elapsed += delta
if active_actions_dirty or active_actions_elapsed >= 0.1:
active_actions_elapsed = 0.0
active_actions_dirty = false
_set_active_page_actions()
func _change_speed(delta: int) -> void:
owniverse.speed = owniverse.speed + delta
var speed: int = owniverse.speed
var ind: int = 1
for icon in g_speed_icons:
if ind <= speed:
icon.visible = true
else:
icon.visible = false
ind += 1
if speed == 1:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "x")
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "2")
elif speed == Global.SPEED_LIMIT:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(Global.SPEED_LIMIT - 1))
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % "x")
else:
g_time_minus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(speed - 1))
g_time_plus.texture_normal = load(SPEED_TEXTURE_NAME_TEMPLATE % str(speed + 1))
func _on_topmenu_button_pressed(screen_name: String) -> void:
for screen_id in screens:
#print(screen_name, " ←→ ", screen_id)
screens[screen_id].visible = screen_id == screen_name
func _on_unlock_and_save_timeout() -> void:
save_data()
_unlock_items()
#region Init save load routines
func load_data() -> bool:
var game_data: Dictionary = SaveManager.load_data("owniverse", "qwerty")
if game_data.is_empty():
if SaveManager.last_error == "":
pending_page = RESOURCE_PAGE
_restore_page.call_deferred()
return false
var restored: Dictionary = game_data.state
# Current definitions are initialized first; reject incompatible saves before publishing.
for id in owniverse.state.amount:
if not restored.amount.has(id) or not restored.stats.total_amount.has(id):
SaveManager.blocked_saves["owniverse"] = true
push_error("Save is missing the current entity: " + id)
return false
var complete: Dictionary = owniverse.state.duplicate(true)
complete.merge(restored, true)
owniverse.state = complete
owniverse.restore_frame_checkpoint(game_data.get("simulation", {}))
owniverse.evolution.initialize_life_batches()
owniverse.presentation.refresh(owniverse.state, owniverse.catalog)
pending_page = clampi(int(game_data.get("ui", {}).get("current_page", 0)), 0, PAGE_COUNT - 1)
_restore_page.call_deferred()
return true
func _restore_page() -> void:
# Wait until containers have calculated the scrollable width.
await get_tree().process_frame
if pending_page >= 0:
stage_page_scroller.scroll_horizontal = pending_page * PAGE_WIDTH
pending_page = -1
func save_data() -> void:
var page: int = pending_page
if page < 0:
page = clampi(roundi(float(stage_page_scroller.scroll_horizontal) / PAGE_WIDTH), 0, PAGE_COUNT - 1)
SaveManager.request_save("owniverse", "qwerty", {
"state": owniverse.state,
"simulation": owniverse.frame_checkpoint(),
"ui": {"current_page": page},
})
var closing: bool = false
func _notification(what: int) -> void:
if not is_node_ready() or closing:
return
if what == NOTIFICATION_WM_CLOSE_REQUEST:
_close_after_save()
elif what == NOTIFICATION_APPLICATION_PAUSED:
save_data()
# The OS may suspend frames immediately; finish the queued write now.
SaveManager.flush_saves()
func _close_after_save() -> void:
closing = true
process_mode = Node.PROCESS_MODE_DISABLED
save_data()
if SaveManager.is_saving():
await SaveManager.saves_drained
get_tree().quit()
func init_enitities() -> Dictionary:
var _result := {
'locked_items': [],
}
owniverse.catalog.load_definitions(Global.OwniverseEntities)
for entity_id in owniverse.catalog.entities:
var entity: OwniverseEntity = owniverse.catalog.entities[entity_id]
owniverse.state.stats.total_amount[entity_id] = 0
owniverse.state.amount[entity_id] = 0
if E.gt(entity.lifespan, 0):
owniverse.state.batches[entity.id] = []
owniverse.batches.add_entity_to_batch(entity_id, 0, 0)
if entity.group_as != "":
owniverse.state.amount[entity.group_as] = 0
owniverse.state.stats.total_amount[entity.group_as] = 0
if entity.unlock != {}:
_result.locked_items.append(entity.id)
return _result
#endregion
func _on_achievements_pressed(extra_arg_0: String) -> void:
pass # Replace with function body.
func _on_credits_pressed(extra_arg_0: String) -> void:
pass # Replace with function body.
+26 -27
View File
@@ -2,7 +2,6 @@ extends SceneTree
func _init(): func _init():
#print("Testing SaveManager...") #print("Testing SaveManager...")
# Instantiate Global manually # Instantiate Global manually
var global_script = load("res://Autoload/Global.gd") var global_script = load("res://Autoload/Global.gd")
var global_instance = global_script.new() var global_instance = global_script.new()
@@ -20,37 +19,37 @@ func _init():
# Workaround: I'll just copy the logic I want to test. # Workaround: I'll just copy the logic I want to test.
var data = global_instance.Owniverse # var data = global_instance.Owniverse
#print("Data to save: ", data) # #print("Data to save: ", data)
var filename = "user://test_save_check.dat" # var filename = "user://test_save_check.dat"
var password = "test" # var password = "test"
var file = FileAccess.open_encrypted_with_pass(filename, FileAccess.WRITE, password) # var file = FileAccess.open_encrypted_with_pass(filename, FileAccess.WRITE, password)
if file == null: # if file == null:
print("Error opening file for write: ", FileAccess.get_open_error()) # print("Error opening file for write: ", FileAccess.get_open_error())
quit(1) # quit(1)
return # return
#print("Saving...") # #print("Saving...")
file.store_var(data) # file.store_var(data)
file.close() # file.close()
#print("Loading...") # #print("Loading...")
file = FileAccess.open_encrypted_with_pass(filename, FileAccess.READ, password) # file = FileAccess.open_encrypted_with_pass(filename, FileAccess.READ, password)
if file == null: # if file == null:
printerr("Error opening file for read") # printerr("Error opening file for read")
quit(1) # quit(1)
return # return
var loaded_data = file.get_var() # var loaded_data = file.get_var()
#print("Loaded data: ", loaded_data) # #print("Loaded data: ", loaded_data)
if str(data) == str(loaded_data): # if str(data) == str(loaded_data):
print("SUCCESS: Data matches.") # print("SUCCESS: Data matches.")
else: # else:
printerr("FAILURE: Data mismatch.") # printerr("FAILURE: Data mismatch.")
print("Original: ", data) # print("Original: ", data)
print("Loaded: ", loaded_data) # print("Loaded: ", loaded_data)
quit() quit()
+207
View File
@@ -0,0 +1,207 @@
# Проверки поэтапного переноса из Owniverse.U
## Производительность на сохранении
```sh
godot --headless --path Owniverse.GI --script res://tests/benchmark_saved_state.gd -- /tmp/save.adventure.json
```
Читает диагностический JSON формата 4 в отдельные экземпляры мира и замеряет
шесть последовательных шагов на скоростях 1, 4, 6. Запись сохранений не вызывается.
Последним аргументом можно задать длительность шага в реальных секундах
(по умолчанию 1/60). Это время расчёта симуляции, без отрисовки интерфейса.
На диагностической копии с 120 партиями прежняя рациональная арифметика после
оптимизации пустых окон давала 90–99 мс на шаг 1/60 секунды на скорости 6.
После перехода на целые блоки и устранения повторного построения физических
количеств повторный замер дал 53–58 мс. При шаге 0,1 секунды: 65–67 мс вместо
117–138 мс. Это замеры расчёта на данной
копии, а не обещание FPS. Для сравнения старый JSON был преобразован только
во временный тестовый файл; в загрузчик игры миграция не добавлена.
Разреженные сценарии сравниваются с полным расчётом в `test_short_lived_events.gd`.
## Целые блоки и дробные остатки
`godot --headless --path Owniverse.GI --script res://tests/test_exact_math.gd`
Независимый эталон Python Fraction: 160 пар с произведением внутри E27; целые
проверяются точно, дроби — с допуском 10^-12. Также границы int64/E27, сериализация,
рецепты с дробными стоимостями, сохранение сумм, время и 100 циклов с меняющимися
долями. Все остальные тесты используют числовое сравнение и сериализацию через
`E`, а не сравнение ссылок на большие числа. Границы точности и новый формат
сохранения описаны в [документации арифметики](../world/owniverse/math/README.md).
## Модули симуляции
`godot --headless --path Owniverse.GI --script res://tests/test_module_lifecycle.gd`
Проверяются отдельные экземпляры модулей и состояния для каждой вселенной, слабая обратная ссылка, освобождение модулей вместе с миром и защита от некорректного delta. Остальные тесты используют прямые API batches, ledger, production, automatic, stellar, life, environment и evolution; временные методы-переадресации Owniverse удалены. Описание границ модулей и порядка фаз: `../world/owniverse/README.md`.
## Математика распределений и каталог
`godot --headless --path Owniverse.GI --script res://tests/test_quantity_catalog.gd`
Проверяются целочисленность и границы распределения, сохранение суммы, разрешение равных остатков, накопление дробей и долгов округления, нормализация весов, размер производственной партии, загрузка каталога и его индексы. Архитектура описана в `../world/owniverse/README.md`. Сохранение игрока не используется.
## Иконки стадий жизни
Тест также проверяет модуль `item_presentation.gd`: отсутствие изменений входного состояния и списка закрытых иконок, решения по разблокировке, отложенную и принудительную публикацию количеств.
`godot --headless --path Owniverse.GI --script res://tests/test_life_icons.gd`
Проверяются одновременная разблокировка подробных и общих иконок EON/LP и C0.0/C0, количества свободных и связанных планет без двойного учёта, переключение подпанелей и очистка счётчика при исчезновении стадии. Сохранение игрока не используется.
## Параметры мира и индикаторы
```sh
godot --headless --path Owniverse.GI --script res://tests/test_world_indicators.gd
```
Проверяются сроки жизни существующих и новых звёзд при смене горючести, вероятности и мощность взрывов, влияние агрессии/порядка/просвещения на жизнь, накопление тенденций по времени и этикам, несколько событий за шаг, продолжение после сериализации, валидация сохранения, границы шкал и описания на двух языках. Сцена использует фикстуру без доступа к сохранению игрока.
## Прямой расчёт завершившихся сверхновых
```sh
godot --headless --path Owniverse.GI --script res://tests/test_short_lived_events.gd
```
Сравниваются ускоренный путь и прежний путь с созданием всех партий, отключаемый только в тестовой фикстуре. Проверяются LRG, HRG, RSG и RHG на границах коротких и длинных интервалов, существующие SN, нехватка энергии, ресурсы, бласты, привязки, остатки округления и живые партии. Дополнительно проверяется, что длинный интервал создаёт не более двух живых окон и одну запись завершений, сохраняя общее количество. Сохранение игрока этот тест не использует.
`test_stellar_rules.gd` также проверяет автоматическое создание HBD: долю 0,1% нового автоматического водорода, появление по одному со случайным округлением, сохранение оплаченного остатка топлива, отсутствие повторного начисления на старый запас, продолжение случайной последовательности после сериализации и переход HBD → CBD с сохранением счётчика BD. Формулы описаны в `../simulation_rules.md`.
## Фоновое сохранение и частота обновления интерфейса
```sh
godot --headless --path Owniverse.GI --script res://tests/test_async_save.gd
godot --headless --path Owniverse.GI --script res://tests/test_ui_updates.gd
```
Сохранение: основной поток создаёт глубокий снимок состояния и параметров. Рабочий поток проверяет данные, записывает зашифрованный временный файл, проверяет чтением и заменяет основное сохранение; диагностический JSON создаётся из того же снимка. Одновременно работает один писатель. Для каждого имени файла хранится только последний ожидающий запрос. `request_save()` подтверждает постановку в очередь; результат записи сообщает сигнал `save_completed`. При закрытии игра ждёт `saves_drained`, при приостановке приложения и уничтожении менеджера очередь завершается через `flush_saves()`. Копирование снимка остаётся в основном потоке.
Тест сохранений пишет только в уникальную временную папку `/tmp`, затем удаляет собственные файлы. Проверяются независимость снимка, работа кадров при записи, объединение запросов, диагностическая копия, сохранность предыдущего файла при ошибках и завершение очереди при уничтожении менеджера. Сообщения `Invalid save`, `Save blocked` и `Cannot write` в этом тесте ожидаемы.
Тест интерфейса проверяет передачу количеств из presentation в контролы, очистку очереди после публикации, отложенное и принудительное обновление, производство по нажатию и формат времени. Stage в текущей реализации применяет очередь счётчиков и время каждый кадр; интервал 0,1 секунды используется для индикаторов. Рефакторинг этот порядок не меняет. Тест использует игровую сцену с отключёнными загрузкой, сохранением и автоматической симуляцией, не обращаясь к сохранению игрока.
## Время: шаг 0,1 игрового года
```sh
godot --headless --path Owniverse.GI --script res://tests/test_time.gd
```
Команда выполняется из общей папки проектов. Тесты используют искусственные состояния; сохранение игрока не читается и не перезаписывается.
Проверяются границы десятых долей года, производство ресурсов на этих границах, накопление дробного остатка, скорости 1–10 000 лет/сек, продолжение после загрузки и недопустимые интервалы.
Схема состояния `0.3.0` хранит:
- `time.datetime` — накопленный возраст, включая необработанную дробную часть;
- `time.year` — последний рассчитанный возраст с точностью до десятой доли года.
Сохранения используют формат 4 и актуальную структуру состояния. Проверяются целостность данных, фоновая запись и повторная загрузка; поддержка и миграция прежних форматов отсутствуют.
Файл с несовместимым номером формата при загрузке переносится в `*.adventure.incompatible.bak` (при совпадении имени добавляется числовой суффикс). Игра начинает новую сессию и может сохранять её в формате 4. Прогресс несовместимого файла не переносится, исходные байты сохраняются в архиве. Ошибка архивирования, расшифровки или повреждение данных текущего формата по-прежнему блокируют перезапись.
## Согласованные правила эволюции
Сохраняются постепенные интервальные окна GI: начало преобразования — через `lifespan`, длительность окна — `lifespan / 40` при `lifespan > 10`, иначе `lifespan`.
Вероятностные исходы используют накопление дробного остатка GI, без случайного округления. Этот же подход выбран для будущего создания планет. Шансы планет записаны долями (`0.01` = 1%), а альтернативные исходы звёзд — процентами (`%0.1` = 0.1%). Парсер планет сохраняет дроби и поддерживает один элемент без `&`.
Уязвимость к бластам читается из `blastability` таблицы GI: HP, EON и цивилизации до C1.2 включительно; C1.3 и выше неуязвимы. Это ограничение относится к бластам уровня 1; локальное уничтожение планет уровня 2 в Unity охватывает все планеты.
```sh
godot --headless --path Owniverse.GI --script res://tests/test_stellar_rules.gd
```
Проверяются парсер планет, граница уязвимости, накопление редких исходов, сериализация остатков и постепенное преобразование реальной партии RD в TWD.
Создание планет подключено к ручному и автоматическому производству звёзд. Бласты обрабатываются как события, а не ресурс. Выжившие планеты переходят преемнику звезды пропорционально числу реально полученных преемников; при отсутствии преемника освобождаются. Локальное разрушение выполняется перед передачей.
Дополнительно проверяются частичная передача, альтернативные преемники, уровни разрушения 1/2, накопление слабых бластов, сохранения, ручное/автоматическое создание планет и несколько поколений за длинный шаг. Правила и формулы описаны в `../simulation_rules.md`.
## Описания выбранных объектов
```sh
godot --headless --path Owniverse.GI --script res://tests/test_descriptions.gd
```
Источник текста — `Global.Templates[Global.Locale]`. Заголовок берётся из `Name`, основной текст — из `Description`. Поддерживаются ключи с классом (`RD.Entity.Description`) и старые ключи без класса (`RD.Description`).
`%valueN%` заменяется значением переменной, имя которой записано в поле `valueN` этой строки. Поддерживаются `amount`, `colored costs`, `lifespan`, `voids`, `he / h`, `metallicity`, показатели энергии, плотности и скорости времени. `amount1`–`amount4` сил пока отображаются как `—`; неизвестные непустые обозначения тоже дают `—`, пустые поля — пустую строку. `[p]` превращается в разделение абзацев, цветовые BBCode-теги сохраняются.
Доступные требования зелёные, недоступные красные. Для объектов со связанными экземплярами выводится доступное количество и серым общее; для планет — общее количество. Скорость изменения вычисляется по реальному времени и обновляется раз в 0,25 секунды. Доли He/H вычисляются из текущих свободных запасов; при пустой смеси показывается `—`. Металличность и плотность используют расчёт среды GI. Счётчики исходной материи и этики Unity в текущей GI отсутствуют и здесь не добавляются.
## Первичная жизнь
```sh
godot --headless --path Owniverse.GI --script res://tests/test_life.gd
```
Проверяются абиогенез, деградация, повторные попытки без создания дополнительных планет, появление C0.0 на прежней звезде, остатки вероятностей, сохранение/продолжение, однократная инициализация старых планет и отсутствие воскрешения после бластов.
Проверка загрузки этических правил, распределений и отделения космических цивилизаций:
```sh
godot --headless --path Owniverse.GI --script res://tests/test_civilization_state.gd
```
Тест цивилизаций дополнительно проверяет общий звёздный бюджет, повторное использование резерва при переходе, звёзды в структурах, массовый эквивалент SMBH, блокировку неподдержанного прогресса, каскад деградации и повторное применение ограничений без потерь.
## Полная эволюция цивилизаций
```sh
godot --headless --path Owniverse.GI --script res://tests/test_civilization_evolution.gd
```
Проверяются реальные коэффициенты C0.2, войны и побочный ущерб C2.0, замена планет колониями с сохранением хозяина, дипломатическое влияние, бонус периода от структур и деградация при их отсутствии. Ускоренная модель проходит все стадии C0.2 → C4.4 → Ct. Проверки контролируют сохранение населения, целочисленность этик, валидацию сохранения и детерминированное продолжение после сериализации.
## Профиль цивилизаций на шестой скорости
```sh
godot --headless --path Owniverse.GI --script res://tests/benchmark_civilizations.gd -- frames=20 profile
godot --path Owniverse.GI --script res://tests/benchmark_civilizations.gd -- ui scenario=mixed frames=10 profile
```
Сценарии `mixed`, `large`, `fragmented` заполняют все стадии и этики, синхронизируя
переходы; `large` использует по 6e20 цивилизаций, `fragmented` — десять партий.
Это искусственные стрессовые сценарии. `scenario=stable` использует штатные
сроки стадий. Параметр `snapshot=/tmp/civil` сохраняет состояние каждого сценария
для сравнения до и после изменения. UI запускает настоящую сцену со страницей
жизни и реальным delta, без загрузки и записи сохранения игрока.
`profile` выводит суммарные микросекунды и число вызовов по этапам. Вложенные
этапы входят во время родительских; складывать их нельзя. В игре сбор выключен.
Кэши физических количеств принадлежат отдельному миру и проверяют изменения
количеств, вложенных привязок и индексов каталога. Кэш структуры правил не входит
в сохранение: при изменении Claim/бонусов нужно перестроить индексы каталога,
при изменении home в существующей таблице — invalidate_civilization_layout().
После оптимизации на M4 Pro, по 20 шагов 1/60 секунды, среднее время:
`mixed` 295 → 235 мс, `large` 666 → 539 мс, `fragmented` 359 → 282 мс.
Полные состояния всех трёх сценариев после 20 шагов совпали до и после изменения.
Дополнительно тест распределений сравнивает новый путь с прежним на 300
случайных наборах, включая 1e40 и накопленные долги округления.
## Расчёт между кадрами
`godot --headless --path Owniverse.GI --script res://tests/test_frame_evolution.gd`
Stage вызывает `evolute_frame`: транзакция получает бюджет 40 мс и уступает
следующему кадру внутри создания партий и обработки стадий. Расчёт остаётся
на главном потоке, состояние публикуется только после полного завершения.
Длительность одной транзакции ограничена обычным шагом 1/60 секунды выбранной
скорости. Запрошенное время хранится отдельно, поэтому отставание не превращается
в один всё более тяжёлый шаг. При предельной нагрузке время симуляции может
отставать от запрошенного; это не ограничение FPS интерфейса и не удаление событий.
Производство во время транзакции выполняется после её завершения. Запрошенное
время, активный интервал, скорость и очередь производства входят в сохранение;
при загрузке незавершённый интервал пересчитывается с опубликованного состояния.
Сброс мира отменяет отложенный расчёт. Тест проверяет точное совпадение непрерывного
и распределённого расчёта, очереди, переключение скорости, восстановление и отмену.
На M4 Pro, 180 кадров реального UI на шестой скорости: смешанный сценарий
15.9 FPS (максимальный кадр 98 мс), большие количества 17.5 FPS (106 мс),
много партий 16.3 FPS (97 мс).
Это FPS отрисовки, а не число завершённых транзакций симуляции в секунду.
+74
View File
@@ -0,0 +1,74 @@
extends SceneTree
const Fixture = preload("res://tests/fixtures/civilization_benchmark.gd")
func _initialize(): call_deferred("run")
func run():
var ui: bool = "ui" in OS.get_cmdline_user_args()
var scenarios: Array = ["mixed", "large", "fragmented"]
var frames: int = 120
var step_delta: float = 1.0 / 60.0
for argument in OS.get_cmdline_user_args():
if argument.begins_with("scenario="): scenarios = [argument.trim_prefix("scenario=")]
if argument.begins_with("delta="): step_delta = float(argument.trim_prefix("delta="))
if argument.begins_with("frames="): frames = maxi(2, int(argument.trim_prefix("frames=")))
Engine.max_fps = 60
if ui: DisplayServer.window_set_size(Vector2i(540, 960))
for scenario in scenarios:
var scene
var stage
var world
if ui:
scene = load("res://world/world.tscn").instantiate()
stage = scene.get_node("Stage")
stage.owniverse.free()
stage.set_script(load("res://tests/fixtures/benchmark_ui_stage.gd"))
root.add_child(scene)
await process_frame
await process_frame
world = stage.owniverse
else:
world = load("res://world/owniverse/owniverse.gd").new()
world.catalog.load_definitions(root.get_node("Global").OwniverseEntities)
Fixture.seed(world, root.get_node("Global"), scenario == "fragmented", scenario == "large", scenario == "stable")
world.profile_enabled = "profile" in OS.get_cmdline_user_args()
var samples: Array = []
if ui:
stage.stage_page_scroller.scroll_horizontal = 4 * stage.PAGE_WIDTH
for item in stage.owniverse_items.values(): item.visible = true
for page in stage.item_pages: page.visible = true
stage._set_item_description(stage.owniverse_items["C2.0"])
stage._refresh_universe_ui()
for warmup in 10: await process_frame
stage.measuring = true
for frame in frames:
await process_frame
if (frame + 1) % 10 == 0:
print("%s: measured %d UI frames" % [scenario, frame + 1])
stage.measuring = false
samples = stage.process_samples
report(scenario + " UI frame", stage.frame_samples)
else:
for frame in frames:
var started: int = Time.get_ticks_usec()
world.evolute(step_delta)
samples.append((Time.get_ticks_usec() - started) / 1000.0)
report(scenario + (" UI handler" if ui else " CPU"), samples)
if ui:
print("Completed simulation transactions: ", world.frame_commits, "; published year: ", world.state.time.year, "; requested year: ", world.frame_clock.get("year", 0))
print("Statistics ", world.state.civilization_stats)
if world.profile_enabled: print("Profile microseconds/calls: ", world.profile)
for argument in OS.get_cmdline_user_args():
if argument.begins_with("snapshot="):
var file = FileAccess.open(argument.trim_prefix("snapshot=") + "-" + scenario + ".json", FileAccess.WRITE)
file.store_string(JSON.stringify(world.E.encode(world.state)))
for entity in world.catalog.entities.values(): entity.free()
world.free()
if ui: scene.free()
quit()
func report(label: String, samples: Array):
var total: float = 0.0
for sample in samples: total += sample
samples.sort()
print("%s: mean %.2f ms, p95 %.2f ms, max %.2f ms, %.1f per second" % [label, total / samples.size(), samples[ceili(samples.size() * 0.95) - 1], samples.back(), samples.size() * 1000 / total])
+1
View File
@@ -0,0 +1 @@
uid://b5w4sp6eepypa
+47
View File
@@ -0,0 +1,47 @@
extends SceneTree
## Read-only benchmark. Loads a diagnostic JSON, never invokes SaveManager.
const E = preload("res://world/owniverse/math/exact.gd")
func _initialize():
call_deferred("run")
func restore_json_integers(value):
# JSON parses ordinary integer tokens as float. Large integers are $exact.
if value is float and value == floorf(value) and absf(value) <= 9007199254740991:
return int(value)
if value is Dictionary:
for key in value: value[key] = restore_json_integers(value[key])
elif value is Array:
for i in value.size(): value[i] = restore_json_integers(value[i])
return value
func run():
var args = OS.get_cmdline_user_args()
if args.is_empty():
print("Usage: --script tests/benchmark_saved_state.gd -- /path/to/save.adventure.json [delta_seconds]")
quit(1)
return
var data = JSON.parse_string(FileAccess.get_file_as_string(args[0]))
if not data is Dictionary or data.get("format_version") != 5:
push_error("Expected diagnostic JSON format 5")
quit(1)
return
var initial: Dictionary = E.decode(restore_json_integers(data)).state
var delta: float = args[1].to_float() if args.size() > 1 else 1.0 / 60.0
if not is_finite(delta) or delta <= 0:
quit(1)
return
for speed in [1, 4, 6]:
var world = load("res://world/owniverse/owniverse.gd").new()
world.catalog.load_definitions(root.get_node("Global").OwniverseEntities)
world.state = initial.duplicate(true)
world.speed = speed
var elapsed: Array = []
for cycle in 6:
var start: int = Time.get_ticks_usec()
world.evolute(delta)
elapsed.append((Time.get_ticks_usec() - start) / 1000.0)
print("Speed %d, six consecutive %s-second steps, ms: %s" % [speed, delta, elapsed])
for entity in world.catalog.entities.values(): entity.free()
world.free()
quit()
+1
View File
@@ -0,0 +1 @@
uid://dji1apht4pn5y
+40
View File
@@ -0,0 +1,40 @@
extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
func _initialize(): call_deferred("run")
func run():
for scenario in ["ordinary", "hypergiants"]:
var world = load("res://world/owniverse/owniverse.gd").new()
world.catalog.load_definitions(root.get_node("Global").OwniverseEntities)
for id in world.catalog.entities:
world.state.amount[id] = 0
world.state.stats.total_amount[id] = 0
var group: String = world.catalog.entities[id].group_as
if group != "":
world.state.amount[group] = 0
world.state.stats.total_amount[group] = 0
world.speed = 6
world.state.amount.S = E.of("1e24")
world.state.amount.H = E.of("1e24")
for entry in [["RD", 1234567], ["YD", 765432], ["STN", 654321]]:
world.state.amount[entry[0]] = entry[1]
world.batches.append_batch(world.state, entry[0], entry[1], 0, 0)
if scenario == "hypergiants":
world.state.amount.HG = E.of("1e20")
world.batches.append_batch(world.state, "HG", E.of("1e20"), 0, 0)
var start_year = E.subtract(world.catalog.entities.HG.lifespan, 1000)
world.state.time = {"datetime": start_year, "year": start_year}
var samples: Array = []
var total: int = 0
for frame in 600:
var started: int = Time.get_ticks_usec()
world.evolute(1.0 / 60.0)
var duration: int = Time.get_ticks_usec() - started
samples.append(duration)
total += duration
samples.sort()
print("Speed 6 %s: 600 frames, mean %.3f ms, p95 %.3f ms, max %.3f ms, %.1f cycles/sec" % [scenario, total / 600000.0, samples[569] / 1000.0, samples.back() / 1000.0, 600000000.0 / total])
for entity in world.catalog.entities.values(): entity.free()
world.free()
quit()
+1
View File
@@ -0,0 +1 @@
uid://bboo6op14es24
+56
View File
@@ -0,0 +1,56 @@
extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
func _initialize(): call_deferred("run")
func report(label: String, samples: Array):
var total: float = 0.0
var slow: int = 0
for sample in samples:
total += sample
if sample > 33.333: slow += 1
samples.sort()
print("%s: %d samples, mean %.3f ms, p95 %.3f ms, max %.3f ms, >33ms %d" % [label, samples.size(), total / samples.size(), samples[int(samples.size() * 0.95) - 1], samples.back(), slow])
func run():
Engine.max_fps = 60
DisplayServer.window_set_size(Vector2i(540, 960))
print("Renderer: ", RenderingServer.get_current_rendering_method(), " adapter: ", RenderingServer.get_video_adapter_name())
for scenario in ["ordinary", "hypergiants"]:
for page in ([2] if "stars" in OS.get_cmdline_user_args() else [1, 2]):
var scene = load("res://world/world.tscn").instantiate()
var stage = scene.get_node("Stage")
stage.owniverse.free()
stage.set_script(load("res://tests/fixtures/benchmark_ui_stage.gd"))
root.add_child(scene)
await process_frame
await process_frame
var world = stage.owniverse
world.speed = 6
world.state.amount.S = E.of("1e24")
world.state.amount.H = E.of("1e24")
for entry in [["RD", 1234567], ["YD", 765432], ["STN", 654321]]:
world.state.amount[entry[0]] = entry[1]
world.batches.append_batch(world.state, entry[0], entry[1], 0, 0)
if scenario == "hypergiants":
world.state.amount.HG = E.of("1e20")
world.batches.append_batch(world.state, "HG", E.of("1e20"), 0, 0)
var start_year = E.subtract(world.catalog.entities.HG.lifespan, 1000)
world.state.time = {"datetime": start_year, "year": start_year}
stage.stage_page_scroller.scroll_horizontal = page * stage.PAGE_WIDTH
for item in stage.owniverse_items.values(): item.visible = true
if page == 2: stage._control_page(stage.owniverse_items.HG)
stage._set_item_description(stage.owniverse_items.HG if page == 2 else stage.owniverse_items.H)
stage._refresh_universe_ui()
for warmup in 30: await process_frame
stage.measuring = true
for frame in 600: await process_frame
stage.measuring = false
var label: String = "%s page %d" % [scenario, page]
report(label + " Stage CPU", stage.process_samples)
report(label + " frame wall", stage.frame_samples)
print("UI counters: H=", stage.owniverse_items.H.description.text, " HG=", stage.owniverse_items.HG.description.text, " date=", stage.date_time.text)
for entity in world.catalog.entities.values(): entity.free()
world.free()
scene.free()
quit()
+1
View File
@@ -0,0 +1 @@
uid://b3gmlo2vq6kk4
+19
View File
@@ -0,0 +1,19 @@
extends "res://stage/stage.gd"
var measuring: bool = false
var process_samples: Array = []
var frame_samples: Array = []
var previous_frame: int = 0
# Exercise the production Stage, with isolated state and no player-save I/O.
func load_data() -> bool: return false
func save_data() -> void: pass
func _notification(_what: int) -> void: pass
func _process(delta: float) -> void:
if not measuring: return
var started: int = Time.get_ticks_usec()
if previous_frame: frame_samples.append((started - previous_frame) / 1000.0)
previous_frame = started
super._process(delta)
process_samples.append((Time.get_ticks_usec() - started) / 1000.0)
+1
View File
@@ -0,0 +1 @@
uid://d1wm7nav71y3o
File diff suppressed because one or more lines are too long
+30
View File
@@ -0,0 +1,30 @@
extends RefCounted
const E = preload("res://world/owniverse/math/exact.gd")
static func seed(world, global, fragmented: bool = false, large: bool = false, stable: bool = false):
for id in world.catalog.entities:
world.state.amount[id] = 0
world.state.stats.total_amount[id] = 0
var entity = world.catalog.entities[id]
if entity.group_as != "":
world.state.amount[entity.group_as] = 0
world.state.stats.total_amount[entity.group_as] = 0
for id in ["RD", "BG", "TWD", "SNS", "MGT", "BH25", "SMBH", "SCD", "GEM", "LGG", "LSC", "LGF", "LGW", "LUB"]:
world.state.amount[id] = E.of("1e48")
world.state.amount.S = E.of("1e50")
world.state.amount.H = E.of("1e48")
world.state.binds.RD = {"HP": E.of("1e30"), "RP": E.of("1e30"), "GG": E.of("1e30"), "AB": E.of("1e30")}
var count = E.of("6e20") if large else 6000
for id in global.CivilizationRules:
if E.le(global.CivilizationRules[id].span, 0): continue
world.state.amount[id] = count
world.state.ethics[id] = {}
for ethic in ["m", "l", "w", "d", "c", "b"]:
world.state.ethics[id][ethic] = E.divide(count, 6)
world.state.batches[id] = []
var parties: int = 10 if fragmented else 1
for i in parties:
var lifespan = E.of(global.CivilizationRules[id].span) if stable else 1
world.state.batches[id].append({"amount": E.divide(count, parties), "created_from": i * 100, "created_to": 1000 + i * 100, "start_year": E.add(lifespan, i * 100), "end_year": E.add(lifespan, 1000 + i * 100)})
world.ledger.refresh_groups(world.state)
world.speed = 6
+1
View File
@@ -0,0 +1 @@
uid://bjloakx4qdpsj
File diff suppressed because one or more lines are too long
+59
View File
@@ -0,0 +1,59 @@
extends RefCounted
const E = preload("res://world/owniverse/math/exact.gd")
# Frozen apportionment before the civilization performance refactor.
static func allocate_whole(requests: Dictionary, limit: Variant) -> Dictionary:
var total: Variant = 0
for amount in requests.values():
total = E.add(total, E.floor_value(E.maximum(0, amount)))
var available: Variant = E.floor_value(E.minimum(E.maximum(0, limit), total))
var result: Dictionary = {}
var order: Array = []
var assigned: Variant = 0
for id in requests:
var expected: Variant = (E.mul_div(E.floor_value(E.maximum(0, requests[id])), available, total) if E.gt(total, 0) else 0)
result[id] = E.floor_value(expected)
assigned = E.add(assigned, result[id])
order.append({"id": id, "rest": E.subtract(expected, result[id])})
order.sort_custom(func ( a : Dictionary , b : Dictionary ) -> bool : return (E.gt(a.rest, b.rest) if E.ne(a.rest, b.rest) else E.lt(str(a.id), str(b.id))))
for item : Dictionary in order:
if E.ge(assigned, available):
break
if E.lt(result[item.id], E.floor_value(requests[item.id])):
result[item.id] = E.add(result[item.id], 1)
assigned = E.add(assigned, 1)
return result
static func sum(pop: Dictionary) -> Variant:
var result: Variant = 0
for n in pop.values(): result = E.add(result, n)
return result
static func split(remainders: Dictionary, key: String, count: Variant, weights: Dictionary) -> Dictionary:
var result: Dictionary = {}
var sum_weights: Variant = sum(weights)
if (E.le(count, 0) or E.le(sum_weights, 0)): return result
var expected: Dictionary = {}
var positive_sum: Variant = 0
for id in weights:
expected[id] = E.add(E.mul_div(count, weights[id], sum_weights), remainders.get(E.add(E.add(key, ":"), id), 0))
positive_sum = E.add(positive_sum, E.maximum(0, expected[id]))
var order: Array = []
var assigned: Variant = 0
for id in weights:
var normalized: Variant = (E.mul_div(E.maximum(0, expected[id]), count, positive_sum) if E.gt(positive_sum, 0) else 0)
result[id] = E.floor_value(normalized)
assigned = E.add(assigned, result[id])
order.append({"id": id, "rest": E.subtract(normalized, result[id])})
order.sort_custom(func ( a , b ) : return (E.gt(a.rest, b.rest) if E.ne(a.rest, b.rest) else E.lt(str(a.id), str(b.id))))
for entry in order:
if E.ge(assigned, count): break
result[entry.id] = E.add(result[entry.id], 1)
assigned = E.add(assigned, 1)
for id in weights:
remainders[E.add(E.add(key, ":"), id)] = E.clamp_value(E.subtract(expected[id], result[id]), E.neg(1), 1)
return result
+1
View File
@@ -0,0 +1 @@
uid://dxsly3qpyqrjy

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