init commit
This commit is contained in:
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Disable autocrlf on generated files, they always generate with LF
|
||||
# Add any extra files or paths here to make git stop saying they
|
||||
# are changed when only line endings change.
|
||||
src/generated/**/.cache/cache text eol=lf
|
||||
src/generated/**/*.json text eol=lf
|
||||
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# eclipse
|
||||
bin
|
||||
*.launch
|
||||
.settings
|
||||
.metadata
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# idea
|
||||
out
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# gradle
|
||||
build
|
||||
.gradle
|
||||
|
||||
# other
|
||||
eclipse
|
||||
run
|
||||
|
||||
# Files from Forge MDK
|
||||
forge*changelog.txt
|
||||
353
LICENSE
Normal file
353
LICENSE
Normal file
@@ -0,0 +1,353 @@
|
||||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
|
||||
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.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
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.
|
||||
|
||||
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-ShareAlike 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-ShareAlike 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. BY-NC-SA Compatible License means a license listed at
|
||||
creativecommons.org/compatiblelicenses, approved by Creative Commons
|
||||
as essentially the equivalent of this Public License.
|
||||
- d. 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.
|
||||
- e. 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.
|
||||
- f. 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.
|
||||
- g. License Elements means the license attributes listed in the name
|
||||
of a Creative Commons Public License. The License Elements of this
|
||||
Public License are Attribution, NonCommercial, and ShareAlike.
|
||||
- h. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public License.
|
||||
- i. 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.
|
||||
- j. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
- k. 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.
|
||||
- l. 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.
|
||||
- m. 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.
|
||||
- n. 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. Additional offer from the Licensor – Adapted Material.
|
||||
Every recipient of Adapted Material from You automatically
|
||||
receives an offer from the Licensor to exercise the Licensed
|
||||
Rights in the Adapted Material under the conditions of the
|
||||
Adapter's License You apply.
|
||||
- C. 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.
|
||||
- b. ShareAlike.In addition to the conditions in Section 3(a), if You
|
||||
Share Adapted Material You produce, the following conditions also
|
||||
apply.
|
||||
- 1. The Adapter's License You apply must be a Creative Commons
|
||||
license with the same License Elements, this version or later,
|
||||
or a BY-NC-SA Compatible License.
|
||||
- 2. You must include the text of, or the URI or hyperlink to, the
|
||||
Adapter's License You apply. You may satisfy this condition in
|
||||
any reasonable manner based on the medium, means, and context in
|
||||
which You Share Adapted Material.
|
||||
- 3. You may not offer or impose any additional or different terms
|
||||
or conditions on, or apply any Effective Technological Measures
|
||||
to, Adapted Material that restrict exercise of the rights
|
||||
granted under the Adapter's License You apply.
|
||||
|
||||
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,
|
||||
including for purposes of Section 3(b); 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.
|
||||
59
README.md
Normal file
59
README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Timelord
|
||||
|
||||
Ваш лучший помощник в вопросах настройки времени! На Forge версии 1.16.5 и только. Отдельная благодарность Мсе за большую часть логики, которую я взял у него.
|
||||
|
||||
|
||||
## Как это работает
|
||||
|
||||
При запуске игры у вас создадутся файлики в ./config/timelord - на каждый дименшен по файлу. В этих файлах, собственно, все и настраивается. Для каждого дименшена файл выглядит как-то так:
|
||||
|
||||
```json
|
||||
{
|
||||
"active": false,
|
||||
"rain": {
|
||||
"endlessRain": false,
|
||||
"endlessThunder": false,
|
||||
"income": 0,
|
||||
"outcome": 0,
|
||||
"thunder": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"dice": 0
|
||||
},
|
||||
"time": {
|
||||
"hours_offset": 0,
|
||||
"scale": 0.0,
|
||||
"fixedDayTime": -1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Для того, чтобы таймлорд работал, вам нужно изменить active на true. По умолчанию он не работает ни для какого дименшена.
|
||||
|
||||
Начнем c time.
|
||||
|
||||
1. Если задан fixedDayTime в пределах от 0 до 24000, то назначается он. Это позволяет сделать в дименшене фиксированное время. Значения остальных полей игнорируются, т.е. если вы не хотите, чтобы было фиксированное время, то сделайте -1 или 24001 и так далее.
|
||||
2. Если scale больше нуля, то считается, что вы хотите именно его. Скейл это ускорение или замедление течения времени относительно обычного времени. Например, если scale 3.0, то время будет идти в три раза быстрее, а если 0.5 - то в 2 раза медленнее. Если активируется scale, то игнорируется hours_offset.
|
||||
3. Наконец, hours_offset. Он может быть от -18 до 18 и выражает собой отступ в часах от текущего серверного времени. Он может быть 0, тогда игровое время будет полностью соответствовать времени сервера. Если вы хотите и его отключить, то сделайте его больше 18 или меньше -18.
|
||||
Таким образом, если у вас hours_offset: 9, scale: 0 и fixed_day_time: -1, то время будет идти как в ванилле. Это может быть полезно, если вам нужно сохранить фичи дождя.
|
||||
|
||||
Перейдем к rain.
|
||||
|
||||
Дождь работает по следующему принципу - есть условная "ванная", которая у каждого мира своя. В эту замечательную ванную, когда нет дождя, каждый тик добавляется incomе. Если накопленный объем больше min, то каждый тик делается бросок дайса с dice граней. Если выпадает 0, то дайс считается успешным и начинается дождь. То есть, например, если вы хотите, чтобы шанс дождя был 50% (напомню, что чек делается каждый тик, поэтому это скорее всего означает мгновенный дождь), то можете задать dice = 1. Если объем накопленного дождя дошел до maх, а дождь так и не начался, то он случается вне зависимости от результатов ролла. При этом, если в момент начала дождя текущий накопленный дождь был выше thunder, то начнется гроза. Когда дождь начался, то каждый тик он забирает outcome из накопленного запаса "ванны", и когда этот запас доходит до 0, отключает дождь. Может звучать сложно, но вот вам пример:
|
||||
```json
|
||||
{
|
||||
"rain": {
|
||||
"endlessRain": false,
|
||||
"endlessThunder": false,
|
||||
"income": 1,
|
||||
"outcome": 5,
|
||||
"thunder": 7500,
|
||||
"min": 5000,
|
||||
"max": 10000,
|
||||
"dice": 5000
|
||||
}
|
||||
}
|
||||
```
|
||||
В данной ситуации, каждый тик добавляется по 1 дождю в "ванную", пока оно не дойдет до 5 тысяч. То есть через 5000 тиков каждый тик будет кидаться дайс, и если выпадает 0, то случается дождь. Если при этом дождь должен начаться после того, как его накопилось 7500, то будет гроза. Если дайсик ни разу не прокнул и накопленный дождь дошел до 10000, то он начнется, и это обязательно будет гроза (поскольку 10000 > 7500).
|
||||
|
||||
Так же есть endlessRain и endlessThunder. Они отключают всю остальную логику, просто включая дождь или грозу, если они должны быть. Учтите, что технически гроза может быть без дождя, но я не уверен, как именно это работает. Так же учтите, что если вы включили endlessRain, то включение endlessThunder ничего не сделает - их нужно включать одновременно. Поэтому если вам нужны обе эти штуки, то включайте их одновременно.
|
||||
176
build.gradle
Normal file
176
build.gradle
Normal file
@@ -0,0 +1,176 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url = 'https://maven.minecraftforge.net' }
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
|
||||
}
|
||||
}
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
version = '1.0'
|
||||
group = 'stargazer.timelord' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
archivesBaseName = 'timelord'
|
||||
|
||||
java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8.
|
||||
|
||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||
minecraft {
|
||||
// The mappings can be changed at any time, and must be in the following format.
|
||||
// Channel: Version:
|
||||
// snapshot YYYYMMDD Snapshot are built nightly.
|
||||
// stable # Stables are built at the discretion of the MCP team.
|
||||
// official MCVersion Official field/method names from Mojang mapping files
|
||||
//
|
||||
// You must be aware of the Mojang license when using the 'official' mappings.
|
||||
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
|
||||
//
|
||||
// Use non-default mappings at your own risk. they may not always work.
|
||||
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||
mappings channel: 'snapshot', version: '20210309-1.16.5'
|
||||
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
|
||||
|
||||
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||
args '--mod', 'examplemod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include resources generated by data generators.
|
||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains:annotations:20.1.0'
|
||||
|
||||
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
|
||||
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
|
||||
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||
minecraft 'net.minecraftforge:forge:1.16.5-36.2.34'
|
||||
|
||||
// You may put jars on which you depend on in ./libs or you may define them like so..
|
||||
// compile "some.group:artifact:version:classifier"
|
||||
// compile "some.group:artifact:version"
|
||||
|
||||
// Real examples
|
||||
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
|
||||
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
|
||||
|
||||
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
|
||||
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// These dependencies get remapped to your current MCP mappings
|
||||
// deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// For more info...
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
|
||||
}
|
||||
|
||||
// Example for how to get properties into the manifest for reading by the runtime..
|
||||
jar {
|
||||
manifest {
|
||||
attributes([
|
||||
"Specification-Title": "timelord",
|
||||
"Specification-Vendor": "stargazer",
|
||||
"Specification-Version": "1", // We are version 1 of ourselves
|
||||
"Implementation-Title": project.name,
|
||||
"Implementation-Version": "${version}",
|
||||
"Implementation-Vendor" :"stargazer",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// Example configuration to allow publishing using the maven-publish task
|
||||
// This is the preferred method to reobfuscate your jar file
|
||||
jar.finalizedBy('reobfJar')
|
||||
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
|
||||
//publish.dependsOn('reobfJar')
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact jar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file:///${project.projectDir}/mcmodsrepo"
|
||||
}
|
||||
}
|
||||
}
|
||||
4
gradle.properties
Normal file
4
gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
185
gradlew
vendored
Normal file
185
gradlew
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
gradlew.bat
vendored
Normal file
89
gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
109
src/main/java/stargazer/timelord/Timelord.java
Normal file
109
src/main/java/stargazer/timelord/Timelord.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package stargazer.timelord;
|
||||
|
||||
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
import net.minecraftforge.fml.network.simple.SimpleChannel;
|
||||
import net.minecraftforge.server.command.ConfigCommand;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import stargazer.timelord.commands.TimelordCommands;
|
||||
import stargazer.timelord.config.Configuration;
|
||||
import stargazer.timelord.config.DimensionTimeConfig;
|
||||
import stargazer.timelord.logic.TimelordClient;
|
||||
import stargazer.timelord.logic.TimelordServer;
|
||||
import stargazer.timelord.net.TimePacket;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT;
|
||||
import static stargazer.timelord.config.Configuration.initFromString;
|
||||
|
||||
@Mod(Timelord.MODID)
|
||||
public class Timelord {
|
||||
public static final String MODID = "timelord";
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static final String PROTOCOL_VERSION = "1";
|
||||
public static SimpleChannel TIME_CHANNEL;
|
||||
private static final Map<ResourceLocation, DimensionTimeConfig> dimensionsConfigMap = new HashMap<>();
|
||||
|
||||
public static Map<ResourceLocation, DimensionTimeConfig> getDimensionsConfigMap() {
|
||||
return dimensionsConfigMap;
|
||||
}
|
||||
|
||||
public static void putStringIntoDimensionsConfigMap(ResourceLocation resourceLocation, String string) {
|
||||
dimensionsConfigMap.put(resourceLocation, initFromString(string));
|
||||
}
|
||||
|
||||
|
||||
public Timelord() {
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onCommonSetupEvent);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::onCommandsRegister);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::doWorldTick);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::doRenderTick);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::onLogin);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::onWorldLoaded);
|
||||
MinecraftForge.EVENT_BUS.addListener(this::onChangeDimension);
|
||||
}
|
||||
|
||||
private void onCommandsRegister(RegisterCommandsEvent event) {
|
||||
new TimelordCommands(event.getDispatcher());
|
||||
ConfigCommand.register(event.getDispatcher());
|
||||
}
|
||||
|
||||
private void doWorldTick(TickEvent.WorldTickEvent event) {
|
||||
if (event.world.isRemote) return;
|
||||
TimelordServer.worldTick(event);
|
||||
}
|
||||
|
||||
private void doRenderTick(TickEvent.RenderTickEvent event) {
|
||||
TimelordClient.renderTick(event);
|
||||
}
|
||||
|
||||
private void onCommonSetupEvent(FMLCommonSetupEvent ezvent) {
|
||||
if (!new File("./config/timelord/").exists()) {
|
||||
if (!new File("./config/timelord/").mkdir()) {
|
||||
System.out.println("Error creating Timelord folder, check permissions?");
|
||||
} else {
|
||||
System.out.println("Successfully created Timelord folder");
|
||||
}
|
||||
}
|
||||
TIME_CHANNEL = NetworkRegistry.newSimpleChannel(new ResourceLocation("timelord", "timelord"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals);
|
||||
int index = 0;
|
||||
TIME_CHANNEL.registerMessage(index++, TimePacket.class, TimePacket::encode, TimePacket::decode, TimePacket::handle, Optional.of(PLAY_TO_CLIENT));
|
||||
}
|
||||
|
||||
private void onLogin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
if (event.getPlayer().world.isRemote) return;
|
||||
ResourceLocation rl = event.getPlayer().world.getDimensionKey().getLocation();
|
||||
TIME_CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) event.getPlayer()), new TimePacket(rl, Configuration.getConfigAsString(dimensionsConfigMap.get(rl))));
|
||||
}
|
||||
|
||||
private void onChangeDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
|
||||
if (event.getPlayer().world.isRemote) return;
|
||||
ResourceLocation rl = event.getPlayer().world.getDimensionKey().getLocation();
|
||||
TIME_CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) event.getPlayer()), new TimePacket(rl, Configuration.getConfigAsString(dimensionsConfigMap.get(rl))));
|
||||
}
|
||||
|
||||
private void onWorldLoaded(WorldEvent.Load event) {
|
||||
if (!event.getWorld().isRemote() && event.getWorld() instanceof ServerWorld) {
|
||||
ServerWorld sw = (ServerWorld) event.getWorld();
|
||||
dimensionsConfigMap.put(sw.getDimensionKey().getLocation(), Configuration.init(sw));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package stargazer.timelord.commands;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.Commands;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.fml.network.PacketDistributor;
|
||||
import stargazer.timelord.Timelord;
|
||||
import stargazer.timelord.config.Configuration;
|
||||
import stargazer.timelord.net.TimePacket;
|
||||
|
||||
import static stargazer.timelord.Timelord.getDimensionsConfigMap;
|
||||
|
||||
public class TimelordCommands {
|
||||
public TimelordCommands(CommandDispatcher<CommandSource> dispatcher) {
|
||||
dispatcher.register(Commands.literal("timelord").then(Commands.literal("reload").requires(s -> s.hasPermissionLevel(4)).executes((command) -> {
|
||||
return reload(command.getSource());
|
||||
})));
|
||||
}
|
||||
|
||||
private int reload(CommandSource source) throws CommandSyntaxException {
|
||||
|
||||
ServerWorld sw = source.getWorld();
|
||||
for (ServerWorld world : sw.getServer().getWorlds()) {
|
||||
ResourceLocation rl = world.getDimensionKey().getLocation();
|
||||
getDimensionsConfigMap().put(rl, Configuration.init(world));
|
||||
Timelord.TIME_CHANNEL.send(PacketDistributor.ALL.noArg(),
|
||||
new TimePacket(rl, Configuration.getConfigAsString(getDimensionsConfigMap().get(rl)))
|
||||
);
|
||||
|
||||
source.sendFeedback(new StringTextComponent("Timelord config reloaded for " + world.getDimensionKey().getLocation()), true);
|
||||
}
|
||||
source.sendFeedback(new StringTextComponent("Timelord config succesfully reloaded!"), true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
47
src/main/java/stargazer/timelord/config/Configuration.java
Normal file
47
src/main/java/stargazer/timelord/config/Configuration.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package stargazer.timelord.config;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class Configuration {
|
||||
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
|
||||
public static DimensionTimeConfig initFromString(String string) {
|
||||
return gson.fromJson(string, DimensionTimeConfig.class);
|
||||
}
|
||||
|
||||
public static DimensionTimeConfig init(ServerWorld sw) {
|
||||
String filePath = String.format("./config/timelord/%s.json", sw.getDimensionKey().getLocation()).replace(":", "_");
|
||||
return loadOrCreateDimensionConfig(filePath);
|
||||
}
|
||||
|
||||
public static String getConfigAsString(DimensionTimeConfig timeConfig) {
|
||||
return gson.toJson(timeConfig);
|
||||
}
|
||||
|
||||
|
||||
private static DimensionTimeConfig loadOrCreateDimensionConfig(String filePath) {
|
||||
try {
|
||||
JsonReader reader = new JsonReader(new FileReader(filePath));
|
||||
return gson.fromJson(reader, DimensionTimeConfig.class);
|
||||
} catch (FileNotFoundException ex) {
|
||||
DimensionTimeConfig cfg = new DimensionTimeConfig();
|
||||
try {
|
||||
Writer writer = Files.newBufferedWriter(Paths.get(filePath));
|
||||
gson.toJson(cfg, writer);
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package stargazer.timelord.config;
|
||||
|
||||
public class DimensionTimeConfig {
|
||||
public boolean active = false;
|
||||
|
||||
public Rain rain = new Rain();
|
||||
public Time time = new Time();
|
||||
|
||||
public static class Rain {
|
||||
public boolean endlessRain = false;
|
||||
public boolean endlessThunder = false;
|
||||
public long income = 0;
|
||||
public long outcome = 0;
|
||||
public long thunder = 0;
|
||||
public long min = 0;
|
||||
public long max = 0;
|
||||
public int dice = 0;
|
||||
}
|
||||
|
||||
public class Time {
|
||||
public short hours_offset = 0;
|
||||
public double scale = 0;
|
||||
|
||||
public short fixedDayTime = -1;
|
||||
|
||||
}
|
||||
}
|
||||
62
src/main/java/stargazer/timelord/logic/TimelordClient.java
Normal file
62
src/main/java/stargazer/timelord/logic/TimelordClient.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package stargazer.timelord.logic;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.IWorldInfo;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import stargazer.timelord.Timelord;
|
||||
import stargazer.timelord.config.DimensionTimeConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
public class TimelordClient {
|
||||
|
||||
@Nullable
|
||||
private static DimensionTimeConfig getConfig(World world) {
|
||||
return Timelord.getDimensionsConfigMap().get(world.getDimensionKey().getLocation());
|
||||
}
|
||||
|
||||
public static void renderTick(TickEvent.RenderTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.START) return;
|
||||
final World world = Minecraft.getInstance().world;
|
||||
if (world == null) return;
|
||||
handleTime(world, getConfig(world));
|
||||
}
|
||||
|
||||
|
||||
private static void handleTime(World world, DimensionTimeConfig cfg) {
|
||||
if (cfg == null || cfg.time == null || !cfg.active) return;
|
||||
|
||||
if (cfg.time.fixedDayTime <= 24000 && cfg.time.fixedDayTime >= 0) {
|
||||
setFixedTime((ClientWorld) world, cfg.time.fixedDayTime);
|
||||
} else if (cfg.time.scale > 0) {
|
||||
setScaledTime((ClientWorld) world, cfg.time.scale);
|
||||
} else if (cfg.time.hours_offset >= -18 && cfg.time.hours_offset <= 18) {
|
||||
setRealTime((ClientWorld) world, ZoneOffset.ofTotalSeconds(cfg.time.hours_offset * 3600));
|
||||
}
|
||||
}
|
||||
|
||||
private static void setFixedTime(ClientWorld world, int fixedTime) {
|
||||
world.setDayTime(fixedTime);
|
||||
}
|
||||
|
||||
private static void setRealTime(ClientWorld world, ZoneId timezone) {
|
||||
final Duration mcTimeFix = Duration.ofHours(6);
|
||||
final LocalDateTime now = LocalDateTime.now(timezone).minus(mcTimeFix);
|
||||
|
||||
final long secs = now.toEpochSecond(ZoneOffset.UTC);
|
||||
final long time = (secs * 24000) / 86400; // Convert from real day to minecraft day
|
||||
world.setDayTime(time);
|
||||
}
|
||||
|
||||
private static void setScaledTime(ClientWorld world, double scale) {
|
||||
final IWorldInfo wi = world.getWorldInfo();
|
||||
final long tt = wi.getGameTime();
|
||||
world.setDayTime((long) (tt * scale));
|
||||
}
|
||||
}
|
||||
107
src/main/java/stargazer/timelord/logic/TimelordServer.java
Normal file
107
src/main/java/stargazer/timelord/logic/TimelordServer.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package stargazer.timelord.logic;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.storage.IServerWorldInfo;
|
||||
import net.minecraft.world.storage.IWorldInfo;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import stargazer.timelord.Timelord;
|
||||
import stargazer.timelord.config.DimensionTimeConfig;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
public class TimelordServer {
|
||||
|
||||
@Nullable
|
||||
private static DimensionTimeConfig getConfig(World world) {
|
||||
return Timelord.getDimensionsConfigMap().get(world.getDimensionKey().getLocation());
|
||||
}
|
||||
|
||||
public static void worldTick(TickEvent.WorldTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) return;
|
||||
final DimensionTimeConfig cfg = getConfig(event.world);
|
||||
if (cfg == null) return;
|
||||
if (!event.world.isRemote() && event.world instanceof ServerWorld) {
|
||||
final TimelordWorldData data = TimelordWorldData.getForWorld((ServerWorld) event.world);
|
||||
handleRain((ServerWorld) event.world, cfg, data);
|
||||
}
|
||||
handleTime(event.world, cfg);
|
||||
}
|
||||
|
||||
private static void handleTime(World world, DimensionTimeConfig cfg) {
|
||||
if (cfg == null || cfg.time == null || !cfg.active) return;
|
||||
|
||||
if (cfg.time.fixedDayTime <= 24000 && cfg.time.fixedDayTime >= 0) {
|
||||
setFixedTime((ServerWorld) world, cfg.time.fixedDayTime);
|
||||
} else if (cfg.time.scale > 0) {
|
||||
setScaledTime((ServerWorld) world, cfg.time.scale);
|
||||
} else if (cfg.time.hours_offset >= -18 && cfg.time.hours_offset <= 18) {
|
||||
setRealTime((ServerWorld) world, ZoneOffset.ofTotalSeconds(cfg.time.hours_offset * 3600));
|
||||
}
|
||||
}
|
||||
|
||||
private static void setFixedTime(ServerWorld world, int fixedTime) {
|
||||
world.setDayTime(fixedTime);
|
||||
}
|
||||
|
||||
private static void setRealTime(ServerWorld world, ZoneId timezone) {
|
||||
final Duration mcTimeFix = Duration.ofHours(6);
|
||||
final LocalDateTime now = LocalDateTime.now(timezone).minus(mcTimeFix);
|
||||
|
||||
final long secs = now.toEpochSecond(ZoneOffset.UTC);
|
||||
final long time = (secs * 24000) / 86400; // Convert from real day to minecraft day
|
||||
world.setDayTime(time);
|
||||
}
|
||||
|
||||
private static void setScaledTime(ServerWorld world, double scale) {
|
||||
final IWorldInfo wi = world.getWorldInfo();
|
||||
final long tt = wi.getGameTime();
|
||||
world.setDayTime((long) (tt * scale));
|
||||
}
|
||||
|
||||
private static void handleRain(ServerWorld world, DimensionTimeConfig cfg, TimelordWorldData data) {
|
||||
if (cfg == null || cfg.rain == null || !cfg.active) return;
|
||||
|
||||
final IServerWorldInfo wi = (IServerWorldInfo) world.getWorldInfo();
|
||||
|
||||
wi.setRainTime(Integer.MAX_VALUE);
|
||||
wi.setThunderTime(Integer.MAX_VALUE);
|
||||
wi.setClearWeatherTime(0);
|
||||
|
||||
if (cfg.rain.endlessRain && wi.isRaining()) return;
|
||||
if (cfg.rain.endlessThunder && wi.isThundering()) return;
|
||||
|
||||
if (cfg.rain.endlessRain) {
|
||||
world.getWorldInfo().setRaining(true);
|
||||
} else if (cfg.rain.endlessThunder) {
|
||||
wi.setThundering(true);
|
||||
} else {
|
||||
if (wi.isRaining()) {
|
||||
data.rainAcc -= cfg.rain.outcome;
|
||||
if (data.rainAcc <= 0) {
|
||||
System.out.println("Timelord: succesfull rain stop");
|
||||
world.getWorldInfo().setRaining(false);
|
||||
wi.setThundering(false);
|
||||
}
|
||||
} else {
|
||||
if (cfg.rain.income == 0) return;
|
||||
|
||||
data.rainAcc += cfg.rain.income;
|
||||
final boolean shouldRoll = data.rainAcc >= cfg.rain.min && cfg.rain.dice > 0;
|
||||
final boolean roll = shouldRoll && world.rand.nextInt(cfg.rain.dice) == 0;
|
||||
if (roll) {
|
||||
System.out.printf("Timelord: [%s] successful rainfall dice roll (while %d>=%d)%n",
|
||||
wi.getWorldName(), data.rainAcc, cfg.rain.min);
|
||||
}
|
||||
if (roll || data.rainAcc > cfg.rain.max) {
|
||||
world.getWorldInfo().setRaining(true);
|
||||
wi.setThundering(data.rainAcc > cfg.rain.thunder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package stargazer.timelord.logic;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.storage.DimensionSavedDataManager;
|
||||
import net.minecraft.world.storage.WorldSavedData;
|
||||
import stargazer.timelord.Timelord;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class TimelordWorldData extends WorldSavedData implements Supplier {
|
||||
|
||||
public TimelordWorldData() {
|
||||
super(DATA_NAME);
|
||||
}
|
||||
|
||||
public TimelordWorldData(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
private static final String DATA_NAME = Timelord.MODID + ".timedata";
|
||||
|
||||
long rainAcc = 0;
|
||||
|
||||
public static TimelordWorldData getForWorld(ServerWorld world) {
|
||||
final DimensionSavedDataManager storage = world.getSavedData();
|
||||
Supplier<TimelordWorldData> supplier = new TimelordWorldData();
|
||||
TimelordWorldData instance = storage.getOrCreate(supplier, DATA_NAME);
|
||||
if (instance == null) {
|
||||
instance = new TimelordWorldData();
|
||||
storage.set(instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT nbt) {
|
||||
rainAcc = nbt.getLong("rain");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.putLong("rain", rainAcc);
|
||||
return compound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
44
src/main/java/stargazer/timelord/net/TimePacket.java
Normal file
44
src/main/java/stargazer/timelord/net/TimePacket.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package stargazer.timelord.net;
|
||||
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.network.NetworkEvent;
|
||||
import stargazer.timelord.Timelord;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TimePacket {
|
||||
|
||||
private final ResourceLocation worldResourceLocation;
|
||||
private final String stringedJson;
|
||||
|
||||
public TimePacket(ResourceLocation worldResourceLocation, final String stringedJson) {
|
||||
this.worldResourceLocation = worldResourceLocation;
|
||||
this.stringedJson = stringedJson;
|
||||
}
|
||||
|
||||
public static void encode(final TimePacket packet, final PacketBuffer buf) {
|
||||
buf.writeResourceLocation(packet.worldResourceLocation);
|
||||
buf.writeString(packet.stringedJson);
|
||||
|
||||
}
|
||||
|
||||
public static TimePacket decode(final PacketBuffer buf) {
|
||||
return new TimePacket(buf.readResourceLocation(), buf.readString());
|
||||
}
|
||||
|
||||
public static void handle(TimePacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
NetworkEvent.Context context = ctx.get();
|
||||
context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> clientHandler(msg)));
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void clientHandler(final TimePacket message) {
|
||||
Timelord.putStringIntoDimensionsConfigMap(message.worldResourceLocation, message.stringedJson);
|
||||
|
||||
}
|
||||
}
|
||||
58
src/main/resources/META-INF/mods.toml
Normal file
58
src/main/resources/META-INF/mods.toml
Normal file
@@ -0,0 +1,58 @@
|
||||
# This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
# The overall format is standard TOML format, v0.5.0.
|
||||
# Note that there are a couple of TOML lists in this file.
|
||||
# Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader="javafml" #mandatory
|
||||
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
|
||||
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
|
||||
license="All rights reserved"
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
modId="timelord" #mandatory
|
||||
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
# see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="${file.jarVersion}" #mandatory
|
||||
# A display name for the mod
|
||||
displayName="Timelord" #mandatory
|
||||
# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
|
||||
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
|
||||
# A URL for the "homepage" for this mod, displayed in the mod UI
|
||||
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
|
||||
# A file name (in the root of the mod JAR) containing a logo for display
|
||||
logoFile="examplemod.png" #optional
|
||||
# A text field displayed in the mod UI
|
||||
credits="Thanks to Msifeed for most of the mod logic" #optional
|
||||
# A text field displayed in the mod UI
|
||||
authors="Marduk, Stargazer Roleplay Project" #optional
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description='''
|
||||
Timelord allows you to change time rules per dimension. Also affects rain.
|
||||
'''
|
||||
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
|
||||
[[dependencies.timelord]] #optional
|
||||
# the modid of the dependency
|
||||
modId="forge" #mandatory
|
||||
# Does this dependency have to exist - if not, ordering below must be specified
|
||||
mandatory=true #mandatory
|
||||
# The version range of the dependency
|
||||
versionRange="[36,)" #mandatory
|
||||
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||
ordering="NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
side="BOTH"
|
||||
# Here's another dependency
|
||||
[[dependencies.timelord]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange="[1.16.5,1.17)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
7
src/main/resources/pack.mcmeta
Normal file
7
src/main/resources/pack.mcmeta
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "examplemod resources",
|
||||
"pack_format": 6,
|
||||
"_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user