diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ab9d773..49e4562 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -8,7 +8,7 @@ on: - '.github/workflows/build.yaml' env: - VERSION: "1.5" + VERSION: "2.0" USER: Mikk155 REPOSITORY: ripent.py @@ -21,6 +21,11 @@ jobs: - name: Checkout code uses: actions/checkout@v2 + - name: Installing Python + run: | + pip install --upgrade pip + pip install -r requirements.txt + - name: Install pyinstaller run: pip install pyinstaller @@ -48,6 +53,11 @@ jobs: - name: Checkout code uses: actions/checkout@v2 + - name: Installing Python + run: | + pip install --upgrade pip + pip install -r requirements.txt + - name: Install pyinstaller run: pip install pyinstaller diff --git a/.gitignore b/.gitignore index 68bc17f..e25c546 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Testing +ripent.bat +maps/* + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/LICENSE b/LICENSE index c657cab..5cdd612 100644 --- a/LICENSE +++ b/LICENSE @@ -1,407 +1,22 @@ -Attribution-NonCommercial 4.0 International -======================================================================= +The MIT License (MIT) -Creative Commons Corporation ("Creative Commons") is not a law firm and -does not provide legal services or legal advice. Distribution of -Creative Commons public licenses does not create a lawyer-client or -other relationship. Creative Commons makes its licenses and related -information available on an "as-is" basis. Creative Commons gives no -warranties regarding its licenses, any material licensed under their -terms and conditions, or any related information. Creative Commons -disclaims all liability for damages resulting from their use to the -fullest extent possible. +Copyright (c) 2024 Mikk -Using Creative Commons Public Licenses +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: -Creative Commons public licenses provide a standard set of terms and -conditions that creators and other rights holders may use to share -original works of authorship and other material subject to copyright -and certain other rights specified in the public license below. The -following considerations are for informational purposes only, are not -exhaustive, and do not form part of our licenses. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - Considerations for licensors: Our public licenses are - intended for use by those authorized to give the public - permission to use material in ways otherwise restricted by - copyright and certain other rights. Our licenses are - irrevocable. Licensors should read and understand the terms - and conditions of the license they choose before applying it. - Licensors should also secure all rights necessary before - applying our licenses so that the public can reuse the - material as expected. Licensors should clearly mark any - material not subject to the license. This includes other CC- - licensed material, or material used under an exception or - limitation to copyright. More considerations for licensors: - wiki.creativecommons.org/Considerations_for_licensors - - Considerations for the public: By using one of our public - licenses, a licensor grants the public permission to use the - licensed material under specified terms and conditions. If - the licensor's permission is not necessary for any reason--for - example, because of any applicable exception or limitation to - copyright--then that use is not regulated by the license. Our - licenses grant only permissions under copyright and certain - other rights that a licensor has authority to grant. Use of - the licensed material may still be restricted for other - reasons, including because others have copyright or other - rights in the material. A licensor may make special requests, - such as asking that all changes be marked or described. - Although not required by our licenses, you are encouraged to - respect those requests where reasonable. More considerations - for the public: - wiki.creativecommons.org/Considerations_for_licensees - -======================================================================= - -Creative Commons Attribution-NonCommercial 4.0 International Public -License - -By exercising the Licensed Rights (defined below), You accept and agree -to be bound by the terms and conditions of this Creative Commons -Attribution-NonCommercial 4.0 International Public License ("Public -License"). To the extent this Public License may be interpreted as a -contract, You are granted the Licensed Rights in consideration of Your -acceptance of these terms and conditions, and the Licensor grants You -such rights in consideration of benefits the Licensor receives from -making the Licensed Material available under these terms and -conditions. - - -Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - d. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - e. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - f. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - g. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - h. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - i. NonCommercial means not primarily intended for or directed towards - commercial advantage or monetary compensation. For purposes of - this Public License, the exchange of the Licensed Material for - other material subject to Copyright and Similar Rights by digital - file-sharing or similar means is NonCommercial provided there is - no payment of monetary compensation in connection with the - exchange. - - j. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - k. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - l. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - -Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part, for NonCommercial purposes only; and - - b. produce, reproduce, and Share Adapted Material for - NonCommercial purposes only. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties, including when - the Licensed Material is used other than for NonCommercial - purposes. - - -Section 3 -- License Conditions. - -Your exercise of the Licensed Rights is expressly made subject to the -following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - 4. If You Share Adapted Material You produce, the Adapter's - License You apply must not prevent recipients of the Adapted - Material from complying with this Public License. - - -Section 4 -- Sui Generis Database Rights. - -Where the Licensed Rights include Sui Generis Database Rights that -apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database for NonCommercial purposes - only; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material; and - - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - -For the avoidance of doubt, this Section 4 supplements and does not -replace Your obligations under this Public License where the Licensed -Rights include other Copyright and Similar Rights. - - -Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - -Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - -Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - -Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - -======================================================================= - -Creative Commons is not a party to its public -licenses. Notwithstanding, Creative Commons may elect to apply one of -its public licenses to material it publishes and in those instances -will be considered the “Licensor.” The text of the Creative Commons -public licenses is dedicated to the public domain under the CC0 Public -Domain Dedication. Except for the limited purpose of indicating that -material is shared under a Creative Commons public license or as -otherwise permitted by the Creative Commons policies published at -creativecommons.org/policies, Creative Commons does not authorize the -use of the trademark "Creative Commons" or any other trademark or logo -of Creative Commons without its prior written consent including, -without limitation, in connection with any unauthorized modifications -to any of its public licenses or any other arrangements, -understandings, or agreements concerning use of licensed material. For -the avoidance of doubt, this paragraph does not form part of the -public licenses. - -Creative Commons may be contacted at creativecommons.org. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index cde5d1c..c8335c7 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,44 @@ -| #Trans | -|---| -| [English](#en) | -| [Español](#es) | +# About -# EN +ripent.py is a python script for exporting, importing and modifying entity data by using logic rules - +This is heavily inspired in [lazyripent.py](https://github.com/Zode/lazyripent) -### ripent.py is a utility for goldsource BSP maps. +[![Release](https://github.com/Mikk155/ripent.py/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/Mikk155/ripent.py/actions/workflows/build.yaml) -#### This tool allows modifying the structure of entities massively through a configuration. +# Installing - +- [windows](https://github.com/Mikk155/ripent.py/releases/download/2.0/ripent.exe) + - It may be threated as malware due to python being repacked within the executable + - It is trustful, you can see the [workflows](https://github.com/Mikk155/ripent.py/actions) where it is built + - If you still have your doubts you can always install python and use the open-source library -- This script is heavily inspired by [lazyripent.py](https://github.com/Zode/lazyripent) +- [python](https://github.com/Mikk155/ripent.py/releases/download/2.0/ripent.py) + - Requires library [MikkUtils](https://github.com/Mikk155/MikkUtils) >= 0.0.4 + > ``` + > pip install MikkUtils + > ``` +- [linux](https://github.com/Mikk155/ripent.py/releases/download/2.0/ripent) + - Probably the same as windows executable + - This [workflows](https://github.com/Mikk155/ripent.py/actions) program has not been tested yet so i'm unsure if this even works -## Special Thanks to: +- rules + - This is a example rules made for another project that is using this tool -- [Zode](https://github.com/Zode) -- omamfan -- [Erty](https://github.com/Erty-Gamedev) +# Using ---- -> NOTE: It is recommended to use a decent program if you are not familiar with JSON, as these will show you your errors if you make any. [Visual Studio Code](https://code.visualstudio.com/) is recommended. +Run the script and follow the instructions or use it in with arguments for advanced mode ---- +## Advanced mode -# rules.json +# Logic Rules -The JSON format we will use is composed of an array of dictionaries +--- +> NOTE: It is recommended to use a decent program if you are not familiar with JSON, as these will show you your errors if you make any. [Visual Studio Code](https://code.visualstudio.com/) is recommended. +--- -```json -[ - { }, - { }, - { } -] -``` +The JSON format we will use is composed of an array of dictionaries Each dictionary represents a rule to be applied to the map entities. @@ -52,41 +53,30 @@ graph TD; b["{ }"]; b --> c["match\n{ }"]; c --> e1["string"]; - b --> c2["not_match\n{ }"]; c2 --> e2["string"]; - b --> c3["have\n[ ]"]; c3 --> e4["string"]; - b --> c4["not_have\n[ ]"]; c4 --> e5["string"]; - b --> c5["replace\n{ }"]; c5 --> e6["string"]; - b --> c6["rename\n{ }"]; c6 --> e7["string"]; - b --> c7["add\n{ }"]; c7 --> e8["string"]; - b --> c8["remove\n[ ]"]; c8 --> e9["string"]; - b --> c9["new_entity\n[ ]"]; c9 --> e10["{ }"]; e10 --> e10b["string"]; - b --> c10["maps\n[ ]"]; c10 --> e11["string"]; ``` ---- - -# Selectors +## Selectors -### match +### match ```json "match": @@ -97,7 +87,7 @@ graph TD; ``` The entity MUST have the following values defined. -### not_match +### not_match ```json "not_match": @@ -107,7 +97,7 @@ The entity MUST have the following values defined. ``` The entity MUST NOT have the following values defined. -### maps +### maps ```json "maps": @@ -118,9 +108,9 @@ The entity MUST NOT have the following values defined. ``` The map MUST be named one of these. -> NOTE: maps, match and not_match are special and support initial and final wildcarding with an asterisk * +> NOTE: maps, match and not_match are special and support initial and final wildcarding with an asterisk ``*`` -### have +### have ```json "have": @@ -131,7 +121,7 @@ The map MUST be named one of these. ``` The entity MUST have these keys, regardless of their value. -### not_have +### not_have ```json "not_have": @@ -141,16 +131,16 @@ The entity MUST have these keys, regardless of their value. ``` The entity MUST NOT have these keys, regardless of their value. -# Actions +## Actions -### delete +### delete ```json "delete": true ``` Deletes the entity -### replace +### replace ```json "replace": @@ -160,7 +150,7 @@ Deletes the entity ``` Replaces the value of a key. -### rename +### rename ```json "rename": @@ -170,7 +160,7 @@ Replaces the value of a key. ``` Renames the key while keeping the original value. -### add +### add ```json "add": @@ -180,7 +170,7 @@ Renames the key while keeping the original value. ``` Adds a new key-value pair. -### remove +### remove ```json "remove": @@ -190,7 +180,7 @@ Adds a new key-value pair. ``` Removes the key and its value. -### new_entity +### new_entity ```json "new_entity": @@ -204,10 +194,10 @@ Removes the key and its value. Creates one or more new entities. --- -### maintain values -In some cases, you can use a dollar sign $ at the beginning to copy the original value of the entity. +### values +In some cases, you can use a dollar sign ``$`` at the beginning to copy the original value of the entity. -> For example: "body": "$bodygroup" +> For example: ``"body": "$bodygroup"`` In this case, we are copying the existing value in the "bodygroup" key. @@ -216,221 +206,10 @@ That feature works for the values of: - replace - add ---- - -# ES - - - -### ripent.py es una utilidad para los mapas BSP de goldsource. - -#### Esta herramienta permite modificar la estructura de las entidades masivamente mediante una configuración. - - - -- Este script esta fuerte mente inspirado en [lazyripent.py](https://github.com/Zode/lazyripent) - - -## Agradecimientos especiales a: +# Credits - [Zode](https://github.com/Zode) -- omamfan -- Erty - ---- - -> NOTA: Es recomendable usar un programa decente si no estas relacionado a json, ya que estos van a enseñarte tus errores, si cometes alguno. Se recomienda [Visual Studio Code](https://code.visualstudio.com/) - ---- - -# rules.json - -El formato de json que utilizaremos esta compuesto de una array de diccionarios - -```json -[ - { }, - { }, - { } -] -``` - -Cada diccionario representa una regla a aplicar a las entidades del mapa. - -Existen dos tipos de reglas los selectores y las acciones. - -Mientras que los selectores se encargan de "escoger" entidades las acciones se encargan de ejecutar ciertas acciones si fueron escogidas. -```mermaid -graph TD; - a["["] --> b["{ }"]; - a1["]"] --> b["{ }"]; - b["{ }"]; - b --> c["match\n{ }"]; - c --> e1["string"]; - - b --> c2["not_match\n{ }"]; - c2 --> e2["string"]; - - b --> c3["have\n[ ]"]; - c3 --> e4["string"]; - - b --> c4["not_have\n[ ]"]; - c4 --> e5["string"]; - - b --> c5["replace\n{ }"]; - c5 --> e6["string"]; - - b --> c6["rename\n{ }"]; - c6 --> e7["string"]; - - b --> c7["add\n{ }"]; - c7 --> e8["string"]; - - b --> c8["remove\n[ ]"]; - c8 --> e9["string"]; - - b --> c9["new_entity\n[ ]"]; - c9 --> e10["{ }"]; - e10 --> e10b["string"]; - - b --> c10["maps\n[ ]"]; - c10 --> e11["string"]; -``` - ---- - -# Selectores - -### match - -```json -"match": -{ - "classname": "monster_barney", - "models": "models/barney2.mdl" -} -``` -La entidad DEBE tener los siguientes valores definidos. - -### not_match - -```json -"not_match": -{ - "weapons": "1" -} -``` -La entidad NO DEBE tener los siguientes valores definidos. - -### maps - -```json -"maps": -[ - "c1a0", - "c1a1" -] -``` -El mapa DEBE llamarse igual a uno de estos. - -> NOTA: maps, match y not_match son especiales y soportan wildcarding inicial y final con un asterisco * - -### have - -```json -"have": -[ - "body", - "skin" -] -``` -La entidad DEBE tener estas keys, no importa su valor. - -### not_have - -```json -"not_have": -[ - "spawnflags" -] -``` -La entidad NO DEBE tener estas keys, no importa su valor. - -# Acciones - -### delete - -```json -"delete": true -``` -Elimina la entidad - -### replace - -```json -"replace": -{ - "models": "models/mymod/barney.mdl" -} -``` -Reemplaza el valor de una key. - -### rename - -```json -"rename": -{ - "body": "bodygroup" -} -``` -Cambia el nombre de la key manteniendo el valor original. - -### add - -```json -"add": -{ - "weapons": "1" -} -``` -Añade una key-value nueva. - -### remove - -```json -"remove": -[ - "skin" -] -``` -Elimina el valor y la key. - -### new_entity - -```json -"new_entity": -[ - { - "classname": "env_sprite_follow", - "target": "$targetname" - } -] -``` -Crea una o varias entidades nuevas. - ---- - -### mantener valores -En algunos casos puedes utilizar un signo de dolar $ al inicio para copiar el valor original de la entidad. - -> por ejemplo: ``"body": "$bodygroup"`` - -En este caso estamos copiando el valor existente en la key "bodygroup" - -Esta mecanica funciona con los valores de: -- new_entity -- replace -- add +- omamfan ---- +- [Erty](https://github.com/Erty-Gamedev) diff --git a/changelog.md b/changelog.md index e69de29..fc0c730 100644 --- a/changelog.md +++ b/changelog.md @@ -0,0 +1,4 @@ +## 10/8/2024 + +- Added support for wildcard **any** part of the string +- Reworked script start up so it give options to do proper uses diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1e3d69c --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +MikkUtils \ No newline at end of file diff --git a/ripent.py b/ripent.py index caf7fe4..09133f1 100644 --- a/ripent.py +++ b/ripent.py @@ -1,122 +1,104 @@ import os -import sys import json import locale -# Delete json files when importing data -DeleteJson = True - -#======================================================================== -#======================== Message stuff -#======================================================================== +from MikkUtils import Ripent, wildcard, format, jsonc messages = { - "press_input": + "EnterExit": { "english": "Press Enter to exit...", "spanish": "Presiona Enter para salir...", }, - "drag_and_drop_bsp": + "EnterContinue": + { + "english": "Press Enter to continue", + "spanish": "Presiona Enter para continuar", + }, + "exit": + { + "english": "{} Exit.", + "spanish": "{} Salir.", + }, + "export": { - "english": "Drag and drop a BSP file to the script to extract the entity data.", - "spanish": "Arrastra y suelta un archivo BSP el script para extraer la informacion de entidades.", + "english": "{} Export entity data", + "spanish": "{} Exportar datos de entidades", }, - "drag_and_drop_ent": + "rules": { - "english": "Drag and drop a JSON file to the script to import the entity data.", - "spanish": "Arrastra y suelta un archivo JSON a el script para importar la informacion de entidades.", + "english": "{} Apply logic rules to entity data json", + "spanish": "{} Aplicar reglas logicas a la informacion de entidades json", }, - "sys_export": + "rules_path": { - "english": "Write the absolute path to a BSP file to extract the entity data.", - "spanish": "Escribe la ruta completa hacia un archivo BSP para exportar la informacion de entidades.", + "english": "Locate rules.json in\n{}", + "spanish": "Pon rules.json en\n{}", }, - "sys_import": + "import": { - "english": "Write the absolute path to a JSON file to import the entity data.", - "spanish": "Escribe la ruta completa hacia un archivo JSON para importar la informacion de entidades.", + "english": "{} Import entity data", + "spanish": "{} Importar datos de entidades", }, - "sys_all": + "export_folder": { - "english": "$cmd$ \"Absolute/path/to/a/folder\"", - "spanish": "$cmd$ \"Ruta/completa/hacia/una/carpeta\"", + "english": "Locate all the map files that you want to export/import in\n{}", + "spanish": "Pon todos los archivos de mapas que quieres exportar/importar en\n{}", }, - "skipping_map": + "exporting_map": { - "english": "Something went wrong, Skipping map $map$", - "spanish": "Algo salio mal, Saltando mapa $map$", + "english": "Exporting {}", + "spanish": "Exportando {}", }, - "writting_map": + "importing_map": { - "english": "Writting to $map$", - "spanish": "Escribiendo en $map$", + "english": "Writting to {}", + "spanish": "Escribiendo en {}", }, - "apply_rules": + "delete_jsons": { - "english": "Press R and enter to apply rules.json into the BSP files. Press Enter to not.", - "spanish": "Presiona R y Enter para aplicar rules.json dentro de los archivos BSP. Presiona Enter para no hacerlo.", + "english": "{} Delete json files of entity data", + "spanish": "{} Elimina los archivos json de informacion de entidades", }, - "applying_rule": + "deleting_json": { - "english": "Applying rule $index$...", - "spanish": "Aplicando regla $index$...", + "english": "Deleted {}", + "spanish": "Eliminado {}", }, } +supported = ( '.bsp' ) +#supported = ( '.bsp', '.rmf', '.map', '.jmf' ) + syslang = locale.getlocale() + lang = syslang[0] + if lang.find( '_' ) != -1: lang = lang[ 0 : lang.find( '_' ) ] -lang = lang.lower() - -def cornc(msg, args={}): - msgArgs = '' - if lang in messages.get( msg, {} ): - msgArgs = f'{messages.get( msg, {} ).get( lang ) }' - else: - msgArgs = f'{messages.get( msg, {} ).get( "english" ) }' - - if len(args) > 0: - for key, value in args.items(): - msgArgs = msgArgs.replace( f'${key}$', value ) - return msgArgs - -def printl( msg, args={} ): - print(f'{cornc(msg, args)}\n') - -def log( msg, args={} ): - print(f'{cornc(msg, args)}') - -#======================================================================== -#======================== Rules logic -#======================================================================== - -def get_rules(): - - js = {} - - with open( os.path.abspath( 'rules.json' ), 'r' ) as file: - - jsdata = '' - lines = file.readlines() - for t, line in enumerate( lines ): - - line = line.strip() +lang = lang.lower() - if line and line != '' and not line.startswith( '//' ): - jsdata = f'{jsdata}\n{line}' +def printl(msg, args={}): + print( format( messages.get( msg, {} ).get( ( lang if lang in messages.get( msg, {} ) else "english" ) ), args ) + '\n' ) - js = json.loads( jsdata ) - file.close() +def waitl( msg ): + printl( msg ) + input("") - return js +def clear(): + if os.name == 'nt': + os.system('cls') + else: + os.system('clear') -def wildcard( _f, _t ): +def get_files( path ): + files = [] + for file in os.listdir( path ): + if file.endswith( supported ): + files.append( file ) - if _f == _t or _f.startswith('*') and _t.endswith(_f[1:]) or _f.endswith('*') and _t.startswith(_f[:len(_f)-1]): - return True - return False + return files def is_matched( entblock = {}, rules = {}, i = 0, mapname='' ): @@ -126,12 +108,12 @@ def is_matched( entblock = {}, rules = {}, i = 0, mapname='' ): if 'match' in rules: for k, v in rules.get( 'match', {} ).items(): selectors+=1 - if k in entblock and wildcard( v, entblock.get( k, '' ) ): + if k in entblock and wildcard( entblock.get( k, '' ), v ): passed +=1 if 'not_match' in rules: for k, v in rules.get( 'not_match', {} ).items(): selectors+=1 - if not k in entblock and not wildcard( v, entblock.get( k, '' ) ): + if not k in entblock and not wildcard( entblock.get( k, '' ), v ): passed +=1 if 'have' in rules: for k in rules.get( 'have', [] ): @@ -155,241 +137,170 @@ def is_matched( entblock = {}, rules = {}, i = 0, mapname='' ): passed +=1 else: for map in rules.get( 'maps', [] ): - if wildcard( map, map_name ): + if wildcard( map_name, map ): passed +=1 break if selectors > 0 and passed == selectors: - log(f'applying_rule', { "index": str(i) } ) + print(f'applying_rule', { "index": str(i) } ) return True return False -def ripent( entdata = [], mapname = '' ): - - NewEntData = [] - - for entblock in entdata: - - SaveEntity = True - rules_list = get_rules() - - for i, rules in enumerate(rules_list): - - # matched all selectors, aplying actions - if is_matched( entblock=entblock, rules=rules, i=i, mapname=mapname ): - - OldEntBlock = entblock.copy() # Used for value-copying - - if 'delete' in rules and rules.get( 'delete', False ): - SaveEntity = False - break - - if 'new_entity' in rules: - for e in rules.get( 'new_entity', [] ): - if len(e) > 0: - for k, v in e.items(): - if v.startswith( '$' ): - e[ k ] = OldEntBlock.get( v[1:], '' ) - NewEntData.append(e) - - if 'replace' in rules: - for k, v in rules.get( 'replace', {} ).items(): - entblock[ k ] = OldEntBlock.get( v[1:], '' ) if v.startswith( '$' ) else v - - if 'rename' in rules: - for k, v in rules.get( 'rename', {} ).items(): - entblock.pop( k, '' ) - entblock[ v ] = OldEntBlock.get( k, '' ) - - if 'add' in rules: - for k, v in rules.get( 'add', {} ).items(): - entblock[ k ] = OldEntBlock.get( v[1:], '' ) if v.startswith( '$' ) else v - - if 'remove' in rules: - for k in rules.get( 'remove', [] ): - entblock.pop( k, '' ) - - if len(entblock) == 0: # Somehow a empty entity ended here - SaveEntity = False - break - - if SaveEntity: - NewEntData.append(entblock) - - return NewEntData - #======================================================================== -#======================== Formatting logic +#======================== main #======================================================================== -def bsp_read( bsp_name, writedata = None ): - - with open( bsp_name, 'rb+' ) as bsp_file: - - bsp_file.read(4) # BSP version. - entities_lump_start_pos = bsp_file.tell() - read_start = int.from_bytes( bsp_file.read(4), byteorder='little' ) - read_len = int.from_bytes( bsp_file.read(4), byteorder='little' ) - bsp_file.seek( read_start ) - - if writedata != None: - writedata_bytes = writedata.encode('ascii') - new_len = len(writedata_bytes) - - if new_len <= read_len: - bsp_file.write(writedata_bytes) - if new_len < read_len: - bsp_file.write(b'\x00' * (read_len - new_len)) - else: - bsp_file.seek(0, os.SEEK_END) - new_start = bsp_file.tell() - bsp_file.write(writedata_bytes) - - bsp_file.seek(entities_lump_start_pos) - bsp_file.write(new_start.to_bytes(4, byteorder='little')) - bsp_file.write(new_len.to_bytes(4, byteorder='little')) - else: - entities_lump = bsp_file.read( read_len ) - return entities_lump.decode('ascii').splitlines() - return None - -def convert( maps=[] ): - - APPLY_RULES = False - - if maps[0].endswith( '.json' ): - - printl('apply_rules') - ApplyRules = input() - - if ApplyRules.upper() == 'R': - APPLY_RULES = True - - for map in maps: - - if map.endswith( '.bsp' ): - - entdata = [] - - lines = bsp_read( map ) - - if lines == None: - printl('skipping_map', { 'map': map } ) - continue - - entity = {} - oldline = '' - - for line in lines: - - if line == '{': - continue - - line = line.strip() - - if not line.endswith( '"' ): - oldline = line - elif oldline != '' and not line.startswith( '"' ): - line = f'{oldline}{line}' - - if line.find( '\\' ) != -1: - line = line.replace( '\\', '\\\\' ) - - line = line.strip( '"' ) - - if not line or line == '': - continue - - if line.startswith( '}' ): # startswith due to [NULL] - entdata.append( json.dumps( entity ) ) - entity.clear() - else: - keyvalues = line.split( '" "' ) - if len( keyvalues ) == 2: - entity[ keyvalues[0] ] = keyvalues[1] - - with open( map.replace( '.bsp', '.json' ), 'w' ) as jsonfile: - - printl('writting_map', { 'map': map.replace( '.bsp', '.json' ) } ) - - jsonfile.write( '[\n' ) - FirstBlockOf = True - FirstKeyOf = True +abs = f"{os.path.abspath( '' )}\\" + +def main(): + clear() + printl('exit',[ ' [ E ] -']) + printl('export',[ ' [ 1 ] -']) + printl('import',[ ' [ 2 ] -']) + printl('rules',[ ' [ 3 ] -']) + printl('delete_jsons',[ ' [ 4 ] -']) + + command = input().upper() + + clear() + + if command == 'E': + exit(0) + elif command == '1': + printl('exit',[ ' [ E ] -']) + printl('export_folder',[ f'"{abs}maps\\"']) + printl('EnterContinue') + if input().upper() == 'E': + exit(0) + clear() + maps = get_files( f'{abs}maps\\' ) + for map in maps: + if map.endswith( supported ): + mapfile = Ripent( f'{abs}\\maps\\{map}' ) + mapfile.export( True ) + printl('exporting_map', [ map ] ) + waitl( 'EnterContinue' ) + elif command == '2': + printl('exit',[ ' [ E ] -']) + printl('export_folder',[ f'"{abs}maps\\"']) + printl('EnterContinue') + if input().upper() == 'E': + exit(0) + clear() + maps = get_files( f'{abs}maps\\' ) + for map in maps: + if map.endswith( '.json' ) and map != 'rules.json': + + r = f'{abs}\\maps\\{map}' + if os.path.exists( r.replace( '.json', '.bsp' ) ): + r = map.replace( '.json', '.bsp' ) + elif os.path.exists( r.replace( '.json', '.map' ) ): + r = map.replace( '.json', '.map' ) + elif os.path.exists( r.replace( '.json', '.rmf' ) ): + r = map.replace( '.json', '.rmf' ) + elif os.path.exists( r.replace( '.json', '.jmf' ) ): + r = map.replace( '.json', '.jmf' ) + + entity_data = json.load( open( f'{abs}\\maps\\{map}', 'r' ) ) + mapfile = Ripent( f'{abs}\\maps\\{r}' ) + mapfile.import_( entity_data ) + printl('importing_map', [ map ] ) + waitl( 'EnterContinue' ) + elif command == '3': + printl('exit',[ ' [ E ] -']) + printl('rules_path',[ f'"{abs}maps\\rules.json"']) + printl('EnterContinue') + if input().upper() == 'E': + exit(0) + clear() + maps = get_files( f'{abs}maps\\' ) + rules_list = jsonc( f'{abs}\\maps\\rules.json' ) + + for map in maps: + if map.endswith( '.json' ) and map != 'rules.json': + + r = f'{abs}\\maps\\{map}' + if os.path.exists( r.replace( '.json', '.bsp' ) ): + r = map.replace( '.json', '.bsp' ) + elif os.path.exists( r.replace( '.json', '.map' ) ): + r = map.replace( '.json', '.map' ) + elif os.path.exists( r.replace( '.json', '.rmf' ) ): + r = map.replace( '.json', '.rmf' ) + elif os.path.exists( r.replace( '.json', '.jmf' ) ): + r = map.replace( '.json', '.jmf' ) + + entdata = json.load( open( f'{abs}\\maps\\{map}', 'r' ) ) + mapfile = Ripent( f'{abs}\\maps\\{r}' ) + printl('importing_map', [ map ] ) + mapname=map.replace( '.json', '' ) + + NewEntData = [] for entblock in entdata: - if FirstBlockOf: - FirstBlockOf = False - else: - jsonfile.write( ',\n' ) - - FirstKeyOf = True - - jsonfile.write( '\t{\n' ) - - for key, value in json.loads( entblock ).items(): - - if FirstKeyOf: - FirstKeyOf = False - else: - jsonfile.write( ',\n' ) - - jsonfile.write( f'\t\t"{key}": "{value}"' ) - - jsonfile.write( '\n\t}' ) - - jsonfile.write( '\n]\n' ) - jsonfile.close() - - elif map.endswith( '.json' ) and os.path.exists( map.replace( '.json', '.bsp' ) ): - - with open( map, 'r' ) as jsonfile: - - entitydata = json.load( jsonfile ) - - if APPLY_RULES: - entitydata = ripent( entdata = entitydata, mapname=map ) - - newdata = '' - - for entblock in entitydata: - newdata += '{\n' - for key, value in entblock.items(): - newdata += f'"{key}" "{value}"\n' - newdata += '}\n' - - printl('writting_map', { 'map': map.replace( '.json', '.bsp' ) } ) - - bsp_read( map.replace( '.json', '.bsp' ), writedata=newdata ) - - if DeleteJson: - os.remove( map ) - -#======================================================================== -#======================== Inputs -#======================================================================== -print('') -if len(sys.argv) == 1: - printl('drag_and_drop_bsp') - printl('drag_and_drop_ent') - printl('sys_export') - printl('sys_import') - printl('sys_all', { 'cmd':'-import' }) - printl('sys_all', { 'cmd':'-export' }) - printl('press_input') - sys.argv = input("").split() -if len(sys.argv) >= 1: - maps=[] - if sys.argv[0] in [ '-export', '-import' ]: - folder = os.path.abspath( '' )+'\\' - if len(sys.argv) > 1 and not sys.argv[1].endswith( '\\' ) and not sys.argv[1].endswith( '/' ): - folder =f'{sys.argv[1]}\\' - for file in os.listdir( f'{folder}'): - if sys.argv[0] == '-export' and file.endswith( ".bsp" ) or sys.argv[0] == '-import' and file.endswith( ".json" ): - maps.append(file) - else: - maps = sys.argv - if maps[0].endswith( '.py' ): - maps.pop(0) - if len(maps) > 0: - convert( maps=maps ) + SaveEntity = True + + for i, rules in enumerate(rules_list): + + # matched all selectors, aplying actions + if is_matched( entblock=entblock, rules=rules, i=i, mapname=mapname ): + + OldEntBlock = entblock.copy() # Used for value-copying + + if 'delete' in rules and rules.get( 'delete', False ): + SaveEntity = False + continue + + if 'new_entity' in rules: + for e in rules.get( 'new_entity', [] ): + if len(e) > 0: + for k, v in e.items(): + if v.startswith( '$' ): + e[ k ] = OldEntBlock.get( v[1:], '' ) + NewEntData.append(e) + + if 'replace' in rules: + for k, v in rules.get( 'replace', {} ).items(): + entblock[ k ] = OldEntBlock.get( v[1:], '' ) if v.startswith( '$' ) else v + + if 'rename' in rules: + for k, v in rules.get( 'rename', {} ).items(): + entblock.pop( k, '' ) + entblock[ v ] = OldEntBlock.get( k, '' ) + + if 'add' in rules: + for k, v in rules.get( 'add', {} ).items(): + entblock[ k ] = OldEntBlock.get( v[1:], '' ) if v.startswith( '$' ) else v + + if 'remove' in rules: + for k in rules.get( 'remove', [] ): + entblock.pop( k, '' ) + + if len(entblock) == 0: # Somehow a empty entity ended here + SaveEntity = False + break + + if SaveEntity: + NewEntData.append(entblock) + + mapfile.import_( NewEntData ) + mapfile.export( True ) + + waitl( 'EnterContinue' ) + elif command == '4': + printl('exit',[ ' [ E ] -']) + printl('EnterContinue') + if input().upper() == 'E': + exit(0) + clear() + maps = get_files( f'{abs}maps\\' ) + for map in maps: + if map.endswith( supported ): + ptz = f'{abs}\\maps\\{map[ : map.rfind( "." ) ]}.json' + if os.path.exists( ptz ): + printl('deleting_json', [ ptz ] ) + os.remove( ptz ) + waitl( 'EnterContinue' ) + main() + +main()