Compare commits
4 Commits
architectu
...
1.20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aabb728303 | ||
|
|
3b93a52568 | ||
|
|
797ab519de | ||
|
|
18df94c4e4 |
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: 'Bug: TITLE HERE'
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
@@ -21,17 +21,15 @@ Steps to reproduce the behavior:
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots or videos to help explain your problem.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. Windows / Linux / MacOS]
|
||||
- Minecraft [e.g. 1.20.4]
|
||||
- Modloader [e.g. Fabric Loader 0.15.6]
|
||||
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
|
||||
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
|
||||
- OS: [e.g. Linux]
|
||||
- Minecraft [e.g. 1.14.4]
|
||||
- Fabric [e.g. fabric 0.7.2+build.174]
|
||||
- Mods [e.g. aurora_keystrokes v1.0.0, modmenu v1.7.15]
|
||||
- Version [e.g. 1.0.0]
|
||||
- Remove this line if you actually completed it
|
||||
- Branch [e.g. dev]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
In case of a crash, please provide the crash log.
|
||||
|
||||
40
.github/ISSUE_TEMPLATE/controller_support.md
vendored
@@ -1,40 +0,0 @@
|
||||
---
|
||||
name: Controller support
|
||||
about: Report a problem related to a specific controller
|
||||
title: 'Controller Issues: CONTROLLER NAME HERE'
|
||||
labels: controller
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the current state**
|
||||
A clear and concise description of current state of support for the controller and the issues.
|
||||
|
||||
**To Reproduce**
|
||||
If needed, specify steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots or videos to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- Have you checked #263 for your controller? [e.g. Yes/No]
|
||||
- Connection method [e.g. Wired / Bluetooth]
|
||||
|
||||
- OS: [e.g. Windows / Linux / MacOS]
|
||||
- Minecraft [e.g. 1.20.4]
|
||||
- Modloader [e.g. Fabric Loader 0.15.6]
|
||||
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
|
||||
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
|
||||
- Version [e.g. 1.0.0]
|
||||
- Remove this line if you actually completed it
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
In case of a crash, please provide the crash log.
|
||||
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'Feature: TITLE HERE'
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
@@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots/videos about the feature request here.
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/mod_support.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Mod Support
|
||||
about: Compatibility improvements with a specific mod (not for crashes)
|
||||
title: 'Mod Support: MOD NAME HERE'
|
||||
labels: mod compatibility
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your compatibility request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I've always wanted to [...]
|
||||
|
||||
**Describe the way of compatibility you'd imagine**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative mods or workarounds you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots/videos about the compatibility request here.
|
||||
29
.github/workflows/build.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: Build with Gradle
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
check-latest: true
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
- name: Upload artifacts to GitHub
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MidnightControls-Artifacts
|
||||
path: |
|
||||
fabric/build/libs/
|
||||
neoforge/build/libs/
|
||||
23
.github/workflows/gradlebuild.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
name: Gradle Build
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 16
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Artifacts
|
||||
path: ./build/libs/
|
||||
40
.github/workflows/publish.yml → .github/workflows/gradlepublish.yml
vendored
Normal file → Executable file
@@ -1,26 +1,30 @@
|
||||
name: Publish to Modrinth
|
||||
name: Gradle Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-24.04
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
java-version: 16
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
check-latest: true
|
||||
name: Artifacts
|
||||
path: ./build/libs/
|
||||
|
||||
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
||||
# the publishing section of your build.gradle
|
||||
- name: Publish to GitHub Packages and other Mavens
|
||||
@@ -34,7 +38,3 @@ jobs:
|
||||
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
||||
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
- name: Publish to Modrinth
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
run: ./gradlew publishModrinth
|
||||
23
.github/workflows/modrinth_update.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
name: Gradle Build
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 16
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
run: ./gradlew publishModrinth
|
||||
@@ -8,7 +8,7 @@
|
||||
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
||||

|
||||
[![Mod loader: Quilt/Fabric]][Quilt]
|
||||
[](https://www.oracle.com/java/technologies/downloads/#java21)
|
||||
[](https://www.oracle.com/java/technologies/downloads/#java17)
|
||||
[](LICENSE)
|
||||
|
||||
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
||||
@@ -64,7 +64,11 @@ After this is done, everything should be built just fine!
|
||||
|
||||
## FAQ:
|
||||
### The controller does not work, and it's name appears in orange, what can I do?
|
||||
Create a custom mapping as pointed out in the [wiki](https://midnightdust.eu/wiki/midnightcontrols/)
|
||||
Orange controller names indicate a missing controller mapping.
|
||||
Download [GamepadTool](https://generalarcade.com/gamepadtool/), create and copy a mapping, go to MidnightControls' Mappings File Editor and paste the string.
|
||||
Alternatively, you can use [AntiMicroX](https://github.com/AntiMicroX/antimicroX) to create the mappings, in case the Gamepad Tool is not working for you.
|
||||
If that works, you might as well consider submitting the mapping by opening a PR in this repo: https://github.com/gabomdq/SDL_GameControllerDB
|
||||
That will make sure other people using the same controller as you don't have to use gamepad-tool anymore.
|
||||
|
||||
[Quilt]: https://quiltmc.org
|
||||
|
||||
|
||||
234
build.gradle
@@ -1,92 +1,186 @@
|
||||
plugins {
|
||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||
id "dev.architectury.loom" version "1.13-SNAPSHOT" apply false
|
||||
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
id 'fabric-loom' version '1.1-SNAPSHOT'
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||
id 'com.modrinth.minotaur' version '2.+'
|
||||
id 'net.darkhax.curseforgegradle' version '1.+'
|
||||
}
|
||||
|
||||
architectury {
|
||||
minecraft = rootProject.minecraft_version
|
||||
import net.darkhax.curseforgegradle.TaskPublishCurseForge
|
||||
|
||||
group = project.maven_group
|
||||
version = "${project.mod_version}+${getMCVersionString()}"
|
||||
|
||||
// This field defines the Java version your mod target.
|
||||
def targetJavaVersion = 17
|
||||
|
||||
boolean isMCVersionNonRelease() {
|
||||
return project.minecraft_version.matches('^\\d\\dw\\d\\d[a-z]$')
|
||||
|| project.minecraft_version.matches('\\d+\\.\\d+-(pre|rc)(\\d+)')
|
||||
}
|
||||
|
||||
String getMCVersionString() {
|
||||
if (isMCVersionNonRelease() || project.minecraft_version == "1.20.4") {
|
||||
return project.minecraft_version
|
||||
}
|
||||
def version = project.minecraft_version.split('\\.')
|
||||
return version[0] + '.' + version[1]
|
||||
}
|
||||
|
||||
boolean pingUrl(String address) {
|
||||
try {
|
||||
def conn = (HttpURLConnection) new URL(address).openConnection()
|
||||
int responseCode = conn.getResponseCode()
|
||||
return (200 <= responseCode && responseCode <= 399)
|
||||
} catch (IOException ignored) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
String parseReadme() {
|
||||
def excludeRegex = /(?m)<!-- modrinth_exclude\.start -->(.|\n)*?<!-- modrinth_exclude\.end -->/
|
||||
def linkRegex = /!\[([A-z_ ]+)]\((images\/[A-z.\/_]+)\)/
|
||||
|
||||
def readme = (String) file('README.md').text
|
||||
readme = readme.replaceAll(excludeRegex, '')
|
||||
return readme
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven { url 'https://aperlambda.github.io/maven' }
|
||||
maven {
|
||||
url = "https://api.modrinth.com/maven"
|
||||
name 'Gegy'
|
||||
url 'https://maven.gegy.dev'
|
||||
}
|
||||
flatDir {
|
||||
dirs("localMaven")
|
||||
maven {
|
||||
name = "CottonMC"
|
||||
url = "https://server.bbkr.space/artifactory/libs-release"
|
||||
}
|
||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||
maven { url 'https://maven.kosmx.dev' }
|
||||
maven { url 'https://maven.isxander.dev/releases' }
|
||||
maven { url 'https://maven.shedaniel.me/' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url "https://api.modrinth.com/maven" }
|
||||
maven { url 'https://maven.quiltmc.org/repository/release'}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
apply plugin: "dev.architectury.loom"
|
||||
repositories {
|
||||
maven {
|
||||
url = "https://api.modrinth.com/maven"
|
||||
}
|
||||
maven {
|
||||
name 'Gegy'
|
||||
url 'https://maven.gegy.dev'
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
flatDir {
|
||||
dirs("../localMaven")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||
// The following line declares the mojmap mappings, you may use other mappings as well
|
||||
//mappings loom.officialMojangMappings()
|
||||
// The following line declares the yarn mappings you may select this one as well.
|
||||
mappings loom.layered {
|
||||
it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2")
|
||||
it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version")
|
||||
}
|
||||
}
|
||||
configurations {
|
||||
shadow
|
||||
api.extendsFrom shadow
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//to change the versions see the gradle.properties file
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
allprojects {
|
||||
apply plugin: "java"
|
||||
apply plugin: "architectury-plugin"
|
||||
apply plugin: "maven-publish"
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
|
||||
archivesBaseName = rootProject.archives_base_name
|
||||
version = rootProject.mod_version
|
||||
group = rootProject.maven_group
|
||||
|
||||
repositories {
|
||||
maven { url 'https://aperlambda.github.io/maven' }
|
||||
modImplementation ("dev.lambdaurora:spruceui:${project.spruceui_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
dependencies {
|
||||
implementation('org.aperlambda:lambdajcommon:1.8.1') {
|
||||
exclude group: 'com.google.code.gson'
|
||||
exclude group: 'com.google.guava'
|
||||
}
|
||||
include "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||
api('org.aperlambda:lambdajcommon:1.8.1') {
|
||||
exclude group: 'com.google.code.gson'
|
||||
exclude group: 'com.google.guava'
|
||||
}
|
||||
include 'org.aperlambda:lambdajcommon:1.8.1'
|
||||
|
||||
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
options.release = 21
|
||||
}
|
||||
ext {
|
||||
releaseChangelog = {
|
||||
def changes = new StringBuilder()
|
||||
changes << "## MidnightControls v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightControls/commits/)"
|
||||
def proc = "git log --max-count=1 --pretty=format:%s".execute()
|
||||
proc.in.eachLine { line ->
|
||||
def processedLine = line.toString()
|
||||
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
|
||||
changes << "\n- ${processedLine.capitalize()}"
|
||||
}
|
||||
}
|
||||
proc.waitFor()
|
||||
return changes.toString()
|
||||
}
|
||||
// Compatibility mods
|
||||
|
||||
// Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions.
|
||||
// modImplementation("maven.modrinth:ok-zoomer:${project.ok_zoomer_version}")
|
||||
// modImplementation "io.github.ennuil:LibZoomer:${project.libzoomer_version}"
|
||||
|
||||
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
||||
modCompileOnly "maven.modrinth:sodium:${project.sodium_version}"
|
||||
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
||||
modCompileOnlyApi "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||
modCompileOnlyApi "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||
modCompileOnlyApi "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
||||
modCompileOnlyApi "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}"
|
||||
modCompileOnlyApi "maven.modrinth:bedrockify:${project.bedrockify_version}"
|
||||
// Required for Inventory Tabs
|
||||
modCompileOnlyApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||
|
||||
shadow 'com.electronwill.night-config:core:3.6.3'
|
||||
shadow 'com.electronwill.night-config:toml:3.6.3'
|
||||
apply plugin: 'java-library'
|
||||
}
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
||||
targetCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
||||
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.encoding = 'UTF-8'
|
||||
|
||||
it.options.release.set(targetJavaVersion)
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property 'version', project.version
|
||||
|
||||
filesMatching('fabric.mod.json') {
|
||||
expand 'version': project.version
|
||||
}
|
||||
}
|
||||
modrinth {
|
||||
token = System.getenv("MODRINTH_TOKEN") // Remember to have the MODRINTH_TOKEN environment variable set or else this will fail - just make sure it stays private!
|
||||
projectId = project.archives_base_name // This can be the project ID or the slug. Either will work!
|
||||
versionNumber = project.version // You don't need to set this manually. Will fail if Modrinth has this version already
|
||||
versionName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
|
||||
versionType = isMCVersionNonRelease() ? "beta" : "release" // Can also be `beta` or `alpha`
|
||||
uploadFile = remapJar // With Loom, this MUST be set to `remapJar` instead of `jar`!
|
||||
gameVersions = [(String) project.minecraft_version] // Must be an array, even with only one version
|
||||
loaders = ["fabric","quilt"] // Must also be an array - no need to specify this if you're using Loom or ForgeGradle
|
||||
dependencies { // A special DSL for creating dependencies
|
||||
// scope.type
|
||||
// The scope can be `required`, `optional`, `incompatible`, or `embedded`
|
||||
// The type can either be `project` or `version`
|
||||
required.project "midnightlib" // Creates a new required dependency on MidnightLib
|
||||
}
|
||||
changelog = project.changelog
|
||||
}
|
||||
tasks.register('publishCurseForge', TaskPublishCurseForge) {
|
||||
|
||||
// This token is used to authenticate with CurseForge. It should be handled
|
||||
// with the same level of care and security as your actual password. You
|
||||
// should never share your token with an untrusted source or publish it
|
||||
// publicly to GitHub or embed it within a project. The best practice is to
|
||||
// store this token in an environment variable or a build secret.
|
||||
apiToken = System.getenv("CURSEFORGE_TOKEN")
|
||||
|
||||
// Tells CurseForgeGradle to publish the output of the jar task. This will
|
||||
// return a UploadArtifact object that can be used to further configure the
|
||||
// file.
|
||||
def mainFile = upload(project.curseforge_id, remapJar)
|
||||
mainFile.changelog = project.changelog
|
||||
mainFile.displayName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
|
||||
mainFile.addModLoader("Fabric", "Quilt")
|
||||
mainFile.addRequirement("midnightlib")
|
||||
mainFile.releaseType = "release"
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
architectury {
|
||||
common(rootProject.enabled_platforms.split(","))
|
||||
}
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name 'Gegy'
|
||||
url 'https://maven.gegy.dev'
|
||||
}
|
||||
maven {
|
||||
name = "CottonMC"
|
||||
url = "https://server.bbkr.space/artifactory/libs-release"
|
||||
}
|
||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||
maven { url 'https://maven.kosmx.dev' }
|
||||
maven { url 'https://maven.isxander.dev/releases' }
|
||||
maven { url 'https://maven.shedaniel.me/' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url "https://api.modrinth.com/maven" }
|
||||
maven { url 'https://maven.quiltmc.org/repository/release'}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
||||
// Do NOT use other classes from fabric loader
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
// Using the Fabric version of midnightlib here to create a common config and get useful utilities
|
||||
// Just make sure NOT to use classes from the .fabric classpath
|
||||
modCompileOnlyApi "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric"
|
||||
modCompileOnlyApi "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
// Compatibility mods
|
||||
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
||||
modImplementation "maven.modrinth:sodium:${project.sodium_version}-fabric"
|
||||
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
||||
modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||
modCompileOnlyApi "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||
modCompileOnlyApi "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
||||
modCompileOnlyApi "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}"
|
||||
modCompileOnlyApi "maven.modrinth:bedrockify:${project.bedrockify_version}"
|
||||
// Required for Inventory Tabs
|
||||
modCompileOnlyApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenCommon(MavenPublication) {
|
||||
artifactId = rootProject.archives_base_name
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
|
||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||
repositories {
|
||||
// Add repositories to publish to here.
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols;
|
||||
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Represents the MidnightControls mod.
|
||||
*
|
||||
* @author LambdAurora & Motschen
|
||||
* @version 1.8.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MidnightControls {
|
||||
public static boolean isExtrasLoaded;
|
||||
|
||||
public static final Logger logger = LogManager.getLogger("MidnightControls");
|
||||
|
||||
public static void init() {
|
||||
isExtrasLoaded = PlatformFunctions.isModLoaded("midnightcontrols-extra");
|
||||
log("Initializing MidnightControls...");
|
||||
}
|
||||
public static Identifier id(String path) {
|
||||
return Identifier.of(MidnightControlsConstants.NAMESPACE, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message to the terminal.
|
||||
*
|
||||
* @param info the message to print
|
||||
*/
|
||||
public static void log(String info) {
|
||||
logger.info("[MidnightControls] {}", info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a warning to the terminal.
|
||||
*
|
||||
* @param warning the warning to print
|
||||
*/
|
||||
public static void warn(String warning) {
|
||||
logger.warn("[MidnightControls] {}", warning);
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.MouseClickInterceptor;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
|
||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Represents the midnightcontrols client mod.
|
||||
*
|
||||
* @author Motschen, LambdAurora
|
||||
* @version 1.10.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class MidnightControlsClient extends MidnightControls {
|
||||
public static boolean lateInitDone = false;
|
||||
public static final KeyBinding.Category MIDNIGHTCONTROLS_CATEGORY = KeyBinding.Category.create(Identifier.of("midnightcontrols", "keybinds"));
|
||||
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, MIDNIGHTCONTROLS_CATEGORY);
|
||||
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, MIDNIGHTCONTROLS_CATEGORY);
|
||||
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, MIDNIGHTCONTROLS_CATEGORY);
|
||||
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, MIDNIGHTCONTROLS_CATEGORY);
|
||||
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"),
|
||||
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), MIDNIGHTCONTROLS_CATEGORY);
|
||||
public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png");
|
||||
public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png");
|
||||
public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png");
|
||||
public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
||||
public static MinecraftClient client = MinecraftClient.getInstance();
|
||||
public static final MidnightInput input = new MidnightInput();
|
||||
public static final MidnightRing ring = new MidnightRing();
|
||||
public static final MidnightReacharound reacharound = new MidnightReacharound();
|
||||
public static final MouseClickInterceptor clickInterceptor = new MouseClickInterceptor();
|
||||
public static boolean isWayland;
|
||||
private static MidnightControlsHud hud;
|
||||
private static ControlsMode previousControlsMode;
|
||||
|
||||
public static void initClient() {
|
||||
client = MinecraftClient.getInstance();
|
||||
ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
|
||||
|
||||
int delay = 0; // delay for 0 sec.
|
||||
int period = 1; // repeat every 0.001 sec. (1000 times a second)
|
||||
Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
try {
|
||||
if (lateInitDone && client.isRunning()) {
|
||||
if (MidnightControlsConfig.controlsMode != ControlsMode.DEFAULT && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput)) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) input.tickCameraStick();
|
||||
input.updateCamera();
|
||||
}
|
||||
}
|
||||
} catch (Exception | Error e) {
|
||||
MidnightControls.logger.error("Exception encountered in camera loop: ",e);
|
||||
}
|
||||
}
|
||||
}, delay, period);
|
||||
|
||||
isWayland = GLFW.glfwGetVersionString().contains("Wayland");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when Minecraft is initializing.
|
||||
*/
|
||||
public static void onMcInit(@NotNull MinecraftClient client) {
|
||||
ButtonBinding.init(client.options);
|
||||
MidnightControlsConfig.load();
|
||||
if (MidnightControlsConfig.configVersion < 2) {
|
||||
MidnightControlsConfig.mouseScreens.remove("me.jellysquid.mods.sodium.client.gui");
|
||||
MidnightControlsConfig.mouseScreens.remove("net.coderbot.iris.gui");
|
||||
MidnightControlsConfig.mouseScreens.remove("net.minecraft.class_5375");
|
||||
MidnightControlsConfig.mouseScreens.remove("net.minecraft.client.gui.screen.pack.PackScreen");
|
||||
MidnightControlsConfig.configVersion = 2;
|
||||
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
||||
}
|
||||
MidnightControlsHud.isVisible = MidnightControlsConfig.hudEnable;
|
||||
Controller.updateMappings();
|
||||
try {
|
||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||
if (event == GLFW.GLFW_CONNECTED) {
|
||||
var controller = Controller.byId(jid);
|
||||
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.connected", jid),
|
||||
Text.literal(controller.getName())));
|
||||
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.disconnected", jid),
|
||||
null));
|
||||
}
|
||||
|
||||
switchControlsMode();
|
||||
});
|
||||
} catch (Exception e) {e.fillInStackTrace();}
|
||||
|
||||
MidnightControlsCompat.init();
|
||||
}
|
||||
/**
|
||||
* This method is called to initialize keybindings
|
||||
*/
|
||||
public static void initKeybindings() {
|
||||
if (lateInitDone) return;
|
||||
if (KeyBindingIDAccessor.getKEYS_BY_ID() == null || KeyBindingIDAccessor.getKEYS_BY_ID().isEmpty()) return;
|
||||
if (PlatformFunctions.isModLoaded("voxelmap") && !KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) return;
|
||||
if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return;
|
||||
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
|
||||
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
|
||||
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getId().startsWith(excluded))) {
|
||||
if (!keyBinding.getId().contains(MidnightControlsConstants.NAMESPACE)) {
|
||||
AtomicReference<ButtonCategory> category = new AtomicReference<>();
|
||||
InputManager.streamCategories().forEach(buttonCategory -> {
|
||||
if (buttonCategory.getIdentifier().equals(keyBinding.getCategory().id()))
|
||||
category.set(buttonCategory);
|
||||
});
|
||||
if (category.get() == null) {
|
||||
category.set(new ButtonCategory(keyBinding.getCategory().id()));
|
||||
InputManager.registerCategory(category.get());
|
||||
}
|
||||
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getId()).category(category.get()).linkKeybind(keyBinding).register();
|
||||
if (MidnightControlsConfig.debug) {
|
||||
MidnightControls.log(keyBinding.getId());
|
||||
MidnightControls.log(String.valueOf(buttonBinding));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InputManager.loadButtonBindings();
|
||||
lateInitDone = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called every Minecraft tick.
|
||||
*
|
||||
* @param client the client instance
|
||||
*/
|
||||
public static void onTick(@NotNull MinecraftClient client) {
|
||||
initKeybindings();
|
||||
input.tick();
|
||||
reacharound.tick();
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
||||
input.tickController();
|
||||
|
||||
if (BINDING_RING.wasPressed()) {
|
||||
ring.loadFromUnbound();
|
||||
client.setScreen(new RingScreen());
|
||||
}
|
||||
if (client.world != null && MidnightControlsConfig.enableHints && !MidnightControlsConfig.autoSwitchMode && MidnightControlsConfig.controlsMode == ControlsMode.DEFAULT && MidnightControlsConfig.getController().isGamepad()) {
|
||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.tutorial.title"),
|
||||
Text.translatable("midnightcontrols.controller.tutorial.description", Text.translatable("options.title"), Text.translatable("controls.title"),
|
||||
Text.translatable("midnightcontrols.menu.title.controller"))));
|
||||
MidnightControlsConfig.enableHints = false;
|
||||
MidnightControlsConfig.save();
|
||||
}
|
||||
RainbowColor.tick();
|
||||
TouchInput.tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when opening a screen.
|
||||
*/
|
||||
public static void onScreenOpen(Screen screen) {
|
||||
client = MinecraftClient.getInstance();
|
||||
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||
screen = new TouchscreenOverlay();
|
||||
screen.init(client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||
client.skipGameRender = false;
|
||||
client.currentScreen = screen;
|
||||
} else if (screen != null) {
|
||||
MidnightControlsClient.input.onScreenOpen(client.getWindow().getWidth(), client.getWindow().getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when leaving a server.
|
||||
*/
|
||||
public static void onLeave() {
|
||||
MidnightControlsFeature.resetAllAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the controls mode if the auto switch is enabled.
|
||||
*/
|
||||
public static void switchControlsMode() {
|
||||
if (MidnightControlsConfig.autoSwitchMode) {
|
||||
if (MidnightControlsConfig.getController().isGamepad()) {
|
||||
previousControlsMode = MidnightControlsConfig.controlsMode;
|
||||
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||
} else {
|
||||
if (previousControlsMode == null) {
|
||||
previousControlsMode = ControlsMode.DEFAULT;
|
||||
}
|
||||
|
||||
MidnightControlsConfig.controlsMode = previousControlsMode;
|
||||
}
|
||||
NetworkUtil.sendPayloadC2S(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the HUD is enabled or not.
|
||||
*
|
||||
* @param enabled true if the HUD is enabled, else false
|
||||
*/
|
||||
public static void setHudEnabled(boolean enabled) {
|
||||
MidnightControlsConfig.hudEnable = enabled;
|
||||
MidnightControlsHud.isVisible = enabled;
|
||||
}
|
||||
|
||||
private static final MidnightControlsClient INSTANCE = new MidnightControlsClient();
|
||||
/**
|
||||
* Gets the midnightcontrols client instance.
|
||||
*
|
||||
* @return the midnightcontrols client instance
|
||||
*/
|
||||
@Deprecated
|
||||
public static MidnightControlsClient get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayoutManager;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.SynchronousResourceReloader;
|
||||
|
||||
public class MidnightControlsReloadListener implements SynchronousResourceReloader {
|
||||
public static final MidnightControlsReloadListener INSTANCE = new MidnightControlsReloadListener();
|
||||
|
||||
private MidnightControlsReloadListener() {}
|
||||
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
manager.findResources("keyboard_layouts", path -> path.toString().startsWith("midnightcontrols") && path.toString().endsWith(".json")).forEach(KeyboardLayoutManager::loadLayout);
|
||||
}
|
||||
}
|
||||
@@ -1,824 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import dev.lambdaurora.spruceui.navigation.NavigationEvent;
|
||||
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||
import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
|
||||
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceElement;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.config.ControlsInput;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.KeyboardAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
||||
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
||||
import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage;
|
||||
import net.minecraft.client.gui.Click;
|
||||
import net.minecraft.client.gui.navigation.NavigationDirection;
|
||||
import net.minecraft.client.gui.screen.option.KeybindsScreen;
|
||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||
import net.minecraft.client.gui.widget.PressableWidget;
|
||||
import net.minecraft.client.gui.widget.SliderWidget;
|
||||
import net.minecraft.client.input.KeyInput;
|
||||
import net.minecraft.client.input.MouseInput;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.ParentElement;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.glfw.GLFWGamepadState;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* Represents the midnightcontrols' input handler.
|
||||
*
|
||||
* @author Motschen, LambdAurora
|
||||
* @version 1.10.0
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class MidnightInput {
|
||||
public static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||
public static final KeyInput ENTER_KEY_INPUT = new KeyInput(GLFW_KEY_ENTER, 0, 0);
|
||||
// Cooldowns
|
||||
public int actionGuiCooldown = 0;
|
||||
public int joystickCooldown = 0;
|
||||
public boolean ignoreNextARelease = false;
|
||||
public boolean ignoreNextXRelease = false;
|
||||
private double targetYaw = 0.0;
|
||||
private double targetPitch = 0.0;
|
||||
private float prevXAxis = 0.f;
|
||||
private float prevYAxis = 0.f;
|
||||
public float mouseSpeedX = 0.f;
|
||||
public float mouseSpeedY = 0.f;
|
||||
public int inventoryInteractionCooldown = 0;
|
||||
public int screenCloseCooldown = 0;
|
||||
|
||||
private ControlsInput controlsInput = null;
|
||||
|
||||
public MidnightInput() {}
|
||||
|
||||
/**
|
||||
* This method is called every Minecraft tick.
|
||||
*/
|
||||
public void tick() {
|
||||
this.targetYaw = 0.F;
|
||||
this.targetPitch = 0.F;
|
||||
|
||||
// Handles the key bindings.
|
||||
if (MidnightControlsClient.BINDING_LOOK_UP.isPressed()) {
|
||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, -0.8F, 0d));
|
||||
} else if (MidnightControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 0d));
|
||||
}
|
||||
if (MidnightControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, -0.8F, 0d));
|
||||
} else if (MidnightControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 0d));
|
||||
}
|
||||
|
||||
InputManager.INPUT_MANAGER.tick();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called every Minecraft tick for controller input update.
|
||||
*/
|
||||
public void tickController() {
|
||||
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0)
|
||||
.forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
||||
// Decreases the cooldown for GUI actions.
|
||||
if (this.actionGuiCooldown > 0)
|
||||
--this.actionGuiCooldown;
|
||||
if (this.screenCloseCooldown > 0)
|
||||
--this.screenCloseCooldown;
|
||||
if (this.joystickCooldown > 0)
|
||||
--this.joystickCooldown;
|
||||
|
||||
InputManager.updateStates();
|
||||
|
||||
var controller = MidnightControlsConfig.getController();
|
||||
|
||||
if (controller.isConnected()) {
|
||||
var state = controller.getState();
|
||||
this.fetchButtonInput(state, false);
|
||||
this.fetchTriggerInput(state, false);
|
||||
this.fetchJoystickInput(state, false, false);
|
||||
}
|
||||
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||
.ifPresent(joycon -> {
|
||||
var state = joycon.getState();
|
||||
this.fetchButtonInput(state, true);
|
||||
this.fetchTriggerInput(state, true);
|
||||
this.fetchJoystickInput(state, true, false);
|
||||
});
|
||||
|
||||
boolean allowInput = this.controlsInput == null || this.controlsInput.getFocusedBinding() == null;
|
||||
|
||||
if (allowInput)
|
||||
InputManager.updateBindings();
|
||||
|
||||
if (this.controlsInput != null) {
|
||||
InputManager.STATES.forEach((num, button) -> {
|
||||
if (button.isPressed()) System.out.println(num);
|
||||
});
|
||||
}
|
||||
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
||||
//if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit");
|
||||
if (this.controlsInput.getFocusedBinding() != null && !this.controlsInput.isWaiting()) {
|
||||
int[] buttons = new int[this.controlsInput.getCurrentButtons().size()];
|
||||
for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
|
||||
buttons[i] = this.controlsInput.getCurrentButtons().get(i);
|
||||
this.controlsInput.finishBindingEdit(buttons);
|
||||
this.controlsInput = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.inventoryInteractionCooldown > 0)
|
||||
this.inventoryInteractionCooldown--;
|
||||
}
|
||||
/**
|
||||
* This method is called 1000 times a second for smooth camera input
|
||||
*/
|
||||
public void tickCameraStick() {
|
||||
var controller = MidnightControlsConfig.getController();
|
||||
|
||||
if (controller.isConnected()) {
|
||||
this.fetchJoystickInput(controller.getState(), false, true);
|
||||
}
|
||||
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||
.ifPresent(joycon -> this.fetchJoystickInput(joycon.getState(), true, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before the screen is rendered.
|
||||
*
|
||||
* @param screen the screen to render
|
||||
*/
|
||||
public void onPreRenderScreen(@NotNull Screen screen) {
|
||||
if (!isScreenInteractive(screen)) {
|
||||
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to update the camera
|
||||
*/
|
||||
public void updateCamera() {
|
||||
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
||||
return;
|
||||
|
||||
var player = client.player;
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
||||
float rotationYaw = (float) (client.player.lastYaw + (this.targetYaw * 0.175));
|
||||
float rotationPitch = (float) (client.player.lastPitch + (this.targetPitch * 0.175));
|
||||
client.player.lastYaw = rotationYaw;
|
||||
client.player.lastPitch = MathHelper.clamp(rotationPitch, -90.f, 90.f);
|
||||
client.player.setYaw(rotationYaw);
|
||||
client.player.setPitch(MathHelper.clamp(rotationPitch, -90.f, 90.f));
|
||||
if (client.player.isRiding() && client.player.getVehicle() != null) {
|
||||
client.player.getVehicle().onPassengerLookAround(client.player);
|
||||
}
|
||||
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a Screen is opened.
|
||||
*
|
||||
* @param windowWidth the window width
|
||||
* @param windowHeight the window height
|
||||
*/
|
||||
public void onScreenOpen(int windowWidth, int windowHeight) {
|
||||
if (client.currentScreen == null) {
|
||||
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
||||
InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
||||
} else if (isScreenInteractive(client.currentScreen) && MidnightControlsConfig.virtualMouse) {
|
||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
||||
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||
}
|
||||
this.inventoryInteractionCooldown = 5;
|
||||
}
|
||||
|
||||
public void beginControlsInput(ControlsInput widget) {
|
||||
this.controlsInput = widget;
|
||||
if (widget != null) {
|
||||
this.controlsInput.getCurrentButtons().clear();
|
||||
this.controlsInput.setWaiting(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchButtonInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||
var buffer = gamepadState.buttons();
|
||||
for (int i = 0; i < buffer.limit(); i++) {
|
||||
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||
boolean pressed = buffer.get() == (byte) 1;
|
||||
var state = ButtonState.NONE;
|
||||
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
||||
|
||||
if (pressed != previousState.isPressed()) {
|
||||
state = pressed ? ButtonState.PRESS : ButtonState.RELEASE;
|
||||
this.handleButton(ButtonStorage.of(btn, state));
|
||||
if (pressed)
|
||||
BUTTON_COOLDOWNS.put(btn, 5);
|
||||
} else if (pressed) {
|
||||
state = ButtonState.REPEAT;
|
||||
if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) {
|
||||
BUTTON_COOLDOWNS.put(btn, 5);
|
||||
this.handleButton(ButtonStorage.of(btn, state));
|
||||
}
|
||||
}
|
||||
|
||||
InputManager.STATES.put(btn, state);
|
||||
}
|
||||
}
|
||||
final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
||||
|
||||
private void fetchJoystickInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon, boolean cameraTick) {
|
||||
var buffer = gamepadState.axes();
|
||||
|
||||
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone);
|
||||
float leftX = polarUtil.polarX;
|
||||
float leftY = polarUtil.polarY;
|
||||
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone);
|
||||
float rightX = polarUtil.polarX;
|
||||
float rightY = polarUtil.polarY;
|
||||
|
||||
boolean isRadialMenu = client.currentScreen instanceof RingScreen || (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen));
|
||||
|
||||
if (!isRadialMenu) {
|
||||
for (int i = cameraTick ? GLFW_GAMEPAD_AXIS_RIGHT_X : 0; i < (cameraTick ? GLFW_GAMEPAD_AXIS_LEFT_TRIGGER : GLFW_GAMEPAD_AXIS_RIGHT_X); i++) {
|
||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||
float value = buffer.get(i);
|
||||
|
||||
switch (i) {
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
||||
if (MidnightControlsConfig.analogMovement) value = leftX;
|
||||
}
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
||||
if (MidnightControlsConfig.analogMovement) value = leftY;
|
||||
}
|
||||
case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX;
|
||||
case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY;
|
||||
}
|
||||
|
||||
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
||||
value *= -1.0F;
|
||||
|
||||
this.handleJoystickAxis(AxisStorage.of(axis, value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean leftStickActive = leftX != 0 || leftY != 0;
|
||||
handleRadialMenu(leftStickActive ? leftX : rightX, leftStickActive ? leftY : rightY);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchTriggerInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||
var buffer = gamepadState.axes();
|
||||
|
||||
for (int i = GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i <= GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; i++) {
|
||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||
float value = buffer.get(i);
|
||||
|
||||
this.handleTriggerAxis(AxisStorage.of(axis, value, MidnightControlsConfig.triggerDeadZone));
|
||||
}
|
||||
}
|
||||
|
||||
public void handleButton(ButtonStorage storage) {
|
||||
if (this.controlsInput != null && this.controlsInput.getFocusedBinding() != null) {
|
||||
if (storage.state == ButtonState.PRESS && !this.controlsInput.getCurrentButtons().contains(storage.button)) {
|
||||
this.controlsInput.getCurrentButtons().add(storage.button);
|
||||
|
||||
var buttons = new int[this.controlsInput.getCurrentButtons().size()];
|
||||
for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
|
||||
buttons[i] = this.controlsInput.getCurrentButtons().get(i);
|
||||
this.controlsInput.getFocusedBinding().setButton(buttons);
|
||||
this.controlsInput.update();
|
||||
|
||||
this.controlsInput.setWaiting(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.currentScreen != null && storage.state.isPressed() && storage.button == GLFW_GAMEPAD_BUTTON_Y &&
|
||||
MidnightControlsConfig.arrowScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
||||
pressKeyboardKey(client, GLFW.GLFW_KEY_ENTER);
|
||||
this.screenCloseCooldown = 5;
|
||||
}
|
||||
else if (storage.state.isPressed()) {
|
||||
if (client.currentScreen != null && storage.isDpad() && this.actionGuiCooldown == 0) {
|
||||
switch (storage.button) {
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> this.handleLeftRight(client.currentScreen, false);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> this.handleLeftRight(client.currentScreen, true);
|
||||
}
|
||||
if (MidnightControlsConfig.wasdScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
||||
switch (storage.button) {
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> pressKeyboardKey(client, GLFW.GLFW_KEY_W);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> pressKeyboardKey(client, GLFW.GLFW_KEY_S);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> pressKeyboardKey(client, GLFW.GLFW_KEY_A);
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> pressKeyboardKey(client, GLFW.GLFW_KEY_D);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
||||
if (this.actionGuiCooldown == 0) {
|
||||
var focused = client.currentScreen.getFocused();
|
||||
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
||||
if (this.handleAButton(client.currentScreen, focused)) {
|
||||
this.actionGuiCooldown = 5; // Set the cooldown to 5 ticks to avoid unintended button presses.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (PlatformFunctions.isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
||||
&& this.actionGuiCooldown == 0) {
|
||||
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
||||
client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(),
|
||||
client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()) != null) return;
|
||||
if (!this.ignoreNextARelease && client.currentScreen != null) {
|
||||
var accessor = (MouseAccessor) client.mouse;
|
||||
accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY());
|
||||
switch (storage.state) {
|
||||
// Button pressed
|
||||
case PRESS -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW_MOUSE_BUTTON_LEFT, 0), 1);
|
||||
case RELEASE -> { // Button released
|
||||
accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW_MOUSE_BUTTON_LEFT, 0), 0);
|
||||
client.currentScreen.setDragging(false);
|
||||
}
|
||||
case REPEAT -> client.currentScreen.setDragging(true); // Button held down / dragging
|
||||
}
|
||||
this.screenCloseCooldown = 5;
|
||||
} else {
|
||||
this.ignoreNextARelease = false;
|
||||
}
|
||||
}
|
||||
else if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_X && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
||||
&& this.actionGuiCooldown == 0) {
|
||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
||||
mouseX, mouseY) != null) return;
|
||||
if (!this.ignoreNextXRelease && client.currentScreen != null) {
|
||||
if (storage.state == ButtonState.PRESS) client.currentScreen.mouseClicked(new Click(mouseX, mouseY, new MouseInput(GLFW.GLFW_MOUSE_BUTTON_2, 1)), false);
|
||||
else if (storage.state == ButtonState.RELEASE) client.currentScreen.mouseReleased(new Click(mouseX, mouseY, new MouseInput(GLFW.GLFW_MOUSE_BUTTON_2, 0)));
|
||||
this.screenCloseCooldown = 5;
|
||||
} else {
|
||||
this.ignoreNextXRelease = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void handleTriggerAxis(AxisStorage storage) {
|
||||
storage.setupButtonStates();
|
||||
}
|
||||
|
||||
private void handleJoystickAxis(AxisStorage storage) {
|
||||
storage.setupButtonStates();
|
||||
|
||||
this.handleJoystickMovement(storage);
|
||||
|
||||
if (this.handleScreenScrolling(client.currentScreen, storage)) return;
|
||||
|
||||
storage.absValue = (float) MathHelper.clamp(storage.absValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 0.f, 1.f);
|
||||
if (client.currentScreen == null) {
|
||||
// Handles the look direction.
|
||||
this.handleLook(storage);
|
||||
} else {
|
||||
boolean allowMouseControl = true;
|
||||
|
||||
if (this.actionGuiCooldown == 0 && MidnightControlsConfig.isMovementAxis(storage.axis) && isScreenInteractive(client.currentScreen)) {
|
||||
if (MidnightControlsConfig.isForwardButton(storage.axis, false, storage.buttonState)) {
|
||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||
} else if (MidnightControlsConfig.isBackButton(storage.axis, false, storage.buttonState)) {
|
||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, storage.buttonState)) {
|
||||
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
||||
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, storage.buttonState)) {
|
||||
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
||||
}
|
||||
}
|
||||
|
||||
float movementX = 0.f;
|
||||
float movementY = 0.f;
|
||||
|
||||
if (MidnightControlsConfig.isBackButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||
movementY = storage.absValue;
|
||||
} else if (MidnightControlsConfig.isForwardButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||
movementY = -storage.absValue;
|
||||
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||
movementX = -storage.absValue;
|
||||
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||
movementX = storage.absValue;
|
||||
}
|
||||
|
||||
if (client.currentScreen != null && allowMouseControl) {
|
||||
boolean moving = movementY != 0 || movementX != 0;
|
||||
if (moving) {
|
||||
/*
|
||||
Updates the target mouse position when the initial movement stick movement is detected.
|
||||
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
|
||||
*/
|
||||
if (Math.abs(prevXAxis) < storage.deadZone && Math.abs(prevYAxis) < storage.deadZone) {
|
||||
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||
}
|
||||
|
||||
this.mouseSpeedX = movementX;
|
||||
this.mouseSpeedY = movementY;
|
||||
} else {
|
||||
this.mouseSpeedX = 0.f;
|
||||
this.mouseSpeedY = 0.f;
|
||||
}
|
||||
|
||||
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
||||
InputManager.queueMoveMousePosition(
|
||||
this.mouseSpeedX * MidnightControlsConfig.mouseSpeed,
|
||||
this.mouseSpeedY * MidnightControlsConfig.mouseSpeed
|
||||
);
|
||||
}
|
||||
|
||||
InventoryUtil.moveMouseToClosestSlot(client.currentScreen);
|
||||
}
|
||||
|
||||
this.prevXAxis = movementX;
|
||||
this.prevYAxis = movementY;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleJoystickMovement(AxisStorage storage) {
|
||||
float axisValue = storage.absValue;
|
||||
if (!MidnightControlsConfig.analogMovement || (client.player != null && client.player.getVehicle() instanceof BoatEntity)) {
|
||||
axisValue = (float) (storage.absValue - storage.deadZone);
|
||||
axisValue /= (float) (1.0 - storage.deadZone);
|
||||
axisValue *= (float) storage.deadZone;
|
||||
}
|
||||
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 1);
|
||||
if (AxisStorage.isLeftAxis(storage.axis)) MidnightControlsCompat.handleMovement(storage, axisValue);
|
||||
InputManager.BUTTON_VALUES.put(storage.getButtonId(true), storage.polarity == AxisStorage.Polarity.PLUS ? axisValue : 0.f);
|
||||
InputManager.BUTTON_VALUES.put(storage.getButtonId(false), storage.polarity == AxisStorage.Polarity.MINUS ? axisValue : 0.f);
|
||||
storage.absValue = axisValue;
|
||||
}
|
||||
|
||||
private boolean handleScreenScrolling(Screen screen, AxisStorage storage) {
|
||||
if (screen == null) return false;
|
||||
// @TODO allow rebinding to left stick
|
||||
int preferredAxis = true ? GLFW_GAMEPAD_AXIS_RIGHT_Y : GLFW_GAMEPAD_AXIS_LEFT_Y;
|
||||
|
||||
if (this.controlsInput != null && this.controlsInput.getFocusedBinding() != null) {
|
||||
if (storage.buttonState != ButtonState.NONE && !this.controlsInput.getCurrentButtons().contains(storage.getButtonId(storage.buttonState == ButtonState.PRESS))) {
|
||||
|
||||
this.controlsInput.getCurrentButtons().add(storage.getButtonId(storage.buttonState == ButtonState.PRESS));
|
||||
|
||||
int[] buttons = new int[this.controlsInput.getCurrentButtons().size()];
|
||||
for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
|
||||
buttons[i] = this.controlsInput.getCurrentButtons().get(i);
|
||||
this.controlsInput.getFocusedBinding().setButton(buttons);
|
||||
this.controlsInput.update();
|
||||
|
||||
this.controlsInput.setWaiting(false);
|
||||
}
|
||||
return true;
|
||||
} else if (storage.absValue >= storage.deadZone) {
|
||||
if (screen instanceof CreativeInventoryScreen creativeInventoryScreen) {
|
||||
if (storage.axis == preferredAxis) {
|
||||
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||
if (accessor.midnightcontrols$hasScrollbar() && storage.absValue >= storage.deadZone) {
|
||||
creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (screen instanceof AdvancementsScreen advancementsScreen) {
|
||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||
var accessor = (AdvancementsScreenAccessor) advancementsScreen;
|
||||
AdvancementTab tab = accessor.getSelectedTab();
|
||||
tab.move(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -storage.value * 1.0 : 0.0, storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -storage.value * 5.0 : 0.0);
|
||||
return true;
|
||||
}
|
||||
} else if (screen != null) {
|
||||
if (storage.axis == preferredAxis && !handleListWidgetScrolling(screen.children(), storage.value)) {
|
||||
try {
|
||||
screen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
||||
} catch (NullPointerException ignored) {}
|
||||
} else if (isScreenInteractive(screen)) {
|
||||
if (joystickCooldown == 0) {
|
||||
switch (storage.axis) {
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
||||
this.changeFocus(screen, storage.value > 0 ? NavigationDirection.UP : NavigationDirection.DOWN);
|
||||
joystickCooldown = 4;
|
||||
}
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
||||
this.handleLeftRight(screen, storage.value > 0);
|
||||
joystickCooldown = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public void handleRadialMenu(float x, float y) {
|
||||
int index = -1;
|
||||
float border = 0.3f;
|
||||
if (x < -border) {
|
||||
index = 3;
|
||||
if (y < -border) index = 0;
|
||||
else if (y > border) index = 5;
|
||||
} else if (x > border) {
|
||||
index = 4;
|
||||
if (y < -border) index = 2;
|
||||
else if (y > border) index = 7;
|
||||
} else {
|
||||
if (y < -border) index = 1;
|
||||
else if (y > border) index = 6;
|
||||
}
|
||||
if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index;
|
||||
if (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index);
|
||||
}
|
||||
|
||||
public boolean handleListWidgetScrolling(List<? extends Element> children, float value) {
|
||||
return children.stream().filter(element -> element instanceof SpruceEntryListWidget)
|
||||
.map(element -> (SpruceEntryListWidget<?>) element)
|
||||
.filter(AbstractSpruceWidget::isFocusedOrHovered)
|
||||
.anyMatch(element -> {
|
||||
element.mouseScrolled(0.0, 0.0, 0, -value);
|
||||
return true;
|
||||
}) ||
|
||||
children.stream().filter(element -> element instanceof EntryListWidget)
|
||||
.map(element -> (EntryListWidget<?>) element)
|
||||
.filter(element -> element.getType().isFocused())
|
||||
.anyMatch(element -> {
|
||||
element.mouseScrolled(0.0, 0.0, 0, -value / 30);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||
if (focused instanceof PressableWidget widget) {
|
||||
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||
widget.onPress(ENTER_KEY_INPUT);
|
||||
return true;
|
||||
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
|
||||
widget.playDownSound();
|
||||
widget.onPress();
|
||||
return true;
|
||||
} else if (focused instanceof SpruceLabelWidget labelWidget) {
|
||||
labelWidget.onPress();
|
||||
return true;
|
||||
} else if (focused instanceof WorldListWidget list) {
|
||||
list.getSelectedAsOptional().ifPresent(WorldListWidget.WorldEntry::play);
|
||||
return true;
|
||||
} else if (focused instanceof MultiplayerServerListWidget list) {
|
||||
var entry = list.getSelectedOrNull();
|
||||
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
||||
//((MultiplayerScreen) screen).select(entry);
|
||||
entry.connect();
|
||||
}
|
||||
} else if (focused instanceof SpruceParentWidget) {
|
||||
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
||||
if (childFocused != null)
|
||||
return this.handleAButton(screen, childFocused);
|
||||
} else if (focused instanceof ParentElement widget) {
|
||||
var childFocused = widget.getFocused();
|
||||
if (childFocused != null)
|
||||
return this.handleAButton(screen, childFocused);
|
||||
} else if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleAButton(screen, focused)) {
|
||||
return true;
|
||||
}
|
||||
else pressKeyboardKey(screen, GLFW_KEY_ENTER);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the left and right buttons.
|
||||
*
|
||||
* @param screen the current screen
|
||||
* @param right true if the right button is pressed, else false
|
||||
*/
|
||||
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
||||
if (screen instanceof SpruceScreen spruceScreen) {
|
||||
spruceScreen.onNavigation(new NavigationEvent(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false, false));
|
||||
this.actionGuiCooldown = 5;
|
||||
return false;
|
||||
}
|
||||
if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleLeftRight(screen, right)) {
|
||||
this.actionGuiCooldown = 5;
|
||||
return false;
|
||||
}
|
||||
var focused = screen.getFocused();
|
||||
if (focused != null)
|
||||
if (this.handleRightLeftElement(focused, right))
|
||||
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
||||
switch (element) {
|
||||
case SpruceElement spruceElement -> {
|
||||
if (spruceElement.requiresCursor())
|
||||
return true;
|
||||
return !spruceElement.onNavigation(new NavigationEvent(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false, false));
|
||||
}
|
||||
case SliderWidget slider -> {
|
||||
if (slider.active) {
|
||||
slider.keyPressed(new KeyInput(right ? 262 : 263, 0, 0));
|
||||
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// case AlwaysSelectedEntryListWidget<?> alwaysSelectedEntryListWidget -> {
|
||||
// //TODO ((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
||||
// return false;
|
||||
// }
|
||||
case ParentElement entryList -> {
|
||||
var focused = entryList.getFocused();
|
||||
if (focused == null)
|
||||
return true;
|
||||
return this.handleRightLeftElement(focused, right);
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private double prevX = 0;
|
||||
private double prevY = 0;
|
||||
private double xValue;
|
||||
private AxisStorage.Polarity xPolarity;
|
||||
|
||||
/**
|
||||
* Handles the look direction input.
|
||||
*
|
||||
* @param storage the state of the provided axis
|
||||
*/
|
||||
public void handleLook(AxisStorage storage) {
|
||||
if (client.player == null || !(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X)) return;
|
||||
// Handles the look direction.
|
||||
if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) handleFlatLook(storage);
|
||||
else handleAdaptiveLook(storage);
|
||||
MidnightControlsCompat.handleCamera(this.targetYaw, this.targetPitch);
|
||||
}
|
||||
private void handleFlatLook(AxisStorage storage) {
|
||||
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
||||
double rotation = Math.pow(storage.value, 2.0) * 0.11D * storage.polarity.multiplier;
|
||||
|
||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation * MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed / 2;
|
||||
else this.targetYaw = rotation * MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed / 2;
|
||||
}
|
||||
}
|
||||
private void handleAdaptiveLook(AxisStorage storage) {
|
||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||
xValue = storage.value;
|
||||
xPolarity = storage.polarity;
|
||||
}
|
||||
else {
|
||||
double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
||||
double xStep = (MidnightControlsConfig.rotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
||||
float yValue = storage.value;
|
||||
AxisStorage.Polarity yPolarity = storage.polarity;
|
||||
|
||||
double cursorDeltaX = 2 * xValue - this.prevX;
|
||||
double cursorDeltaY = 2 * yValue - this.prevY;
|
||||
boolean slowdown = client.options.getPerspective().isFirstPerson() && Objects.requireNonNull(client.player).isUsingSpyglass();
|
||||
double x = cursorDeltaX * xStep * (slowdown ? xStep : 1);
|
||||
double y = cursorDeltaY * yStep * (slowdown ? yStep : 1);
|
||||
|
||||
double powXValue = Math.pow(x, 2.0);
|
||||
double powYValue = Math.pow(y, 2.0);
|
||||
|
||||
if (xPolarity != AxisStorage.Polarity.ZERO) {
|
||||
double sign = MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed;
|
||||
this.targetYaw = sign * powXValue * 0.11D * xPolarity.multiplier;
|
||||
}
|
||||
if (yPolarity != AxisStorage.Polarity.ZERO) {
|
||||
double sign = MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed;
|
||||
this.targetPitch = sign * powYValue * 0.11D * yPolarity.multiplier;
|
||||
}
|
||||
|
||||
this.prevY = yValue;
|
||||
this.prevX = xValue;
|
||||
}
|
||||
}
|
||||
public void handleTouchscreenLook(AxisStorage storage) {
|
||||
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
||||
double rotation = storage.value * 0.11D * MidnightControlsConfig.touchSpeed/5;
|
||||
|
||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation;
|
||||
else this.targetYaw = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
||||
if (!isScreenInteractive(screen) && !screen.getClass().getCanonicalName().contains("me.jellysquid.mods.sodium.client.gui")) return false;
|
||||
try {
|
||||
if (screen instanceof SpruceScreen spruceScreen) {
|
||||
if (spruceScreen.onNavigation(new NavigationEvent(direction, false, false))) {
|
||||
this.actionGuiCooldown = 5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (direction) {
|
||||
case UP -> pressKeyboardKey(screen, GLFW.GLFW_KEY_UP);
|
||||
case DOWN -> pressKeyboardKey(screen, GLFW.GLFW_KEY_DOWN);
|
||||
case LEFT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_LEFT);
|
||||
case RIGHT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_RIGHT);
|
||||
}
|
||||
this.actionGuiCooldown = 5;
|
||||
return true;
|
||||
} catch (Exception exception) {MidnightControls.warn("Unknown exception encountered while trying to change focus: "+exception);}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to go back.
|
||||
*
|
||||
* @param screen the current screen
|
||||
* @return true if successful, else false
|
||||
*/
|
||||
public boolean tryGoBack(@NotNull Screen screen) {
|
||||
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
||||
if (screen instanceof KeybindsScreen) return false;
|
||||
|
||||
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||
.map(element -> (PressableWidget) element)
|
||||
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||
.anyMatch(element -> {
|
||||
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
|
||||
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
|
||||
element.onPress(ENTER_KEY_INPUT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
||||
return !(screen instanceof HandledScreen || MidnightControlsConfig.joystickAsMouse || MidnightControlsConfig.mouseScreens.stream().anyMatch(a -> screen.getClass().toString().contains(a))
|
||||
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
||||
|| MidnightControlsCompat.requireMouseOnScreen(screen));
|
||||
}
|
||||
|
||||
public void pressKeyboardKey(MinecraftClient client, int key) {
|
||||
((KeyboardAccessor) client.keyboard).midnightcontrols$onKey(client.getWindow().getHandle(), 1, new KeyInput(key, 0, 0));
|
||||
}
|
||||
public void pressKeyboardKey(Screen screen, int key) {
|
||||
screen.keyPressed(new KeyInput(key, 0, 0));
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||
import io.github.kosmx.emotes.arch.screen.ingame.FastMenuScreen;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.input.MouseInput;
|
||||
import org.joml.Vector2i;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class EmotecraftCompat {
|
||||
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
public static void openEmotecraftScreen(Screen parent) {
|
||||
client.setScreen(new FastMenuScreen(parent));
|
||||
}
|
||||
public static boolean isEmotecraftScreen(Screen screen) {
|
||||
return screen instanceof FastMenuScreen;
|
||||
}
|
||||
|
||||
static int prevIndex = -1;
|
||||
public static void handleEmoteSelector(int index) {
|
||||
try {
|
||||
if (client.currentScreen instanceof FastMenuScreen) {
|
||||
boolean stickReleased = index == -1 && prevIndex != -1;
|
||||
var pos = calcMousePos(stickReleased ? prevIndex : index);
|
||||
InputManager.queueMousePosition(pos.x, pos.y);
|
||||
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||
|
||||
if (stickReleased) {
|
||||
((MouseAccessor) client.mouse).midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW.GLFW_MOUSE_BUTTON_LEFT, 0), GLFW.GLFW_PRESS);
|
||||
prevIndex = -1;
|
||||
}
|
||||
else prevIndex = index;
|
||||
} else prevIndex = -1;
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
public static Vector2i calcMousePos(int index) {
|
||||
int x = client.getWindow().getWidth() / 2;
|
||||
int y = client.getWindow().getHeight() / 2;
|
||||
switch (index) {
|
||||
case 0, 3, 5 -> x -= 275;
|
||||
case 2, 4, 7 -> x += 275;
|
||||
}
|
||||
switch (index) {
|
||||
case 0, 1, 2 -> y -= 275;
|
||||
case 5, 6, 7 -> y += 275;
|
||||
}
|
||||
return new Vector2i(x, y);
|
||||
}
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.controller;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
||||
import eu.midnightdust.midnightcontrols.client.util.ToggleSneakSprintUtil;
|
||||
import eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.*;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
||||
import net.minecraft.client.util.ScreenshotRecorder;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
||||
|
||||
/**
|
||||
* Represents some input handlers.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class InputHandlers {
|
||||
private InputHandlers() {
|
||||
}
|
||||
|
||||
public static PressAction handleHotbar(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action == ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
// When in-game
|
||||
if (client.currentScreen == null && client.player != null) {
|
||||
if (!client.player.isSpectator()) {
|
||||
var inv = client.player.getInventory();
|
||||
if (next)
|
||||
inv.setSelectedSlot(inv.getSelectedSlot() < 8 ? inv.getSelectedSlot() + 1 : inv.getSelectedSlot() - 8);
|
||||
else
|
||||
inv.setSelectedSlot(inv.getSelectedSlot() > 0 ? inv.getSelectedSlot() - 1 : inv.getSelectedSlot() + 8);
|
||||
}
|
||||
else {
|
||||
if (client.inGameHud.getSpectatorHud().isOpen()) {
|
||||
client.inGameHud.getSpectatorHud().cycleSlot(next ? -1 : 1);
|
||||
} else {
|
||||
float g = MathHelper.clamp(client.player.getAbilities().getFlySpeed() + (next ? 1 : -1) * 0.005F, 0.0F, 0.2F);
|
||||
client.player.getAbilities().setFlySpeed(g);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof RingScreen) {
|
||||
MidnightControlsClient.ring.cyclePage(next);
|
||||
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
||||
inventory.midnightcontrols$setSelectedTab(ItemGroupUtil.cycleTab(next, client));
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof RecipeBookScreen<?> recipeBookScreen) {
|
||||
RecipeBookWidget<?> recipeBook = ((RecipeBookScreenAccessor) recipeBookScreen).getRecipeBook();
|
||||
|
||||
var recipeBookAccessor = (RecipeBookWidgetAccessor) recipeBook;
|
||||
var tabs = recipeBookAccessor.getTabButtons();
|
||||
var currentTab = recipeBookAccessor.getCurrentTab();
|
||||
if (currentTab == null || !recipeBook.isOpen()) {
|
||||
return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
||||
}
|
||||
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
||||
if (nextTab < 0)
|
||||
nextTab = tabs.size() - 1;
|
||||
else if (nextTab >= tabs.size())
|
||||
nextTab = 0;
|
||||
currentTab.active = false;
|
||||
recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||
currentTab.active = true;
|
||||
recipeBookScreen.refreshRecipeBook();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
||||
var tabs = screen.getTabs().values().stream().distinct().toList();
|
||||
var tab = screen.getSelectedTab();
|
||||
if (tab == null)
|
||||
return false;
|
||||
for (int i = 0; i < tabs.size(); i++) {
|
||||
if (tabs.get(i).equals(tab)) {
|
||||
int nextTab = i + (next ? 1 : -1);
|
||||
if (nextTab < 0)
|
||||
nextTab = tabs.size() - 1;
|
||||
else if (nextTab >= tabs.size())
|
||||
nextTab = 0;
|
||||
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot().getAdvancementEntry(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (client.currentScreen != null && client.currentScreen.children().stream().anyMatch(e -> e instanceof TabNavigationWidget)) {
|
||||
return Lists.newCopyOnWriteArrayList(client.currentScreen.children()).stream().anyMatch(e -> {
|
||||
if (e instanceof TabNavigationWidget tabs) {
|
||||
TabNavigationWidgetAccessor accessor = (TabNavigationWidgetAccessor) tabs;
|
||||
int tabIndex = accessor.getTabs().indexOf(accessor.getTabManager().getCurrentTab());
|
||||
if (next ? tabIndex+1 < accessor.getTabs().size() : tabIndex > 0) {
|
||||
if (next) tabs.selectTab(tabIndex + 1, true);
|
||||
else tabs.selectTab(tabIndex - 1, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
} else return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
public static PressAction handlePage(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action == ButtonState.RELEASE)
|
||||
return false;
|
||||
if (client.currentScreen instanceof CreativeInventoryScreen creativeScreen) {
|
||||
return ItemGroupUtil.cyclePage(next, creativeScreen);
|
||||
}
|
||||
|
||||
|
||||
return MidnightControlsCompat.handlePages(client.currentScreen, next);
|
||||
};
|
||||
}
|
||||
public static PressAction handleExit() {
|
||||
return (client, button, value, action) -> {
|
||||
if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) {
|
||||
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
||||
if (!MidnightControlsClient.input.tryGoBack(client.currentScreen))
|
||||
client.currentScreen.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
public static PressAction handleActions() {
|
||||
return (client, button, value, action) -> {
|
||||
if (!(client.currentScreen instanceof HandledScreen<?> screen)) return false;
|
||||
if (client.interactionManager == null || client.player == null)
|
||||
return false;
|
||||
|
||||
if (MidnightControlsClient.input.inventoryInteractionCooldown > 0)
|
||||
return true;
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
var accessor = (HandledScreenAccessor) screen;
|
||||
Slot slot = accessor.midnightcontrols$getSlotAt(x, y);
|
||||
|
||||
int slotId;
|
||||
if (slot == null) {
|
||||
if (button.getName().equals("take_all")) {
|
||||
return false;
|
||||
}
|
||||
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY()) ? -999 : -1;
|
||||
} else {
|
||||
slotId = slot.id;
|
||||
}
|
||||
var actionType = SlotActionType.PICKUP;
|
||||
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
||||
|
||||
MidnightControlsClient.input.inventoryInteractionCooldown = 5;
|
||||
switch (button.getName()) {
|
||||
case "take_all" -> {
|
||||
if (screen instanceof CreativeInventoryScreen) {
|
||||
if (slot != null && (((CreativeInventoryScreenAccessor) accessor).midnightcontrols$isCreativeInventorySlot(slot) || MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot))))
|
||||
actionType = SlotActionType.CLONE;
|
||||
}
|
||||
}
|
||||
case "take" -> {
|
||||
clickData = GLFW_MOUSE_BUTTON_2;
|
||||
}
|
||||
case "quick_move" -> {
|
||||
actionType = SlotActionType.QUICK_MOVE;
|
||||
}
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
accessor.midnightcontrols$onMouseClick(slot, slotId, clickData, actionType);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean handlePauseGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
||||
if (action == ButtonState.PRESS) {
|
||||
// If in game, then pause the game.
|
||||
if (client.currentScreen == null || client.currentScreen instanceof RingScreen)
|
||||
client.openGameMenu(false);
|
||||
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
||||
client.player.closeHandledScreen();
|
||||
else // Else just close the current screen.
|
||||
client.currentScreen.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the screenshot action.
|
||||
*
|
||||
* @param client the client instance
|
||||
* @param binding the binding which fired the action
|
||||
* @param action the action done on the binding
|
||||
* @return true if handled, else false
|
||||
*/
|
||||
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
||||
if (action == ButtonState.RELEASE)
|
||||
ScreenshotRecorder.saveScreenshot(client.runDirectory, client.getFramebuffer(),
|
||||
text -> client.execute(() -> client.inGameHud.getChatHud().addMessage(text)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||
return ToggleSneakSprintUtil.toggleSneak(button);
|
||||
}
|
||||
public static boolean handleToggleSprint(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||
return ToggleSneakSprintUtil.toggleSprint(button);
|
||||
}
|
||||
|
||||
public static PressAction handleInventorySlotPad(int direction) {
|
||||
return (client, binding, value, action) -> {
|
||||
if (!(client.currentScreen instanceof HandledScreen<?> inventory && action != ButtonState.RELEASE))
|
||||
return false;
|
||||
|
||||
var accessor = (HandledScreenAccessor) inventory;
|
||||
|
||||
Optional<Slot> closestSlot = InventoryUtil.findClosestSlot(inventory, direction);
|
||||
|
||||
if (closestSlot.isPresent()) {
|
||||
var slot = closestSlot.get();
|
||||
int x = accessor.getX() + slot.x + 8;
|
||||
int y = accessor.getY() + slot.y + 8;
|
||||
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
||||
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns always true to the filter.
|
||||
*
|
||||
* @param binding the affected binding
|
||||
* @return true
|
||||
*/
|
||||
public static boolean always(@NotNull ButtonBinding binding) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the client is in game or not.
|
||||
*
|
||||
* @param binding the affected binding
|
||||
* @return true if the client is in game, else false
|
||||
*/
|
||||
public static boolean inGame(@NotNull ButtonBinding binding) {
|
||||
return (client.currentScreen == null && MidnightControlsClient.input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
||||
*
|
||||
* @param binding the affected binding
|
||||
* @return true if the client is in a non-interactive screen, else false
|
||||
*/
|
||||
public static boolean inNonInteractiveScreens(@NotNull ButtonBinding binding) {
|
||||
if (client.currentScreen == null)
|
||||
return false;
|
||||
return !MidnightInput.isScreenInteractive(client.currentScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the client is in an inventory or not.
|
||||
*
|
||||
* @param binding the affected binding
|
||||
* @return true if the client is in an inventory, else false
|
||||
*/
|
||||
public static boolean inInventory(@NotNull ButtonBinding binding) {
|
||||
return client.currentScreen instanceof HandledScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the client is in the advancements screen or not.
|
||||
*
|
||||
* @param binding the affected binding
|
||||
* @return true if the client is in the advancements screen, else false
|
||||
*/
|
||||
public static boolean inAdvancements(@NotNull ButtonBinding binding) {
|
||||
return client.currentScreen instanceof AdvancementsScreen;
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import eu.midnightdust.lib.config.EntryInfo;
|
||||
import eu.midnightdust.lib.config.MidnightConfigListWidget;
|
||||
import eu.midnightdust.lib.config.MidnightConfigScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.DrawnTextConsumer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.tooltip.Tooltip;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||
import net.minecraft.client.input.AbstractInput;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ControllerBindingButton extends ButtonWidget implements ControlsInput {
|
||||
private static final int[] UNBOUND = new int[]{-1};
|
||||
static boolean waiting = false;
|
||||
static List<Integer> currentButtons = new ArrayList<>();
|
||||
private int iconWidth;
|
||||
|
||||
public static void add(ButtonBinding binding, MidnightConfigListWidget list, MidnightConfigScreen screen) {
|
||||
ControllerBindingButton editButton = new ControllerBindingButton(screen.width - 185 + 22, 0, 128, 20, binding);
|
||||
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(net.minecraft.text.Text.translatable("controls.reset"), (button -> {
|
||||
MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton());
|
||||
MidnightControlsClient.input.beginControlsInput(null);
|
||||
editButton.updateMessage(false);
|
||||
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build();
|
||||
resetButton.setPosition(screen.width - 205 + 150 + 25, 0);
|
||||
editButton.resetButton = resetButton;
|
||||
editButton.updateMessage(false);
|
||||
EntryInfo info = new EntryInfo(null, screen.modid);
|
||||
|
||||
TextIconButtonWidget unbindButton = TextIconButtonWidget.builder(net.minecraft.text.Text.translatable("midnightcontrols.narrator.unbound", binding.getText()), (button -> {
|
||||
MidnightControlsConfig.setButtonBinding(binding, UNBOUND);
|
||||
MidnightControlsClient.input.beginControlsInput(null);
|
||||
editButton.updateMessage(false);
|
||||
}), true).texture(Identifier.of("midnightcontrols","icon/unbind"), 12, 12).dimension(20, 20).build();
|
||||
unbindButton.setPosition(screen.width - 205 + 20, 0);
|
||||
unbindButton.setTooltip(Tooltip.of(SpruceTexts.GUI_UNBIND));
|
||||
unbindButton.active = !binding.isNotBound();
|
||||
editButton.unbindButton = unbindButton;
|
||||
|
||||
list.addButton(Lists.newArrayList(editButton, resetButton, unbindButton), net.minecraft.text.Text.translatable(binding.getTranslationKey()), info);
|
||||
}
|
||||
|
||||
private final ButtonBinding binding;
|
||||
private @Nullable ClickableWidget resetButton;
|
||||
private @Nullable ClickableWidget unbindButton;
|
||||
public ControllerBindingButton(int x, int y, int width, int height, ButtonBinding binding) {
|
||||
super(x, y, width, height, binding.getText(), (button) -> {},
|
||||
(textSupplier) -> binding.isNotBound() ? net.minecraft.text.Text.translatable("narrator.controls.unbound", binding.getTranslationKey()) : net.minecraft.text.Text.translatable("narrator.controls.bound", binding.getTranslationKey(), textSupplier.get()));
|
||||
this.binding = binding;
|
||||
updateMessage(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress(AbstractInput input) {
|
||||
MidnightControlsClient.input.beginControlsInput(this);
|
||||
this.updateMessage(true);
|
||||
}
|
||||
|
||||
|
||||
public void updateMessage(boolean focused) {
|
||||
AtomicBoolean hasConflicts = new AtomicBoolean(false);
|
||||
MutableText conflictingBindings = net.minecraft.text.Text.empty();
|
||||
if (focused) this.setMessage(net.minecraft.text.Text.literal("> ").append(getTranslatedButtons().copy().formatted(Formatting.WHITE, Formatting.UNDERLINE)).append(" <").formatted(Formatting.YELLOW));
|
||||
else {
|
||||
this.setMessage(getTranslatedButtons());
|
||||
|
||||
if (!this.binding.isNotBound()) {
|
||||
InputManager.streamBindings().forEach(keyBinding -> {
|
||||
if (keyBinding != this.binding && this.binding.equals(keyBinding)) {
|
||||
if (hasConflicts.get()) conflictingBindings.append(", ");
|
||||
|
||||
hasConflicts.set(true);
|
||||
conflictingBindings.append(net.minecraft.text.Text.translatable(keyBinding.getTranslationKey()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.resetButton != null) this.resetButton.active = !this.binding.isDefault();
|
||||
if (this.unbindButton != null) this.unbindButton.active = !binding.isNotBound();
|
||||
|
||||
if (hasConflicts.get()) {
|
||||
this.setMessage(net.minecraft.text.Text.literal("[ ").append(this.getMessage().copy().formatted(Formatting.WHITE)).append(" ]").formatted(Formatting.RED));
|
||||
this.setTooltip(Tooltip.of(net.minecraft.text.Text.translatable("controls.keybinds.duplicateKeybinds", conflictingBindings)));
|
||||
} else {
|
||||
this.setTooltip(null);
|
||||
}
|
||||
}
|
||||
|
||||
private net.minecraft.text.Text getTranslatedButtons() {
|
||||
return this.binding.isNotBound() ? SpruceTexts.NOT_BOUND.copy() :
|
||||
(binding.getButton().length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : net.minecraft.text.Text.literal("..."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLabel(DrawnTextConsumer consumer) {
|
||||
if (this.binding.getButton().length < 2) super.drawLabel(consumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawIcon(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
|
||||
int x = this.getX();
|
||||
if (this.binding.getButton().length > 1) {
|
||||
x += (this.width / 2 - iconWidth / 2) - 4;
|
||||
}
|
||||
var size = MidnightControlsRenderer.drawButton(context, x, this.getY(), this.binding, MinecraftClient.getInstance());
|
||||
iconWidth = size.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishBindingEdit(int... buttons) {
|
||||
MidnightControlsConfig.setButtonBinding(binding, buttons);
|
||||
updateMessage(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.updateMessage(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWaiting(boolean value) {
|
||||
waiting = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaiting() {
|
||||
return waiting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getCurrentButtons() {
|
||||
return currentButtons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ButtonBinding getFocusedBinding() {
|
||||
return this.binding;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.config;
|
||||
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import eu.midnightdust.lib.config.EntryInfo;
|
||||
import eu.midnightdust.lib.config.MidnightConfigListWidget;
|
||||
import eu.midnightdust.lib.config.MidnightConfigScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import net.minecraft.client.gui.tooltip.Tooltip;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen.searchNextAvailableController;
|
||||
|
||||
public class ControllerSelectionButton {
|
||||
public static void add(MidnightConfigListWidget list, MidnightConfigScreen screen, boolean second) {
|
||||
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
|
||||
if (second) MidnightControlsConfig.secondControllerID = -1;
|
||||
else MidnightControlsConfig.controllerID = 0;
|
||||
screen.updateList();
|
||||
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build();
|
||||
resetButton.setPosition(screen.width - 205 + 150 + 25, 0);
|
||||
ButtonWidget editButton = ButtonWidget.builder(getControllerName(second),
|
||||
button -> {
|
||||
int id = second ? MidnightControlsConfig.getSecondController().map(Controller::id).orElse(-1) : MidnightControlsConfig.getController().id();
|
||||
id += 1;
|
||||
if (id > GLFW.GLFW_JOYSTICK_LAST)
|
||||
id = GLFW.GLFW_JOYSTICK_1;
|
||||
id = searchNextAvailableController(id, second);
|
||||
if (second) {
|
||||
MidnightControlsConfig.setSecondController(Controller.byId(id));
|
||||
} else {
|
||||
MidnightControlsConfig.setController(Controller.byId(id));
|
||||
}
|
||||
if (MidnightControlsConfig.debug && id != -1) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
|
||||
|
||||
resetButton.active = second ? MidnightControlsConfig.getSecondController().isPresent() : false;
|
||||
button.setMessage(getControllerName(second));
|
||||
}).dimensions(screen.width - 185, 0, 150, 20).build();
|
||||
resetButton.active = second ? MidnightControlsConfig.getSecondController().isPresent() : false;
|
||||
if (second) editButton.setTooltip(Tooltip.of(Text.translatable("midnightcontrols.menu.controller2.tooltip")));
|
||||
|
||||
list.addButton(List.of(editButton, resetButton), Text.translatable(second ? "midnightcontrols.menu.controller2" : "midnightcontrols.menu.controller"), new EntryInfo(null, screen.modid));
|
||||
}
|
||||
|
||||
private static Text getControllerName(boolean second) {
|
||||
if (second && MidnightControlsConfig.getSecondController().isEmpty()) return SpruceTexts.OPTIONS_OFF.copyContentOnly().formatted(Formatting.RED);
|
||||
|
||||
var controller = second ? MidnightControlsConfig.getSecondController().get() : MidnightControlsConfig.getController();
|
||||
var controllerName = controller.getName();
|
||||
if (!controller.isConnected())
|
||||
return Text.literal(controllerName).formatted(Formatting.RED);
|
||||
else if (!controller.isGamepad())
|
||||
return Text.literal(controllerName).formatted(Formatting.GOLD);
|
||||
else
|
||||
return Text.literal(controllerName);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.config;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ControlsInput {
|
||||
void setWaiting(boolean value);
|
||||
boolean isWaiting();
|
||||
|
||||
List<Integer> getCurrentButtons();
|
||||
|
||||
ButtonBinding getFocusedBinding();
|
||||
|
||||
void finishBindingEdit(int[] buttons);
|
||||
|
||||
default void update() {};
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.gui.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
||||
import eu.midnightdust.lib.config.EntryInfo;
|
||||
import eu.midnightdust.lib.config.MidnightConfigListWidget;
|
||||
import eu.midnightdust.lib.config.MidnightConfigScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.client.gui.widget.*;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
/**
|
||||
* Represents the controller mappings file editor screen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.4.3
|
||||
*/
|
||||
public class MappingsStringInputWidget {
|
||||
|
||||
public static void add(EntryInfo centered, MidnightConfigListWidget list, MidnightConfigScreen screen) {
|
||||
//SpruceTextAreaWidget editButton = new SpruceTextAreaWidget(Position.of(0, 0), 20, 20, Text.empty());
|
||||
MultilineTextFieldWidget editButton = new MultilineTextFieldWidget(screen.getTextRenderer(), screen.width / 2 - 128, 0, 256, 60, Text.of("TESTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\nnew line!"));
|
||||
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
|
||||
screen.updateList();
|
||||
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 60).build();
|
||||
resetButton.setPosition(screen.width / 2 - 128 + 256 + 4, 0);
|
||||
editButton.setChangedListener(string -> {
|
||||
resetButton.active = !string.isEmpty();
|
||||
});
|
||||
|
||||
list.addButton(List.of(), Text.translatable("midnightcontrols.menu.title.mappings.string"), centered);
|
||||
//screen.addDrawableChild(editButton);
|
||||
list.addButton(Lists.newArrayList(editButton, resetButton), Text.empty(), centered);
|
||||
list.addButton(List.of(), Text.empty(), centered);
|
||||
list.addButton(List.of(), Text.empty(), centered);
|
||||
list.addButton(List.of(), Text.translatable("midnightcontrols.menu.multiple_mapping_tip"), centered);
|
||||
//list.addButton();
|
||||
|
||||
ButtonWidget copyButton = TextIconButtonWidget.builder(Text.of("Copy GUID"), widget -> {
|
||||
client.keyboard.setClipboard(MidnightControlsConfig.getController().getGuid());
|
||||
}).dimensions(screen.width - 185, 0, 150, 20).build();
|
||||
|
||||
list.addButton(List.of(copyButton), Text.translatable("midnightcontrols.menu.current_controller_guid", MidnightControlsConfig.getController().getGuid()), new EntryInfo(null, screen.modid));
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.config;
|
||||
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.widget.ScrollableTextWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class MultilineTextFieldWidget extends TextFieldWidget {
|
||||
public MultilineTextFieldWidget(TextRenderer textRenderer, int x, int y, int width, int height, Text text) {
|
||||
super(textRenderer, x, y, width, height, text);
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.cursor;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.DrawContextAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.cursor.Cursor;
|
||||
import net.minecraft.client.texture.TextureSetup;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Matrix3x2f;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
public abstract class CursorRenderer {
|
||||
public static Cursor currentCursorStyle = Cursor.DEFAULT;
|
||||
|
||||
public abstract void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client);
|
||||
|
||||
public static void drawUnalignedTexturedQuad(RenderPipeline pipeline, Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float u1, float u2, float v1, float v2) {
|
||||
DrawContextAccessor accessor = (DrawContextAccessor) context;
|
||||
var tex = client.getTextureManager().getTexture(texture);
|
||||
accessor.getState().addSimpleElement(new UnalignedTexturedQuadGuiElementRenderState(pipeline, TextureSetup.of(tex.getGlTextureView(), tex.getSampler()), new Matrix3x2f(context.getMatrices()), x1, y1, x2, y2, u1, u2, v1, v2, 0xffffffff, accessor.getScissorStack().peekLast()));
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.cursor;
|
||||
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.gui.ScreenRect;
|
||||
import net.minecraft.client.gui.render.state.SimpleGuiElementRenderState;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.texture.TextureSetup;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3x2f;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public record UnalignedTexturedQuadGuiElementRenderState(RenderPipeline pipeline, TextureSetup textureSetup, Matrix3x2f pose, float x1, float y1, float x2, float y2, float u1, float u2, float v1, float v2, int color, @Nullable ScreenRect scissorArea, @Nullable ScreenRect bounds) implements SimpleGuiElementRenderState {
|
||||
public UnalignedTexturedQuadGuiElementRenderState(RenderPipeline pipeline, TextureSetup textureSetup, Matrix3x2f pose, float x1, float y1, float x2, float y2, float u1, float u2, float v1, float v2, int color, @Nullable ScreenRect scissorArea) {
|
||||
this(pipeline, textureSetup, pose, x1, y1, x2, y2, u1, u2, v1, v2, color, scissorArea, createBounds(x1, y1, x2, y2, pose, scissorArea));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVertices(VertexConsumer vertices) {
|
||||
vertices.vertex(pose(), x1(), y1()).texture(u1(), v1()).color(color());
|
||||
vertices.vertex(pose(), x1(), y2()).texture(u1(), v2()).color(color());
|
||||
vertices.vertex(pose(), x2(), y2()).texture(u2(), v2()).color(color());
|
||||
vertices.vertex(pose(), x2(), y1()).texture(u2(), v1()).color(color());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ScreenRect createBounds(float x1, float y1, float x2, float y2, Matrix3x2f pose, @Nullable ScreenRect scissorArea) {
|
||||
ScreenRect screenRect = (new ScreenRect((int) x1, (int) y1, (int) (x2 - x1), (int) (y2 - y1))).transformEachVertex(pose);
|
||||
return scissorArea != null ? scissorArea.intersection(screenRect) : screenRect;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.cursor;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gl.RenderPipelines;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.Atlases;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||
|
||||
public class VirtualCursorRenderer extends CursorRenderer {
|
||||
private static final VirtualCursorRenderer INSTANCE = new VirtualCursorRenderer();
|
||||
|
||||
public static VirtualCursorRenderer getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
||||
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
||||
return;
|
||||
|
||||
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
||||
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
||||
|
||||
boolean hoverSlot = false;
|
||||
|
||||
if (client.currentScreen instanceof HandledScreenAccessor inventoryScreen) {
|
||||
int guiLeft = inventoryScreen.getX();
|
||||
int guiTop = inventoryScreen.getY();
|
||||
|
||||
Slot slot = inventoryScreen.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||
|
||||
if (slot != null) {
|
||||
mouseX = guiLeft + slot.x;
|
||||
mouseY = guiTop + slot.y;
|
||||
hoverSlot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hoverSlot && client.currentScreen != null) {
|
||||
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY);
|
||||
|
||||
if (slot != null) {
|
||||
mouseX = slot.x();
|
||||
mouseY = slot.y();
|
||||
hoverSlot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hoverSlot) {
|
||||
mouseX -= 8;
|
||||
mouseY -= 8;
|
||||
}
|
||||
|
||||
try {
|
||||
Sprite sprite = client.getAtlasManager().getAtlasTexture(Atlases.GUI).getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : "")));
|
||||
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
||||
} catch (IllegalStateException ignored) {}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui.cursor;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gl.RenderPipelines;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.cursor.StandardCursors;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Atlases;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||
|
||||
public class WaylandCursorRenderer extends CursorRenderer {
|
||||
private static final WaylandCursorRenderer INSTANCE = new WaylandCursorRenderer();
|
||||
|
||||
public static final Identifier WAYLAND_CURSOR_ARROW_LIGHT = id("cursor/light/mouse_arrow");
|
||||
public static final Identifier WAYLAND_CURSOR_ARROW_DARK = id("cursor/dark/mouse_arrow");
|
||||
public static final Identifier WAYLAND_CURSOR_POINTING_LIGHT = id("cursor/light/mouse_pointing_hand");
|
||||
public static final Identifier WAYLAND_CURSOR_POINTING_DARK = id("cursor/dark/mouse_pointing_hand");
|
||||
public static final Identifier WAYLAND_CURSOR_IBEAM_LIGHT = id("cursor/light/mouse_ibeam");
|
||||
public static final Identifier WAYLAND_CURSOR_IBEAM_DARK = id("cursor/dark/mouse_ibeam");
|
||||
public static final Identifier WAYLAND_CURSOR_RESIZE_VERTICAL_LIGHT = id("cursor/light/mouse_resize_vertical");
|
||||
public static final Identifier WAYLAND_CURSOR_REZIZE_VERTICAL_DARK = id("cursor/dark/mouse_resize_vertical");
|
||||
public static final Identifier WAYLAND_CURSOR_RESIZE_HORIZONTAL_LIGHT = id("cursor/light/mouse_resize_horizontal");
|
||||
public static final Identifier WAYLAND_CURSOR_REZIZE_HORIZONTAL_DARK = id("cursor/dark/mouse_resize_horizontal");
|
||||
public static final Identifier WAYLAND_CURSOR_NOT_ALLOWED_LIGHT = id("cursor/light/mouse_not_allowed");
|
||||
public static final Identifier WAYLAND_CURSOR_NOT_ALLOWED_DARK = id("cursor/dark/mouse_not_allowed");
|
||||
|
||||
public static WaylandCursorRenderer getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||
if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return;
|
||||
|
||||
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
||||
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
||||
|
||||
try {
|
||||
Sprite sprite = getSprite(client);
|
||||
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX - 2, mouseX + 6, mouseY - 2, mouseY + 6, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
||||
} catch (IllegalStateException ignored) {}
|
||||
}
|
||||
|
||||
private static Sprite getSprite(@NotNull MinecraftClient client) {
|
||||
boolean isDark = MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK;
|
||||
Identifier spritePath;
|
||||
if (CursorRenderer.currentCursorStyle == StandardCursors.POINTING_HAND) spritePath = isDark ? WAYLAND_CURSOR_POINTING_DARK : WAYLAND_CURSOR_POINTING_LIGHT;
|
||||
else if (CursorRenderer.currentCursorStyle == StandardCursors.IBEAM) spritePath = isDark ? WAYLAND_CURSOR_IBEAM_DARK : WAYLAND_CURSOR_IBEAM_LIGHT;
|
||||
else if (CursorRenderer.currentCursorStyle == StandardCursors.RESIZE_NS) spritePath = isDark ? WAYLAND_CURSOR_REZIZE_VERTICAL_DARK : WAYLAND_CURSOR_RESIZE_VERTICAL_LIGHT;
|
||||
else if (CursorRenderer.currentCursorStyle == StandardCursors.RESIZE_EW) spritePath = isDark ? WAYLAND_CURSOR_REZIZE_HORIZONTAL_DARK : WAYLAND_CURSOR_RESIZE_HORIZONTAL_LIGHT;
|
||||
else if (CursorRenderer.currentCursorStyle == StandardCursors.NOT_ALLOWED) spritePath = isDark ? WAYLAND_CURSOR_NOT_ALLOWED_DARK : WAYLAND_CURSOR_NOT_ALLOWED_LIGHT;
|
||||
else spritePath = isDark ? WAYLAND_CURSOR_ARROW_DARK : WAYLAND_CURSOR_ARROW_LIGHT;
|
||||
|
||||
return client.getAtlasManager().getAtlasTexture(Atlases.GUI).getSprite(spritePath);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.WorldView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(AbstractBlock.class)
|
||||
public interface AbstractBlockAccessor {
|
||||
@Invoker("canPlaceAt")
|
||||
boolean midnightcontrols$canPlaceAt(BlockState state, WorldView world, BlockPos pos);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.util.AbstractSignEditScreenAccessor;
|
||||
import net.minecraft.block.entity.SignBlockEntity;
|
||||
import net.minecraft.block.entity.SignText;
|
||||
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(AbstractSignEditScreen.class)
|
||||
public class AbstractSignEditScreenMixin implements AbstractSignEditScreenAccessor {
|
||||
@Shadow @Final private String[] messages;
|
||||
@Shadow private SignText text;
|
||||
@Shadow @Final protected SignBlockEntity blockEntity;
|
||||
@Shadow @Final private boolean front;
|
||||
|
||||
@Override
|
||||
public String[] midnightcontrols$getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void midnightcontrols$setMessage(int line, String text) {
|
||||
this.messages[line] = text;
|
||||
this.text = this.text.withMessage(line, Text.literal(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void midnightcontrols$writeToBlockEntity() {
|
||||
this.blockEntity.setText(this.text, this.front);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||
import net.minecraft.client.gui.widget.EditBoxWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(BookEditScreen.class)
|
||||
public interface BookEditScreenAccessor {
|
||||
@Accessor("editBox")
|
||||
EditBoxWidget midnightcontrols$getEditBox();
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.BookSigningScreen;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(BookSigningScreen.class)
|
||||
public interface BookSigningScreenAccessor {
|
||||
@Accessor("bookTitleTextField")
|
||||
TextFieldWidget midnightcontrols$getBookTitleTextField();
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.gui.cursor.CursorRenderer;
|
||||
import net.minecraft.client.gui.cursor.Cursor;
|
||||
import net.minecraft.client.util.Window;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Cursor.class)
|
||||
public abstract class CursorMixin {
|
||||
@Inject(method = "applyTo", at = @At("TAIL"))
|
||||
public void midnightcontrols$applyCursorStyle(Window window, CallbackInfo ci) {
|
||||
CursorRenderer.currentCursorStyle = ((Cursor) (Object) this);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.render.state.GuiRenderState;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(DrawContext.class)
|
||||
public interface DrawContextAccessor {
|
||||
@Accessor("state")
|
||||
GuiRenderState getState();
|
||||
|
||||
@Accessor("scissorStack")
|
||||
DrawContext.ScissorStack getScissorStack();
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||
import net.minecraft.client.gui.screen.option.GameOptionsScreen;
|
||||
import net.minecraft.client.gui.widget.OptionListWidget;
|
||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||
|
||||
/**
|
||||
* Injects the new controls settings button.
|
||||
*/
|
||||
@Mixin(GameOptionsScreen.class)
|
||||
public abstract class GameOptionsScreenMixin extends Screen {
|
||||
@Shadow @Nullable protected OptionListWidget body;
|
||||
@Unique TextIconButtonWidget midnightcontrols$button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"),
|
||||
(button -> this.client.setScreen(MidnightControlsConfig.getScreen(this, "midnightcontrols"))), true)
|
||||
.dimension(20,20).texture(id("icon/controller"), 20, 20).build();
|
||||
|
||||
protected GameOptionsScreenMixin(Text title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(method = "initBody", at = @At("TAIL"))
|
||||
public void midnightcontrols$addMCButton(CallbackInfo ci) {
|
||||
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
||||
this.midnightcontrols$setButtonPos();
|
||||
this.addSelectableChild(midnightcontrols$button);
|
||||
}
|
||||
}
|
||||
@Inject(method = "init", at = @At("TAIL"))
|
||||
public void midnightcontrols$drawMCButton(CallbackInfo ci) {
|
||||
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
||||
this.addDrawableChild(midnightcontrols$button);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "refreshWidgetPositions", at = @At("TAIL"))
|
||||
public void midnightcontrols$onResize(CallbackInfo ci) {
|
||||
this.midnightcontrols$setButtonPos();
|
||||
}
|
||||
@Unique
|
||||
public void midnightcontrols$setButtonPos() {
|
||||
if (body != null) {
|
||||
midnightcontrols$button.setPosition(body.getWidth() / 2 + 158, body.getY() + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.cursor.VirtualCursorRenderer;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.cursor.WaylandCursorRenderer;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import org.joml.Matrix4f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public abstract class GameRendererMixin {
|
||||
@Shadow @Final private MinecraftClient client;
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getScaledX(Lnet/minecraft/client/util/Window;)D", shift = At.Shift.BEFORE))
|
||||
private void midnightcontrols$onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
|
||||
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
|
||||
MidnightControlsClient.input.onPreRenderScreen(this.client.currentScreen);
|
||||
}
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.AFTER))
|
||||
private void midnightcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
|
||||
VirtualCursorRenderer.getInstance().renderCursor(drawContext, client);
|
||||
if (MidnightControlsClient.isWayland) WaylandCursorRenderer.getInstance().renderCursor(drawContext, client);
|
||||
}
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;renderHand(FZLorg/joml/Matrix4f;)V"), method = "renderWorld")
|
||||
private void midnigtcontrols$captureMatrices(RenderTickCounter tickCounter, CallbackInfo ci, @Local(ordinal = 0) Matrix4f projectionMatrix, @Local(ordinal = 1) Matrix4f worldSpaceMatrix) {
|
||||
TouchUtils.lastProjMat.set(projectionMatrix);
|
||||
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
|
||||
TouchUtils.lastWorldSpaceMatrix.set(worldSpaceMatrix);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.hud.InGameHud;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(InGameHud.class)
|
||||
public class InGameHudMixin {
|
||||
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
private static void midnightcontrols$initHud(MinecraftClient client, CallbackInfo ci) {
|
||||
MidnightControlsHud.getInstance().init();
|
||||
}
|
||||
|
||||
@Inject(method = "renderMainHud", at = @At("HEAD"))
|
||||
public void midnightcontrols$renderHud(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
|
||||
MidnightControlsHud.getInstance().render(context, tickCounter);
|
||||
}
|
||||
|
||||
@Inject(method = "tick()V", at = @At("HEAD"))
|
||||
public void midnightcontrols$tickHud(CallbackInfo ci) {
|
||||
MidnightControlsHud.getInstance().tick();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.input.Input;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(Input.class)
|
||||
public interface InputAccessor {
|
||||
@Accessor
|
||||
void setMovementVector(Vec2f input);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.Keyboard;
|
||||
import net.minecraft.client.input.KeyInput;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(Keyboard.class)
|
||||
public interface KeyboardAccessor {
|
||||
@Invoker("onKey")
|
||||
void midnightcontrols$onKey(long window, int action, KeyInput input);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.RecipeBookScreen;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(RecipeBookScreen.class)
|
||||
public interface RecipeBookScreenAccessor {
|
||||
@Accessor("recipeBook")
|
||||
RecipeBookWidget<?> getRecipeBook();
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util;
|
||||
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
public interface AbstractSignEditScreenAccessor {
|
||||
@Unique
|
||||
String[] midnightcontrols$getMessages();
|
||||
|
||||
@Unique
|
||||
void midnightcontrols$setMessage(int line, String text);
|
||||
|
||||
@Unique
|
||||
void midnightcontrols$writeToBlockEntity();
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util;
|
||||
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input;
|
||||
|
||||
public class InventoryUtil {
|
||||
// Finds the closest slot in the GUI within 14 pixels.
|
||||
public static Optional<Slot> findClosestSlot(HandledScreen<?> inventory, int direction) {
|
||||
var accessor = (HandledScreenAccessor) inventory;
|
||||
int guiLeft = accessor.getX();
|
||||
int guiTop = accessor.getY();
|
||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
// Finds the hovered slot.
|
||||
var mouseSlot = accessor.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||
return inventory.getScreenHandler().slots.parallelStream()
|
||||
.filter(Predicate.isEqual(mouseSlot).negate())
|
||||
.map(slot -> {
|
||||
int posX = guiLeft + slot.x + 8;
|
||||
int posY = guiTop + slot.y + 8;
|
||||
|
||||
int otherPosX = (int) mouseX;
|
||||
int otherPosY = (int) mouseY;
|
||||
if (mouseSlot != null) {
|
||||
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||
otherPosY = guiTop + mouseSlot.y + 8;
|
||||
}
|
||||
|
||||
// Distance between the slot and the cursor.
|
||||
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
||||
return Pair.of(slot, distance);
|
||||
}).filter(entry -> {
|
||||
var slot = entry.key;
|
||||
int posX = guiLeft + slot.x + 8;
|
||||
int posY = guiTop + slot.y + 8;
|
||||
int otherPosX = (int) mouseX;
|
||||
int otherPosY = (int) mouseY;
|
||||
if (mouseSlot != null) {
|
||||
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||
otherPosY = guiTop + mouseSlot.y + 8;
|
||||
}
|
||||
if (direction == 0)
|
||||
return posY < otherPosY;
|
||||
else if (direction == 1)
|
||||
return posY > otherPosY;
|
||||
else if (direction == 2)
|
||||
return posX > otherPosX;
|
||||
else if (direction == 3)
|
||||
return posX < otherPosX;
|
||||
else
|
||||
return false;
|
||||
})
|
||||
.min(Comparator.comparingDouble(p -> p.value))
|
||||
.map(p -> p.key);
|
||||
}
|
||||
|
||||
private static int targetMouseX = 0;
|
||||
private static int targetMouseY = 0;
|
||||
|
||||
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
||||
public static void moveMouseToClosestSlot(@Nullable Screen screen) {
|
||||
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
||||
if (screen instanceof HandledScreen<?> inventoryScreen) {
|
||||
var accessor = (HandledScreenAccessor) inventoryScreen;
|
||||
int guiLeft = accessor.getX();
|
||||
int guiTop = accessor.getY();
|
||||
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
||||
|
||||
// Finds the closest slot in the GUI within 14 pixels.
|
||||
Optional<net.minecraft.util.Pair<Slot, Double>> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream()
|
||||
.map(slot -> {
|
||||
int x = guiLeft + slot.x + 8;
|
||||
int y = guiTop + slot.y + 8;
|
||||
|
||||
// Distance between the slot and the cursor.
|
||||
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
|
||||
return new net.minecraft.util.Pair<>(slot, distance);
|
||||
}).filter(entry -> entry.getRight() <= 14.0)
|
||||
.min(Comparator.comparingDouble(net.minecraft.util.Pair::getRight));
|
||||
|
||||
if (closestSlot.isPresent() && client.player != null) {
|
||||
var slot = closestSlot.get().getLeft();
|
||||
if (slot.hasStack() || !client.player.getInventory().getSelectedStack().isEmpty()) {
|
||||
int slotCenterXScaled = guiLeft + slot.x + 8;
|
||||
int slotCenterYScaled = guiTop + slot.y + 8;
|
||||
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
||||
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
|
||||
double deltaX = slotCenterX - targetMouseX;
|
||||
double deltaY = slotCenterY - targetMouseY;
|
||||
|
||||
if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) {
|
||||
targetMouseX += (int) (deltaX * 0.75);
|
||||
targetMouseY += (int) (deltaY * 0.75);
|
||||
} else {
|
||||
input.mouseSpeedX *= 0.3F;
|
||||
input.mouseSpeedY *= 0.3F;
|
||||
}
|
||||
input.mouseSpeedX *= .75F;
|
||||
input.mouseSpeedY *= .75F;
|
||||
} else {
|
||||
input.mouseSpeedX *= .1F;
|
||||
input.mouseSpeedY *= .1F;
|
||||
}
|
||||
} else {
|
||||
input.mouseSpeedX *= .3F;
|
||||
input.mouseSpeedY *= .3F;
|
||||
}
|
||||
} else {
|
||||
input.mouseSpeedX = 0.F;
|
||||
input.mouseSpeedY = 0.F;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class RainbowColor {
|
||||
public static float hue;
|
||||
public static void tick() {
|
||||
if (hue > 1) hue = 0f;
|
||||
hue = hue + 0.01f;
|
||||
}
|
||||
|
||||
public static Color radialRainbow(float saturation, float brightness) {
|
||||
return Color.getHSBColor(hue, saturation, brightness);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
public class ToggleSneakSprintUtil {
|
||||
public static boolean toggleSneak(ButtonBinding button) {
|
||||
if (client.player == null) return false;
|
||||
boolean isFlying = client.player.getAbilities().flying;
|
||||
var option = client.options.getSneakToggled();
|
||||
|
||||
button.asKeyBinding().ifPresent(binding -> {
|
||||
boolean sneakToggled = option.getValue();
|
||||
if (isFlying && sneakToggled)
|
||||
option.setValue(false);
|
||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||
option.setValue(!sneakToggled);
|
||||
binding.setPressed(button.isPressed());
|
||||
if (isFlying && sneakToggled)
|
||||
option.setValue(true);
|
||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||
option.setValue(sneakToggled);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
public static boolean toggleSprint(ButtonBinding button) {
|
||||
if (client.player == null) return false;
|
||||
boolean isFlying = client.player.getAbilities().flying;
|
||||
var option = client.options.getSprintToggled();
|
||||
|
||||
button.asKeyBinding().ifPresent(binding -> {
|
||||
boolean sprintToggled = option.getValue();
|
||||
if (isFlying && sprintToggled)
|
||||
option.setValue(false);
|
||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||
option.setValue(!sprintToggled);
|
||||
binding.setPressed(button.isPressed());
|
||||
if (client.player.getAbilities().flying && sprintToggled)
|
||||
option.setValue(true);
|
||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||
option.setValue(sprintToggled);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform;
|
||||
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.client.gui.widget.PressableWidget;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightInput.ENTER_KEY_INPUT;
|
||||
|
||||
public class ItemGroupUtil {
|
||||
@ExpectPlatform
|
||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static boolean cyclePage(boolean next, CreativeInventoryScreen screen) {
|
||||
try {
|
||||
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||
.map(element -> (PressableWidget) element)
|
||||
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||
.anyMatch(element -> {
|
||||
if (next && element.getMessage().getString().equals(">")) {
|
||||
element.onPress(ENTER_KEY_INPUT);
|
||||
return true;
|
||||
} else if (element.getMessage().getString().equals("<")) {
|
||||
element.onPress(ENTER_KEY_INPUT);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static @NotNull ItemGroup cycleTab(boolean next, MinecraftClient client) {
|
||||
ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
|
||||
int currentColumn = currentTab.getColumn();
|
||||
ItemGroup.Row currentRow = currentTab.getRow();
|
||||
ItemGroup newTab = null;
|
||||
List<ItemGroup> visibleTabs = ItemGroupUtil.getVisibleGroups((CreativeInventoryScreen) client.currentScreen);
|
||||
for (ItemGroup tab : visibleTabs) {
|
||||
if (tab.getRow().equals(currentRow) && ((newTab == null && ((next && tab.getColumn() > currentColumn) ||
|
||||
(!next && tab.getColumn() < currentColumn))) || (newTab != null && ((next && tab.getColumn() > currentColumn && tab.getColumn() < newTab.getColumn()) ||
|
||||
(!next && tab.getColumn() < currentColumn && tab.getColumn() > newTab.getColumn())))))
|
||||
newTab = tab;
|
||||
}
|
||||
if (newTab == null)
|
||||
for (ItemGroup tab : visibleTabs) {
|
||||
if ((tab.getRow().compareTo(currentRow)) != 0 && ((next && newTab == null || next && newTab.getColumn() > tab.getColumn()) || (!next && newTab == null) || (!next && newTab.getColumn() < tab.getColumn())))
|
||||
newTab = tab;
|
||||
}
|
||||
if (newTab == null) {
|
||||
for (ItemGroup tab : visibleTabs) {
|
||||
if ((next && tab.getRow() == ItemGroup.Row.TOP && tab.getColumn() == 0) ||
|
||||
!next && tab.getRow() == ItemGroup.Row.BOTTOM && (newTab == null || tab.getColumn() > newTab.getColumn()))
|
||||
newTab = tab;
|
||||
}
|
||||
}
|
||||
if (newTab == null || newTab.equals(currentTab)) newTab = ItemGroups.getDefaultTab();
|
||||
return newTab;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform;
|
||||
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
|
||||
public class NetworkUtil {
|
||||
@ExpectPlatform
|
||||
public static void sendPacketC2S(Packet<?> packet) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
@ExpectPlatform
|
||||
public static void sendPayloadC2S(CustomPayload payload) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.storage;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightInput.BUTTON_COOLDOWNS;
|
||||
import static eu.midnightdust.midnightcontrols.client.controller.InputManager.STATES;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_X;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER;
|
||||
|
||||
public class AxisStorage {
|
||||
public final int axis;
|
||||
public float value, absValue;
|
||||
public final double deadZone;
|
||||
public final Polarity polarity;
|
||||
public final boolean isTrigger;
|
||||
public final ButtonState buttonState;
|
||||
|
||||
// Used for joysticks
|
||||
public static AxisStorage of(int axis, float value) {
|
||||
return new AxisStorage(axis, value, isLeftAxis(axis) ? MidnightControlsConfig.leftDeadZone : MidnightControlsConfig.rightDeadZone);
|
||||
}
|
||||
public static AxisStorage of(int axis, float value, double deadZone) {
|
||||
return new AxisStorage(axis, value, deadZone);
|
||||
}
|
||||
|
||||
private AxisStorage(int axis, float value, double deadZone) {
|
||||
this.axis = axis;
|
||||
this.deadZone = deadZone;
|
||||
|
||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
|
||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
this.isTrigger = true;
|
||||
if (value < -.5f) {
|
||||
value = 0f;
|
||||
}
|
||||
else {
|
||||
// Fixes Triggers not working correctly on some controllers
|
||||
if (MidnightControlsConfig.triggerFix) {
|
||||
value = 1.0f;
|
||||
}
|
||||
}
|
||||
} else isTrigger = false;
|
||||
|
||||
this.value = value;
|
||||
this.buttonState = value > .5f ? ButtonState.PRESS : (value < -.5f ? ButtonState.RELEASE : ButtonState.NONE);
|
||||
this.absValue = Math.abs(value);
|
||||
boolean currentPlusState = value > deadZone;
|
||||
boolean currentMinusState = value < -deadZone;
|
||||
if (isTrigger) currentMinusState = false;
|
||||
else if (!MidnightControlsConfig.analogMovement && isLeftAxis(axis)) {
|
||||
currentPlusState = buttonState == ButtonState.PRESS;
|
||||
currentMinusState = buttonState == ButtonState.RELEASE;
|
||||
}
|
||||
this.polarity = currentPlusState ? AxisStorage.Polarity.PLUS : currentMinusState ? AxisStorage.Polarity.MINUS : AxisStorage.Polarity.ZERO;
|
||||
}
|
||||
/**
|
||||
* Returns the specified axis as a button.
|
||||
*
|
||||
* @param positive true if the axis part is positive, else false
|
||||
* @return the axis as a button
|
||||
*/
|
||||
public int getButtonId(boolean positive) {
|
||||
return ButtonBinding.axisAsButton(axis, positive);
|
||||
}
|
||||
|
||||
public void setupButtonStates() {
|
||||
var posButton = getButtonId(true);
|
||||
var negButton = getButtonId(false);
|
||||
var previousPlusState = STATES.getOrDefault(posButton, ButtonState.NONE);
|
||||
var previousMinusState = STATES.getOrDefault(negButton, ButtonState.NONE);
|
||||
|
||||
if (polarity.isPositive() != previousPlusState.isPressed()) {
|
||||
STATES.put(posButton, polarity.isPositive() ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||
if (polarity.isPositive())
|
||||
BUTTON_COOLDOWNS.put(posButton, 5);
|
||||
} else if (polarity.isPositive()) {
|
||||
STATES.put(posButton, ButtonState.REPEAT);
|
||||
if (BUTTON_COOLDOWNS.getOrDefault(posButton, 0) == 0) {
|
||||
BUTTON_COOLDOWNS.put(posButton, 5);
|
||||
}
|
||||
}
|
||||
|
||||
if (polarity.isNegative() != previousMinusState.isPressed()) {
|
||||
STATES.put(negButton, polarity.isNegative() ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||
if (polarity.isNegative())
|
||||
BUTTON_COOLDOWNS.put(negButton, 5);
|
||||
} else if (polarity.isNegative()) {
|
||||
STATES.put(negButton, ButtonState.REPEAT);
|
||||
if (BUTTON_COOLDOWNS.getOrDefault(negButton, 0) == 0) {
|
||||
BUTTON_COOLDOWNS.put(negButton, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static boolean isLeftAxis(int axis) {
|
||||
return axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER;
|
||||
}
|
||||
public static boolean isRightAxis(int axis) {
|
||||
return !isLeftAxis(axis);
|
||||
}
|
||||
|
||||
public enum Polarity {
|
||||
MINUS(-1), ZERO(0), PLUS(1);
|
||||
|
||||
public final int multiplier;
|
||||
Polarity(int multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
}
|
||||
public boolean isPositive() {
|
||||
return this == PLUS;
|
||||
}
|
||||
public boolean isNegative() {
|
||||
return this == MINUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.storage;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP;
|
||||
|
||||
public class ButtonStorage {
|
||||
public final int button;
|
||||
public final ButtonState state;
|
||||
|
||||
public static ButtonStorage of(int button, ButtonState state) {
|
||||
return new ButtonStorage(button, state);
|
||||
}
|
||||
|
||||
private ButtonStorage(int button, ButtonState state) {
|
||||
this.button = button;
|
||||
this.state = state;
|
||||
}
|
||||
public boolean isDpad() {
|
||||
return button >= GLFW_GAMEPAD_BUTTON_DPAD_UP && button <= GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class KeyboardLayout {
|
||||
|
||||
public static KeyboardLayout QWERTY = new KeyboardLayout("en_US:qwerty", createQwertyLetterLayout(), createSymbolLayout());
|
||||
|
||||
private final String id;
|
||||
private final List<List<String>> letters;
|
||||
private final List<List<String>> symbols;
|
||||
|
||||
private KeyboardLayout(String id, List<List<String>> letters, List<List<String>> symbols) {
|
||||
this.id = id;
|
||||
this.letters = letters;
|
||||
this.symbols = symbols;
|
||||
}
|
||||
|
||||
public static KeyboardLayout fromJson(JsonObject json) {
|
||||
try {
|
||||
return new KeyboardLayout(json.get("id").getAsString(), getFromJson(json, true), getFromJson(json, false));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error loading keyboard definition: %s".formatted(e));
|
||||
}
|
||||
}
|
||||
private static List<List<String>> getFromJson(JsonObject json, boolean letters) {
|
||||
String type = letters ? "letters" : "symbols";
|
||||
List<List<String>> arr = new ArrayList<>();
|
||||
if (json.has(type)) {
|
||||
JsonObject lettersJson = json.get(type).getAsJsonObject();
|
||||
for (int i = 0; ; i++) {
|
||||
if (!lettersJson.has("row"+i)) break;
|
||||
var rowJson = lettersJson.get("row%s".formatted(i)).getAsJsonArray();
|
||||
List<String> row = new ArrayList<>();
|
||||
for (int j = 0; j < rowJson.size(); j++) {
|
||||
row.add(rowJson.get(j).getAsString());
|
||||
}
|
||||
arr.add(row);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
else {
|
||||
return letters ? createQwertyLetterLayout() : createSymbolLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTranslationKey() {
|
||||
String[] identifier = id.split(":");
|
||||
if (identifier.length != 2) return "Invalid Keyboard ID: %s".formatted(id);
|
||||
return "midnightcontrols.virtual_keyboard.layout.%s.%s".formatted(identifier[0], identifier[1]);
|
||||
}
|
||||
|
||||
public List<List<String>> getLetters() {
|
||||
return letters;
|
||||
}
|
||||
|
||||
public List<List<String>> getSymbols() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
private static List<List<String>> createQwertyLetterLayout() {
|
||||
List<List<String>> letters = new ArrayList<>();
|
||||
letters.add(Arrays.asList(
|
||||
"q", "w", "e", "r", "t",
|
||||
"y", "u", "i", "o", "p"
|
||||
));
|
||||
letters.add(Arrays.asList(
|
||||
"a", "s", "d", "f", "g",
|
||||
"h", "j", "k", "l"
|
||||
));
|
||||
letters.add(Arrays.asList(
|
||||
"z", "x", "c", "v",
|
||||
"b", "n", "m"
|
||||
));
|
||||
return letters;
|
||||
}
|
||||
|
||||
private static List<List<String>> createSymbolLayout() {
|
||||
List<List<String>> symbols = new ArrayList<>();
|
||||
symbols.add(Arrays.asList(
|
||||
"1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "0"
|
||||
));
|
||||
symbols.add(Arrays.asList(
|
||||
"@", "#", "$", "%", "&",
|
||||
"*", "-", "+", "(", ")"
|
||||
));
|
||||
symbols.add(Arrays.asList(
|
||||
"!", "\"", "'", ":", ";",
|
||||
",", ".", "?", "/"
|
||||
));
|
||||
return symbols;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class KeyboardLayoutManager {
|
||||
private static final Map<String, KeyboardLayout> KEYBOARD_LAYOUTS = new HashMap<>();
|
||||
|
||||
public static void loadLayout(Identifier id, Resource resource) {
|
||||
try {
|
||||
JsonObject json = JsonParser.parseReader(resource.getReader()).getAsJsonObject();
|
||||
KeyboardLayout layout = KeyboardLayout.fromJson(json);
|
||||
KEYBOARD_LAYOUTS.put(layout.getId(), layout);
|
||||
if (MidnightControlsConfig.debug) System.out.printf("Loaded keyboard layout: %s\n", layout.getId());
|
||||
} catch (IOException e) { throw new RuntimeException(e); }
|
||||
}
|
||||
public static KeyboardLayout getById(String id) {
|
||||
return KEYBOARD_LAYOUTS.get(id) == null ? KeyboardLayout.QWERTY : KEYBOARD_LAYOUTS.get(id);
|
||||
}
|
||||
public static KeyboardLayout getNext(KeyboardLayout current) {
|
||||
KeyboardLayout[] layouts = KEYBOARD_LAYOUTS.values().toArray(KeyboardLayout[]::new);
|
||||
int currentIndex = -1;
|
||||
for (int i = 0; i < layouts.length; i++) {
|
||||
if (layouts[i] == current) currentIndex = i;
|
||||
}
|
||||
currentIndex = currentIndex+1 >= layouts.length ? 0 : currentIndex + 1;
|
||||
return layouts[currentIndex];
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.AbstractScreenClickHandler;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.BookEditScreenClickHandler;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.DefaultScreenClickHandler;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.SignEditScreenClickHandler;
|
||||
import net.minecraft.client.gui.Click;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookSigningScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class MouseClickInterceptor {
|
||||
|
||||
private final Map<Class<?>, AbstractScreenClickHandler<?>> clickHandlers;
|
||||
|
||||
public MouseClickInterceptor() {
|
||||
this.clickHandlers = new HashMap<>();
|
||||
this.clickHandlers.put(BookSigningScreen.class, new BookEditScreenClickHandler.Signing());
|
||||
this.clickHandlers.put(BookEditScreen.class, new BookEditScreenClickHandler());
|
||||
this.clickHandlers.put(SignEditScreen.class, new SignEditScreenClickHandler());
|
||||
this.clickHandlers.put(Screen.class, new DefaultScreenClickHandler());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Screen> void intercept(T screen, Click click) {
|
||||
AbstractScreenClickHandler<T> handler = (AbstractScreenClickHandler<T>) clickHandlers.get(screen.getClass());
|
||||
|
||||
if (handler == null) {
|
||||
handler = (AbstractScreenClickHandler<T>) clickHandlers.get(Screen.class);
|
||||
}
|
||||
|
||||
handler.handle(screen, click.x(), click.y());
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public abstract class AbstractScreenClickHandler<T extends Screen> {
|
||||
public abstract void handle(T screen, double mouseX, double mouseY);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.BookEditScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.BookSigningScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui.VirtualKeyboardScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.BookSigningScreen;
|
||||
import net.minecraft.client.gui.widget.EditBoxWidget;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
public class BookEditScreenClickHandler extends AbstractScreenClickHandler<BookEditScreen> {
|
||||
@Override
|
||||
public void handle(BookEditScreen screen, double mouseX, double mouseY) {
|
||||
// don't open the keyboard if a UI element was clicked
|
||||
if(screen.hoveredElement(mouseX, mouseY).isPresent() && !(screen.hoveredElement(mouseX, mouseY).get() instanceof EditBoxWidget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var accessor = (BookEditScreenAccessor) screen;
|
||||
|
||||
VirtualKeyboardScreen virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getEditBox().getText(), (text) -> {
|
||||
client.setScreen(screen);
|
||||
accessor.midnightcontrols$getEditBox().setText(text);
|
||||
}, true);
|
||||
|
||||
client.setScreen(virtualKeyboardScreen);
|
||||
}
|
||||
public static class Signing extends AbstractScreenClickHandler<BookSigningScreen> {
|
||||
@Override
|
||||
public void handle(BookSigningScreen screen, double mouseX, double mouseY) {
|
||||
// don't open the keyboard if a UI element was clicked
|
||||
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var accessor = (BookSigningScreenAccessor) screen;
|
||||
|
||||
VirtualKeyboardScreen virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getBookTitleTextField().getText(), (text) -> {
|
||||
client.setScreen(screen);
|
||||
accessor.midnightcontrols$getBookTitleTextField().setText(text);
|
||||
}, false);
|
||||
|
||||
client.setScreen(virtualKeyboardScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui.VirtualKeyboardScreen;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.ParentElement;
|
||||
import net.minecraft.client.gui.screen.ChatScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightInput.ENTER_KEY_INPUT;
|
||||
|
||||
public class DefaultScreenClickHandler extends AbstractScreenClickHandler<Screen> {
|
||||
|
||||
private Screen parentScreen;
|
||||
private List<Integer> textFieldElementPath;
|
||||
|
||||
@Override
|
||||
public void handle(Screen screen, double mouseX, double mouseY) {
|
||||
var textField = findClickedTextField(screen.children(), mouseX, mouseY);
|
||||
if (textField == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.parentScreen = screen;
|
||||
this.textFieldElementPath = calculatePathToElement(screen, textField.asElement());
|
||||
|
||||
var virtualKeyboardScreen = new VirtualKeyboardScreen(textField.getText(), this::handleKeyboardClose, false);
|
||||
client.setScreen(virtualKeyboardScreen);
|
||||
}
|
||||
|
||||
private void handleKeyboardClose(String newText) {
|
||||
if (this.parentScreen == null || this.textFieldElementPath == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
client.setScreen(this.parentScreen);
|
||||
TextFieldWrapper textField = findTextFieldByPath(this.parentScreen, this.textFieldElementPath);
|
||||
if (textField == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
textField.setText(newText);
|
||||
|
||||
switch (this.parentScreen) {
|
||||
case CreativeInventoryScreen creativeInventoryScreen -> {
|
||||
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||
accessor.midnightcontrols$search();
|
||||
}
|
||||
case ChatScreen chatScreen -> {
|
||||
// send the chat message
|
||||
chatScreen.keyPressed(ENTER_KEY_INPUT);
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private TextFieldWrapper findClickedTextField(List<? extends Element> elements, double mouseX, double mouseY) {
|
||||
for (Element element : elements) {
|
||||
if (TextFieldWrapper.isValidTextField(element)) {
|
||||
TextFieldWrapper textField = new TextFieldWrapper(element);
|
||||
if (textField.isMouseOver(mouseX, mouseY) && textField.isFocused()) {
|
||||
return textField;
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof ParentElement parentElement) {
|
||||
TextFieldWrapper found = findClickedTextField(parentElement.children(), mouseX, mouseY);
|
||||
if (found != null) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the path between a parent and a target in the UI hierarchy
|
||||
*/
|
||||
protected List<Integer> calculatePathToElement(Element parent, Element target) {
|
||||
if (!(parent instanceof ParentElement parentElement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<? extends Element> children = parentElement.children();
|
||||
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
Element child = children.get(i);
|
||||
|
||||
if (child == target) {
|
||||
return Collections.singletonList(i);
|
||||
}
|
||||
|
||||
if (child instanceof ParentElement) {
|
||||
List<Integer> subPath = calculatePathToElement(child, target);
|
||||
if (subPath != null) {
|
||||
List<Integer> fullPath = new ArrayList<>(subPath.size() + 1);
|
||||
fullPath.add(i);
|
||||
fullPath.addAll(subPath);
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected TextFieldWrapper findTextFieldByPath(Element parent, List<Integer> path) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(parent instanceof ParentElement parentElement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<? extends Element> children = parentElement.children();
|
||||
int index = path.get(0);
|
||||
|
||||
if (index < 0 || index >= children.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Element child = children.get(index);
|
||||
|
||||
if (path.size() == 1) {
|
||||
return TextFieldWrapper.isValidTextField(child) ? new TextFieldWrapper(child) : null;
|
||||
}
|
||||
|
||||
if (child instanceof ParentElement) {
|
||||
return findTextFieldByPath(child, path.subList(1, path.size()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.util.AbstractSignEditScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui.VirtualKeyboardScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
public class SignEditScreenClickHandler extends AbstractScreenClickHandler<SignEditScreen> {
|
||||
@Override
|
||||
public void handle(SignEditScreen screen, double mouseX, double mouseY) {
|
||||
// don't open the keyboard if a UI element was clicked
|
||||
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var accessor = (AbstractSignEditScreenAccessor) screen;
|
||||
|
||||
StringBuilder linesToString = new StringBuilder();
|
||||
String[] messages = accessor.midnightcontrols$getMessages();
|
||||
for (int i = 0; i < Math.min(4, messages.length); i++) {
|
||||
String line = messages[i];
|
||||
linesToString.append(line);
|
||||
if (!line.isEmpty() && i < 3) linesToString.append("\n");
|
||||
}
|
||||
|
||||
VirtualKeyboardScreen virtualKeyboardScreen = new VirtualKeyboardScreen(linesToString.toString(), (text) -> {
|
||||
client.setScreen(screen);
|
||||
String[] lines = text.split("\n");
|
||||
for (int i = 0; i < 4; i++) accessor.midnightcontrols$setMessage(i, lines.length > i ? lines[i] : "");
|
||||
accessor.midnightcontrols$writeToBlockEntity();
|
||||
}, true);
|
||||
|
||||
client.setScreen(virtualKeyboardScreen);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||
|
||||
import dev.lambdaurora.spruceui.widget.text.SpruceTextFieldWidget;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
|
||||
public record TextFieldWrapper(Object textField) {
|
||||
|
||||
public TextFieldWrapper {
|
||||
if (!isValidTextField(textField)) {
|
||||
throw new IllegalArgumentException("Type " + textField.getClass() + " is not marked as a valid text field");
|
||||
}
|
||||
}
|
||||
|
||||
Element asElement() {
|
||||
return (Element) textField;
|
||||
}
|
||||
|
||||
String getText() {
|
||||
switch (textField) {
|
||||
case SpruceTextFieldWidget spruceTextField -> {
|
||||
return spruceTextField.getText();
|
||||
}
|
||||
case TextFieldWidget vanillaTextField -> {
|
||||
return vanillaTextField.getText();
|
||||
}
|
||||
default -> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setText(String text) {
|
||||
switch (textField) {
|
||||
case SpruceTextFieldWidget spruceTextField -> {
|
||||
spruceTextField.setText(text);
|
||||
}
|
||||
case TextFieldWidget vanillaTextField -> {
|
||||
vanillaTextField.setText(text);
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isMouseOver(double mouseX, double mouseY) {
|
||||
switch (textField) {
|
||||
case SpruceTextFieldWidget spruceTextField -> {
|
||||
return spruceTextField.isMouseOver(mouseX, mouseY);
|
||||
}
|
||||
case TextFieldWidget vanillaTextField -> {
|
||||
return vanillaTextField.isMouseOver(mouseX, mouseY);
|
||||
}
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFocused() {
|
||||
switch (textField) {
|
||||
case SpruceTextFieldWidget spruceTextField -> {
|
||||
return spruceTextField.isFocused();
|
||||
}
|
||||
case TextFieldWidget vanillaTextField -> {
|
||||
return vanillaTextField.isFocused();
|
||||
}
|
||||
default -> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isValidTextField(Object textField) {
|
||||
return textField instanceof TextFieldWidget || textField instanceof SpruceTextFieldWidget;
|
||||
}
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui;
|
||||
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayout;
|
||||
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayoutManager;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VirtualKeyboardScreen extends SpruceScreen {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CloseCallback {
|
||||
void onClose(String text);
|
||||
}
|
||||
|
||||
private static final int STANDARD_KEY_WIDTH = 20;
|
||||
private static final int SPECIAL_KEY_WIDTH = (int) (STANDARD_KEY_WIDTH * 1.5);
|
||||
private static final int KEY_HEIGHT = 20;
|
||||
private static final int HORIZONTAL_SPACING = 2;
|
||||
private static final int VERTICAL_SPACING = 4;
|
||||
private static final int CONTAINER_PADDING = 10;
|
||||
|
||||
// Key symbols
|
||||
private static final String BACKSPACE_SYMBOL = "\b";
|
||||
private static final String NEWLINE_SYMBOL = "\n";
|
||||
private static final String SPACE_SYMBOL = " ";
|
||||
|
||||
private final StringBuilder buffer;
|
||||
private final CloseCallback closeCallback;
|
||||
private final KeyboardLayout layout;
|
||||
private final boolean newLineSupport;
|
||||
|
||||
private boolean capsMode;
|
||||
private boolean symbolMode;
|
||||
private SpruceTextAreaWidget bufferDisplayArea;
|
||||
private SpruceContainerWidget keyboardContainer;
|
||||
|
||||
public VirtualKeyboardScreen(String initialText, CloseCallback closeCallback, boolean newLineSupport) {
|
||||
super(Text.translatable("midnightcontrols.virtual_keyboard.screen"));
|
||||
this.buffer = new StringBuilder(initialText);
|
||||
this.closeCallback = closeCallback;
|
||||
this.layout = KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout);
|
||||
this.capsMode = false;
|
||||
this.symbolMode = false;
|
||||
this.newLineSupport = newLineSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
this.bufferDisplayArea = createBufferDisplayArea();
|
||||
this.addDrawableChild(this.bufferDisplayArea);
|
||||
|
||||
rebuildKeyboard();
|
||||
|
||||
int doneButtonY = this.keyboardContainer.getY() + this.keyboardContainer.getHeight() + VERTICAL_SPACING * 2;
|
||||
this.addDrawableChild(
|
||||
new SpruceButtonWidget(
|
||||
Position.of(this, this.width / 2 - 50, doneButtonY),
|
||||
100,
|
||||
20,
|
||||
SpruceTexts.GUI_DONE,
|
||||
btn -> this.close()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPause() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
if (this.closeCallback != null) {
|
||||
this.closeCallback.onClose(this.buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildKeyboard() {
|
||||
if (this.keyboardContainer != null) {
|
||||
this.remove(this.keyboardContainer);
|
||||
}
|
||||
|
||||
var layoutKeys = getActiveKeyLayout();
|
||||
var keyboardContainer = createKeyboardContainer(layoutKeys);
|
||||
|
||||
addLayoutRows(keyboardContainer, layoutKeys);
|
||||
addFunctionKeys(keyboardContainer);
|
||||
addBottomRow(keyboardContainer);
|
||||
|
||||
this.keyboardContainer = keyboardContainer;
|
||||
this.addDrawableChild(this.keyboardContainer);
|
||||
}
|
||||
|
||||
private SpruceContainerWidget createKeyboardContainer(List<List<String>> layoutKeys) {
|
||||
int containerWidth = this.width;
|
||||
int totalKeyboardHeight = calculateKeyboardHeight(layoutKeys);
|
||||
int keyboardY = this.bufferDisplayArea.getY() + this.bufferDisplayArea.getHeight() + VERTICAL_SPACING * 2;
|
||||
|
||||
return new SpruceContainerWidget(
|
||||
Position.of(0, keyboardY),
|
||||
containerWidth,
|
||||
totalKeyboardHeight
|
||||
);
|
||||
}
|
||||
|
||||
private SpruceTextAreaWidget createBufferDisplayArea() {
|
||||
int lineCount = this.newLineSupport ? 4 : 1;
|
||||
int bufferX = this.width / 2 - 100;
|
||||
int bufferY = this.height / 4 - VERTICAL_SPACING * 5 - 5;
|
||||
int bufferWidth = 200;
|
||||
int desiredHeight = (this.textRenderer.fontHeight + 2) * lineCount + 6;
|
||||
|
||||
var bufferDisplay = new SpruceTextAreaWidget(
|
||||
Position.of(bufferX, bufferY),
|
||||
bufferWidth,
|
||||
desiredHeight,
|
||||
Text.literal("Buffer Display")
|
||||
);
|
||||
bufferDisplay.setText(this.buffer.toString());
|
||||
bufferDisplay.setEditable(false);
|
||||
bufferDisplay.setUneditableColor(0xFFFFFFFF);
|
||||
bufferDisplay.setDisplayedLines(lineCount);
|
||||
bufferDisplay.setCursorToEnd();
|
||||
|
||||
return bufferDisplay;
|
||||
}
|
||||
|
||||
private int calculateKeyboardHeight(List<List<String>> keyRows) {
|
||||
return keyRows.size() * (KEY_HEIGHT + VERTICAL_SPACING) +
|
||||
(KEY_HEIGHT + VERTICAL_SPACING) + // space for bottom row
|
||||
CONTAINER_PADDING * 2; // top and bottom padding
|
||||
}
|
||||
|
||||
private void addLayoutRows(SpruceContainerWidget container, List<List<String>> keyLayoutRows) {
|
||||
int currentY = CONTAINER_PADDING;
|
||||
|
||||
for (List<String> row : keyLayoutRows) {
|
||||
int rowWidth = calculateRowWidth(row);
|
||||
// center row
|
||||
int currentX = (container.getWidth() - rowWidth) / 2;
|
||||
|
||||
for (String key : row) {
|
||||
String displayText = (this.capsMode && !this.symbolMode) ? key.toUpperCase() : key;
|
||||
container.addChild(
|
||||
new SpruceButtonWidget(
|
||||
Position.of(currentX, currentY),
|
||||
STANDARD_KEY_WIDTH,
|
||||
KEY_HEIGHT,
|
||||
Text.literal(displayText),
|
||||
btn -> handleKeyPress(displayText)
|
||||
)
|
||||
);
|
||||
|
||||
currentX += STANDARD_KEY_WIDTH + HORIZONTAL_SPACING;
|
||||
}
|
||||
|
||||
currentY += KEY_HEIGHT + VERTICAL_SPACING;
|
||||
}
|
||||
}
|
||||
|
||||
private int calculateRowWidth(List<String> row) {
|
||||
int rowWidth = 0;
|
||||
for (int i = 0; i < row.size(); i++) {
|
||||
rowWidth += STANDARD_KEY_WIDTH;
|
||||
// padding
|
||||
if (i < row.size() - 1) {
|
||||
rowWidth += HORIZONTAL_SPACING;
|
||||
}
|
||||
}
|
||||
return rowWidth;
|
||||
}
|
||||
|
||||
private void addFunctionKeys(SpruceContainerWidget container) {
|
||||
List<String> firstRow = getActiveKeyLayout().getFirst();
|
||||
int firstRowWidth = calculateRowWidth(firstRow);
|
||||
|
||||
// position backspace at the right of the first row
|
||||
int backspaceWidth = (int) (STANDARD_KEY_WIDTH * 1.5);
|
||||
int backspaceX = (container.getWidth() + firstRowWidth) / 2 + HORIZONTAL_SPACING;
|
||||
|
||||
container.addChild(
|
||||
new SpruceButtonWidget(
|
||||
Position.of(backspaceX, CONTAINER_PADDING),
|
||||
backspaceWidth,
|
||||
KEY_HEIGHT,
|
||||
Text.literal("←"),
|
||||
btn -> handleKeyPress(BACKSPACE_SYMBOL)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
if (this.newLineSupport) {
|
||||
// position newline at the right of the second row
|
||||
List<String> secondRow = getActiveKeyLayout().get(1);
|
||||
int newlineWidth = (int) (STANDARD_KEY_WIDTH * 1.5);
|
||||
int secondRowWidth = calculateRowWidth(secondRow);
|
||||
int newlineX = (container.getWidth() + secondRowWidth) / 2 + HORIZONTAL_SPACING;
|
||||
int newlineY = CONTAINER_PADDING + (KEY_HEIGHT + VERTICAL_SPACING);
|
||||
|
||||
container.addChild(
|
||||
new SpruceButtonWidget(
|
||||
Position.of(newlineX, newlineY),
|
||||
newlineWidth,
|
||||
KEY_HEIGHT,
|
||||
Text.literal("⏎"),
|
||||
btn -> handleKeyPress(NEWLINE_SYMBOL)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void addBottomRow(SpruceContainerWidget container) {
|
||||
// calculate positions for bottom row
|
||||
int rowY = CONTAINER_PADDING + getActiveKeyLayout().size() * (KEY_HEIGHT + VERTICAL_SPACING);
|
||||
|
||||
// space bar - wide key in the middle
|
||||
double spaceWidthFactor = 5.0;
|
||||
int spaceKeyWidth = (int) (STANDARD_KEY_WIDTH * spaceWidthFactor);
|
||||
int spaceX = (container.getWidth() - spaceKeyWidth) / 2;
|
||||
|
||||
container.addChild(
|
||||
new SpruceButtonWidget(
|
||||
Position.of(spaceX, rowY),
|
||||
spaceKeyWidth,
|
||||
KEY_HEIGHT,
|
||||
Text.translatable("midnightcontrols.virtual_keyboard.keyboard.space"),
|
||||
btn -> handleKeyPress(SPACE_SYMBOL)
|
||||
)
|
||||
);
|
||||
|
||||
// caps key - left of space
|
||||
if (!this.symbolMode) {
|
||||
int capsX = spaceX - SPECIAL_KEY_WIDTH - HORIZONTAL_SPACING * 2;
|
||||
var capsModeButton = new SpruceButtonWidget(
|
||||
Position.of(capsX, rowY),
|
||||
SPECIAL_KEY_WIDTH,
|
||||
KEY_HEIGHT,
|
||||
Text.literal(this.capsMode ? "caps" : "CAPS"),
|
||||
btn -> toggleCapsMode());
|
||||
|
||||
container.addChild(capsModeButton);
|
||||
}
|
||||
|
||||
// symbols key - right of space
|
||||
int symbolsX = spaceX + spaceKeyWidth + HORIZONTAL_SPACING * 2;
|
||||
var symbolModeButton = new SpruceButtonWidget(
|
||||
Position.of(symbolsX, rowY),
|
||||
SPECIAL_KEY_WIDTH,
|
||||
KEY_HEIGHT,
|
||||
Text.literal(this.symbolMode ? "ABC" : "123?!"),
|
||||
btn -> toggleSymbolMode()
|
||||
);
|
||||
container.addChild(symbolModeButton);
|
||||
}
|
||||
|
||||
private void handleKeyPress(String key) {
|
||||
if (key.equals(BACKSPACE_SYMBOL)) {
|
||||
if (!this.buffer.isEmpty()) {
|
||||
this.buffer.deleteCharAt(buffer.length() - 1);
|
||||
}
|
||||
} else {
|
||||
this.buffer.append(key);
|
||||
}
|
||||
|
||||
if (this.bufferDisplayArea != null) {
|
||||
this.bufferDisplayArea.setText(this.buffer.toString());
|
||||
this.bufferDisplayArea.setCursorToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private List<List<String>> getActiveKeyLayout() {
|
||||
return this.symbolMode ? this.layout.getSymbols() : this.layout.getLetters();
|
||||
}
|
||||
|
||||
private void toggleCapsMode() {
|
||||
this.capsMode = !this.capsMode;
|
||||
rebuildKeyboard();
|
||||
}
|
||||
|
||||
private void toggleSymbolMode() {
|
||||
this.symbolMode = !this.symbolMode;
|
||||
rebuildKeyboard();
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record ControlsModePayload(String controlsMode) implements CustomPayload {
|
||||
public static final Id<ControlsModePayload> PACKET_ID = new Id<>(MidnightControlsConstants.CONTROLS_MODE_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, ControlsModePayload> codec = PacketCodec.of(ControlsModePayload::write, ControlsModePayload::read);
|
||||
|
||||
public static ControlsModePayload read(RegistryByteBuf buf) {
|
||||
return new ControlsModePayload(buf.readString(32));
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
||||
buf.writeString(controlsMode, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
public record FeaturePayload(MidnightControlsFeature... features) implements CustomPayload {
|
||||
public static final Id<FeaturePayload> PACKET_ID = new Id<>(MidnightControlsConstants.FEATURE_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, FeaturePayload> codec = PacketCodec.of(FeaturePayload::write, FeaturePayload::read);
|
||||
|
||||
public static FeaturePayload read(RegistryByteBuf buf) {
|
||||
int featureLength = buf.readVarInt();
|
||||
MidnightControlsFeature[] receivedFeatures = new MidnightControlsFeature[featureLength];
|
||||
for (int i = 0; i < featureLength; i++) {
|
||||
var name = buf.readString(64);
|
||||
boolean allowed = buf.readBoolean();
|
||||
var feature = MidnightControlsFeature.fromName(name);
|
||||
if (feature.isPresent()) {
|
||||
feature.get().setAllowed(allowed);
|
||||
receivedFeatures[i] = feature.get();
|
||||
}
|
||||
}
|
||||
return new FeaturePayload(receivedFeatures);
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
if (features.length == 0)
|
||||
throw new IllegalArgumentException("At least one feature must be provided.");
|
||||
|
||||
buf.writeVarInt(features.length);
|
||||
for (var feature : features) {
|
||||
buf.writeString(feature.getName(), 64);
|
||||
buf.writeBoolean(feature.isAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
public record HelloPayload(String version, String controlsMode) implements CustomPayload {
|
||||
public static final CustomPayload.Id<HelloPayload> PACKET_ID = new CustomPayload.Id<>(MidnightControlsConstants.HELLO_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, HelloPayload> codec = PacketCodec.of(HelloPayload::write, HelloPayload::read);
|
||||
|
||||
public static HelloPayload read(RegistryByteBuf buf) {
|
||||
return new HelloPayload(buf.readString(32), buf.readString(32));
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
buf.writeString(version, 32).writeString(controlsMode, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"accessWidener": "midnightcontrols.accesswidener"
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"id": "de_DE:qwertz",
|
||||
|
||||
"letters": {
|
||||
"row0": ["q", "w", "e", "r", "t", "z", "u", "i", "o", "p", "ü"],
|
||||
"row1": ["a", "s", "d", "f", "g", "h", "j", "k", "l", "ö", "ä"],
|
||||
"row2": ["y", "x", "c", "v", "b", "n", "m", "ß"]
|
||||
},
|
||||
"symbols": {
|
||||
"row0": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
|
||||
"row1": ["@", "#", "$", "%", "&", "*", "-", "+", "(", ")"],
|
||||
"row2": ["!", "\"", "'", ":", ";", ",", ".", "?", "/"]
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"id": "en_US:qwerty",
|
||||
|
||||
"letters": {
|
||||
"row0": ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
|
||||
"row1": ["a", "s", "d", "f", "g", "h", "j", "k", "l"],
|
||||
"row2": ["z", "x", "c", "v", "b", "n", "m"]
|
||||
},
|
||||
"symbols": {
|
||||
"row0": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
|
||||
"row1": ["@", "#", "$", "%", "&", "*", "-", "+", "(", ")"],
|
||||
"row2": ["!", "\"", "'", ":", ";", ",", ".", "?", "/"]
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
{
|
||||
"midnightcontrols.midnightconfig.title": "Pokročilá konfigurace MidnightControls",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "Výchozí světlá",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "Výchozí tmavá",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "Druhá světlá",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_DARK": "Druhá tmavá",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DEFAULT": "Výchozí",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSHOCK": "DualShock",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSENSE": "DualSense",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.SWITCH": "Switch/Wii ovladač",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX": "Xbox One/Series ovladač",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX_360": "Xbox 360 Controller",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_CONTROLLER": "Steam Controller",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_DECK": "Steam Deck",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.OUYA": "OUYA ovladač",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Ovladač s číslicemi",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Klávesnice/Myš",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "Ovladač",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "Dotyk (Beta)",
|
||||
"midnightcontrols.midnightconfig.enum.HudSide.LEFT": "Levá",
|
||||
"midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "Pravá",
|
||||
"midnightcontrols.midnightconfig.enum.TouchMode.CROSSHAIR": "Crosshair režim",
|
||||
"midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Pozice prstu",
|
||||
"midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Plochá",
|
||||
"midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptivní",
|
||||
"key.categories.midnightcontrols": "MidnightControls",
|
||||
"key.midnightcontrols.look_down": "Podívat se dolů",
|
||||
"key.midnightcontrols.look_left": "Podívat se doleva",
|
||||
"key.midnightcontrols.look_right": "Podívat se doprava",
|
||||
"key.midnightcontrols.look_up": "Podívat se nahoru",
|
||||
"key.midnightcontrols.ring": "Otevřít ovládací kroužek",
|
||||
"midnightcontrols.action.attack": "Útok",
|
||||
"midnightcontrols.action.back": "Zpět",
|
||||
"midnightcontrols.action.chat": "Otevřít chat",
|
||||
"midnightcontrols.action.controls_ring": "Otevřít ovládací kroužek",
|
||||
"midnightcontrols.action.debug_screen": "Otevřít debugovací HUD (F3)",
|
||||
"midnightcontrols.action.drop_item": "Odhodit věc",
|
||||
"midnightcontrols.action.drink": "Napít se",
|
||||
"midnightcontrols.action.eat": "Najíst se",
|
||||
"midnightcontrols.action.equip": "Vybavit se",
|
||||
"midnightcontrols.action.exit": "Ukončit",
|
||||
"midnightcontrols.action.forward": "Dopředu",
|
||||
"midnightcontrols.action.hit": "Útok",
|
||||
"midnightcontrols.action.hotbar_left": "Hotbar doleva",
|
||||
"midnightcontrols.action.hotbar_right": "Hotbar doprava",
|
||||
"midnightcontrols.action.inventory": "Inventář",
|
||||
"midnightcontrols.action.jump": "Skok",
|
||||
"midnightcontrols.action.left": "Doleva",
|
||||
"midnightcontrols.action.pause_game": "Pozastavit hru",
|
||||
"midnightcontrols.action.pick_block": "Vybrat blok",
|
||||
"midnightcontrols.action.pickup": "Vzít",
|
||||
"midnightcontrols.action.pickup_all": "Vzít vše",
|
||||
"midnightcontrols.action.place": "Položit",
|
||||
"midnightcontrols.action.player_list": "Seznam hráčů",
|
||||
"midnightcontrols.action.quick_move": "Rychlý přesun",
|
||||
"midnightcontrols.action.right": "Doprava",
|
||||
"midnightcontrols.action.screenshot": "Vyfotit snímek obrazovky",
|
||||
"midnightcontrols.action.slot_up": "Přesunout slot nahoru",
|
||||
"midnightcontrols.action.slot_down": "Přesunout slot dolů",
|
||||
"midnightcontrols.action.slot_left": "Přesunout slot doleva",
|
||||
"midnightcontrols.action.slot_right": "Přesunout slot doprava",
|
||||
"midnightcontrols.action.sneak": "Plížit se",
|
||||
"midnightcontrols.action.sprint": "Sprintovat",
|
||||
"midnightcontrols.action.swap_hands": "Vyměnit si ruce",
|
||||
"midnightcontrols.action.toggle_perspective": "Změnit perspektivu",
|
||||
"midnightcontrols.action.toggle_smooth_camera": "Nastavit kinematografickou kameru",
|
||||
"midnightcontrols.action.page_back": "Předchozí stránka",
|
||||
"midnightcontrols.action.page_next": "Následující stránka",
|
||||
"midnightcontrols.action.tab_back": "Předchozí karta",
|
||||
"midnightcontrols.action.tab_next": "Následující karta",
|
||||
"midnightcontrols.action.take": "Vzít věc",
|
||||
"midnightcontrols.action.take_all": "Vzít stack",
|
||||
"midnightcontrols.action.use": "Použít",
|
||||
"midnightcontrols.action.zoom": "Přiblížit",
|
||||
"midnightcontrols.action.zoom_in": "Zvýšit přiblížení",
|
||||
"midnightcontrols.action.zoom_out": "Snížit příblížení",
|
||||
"midnightcontrols.action.zoom_reset": "Resetovat Přiblížení",
|
||||
"midnightcontrols.action.emi_page_left": "Předchozí stránka",
|
||||
"midnightcontrols.action.emi_page_right": "Následující stránka",
|
||||
"midnightcontrols.category.emi": "EMI",
|
||||
"midnightcontrols.button.a": "A",
|
||||
"midnightcontrols.button.b": "B",
|
||||
"midnightcontrols.button.x": "X",
|
||||
"midnightcontrols.button.y": "Y",
|
||||
"midnightcontrols.button.left_bumper": "Levý bumper",
|
||||
"midnightcontrols.button.right_bumper": "Pravý bumper",
|
||||
"midnightcontrols.button.back": "Zpět",
|
||||
"midnightcontrols.button.start": "Start",
|
||||
"midnightcontrols.button.guide": "Guide",
|
||||
"midnightcontrols.button.left_thumb": "Levá páčka",
|
||||
"midnightcontrols.button.right_thumb": "Pravá páčka",
|
||||
"midnightcontrols.button.dpad_up": "DPAD nahoru",
|
||||
"midnightcontrols.button.dpad_right": "DPAD doprava",
|
||||
"midnightcontrols.button.dpad_down": "DPAD dolů",
|
||||
"midnightcontrols.button.dpad_left": "DPAD doleva",
|
||||
"midnightcontrols.button.l4": "L4",
|
||||
"midnightcontrols.button.l5": "L5",
|
||||
"midnightcontrols.button.r4": "R4",
|
||||
"midnightcontrols.button.r5": "L5",
|
||||
"midnightcontrols.axis.left_x+": "Levý X+",
|
||||
"midnightcontrols.axis.left_y+": "Levý Y+",
|
||||
"midnightcontrols.axis.right_x+": "Pravý X+",
|
||||
"midnightcontrols.axis.right_y+": "Pravý Y+",
|
||||
"midnightcontrols.axis.left_trigger": "Levý trigger",
|
||||
"midnightcontrols.axis.right_trigger": "Pravý trigger",
|
||||
"midnightcontrols.axis.left_x-": "Levý X-",
|
||||
"midnightcontrols.axis.left_y-": "Levý Y-",
|
||||
"midnightcontrols.axis.right_x-": "Pravý X-",
|
||||
"midnightcontrols.axis.right_y-": "Pravý Y-",
|
||||
"midnightcontrols.button.unknown": "Neznámý (%d)",
|
||||
"midnightcontrols.controller.tutorial.title": "Hrajte hru s ovladačem!",
|
||||
"midnightcontrols.controller.tutorial.description": "jděte do %s -> %s -> %s",
|
||||
"midnightcontrols.controller.connected": "Ovladač %d připojen.",
|
||||
"midnightcontrols.controller.disconnected": "Ovladač %d odpojen.",
|
||||
"midnightcontrols.controller.mappings.1": "Chcete-li nakonfigurovat mapování ovladače, použijte %s",
|
||||
"midnightcontrols.controller.mappings.3": "a vložte mapování do editoru souboru mapování.",
|
||||
"midnightcontrols.controller.mappings.error": "Chyba při načítání mapování.",
|
||||
"midnightcontrols.controller.mappings.error.write": "Chyba při zápisu mapování do souboru.",
|
||||
"midnightcontrols.controller.mappings.updated": "Aktualizované mapování!",
|
||||
"midnightcontrols.controller_type.default": "Výchozí",
|
||||
"midnightcontrols.controller_type.dualshock": "DualShock",
|
||||
"midnightcontrols.controller_type.dualsense": "DualSense",
|
||||
"midnightcontrols.controller_type.switch": "Switch/Wii ovladač",
|
||||
"midnightcontrols.controller_type.xbox": "Xbox One/Series ovladač",
|
||||
"midnightcontrols.controller_type.xbox_360": "Xbox 360 ovladač",
|
||||
"midnightcontrols.controller_type.steam_controller": "Steam ovladač",
|
||||
"midnightcontrols.controller_type.steam_deck": "Steam Deck",
|
||||
"midnightcontrols.controller_type.ouya": "OUYA ovladač",
|
||||
"midnightcontrols.controller_type.numbered": "Ovladač s číslicemi",
|
||||
"midnightcontrols.controls_mode.default": "Klávesnice/Myš",
|
||||
"midnightcontrols.controls_mode.controller": "Ovladač",
|
||||
"midnightcontrols.controls_mode.touchscreen": "Dotyk (Beta)",
|
||||
"midnightcontrols.hud_side.LEFT": "Levý",
|
||||
"midnightcontrols.hud_side.RIGHT": "Pravý",
|
||||
"midnightcontrols.menu.analog_movement": "Analogový pohyb",
|
||||
"midnightcontrols.menu.analog_movement.tooltip": "Pokud je to možné, umožňuje analogový pohyb.",
|
||||
"midnightcontrols.menu.auto_switch_mode": "Režim automatického přepínání",
|
||||
"midnightcontrols.menu.auto_switch_mode.tooltip": "Zda se má režim ovládání automaticky přepnout na ovladač, pokud je připojen.",
|
||||
"midnightcontrols.menu.camera_mode": "Režim kamery",
|
||||
"midnightcontrols.menu.controller": "Ovladač",
|
||||
"midnightcontrols.menu.controller2": "Druhý ovladač",
|
||||
"midnightcontrols.menu.controller2.tooltip": "Použije druhý ovladač, který umožňuje (například) podporu Joy-Conů.",
|
||||
"midnightcontrols.menu.controller_toggle_sneak": "Přepnutí plížení na ovladači",
|
||||
"midnightcontrols.menu.controller_toggle_sprint": "Přepnutí sprintování na ovladačí",
|
||||
"midnightcontrols.menu.controller_type": "Typ ovladače",
|
||||
"midnightcontrols.menu.controller_type.tooltip": "Typ používaného ovladače (potřebné pro zobrazení správných tlačítek).",
|
||||
"midnightcontrols.menu.controls_mode": "Režim",
|
||||
"midnightcontrols.menu.controls_mode.tooltip": "Režim ovládání.",
|
||||
"midnightcontrols.menu.copy_controller_guid": "Zkopírovat GUID",
|
||||
"midnightcontrols.menu.current_controller_guid": "GUID aktuálního ovladače: %s",
|
||||
"midnightcontrols.menu.double_tap_to_sprint": "Dvojité klepnutí na sprintování",
|
||||
"midnightcontrols.menu.double_tap_to_sprint.tooltip": "Přepíná, zda klávesa chůze vpřed při dvojitém rychlém poklepání umožní hráči sprintovat.",
|
||||
"midnightcontrols.menu.fast_block_placing": "Rychlé pokládání bloků",
|
||||
"midnightcontrols.menu.fast_block_placing.tooltip": "Při letu v kreativním režimu umožňuje rychlé pokládání bloků v závislosti na vaší rychlosti. §cNa některých serverech to může být považováno za podvádění§r.",
|
||||
"midnightcontrols.menu.fly_drifting": "Fly Drifting",
|
||||
"midnightcontrols.menu.fly_drifting.tooltip": "Za letu umožňuje Vanilla driftování/setrvačnost.",
|
||||
"midnightcontrols.menu.fly_drifting_vertical": "Vertikální Fly Drifting",
|
||||
"midnightcontrols.menu.fly_drifting_vertical.tooltip": "Za letu umožňuje Vanilla vertikální driftování/setrvačnost.",
|
||||
"midnightcontrols.menu.hud_enable": "Zapnout HUD",
|
||||
"midnightcontrols.menu.hud_enable.tooltip": "Přepíná indikátor tlačítek ovladače na obrazovce.",
|
||||
"midnightcontrols.menu.hud_side": "Strana HUD",
|
||||
"midnightcontrols.menu.hud_side.tooltip": "Pozice HUD.",
|
||||
"midnightcontrols.menu.invert_right_x_axis": "Invertovat pravý X",
|
||||
"midnightcontrols.menu.invert_right_y_axis": "Invertovat pravý Y",
|
||||
"midnightcontrols.menu.joystick_as_mouse": "Vždy použít levou páčku jako myš",
|
||||
"midnightcontrols.menu.joystick_as_mouse.tooltip": "V každém menu se páčka chová jako myš.",
|
||||
"midnightcontrols.menu.eye_tracker_as_mouse": "Použití eye trackeru jako myši"
|
||||
"midnightcontrols.menu.eye_tracker_as_mouse.tooltip": "Nahraďte myš zařízením pro sledování očí (například Tobii 5).",
|
||||
"midnightcontrols.menu.eye_tracker_deadzone": "Velikost mrtvé zóny eye trackeru",
|
||||
"midnightcontrols.menu.eye_tracker_deadzone.tooltip": "Zastaví pohyb kamery při pohledu do blízkosti crosshair",
|
||||
"midnightcontrols.menu.keyboard_controls": "Ovládání klávesnice...",
|
||||
"midnightcontrols.menu.left_dead_zone": "Mrtvá zóna levé páčky",
|
||||
"midnightcontrols.menu.left_dead_zone.tooltip": "Mrtvá zóna levé analogové páčky ovladače.",
|
||||
"midnightcontrols.menu.mappings.open_input_str": "Otevřít editor souborů mapování",
|
||||
"midnightcontrols.menu.max_left_x_value": "Maximální hodnota levé osy X",
|
||||
"midnightcontrols.menu.max_left_x_value.tooltip": "Změní hodnotu, kterou mod považuje za nejvyšší pro levou osu X. Užitečné, pokud osa nevyužívá celý rozsah a zdá se pomalá.",
|
||||
"midnightcontrols.menu.max_left_y_value": "Maximální hodnota levé osy Y",
|
||||
"midnightcontrols.menu.max_left_y_value.tooltip": "Změní hodnotu, kterou mod považuje za nejvyšší pro levou osu Y. Užitečné, pokud osa nevyužívá celý rozsah a zdá se pomalá.",
|
||||
"midnightcontrols.menu.max_right_x_value": "Maximální hodnota pravé osy X",
|
||||
"midnightcontrols.menu.max_right_x_value.tooltip": "Změní hodnotu, kterou mod považuje za nejvyšší pro pravou osu X. Užitečné, pokud osa nevyužívá celý rozsah a zdá se pomalá.",
|
||||
"midnightcontrols.menu.max_right_y_value": "Maximální hodnota pravé osy Y",
|
||||
"midnightcontrols.menu.max_right_y_value.tooltip": "Změní hodnotu, kterou mod považuje za nejvyšší pro pravou osu Y. Užitečné, pokud osa nevyužívá celý rozsah a zdá se pomalá.",
|
||||
"midnightcontrols.menu.mouse_speed": "Rychlost myši",
|
||||
"midnightcontrols.menu.mouse_speed.tooltip": "Rychlost emulované myši ovladače.",
|
||||
"midnightcontrols.menu.move_chat": "Přesunutí vstupního pole chatu nahoru",
|
||||
"midnightcontrols.menu.move_chat.tooltip": "Přesune pole pro zadávání chatu nahoru, aby se lépe zadávalo na zařízeních s klávesnicí na obrazovce.",
|
||||
"midnightcontrols.menu.multiple_mapping_tip": "(Tip: Můžete také vložit více mapování najednou.)",
|
||||
"midnightcontrols.menu.reacharound.horizontal": "Pokládání předního bloku",
|
||||
"midnightcontrols.menu.reacharound.horizontal.tooltip": "Umožňuje umístění předního bloku, §ccož může být na některých serverech považováno za podvod.§r",
|
||||
"midnightcontrols.menu.reacharound.vertical": "Vertikální dosah",
|
||||
"midnightcontrols.menu.reacharound.vertical.tooltip": "Zapiná vertikální dosah, §ccož může být na některých serverech považováno za podvod.§r",
|
||||
"midnightcontrols.menu.reload_controller_mappings": "Opětovné načíst mapování ovladače",
|
||||
"midnightcontrols.menu.reload_controller_mappings.tooltip": "Znovu načte soubor mapování ovladače.",
|
||||
"midnightcontrols.menu.right_dead_zone": "Mrtvá zóna pravé páčky",
|
||||
"midnightcontrols.menu.right_dead_zone.tooltip": "Mrtvá zóna pravé analogové páčky ovladače.",
|
||||
"midnightcontrols.menu.rotation_speed": "Rychlost otáčení osy X",
|
||||
"midnightcontrols.menu.rotation_speed.tooltip": "Rychlost otáčení osy X v režimu ovladače.",
|
||||
"midnightcontrols.menu.y_axis_rotation_speed": "Rychlost otáčení osy Y",
|
||||
"midnightcontrols.menu.y_axis_rotation_speed.tooltip": "Rychlost otáčení osy Y v režimu ovladače.",
|
||||
"midnightcontrols.menu.separate_controller_profile": "Samostatný profil ovladače",
|
||||
"midnightcontrols.menu.separator.controller": "Ovladač",
|
||||
"midnightcontrols.menu.separator.general": "Obecné",
|
||||
"midnightcontrols.menu.title": "MidnightControls - Nastavení",
|
||||
"midnightcontrols.menu.title.controller": "Nastavení ovladače",
|
||||
"midnightcontrols.menu.title.controller_controls": "Vazby ovladače",
|
||||
"midnightcontrols.menu.title.gameplay": "Herní možnosti",
|
||||
"midnightcontrols.menu.title.general": "Obecné možnosti",
|
||||
"midnightcontrols.menu.title.hud": "Možnosti HUD",
|
||||
"midnightcontrols.menu.title.mappings.string": "Editor souborů mapování",
|
||||
"midnightcontrols.menu.title.touch": "Možnosti dotyku",
|
||||
"midnightcontrols.menu.title.visual": "Možnosti vzhledu",
|
||||
"midnightcontrols.menu.touch_break_delay": "Zpoždění přerušení dotyku",
|
||||
"midnightcontrols.menu.touch_speed": "Rychlost dotyku",
|
||||
"midnightcontrols.menu.invert_touch": "Invertování směru dotyku",
|
||||
"midnightcontrols.menu.touch_mode": "Režim dotykové interakce",
|
||||
"midnightcontrols.menu.touch_transparency": "Průhlednost dotykového HUD",
|
||||
"midnightcontrols.menu.touch_with_controller": "Dotyk v režimu ovladače",
|
||||
"midnightcontrols.menu.unfocused_input": "Nezaostřený vstup",
|
||||
"midnightcontrols.menu.unfocused_input.tooltip": "Umožňuje vstup do ovladače, když okno není zaostřené.",
|
||||
"midnightcontrols.menu.virtual_mouse": "Virtuální myš",
|
||||
"midnightcontrols.menu.virtual_mouse.tooltip": "Povoluje virtuální myš, která je užitečná při rozdělené obrazovce.",
|
||||
"midnightcontrols.menu.virtual_mouse.skin": "Skin virtuální myši",
|
||||
"midnightcontrols.menu.hide_cursor": "Skrytí normálního kurzoru myši",
|
||||
"midnightcontrols.menu.hide_cursor.tooltip": "Skryje normální kurzor myši a ponechá viditelný pouze virtuální kurzor myši.",
|
||||
"midnightcontrols.narrator.unbound": "Zrušení vazby na tlačítko %s",
|
||||
"midnightcontrols.not_bound": "Není vázano",
|
||||
"midnightcontrols.virtual_mouse.skin.default_light": "Výchozí světlá",
|
||||
"midnightcontrols.virtual_mouse.skin.default_dark": "Výchozí tmavá",
|
||||
"midnightcontrols.virtual_mouse.skin.second_light": "Druhá světlá",
|
||||
"midnightcontrols.virtual_mouse.skin.second_dark": "Druhá tmavá",
|
||||
"midnightcontrols.midnightconfig.category.controller": "Ovladač",
|
||||
"midnightcontrols.midnightconfig.category.misc": "Různé",
|
||||
"midnightcontrols.midnightconfig.category.screens": "Obrazovky",
|
||||
"midnightcontrols.midnightconfig.category.gameplay": "Hra",
|
||||
"midnightcontrols.midnightconfig.category.touch": "Dotyk",
|
||||
"midnightcontrols.midnightconfig.category.visual": "Vizuál",
|
||||
"modmenu.descriptionTranslation.midnightcontrols": "Přidává podporu ovladačů a celkově vylepšuje ovládání.\nPřevzato z LambdaControls, jehož vývoj byl ukončen."
|
||||
}
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
{
|
||||
"midnightcontrols.midnightconfig.title": "Configurações avançadas do MidnightControls",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "Padrão claro",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "Padrão escuro",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "Segundo claro",
|
||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_DARK": "Segundo escuro",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DEFAULT": "Padrão",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSHOCK": "DualShock",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSENSE": "DualSense",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.SWITCH": "Controle de Switch/Wii",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX": "Controle de Xbox One/Series",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX_360": "Controle de Xbox 360",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_CONTROLLER": "Controle da Steam",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_DECK": "Steam Deck",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.OUYA": "Controle de OUYA",
|
||||
"midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Controle númerado",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Teclado/Mouse",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "Controle",
|
||||
"midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "Tela sensível ao toque (Beta)",
|
||||
"midnightcontrols.midnightconfig.enum.HudSide.LEFT": "Esquerda",
|
||||
"midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "Direita",
|
||||
"midnightcontrols.midnightconfig.enum.TouchMode.CROSSHAIR": "Na mira",
|
||||
"midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Posição do dedo",
|
||||
"midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Plano",
|
||||
"midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptativo",
|
||||
"key.categories.midnightcontrols": "MidnightControls",
|
||||
"key.midnightcontrols.look_down": "Olhar para baixo",
|
||||
"key.midnightcontrols.look_left": "Olhar para a esquerda",
|
||||
"key.midnightcontrols.look_right": "Olhar para a direita",
|
||||
"key.midnightcontrols.look_up": "Olhar para cima",
|
||||
"key.midnightcontrols.ring": "Abrir anel de teclas não vinculadas",
|
||||
"midnightcontrols.action.attack": "Atacar",
|
||||
"midnightcontrols.action.back": "Voltar",
|
||||
"midnightcontrols.action.chat": "Abrir bate-papo",
|
||||
"midnightcontrols.action.controls_ring": "Abrir anel de teclas não vinculadas",
|
||||
"midnightcontrols.action.debug_screen": "Abrir HUD de depuração (F3)",
|
||||
"midnightcontrols.action.drop_item": "Soltar item",
|
||||
"midnightcontrols.action.drink": "Beber",
|
||||
"midnightcontrols.action.eat": "Comer",
|
||||
"midnightcontrols.action.equip": "Equipar",
|
||||
"midnightcontrols.action.exit": "Sair da tela",
|
||||
"midnightcontrols.action.forward": "Para frente",
|
||||
"midnightcontrols.action.hit": "Atacar",
|
||||
"midnightcontrols.action.hotbar_left": "Move a barra rápida para esquerda",
|
||||
"midnightcontrols.action.hotbar_right": "Move a barra rápida para direita",
|
||||
"midnightcontrols.action.inventory": "Invetário",
|
||||
"midnightcontrols.action.jump": "Pular",
|
||||
"midnightcontrols.action.left": "Esquerda",
|
||||
"midnightcontrols.action.pause_game": "Pausar",
|
||||
"midnightcontrols.action.pick_block": "Pegar bloco",
|
||||
"midnightcontrols.action.pickup": "Pegar",
|
||||
"midnightcontrols.action.pickup_all": "Pegar todos",
|
||||
"midnightcontrols.action.place": "Colocar",
|
||||
"midnightcontrols.action.player_list": "Lista de jogadores",
|
||||
"midnightcontrols.action.quick_move": "Mover rápido",
|
||||
"midnightcontrols.action.right": "Direita",
|
||||
"midnightcontrols.action.screenshot": "Tirar Screenshot",
|
||||
"midnightcontrols.action.slot_up": "Mover Slot para cima",
|
||||
"midnightcontrols.action.slot_down": "Mover Slot para baixo",
|
||||
"midnightcontrols.action.slot_left": "Mover Slot para esquerda",
|
||||
"midnightcontrols.action.slot_right": "Mover Slot para direita",
|
||||
"midnightcontrols.action.sneak": "Esgueirar",
|
||||
"midnightcontrols.action.sprint": "Correr",
|
||||
"midnightcontrols.action.swap_hands": "Trocar de mãos",
|
||||
"midnightcontrols.action.toggle_perspective": "Alternar perspectiva",
|
||||
"midnightcontrols.action.toggle_smooth_camera": "Ativar câmera cinemática",
|
||||
"midnightcontrols.action.page_back": "Página anterior",
|
||||
"midnightcontrols.action.page_next": "Próxima página",
|
||||
"midnightcontrols.action.tab_back": "Aba anterior",
|
||||
"midnightcontrols.action.tab_next": "Próxima aba",
|
||||
"midnightcontrols.action.take": "Pegar item",
|
||||
"midnightcontrols.action.take_all": "Pegar pilha",
|
||||
"midnightcontrols.action.use": "Usar",
|
||||
"midnightcontrols.action.zoom": "Zoom",
|
||||
"midnightcontrols.action.zoom_in": "Aumentar o Zoom",
|
||||
"midnightcontrols.action.zoom_out": "Diminuir o Zoom",
|
||||
"midnightcontrols.action.zoom_reset": "Resetar o Zoom",
|
||||
"midnightcontrols.action.emi_page_left": "Página anterior",
|
||||
"midnightcontrols.action.emi_page_right": "Próxima pickup",
|
||||
"midnightcontrols.category.emi": "EMI",
|
||||
"midnightcontrols.button.a": "A",
|
||||
"midnightcontrols.button.b": "B",
|
||||
"midnightcontrols.button.x": "X",
|
||||
"midnightcontrols.button.y": "Y",
|
||||
"midnightcontrols.button.left_bumper": "Botão L1",
|
||||
"midnightcontrols.button.right_bumper": "Botão R1",
|
||||
"midnightcontrols.button.back": "Voltar",
|
||||
"midnightcontrols.button.start": "Começar",
|
||||
"midnightcontrols.button.guide": "Guia",
|
||||
"midnightcontrols.button.left_thumb": "Analógico esquerdo",
|
||||
"midnightcontrols.button.right_thumb": "Analógico direito",
|
||||
"midnightcontrols.button.dpad_up": "Botão direcional para cima",
|
||||
"midnightcontrols.button.dpad_right": "Botão direcional para direita",
|
||||
"midnightcontrols.button.dpad_down": "Botão direcional para baixo",
|
||||
"midnightcontrols.button.dpad_left": "Botão direcional para esquerda",
|
||||
"midnightcontrols.button.l4": "L4",
|
||||
"midnightcontrols.button.l5": "L5",
|
||||
"midnightcontrols.button.r4": "R4",
|
||||
"midnightcontrols.button.r5": "L5",
|
||||
"midnightcontrols.axis.left_x+": "Esquerda X+",
|
||||
"midnightcontrols.axis.left_y+": "Esquerda Y+",
|
||||
"midnightcontrols.axis.right_x+": "Direita X+",
|
||||
"midnightcontrols.axis.right_y+": "Direita Y+",
|
||||
"midnightcontrols.axis.left_trigger": "Gatilho da esquerda",
|
||||
"midnightcontrols.axis.right_trigger": "Gatilho da direita",
|
||||
"midnightcontrols.axis.left_x-": "Esquerda X-",
|
||||
"midnightcontrols.axis.left_y-": "Esquerda Y-",
|
||||
"midnightcontrols.axis.right_x-": "Direita X-",
|
||||
"midnightcontrols.axis.right_y-": "Direita Y-",
|
||||
"midnightcontrols.button.unknown": "Desconhecido (%d)",
|
||||
"midnightcontrols.controller.tutorial.title": "Jogue o jogo com um controle!",
|
||||
"midnightcontrols.controller.tutorial.description": "Vá para %s -> %s -> %s",
|
||||
"midnightcontrols.controller.connected": "Controle %d conectado.",
|
||||
"midnightcontrols.controller.disconnected": "Controle %d desconectado.",
|
||||
"midnightcontrols.controller.mappings.1": "Para configurar o mapeamento do controle, por favor use %s",
|
||||
"midnightcontrols.controller.mappings.3": "e cole o mapeamento no editor de arquivos do mapeamento.",
|
||||
"midnightcontrols.controller.mappings.error": "Erro ao carregar mapeamentos.",
|
||||
"midnightcontrols.controller.mappings.error.write": "Erro ao gravar mapeamentos no arquivo.",
|
||||
"midnightcontrols.controller.mappings.updated": "Atualizando mapeamentos!",
|
||||
"midnightcontrols.controller_type.default": "Padrão",
|
||||
"midnightcontrols.controller_type.dualshock": "DualShock",
|
||||
"midnightcontrols.controller_type.dualsense": "DualSense",
|
||||
"midnightcontrols.controller_type.switch": "Controle de Switch/Wii",
|
||||
"midnightcontrols.controller_type.xbox": "Controle de Xbox One/Series",
|
||||
"midnightcontrols.controller_type.xbox_360": "Controle de Xbox 360",
|
||||
"midnightcontrols.controller_type.steam_controller": "Controle da Steam",
|
||||
"midnightcontrols.controller_type.steam_deck": "Steam Deck",
|
||||
"midnightcontrols.controller_type.ouya": "Controle de OUYA",
|
||||
"midnightcontrols.controller_type.numbered": "Controle númerado",
|
||||
"midnightcontrols.controls_mode.default": "Teclado/Mouse",
|
||||
"midnightcontrols.controls_mode.controller": "Controle",
|
||||
"midnightcontrols.controls_mode.touchscreen": "Tela sensível ao toque (Beta)",
|
||||
"midnightcontrols.hud_side.LEFT": "Esquerda",
|
||||
"midnightcontrols.hud_side.RIGHT": "Direita",
|
||||
"midnightcontrols.menu.analog_movement": "Movemento analógico",
|
||||
"midnightcontrols.menu.analog_movement.tooltip": "Quando possível, ative o movemento analógico.",
|
||||
"midnightcontrols.menu.auto_switch_mode": "Modo de troca automática",
|
||||
"midnightcontrols.menu.auto_switch_mode.tooltip": "Se o modo de controle deve ser alterado automaticamente para o controle quando um for conectado.",
|
||||
"midnightcontrols.menu.camera_mode": "Modo de câmera",
|
||||
"midnightcontrols.menu.controller": "Controle",
|
||||
"midnightcontrols.menu.controller2": "Segundo controle",
|
||||
"midnightcontrols.menu.controller2.tooltip": "Segundo controle a ser usado, o que permite (por exemplo) o suporte a Joy-Cons.",
|
||||
"midnightcontrols.menu.controller_toggle_sneak": "Alternar Esgueirar no Controle",
|
||||
"midnightcontrols.menu.controller_toggle_sprint": "Alternar Correr no Controle",
|
||||
"midnightcontrols.menu.controller_type": "Tipo de controle",
|
||||
"midnightcontrols.menu.controller_type.tooltip": "O tipo de controle que você está usando (é preciso para mostrar os botões corretos)",
|
||||
"midnightcontrols.menu.controls_mode": "Modo",
|
||||
"midnightcontrols.menu.controls_mode.tooltip": "O modo de controle.",
|
||||
"midnightcontrols.menu.copy_controller_guid": "Copiar o GUID",
|
||||
"midnightcontrols.menu.current_controller_guid": "GUID do controle atual: %s",
|
||||
"midnightcontrols.menu.double_tap_to_sprint": "Toque duplo para correr",
|
||||
"midnightcontrols.menu.double_tap_to_sprint.tooltip": "Alterna se a tecla Andar para Frente faz o jogador correr quando pressionada duas vezes rapidamente",
|
||||
"midnightcontrols.menu.fast_block_placing": "Colocação Rápida de Blocos",
|
||||
"midnightcontrols.menu.fast_block_placing.tooltip": "Enquanto voando no criativo, ativar a Colocação de Rápida de Blocos. §cEm alguns servidores isso pode ser considerado como trapaça.",
|
||||
"midnightcontrols.menu.fly_drifting": "Derrapagem ao Voar",
|
||||
"midnightcontrols.menu.fly_drifting.tooltip": "Enquanto voando, ativa a deparragem/inércia Vanilla.",
|
||||
"midnightcontrols.menu.fly_drifting_vertical": "Derrapagem vertical ao Voar",
|
||||
"midnightcontrols.menu.fly_drifting_vertical.tooltip": "Enquanto voando, ativa a deparragem/inércia vertical Vanilla.",
|
||||
"midnightcontrols.menu.hud_enable": "Ativar HUD",
|
||||
"midnightcontrols.menu.hud_enable.tooltip": "Alterna o indicador de botão do controle na tela.",
|
||||
"midnightcontrols.menu.hud_side": "Lado do HUD",
|
||||
"midnightcontrols.menu.hud_side.tooltip": "A posição do HUD.",
|
||||
"midnightcontrols.menu.invert_right_x_axis": "Inverter X Direito",
|
||||
"midnightcontrols.menu.invert_right_y_axis": "Inverter Y Direito",
|
||||
"midnightcontrols.menu.joystick_as_mouse": "Sempre usar analógico esquerdo como mouse",
|
||||
"midnightcontrols.menu.joystick_as_mouse.tooltip": "Fazer o analógico agir como um mouse em todos os menus.",
|
||||
"midnightcontrols.menu.eye_tracker_as_mouse": "Usar o rastreador ocular como um mouse",
|
||||
"midnightcontrols.menu.eye_tracker_as_mouse.tooltip": "Substituir o mouse com um dispositivo de rastreamento ocular, (por exemplo) o Tobii 5.",
|
||||
"midnightcontrols.menu.eye_tracker_deadzone": "Tamanho da zona morta do rastreador ocular",
|
||||
"midnightcontrols.menu.eye_tracker_deadzone.tooltip": "Parar o movimento da camera quando olhar perto da mira",
|
||||
"midnightcontrols.menu.keyboard_controls": "Controles do teclado...",
|
||||
"midnightcontrols.menu.left_dead_zone": "Zona morta do analógico esquerdo",
|
||||
"midnightcontrols.menu.left_dead_zone.tooltip": "A zona morta para o analógico esquerdo do controle.",
|
||||
"midnightcontrols.menu.mappings.open_input_str": "Abrir editor de arquivo de mapeamentos",
|
||||
"midnightcontrols.menu.max_left_x_value": "Valor máximo do eixo X esquerdo",
|
||||
"midnightcontrols.menu.max_left_x_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo X esquerdo. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
||||
"midnightcontrols.menu.max_left_y_value": "Valor máximo do eixo Y esquerdo",
|
||||
"midnightcontrols.menu.max_left_y_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo Y esquerdo. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
||||
"midnightcontrols.menu.max_right_x_value": "Valor máximo do eixo X direito",
|
||||
"midnightcontrols.menu.max_right_x_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo X direito. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
||||
"midnightcontrols.menu.max_right_y_value": "Valor máximo do eixo Y direito",
|
||||
"midnightcontrols.menu.max_right_y_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo Y direito. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
||||
"midnightcontrols.menu.mouse_speed": "Velocidade do mouse",
|
||||
"midnightcontrols.menu.mouse_speed.tooltip": "A velocidade do mouse emulado pelo controle",
|
||||
"midnightcontrols.menu.move_chat": "Mover a caixa do chat para o topo",
|
||||
"midnightcontrols.menu.move_chat.tooltip": "Move a caixa do chat para o topo, para uma melhor digitação em dispositivos com teclados na tela.",
|
||||
"midnightcontrols.menu.multiple_mapping_tip": "(Dica: Você também pode inserir múltiplos mapeamentos ao mesmo tempo)",
|
||||
"midnightcontrols.menu.reacharound.horizontal": "Colocação frontal de blocos",
|
||||
"midnightcontrols.menu.reacharound.horizontal.tooltip": "Ativa colocação frontal de blocos, §cEm alguns servidores isso pode ser considerado como trapaça.§r.",
|
||||
"midnightcontrols.menu.reacharound.vertical": "Alcance vertical",
|
||||
"midnightcontrols.menu.reacharound.vertical.tooltip": "Ativa alcance vertical, §c§cEm alguns servidores isso pode ser considerado como trapaça.§r.",
|
||||
"midnightcontrols.menu.reload_controller_mappings": "Recarregar o mapeamento do controle",
|
||||
"midnightcontrols.menu.reload_controller_mappings.tooltip": "Recarrega o arquivo de mapeamentos do controle.",
|
||||
"midnightcontrols.menu.right_dead_zone": "Zona morta do analógico direito",
|
||||
"midnightcontrols.menu.right_dead_zone.tooltip": "A zona morta para o analógico direito do controle..",
|
||||
"midnightcontrols.menu.rotation_speed": "Velocidade de rotação do eixo X",
|
||||
"midnightcontrols.menu.rotation_speed.tooltip": "A velocidade de rotação do eixo X da câmera no modo controle.",
|
||||
"midnightcontrols.menu.y_axis_rotation_speed": "Velocidade de rotação do eixo Y",
|
||||
"midnightcontrols.menu.y_axis_rotation_speed.tooltip": "A velocidade de rotação do eixo Y da câmera no modo controle.",
|
||||
"midnightcontrols.menu.separate_controller_profile": "Separar perfil do controle",
|
||||
"midnightcontrols.menu.separator.controller": "Controle",
|
||||
"midnightcontrols.menu.separator.general": "Geral",
|
||||
"midnightcontrols.menu.title": "MidnightControls - Configurações",
|
||||
"midnightcontrols.menu.title.controller": "Configurações do controle",
|
||||
"midnightcontrols.menu.title.controller_controls": "Mapeamento de controle",
|
||||
"midnightcontrols.menu.title.gameplay": "Configurações de jogabilidade",
|
||||
"midnightcontrols.menu.title.general": "Configurações gerais",
|
||||
"midnightcontrols.menu.title.hud": "Configurações de HUD",
|
||||
"midnightcontrols.menu.title.mappings.string": "Editor de arquivo de mapeamentos",
|
||||
"midnightcontrols.menu.title.touch": "Configurações de toque",
|
||||
"midnightcontrols.menu.title.visual": "Configurações de aparência",
|
||||
"midnightcontrols.menu.touch_break_delay": "Atrasado de destruição do toque",
|
||||
"midnightcontrols.menu.touch_speed": "Velocidade do toque",
|
||||
"midnightcontrols.menu.invert_touch": "Inverter direção do toque",
|
||||
"midnightcontrols.menu.touch_mode": "Modo de interação de toque",
|
||||
"midnightcontrols.menu.touch_transparency": "Transparência do HUD de toque",
|
||||
"midnightcontrols.menu.touch_with_controller": "Toque no modo do controle",
|
||||
"midnightcontrols.menu.unfocused_input": "Entrada desfocada",
|
||||
"midnightcontrols.menu.unfocused_input.tooltip": "Permite entrada de sinais do controle quando a janela não está em foco.",
|
||||
"midnightcontrols.menu.virtual_mouse": "Mouse virtual",
|
||||
"midnightcontrols.menu.virtual_mouse.tooltip": "Ativa o mouse virtual, que é útil durante o modo tela dividida.",
|
||||
"midnightcontrols.menu.virtual_mouse.skin": "Tema do mouse virtual",
|
||||
"midnightcontrols.menu.hide_cursor": "Desativar cursor do mouse padrão",
|
||||
"midnightcontrols.menu.hide_cursor.tooltip": "Esconde o cursor padrão do mouse, deixando apenas o mouse virtual visível.",
|
||||
"midnightcontrols.narrator.unbound": "Desmapear %s",
|
||||
"midnightcontrols.not_bound": "Não mapeado",
|
||||
"midnightcontrols.virtual_mouse.skin.default_light": "Padrão claro",
|
||||
"midnightcontrols.virtual_mouse.skin.default_dark": "Padrão escuro",
|
||||
"midnightcontrols.virtual_mouse.skin.second_light": "Segundo claro",
|
||||
"midnightcontrols.virtual_mouse.skin.second_dark": "Segundo escuro",
|
||||
"midnightcontrols.midnightconfig.category.controller": "Controle",
|
||||
"midnightcontrols.midnightconfig.category.misc": "Variados",
|
||||
"midnightcontrols.midnightconfig.category.screens": "Telas",
|
||||
"midnightcontrols.midnightconfig.category.gameplay": "Jogabilidade",
|
||||
"midnightcontrols.midnightconfig.category.touch": "Toque",
|
||||
"midnightcontrols.midnightconfig.category.visual": "Visual",
|
||||
"modmenu.descriptionTranslation.midnightcontrols": "Adiciona suporte a controles e aprimora o controle no geral.\nDerivado do LambdaControls, que infelizmente foi descontinuado."
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 298 B |
|
Before Width: | Height: | Size: 341 B |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 312 B |
|
Before Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 266 B |
|
Before Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 261 B |
@@ -1,3 +0,0 @@
|
||||
accessWidener v1 named
|
||||
|
||||
accessible class net/minecraft/client/gui/DrawContext$ScissorStack
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"pack": {
|
||||
"pack_format": 15,
|
||||
"supported_formats": [15, 255],
|
||||
"min_format": 15,
|
||||
"max_format": 255,
|
||||
"description": "Makes controller icons look similar to Legacy Console Edit."
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
fabric()
|
||||
}
|
||||
|
||||
loom {
|
||||
}
|
||||
|
||||
configurations {
|
||||
common
|
||||
shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentFabric.extendsFrom common
|
||||
archivesBaseName = rootProject.archives_base_name + "-fabric"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
|
||||
modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric")
|
||||
modImplementation ("dev.lambdaurora:spruceui:${project.spruceui_version}")
|
||||
include("dev.yumi.mc.core:yumi-mc-foundation:1.0.0-beta.1+1.21.11")
|
||||
include 'org.aperlambda:lambdajcommon:1.8.1'
|
||||
modCompileOnly "maven.modrinth:emi:${project.emi_version}"
|
||||
|
||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand "version": project.version
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
exclude "architectury.common.json"
|
||||
|
||||
configurations = [project.configurations.shadowCommon]
|
||||
archiveClassifier = "dev-shadow"
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
dependsOn shadowJar
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
def commonSources = project(":common").sourcesJar
|
||||
dependsOn commonSources
|
||||
from commonSources.archiveFile.map { zipTree(it) }
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "MidnightControls $project.version - Fabric $project.minecraft_version"
|
||||
releaseType = "$project.release_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = []
|
||||
gameLoaders = ["fabric","quilt"]
|
||||
mainPublication remapJar
|
||||
relations {
|
||||
depends {
|
||||
curseforge = "fabric-api"
|
||||
modrinth = "fabric-api"
|
||||
}
|
||||
includes {
|
||||
curseforge = "midnightlib"
|
||||
modrinth = "midnightlib"
|
||||
}
|
||||
includes {
|
||||
curseforge = "obsidianui"
|
||||
modrinth = "obsidianui"
|
||||
}
|
||||
}
|
||||
|
||||
var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN")
|
||||
if (CURSEFORGE_TOKEN != null) {
|
||||
curseforge {
|
||||
token = CURSEFORGE_TOKEN
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 21", project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version-$project.name"
|
||||
gameVersions.addAll project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform.fabric;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of fabric methods for
|
||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil
|
||||
*/
|
||||
public class ItemGroupUtilImpl {
|
||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||
return (screen.getItemGroupsOnPage(screen.getCurrentPage()));
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform.fabric;
|
||||
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
/**
|
||||
* Implementation of fabric methods for
|
||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil
|
||||
*/
|
||||
public class NetworkUtilImpl {
|
||||
private static final ClientPlayNetworkHandler handler = client.getNetworkHandler();
|
||||
|
||||
public static void sendPacketC2S(Packet<?> packet) {
|
||||
if (handler != null)
|
||||
handler.sendPacket(packet);
|
||||
}
|
||||
public static void sendPayloadC2S(CustomPayload payload) {
|
||||
if (handler != null && client.world != null)
|
||||
handler.sendPacket(new CustomPayloadC2SPacket(payload));
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.fabric;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsReloadListener;
|
||||
import eu.midnightdust.midnightcontrols.fabric.event.MouseClickListener;
|
||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||
import eu.midnightdust.midnightcontrols.packet.FeaturePayload;
|
||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
|
||||
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_DOWN;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_LEFT;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_RIGHT;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_UP;
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_RING;
|
||||
|
||||
public class MidnightControlsClientFabric implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||
ClientPlayNetworking.registerGlobalReceiver(ControlsModePayload.PACKET_ID, (payload, context) ->
|
||||
context.responseSender().sendPacket(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName())));
|
||||
ClientPlayNetworking.registerGlobalReceiver(FeaturePayload.PACKET_ID, ((payload, context) -> {}));
|
||||
|
||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||
var version = "";
|
||||
Optional<ModContainer> container;
|
||||
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
|
||||
version = container.get().getMetadata().getVersion().getFriendlyString();
|
||||
}
|
||||
var controlsMode = MidnightControlsConfig.controlsMode.getName();
|
||||
sender.sendPacket(new HelloPayload(version, controlsMode));
|
||||
sender.sendPacket(new ControlsModePayload(controlsMode));
|
||||
});
|
||||
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> MidnightControlsClient.onLeave());
|
||||
|
||||
ClientTickEvents.START_CLIENT_TICK.register(MidnightControlsClient::onTick);
|
||||
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
|
||||
ScreenMouseEvents.allowMouseClick(screen).register(new MouseClickListener(screen));
|
||||
});
|
||||
|
||||
FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE).ifPresent(modContainer -> {
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(id("bedrock"), modContainer, ResourcePackActivationType.NORMAL);
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(id("legacy"), modContainer, ResourcePackActivationType.NORMAL);
|
||||
});
|
||||
MidnightControlsClient.initClient();
|
||||
|
||||
ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() {
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return id("keyboard_layouts");
|
||||
}
|
||||
@Override
|
||||
public void reload(ResourceManager manager) {
|
||||
MidnightControlsReloadListener.INSTANCE.reload(manager);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.fabric;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import eu.midnightdust.midnightcontrols.fabric.event.PlayerChangeControlsModeCallback;
|
||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||
import eu.midnightdust.midnightcontrols.packet.FeaturePayload;
|
||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
public class MidnightControlsFabric implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
MidnightControls.init();
|
||||
PayloadTypeRegistry.playC2S().register(HelloPayload.PACKET_ID, HelloPayload.codec);
|
||||
PayloadTypeRegistry.playC2S().register(ControlsModePayload.PACKET_ID, ControlsModePayload.codec);
|
||||
PayloadTypeRegistry.playS2C().register(ControlsModePayload.PACKET_ID, ControlsModePayload.codec);
|
||||
PayloadTypeRegistry.playS2C().register(FeaturePayload.PACKET_ID, FeaturePayload.codec);
|
||||
|
||||
ServerPlayNetworking.registerGlobalReceiver(HelloPayload.PACKET_ID, (payload, context) -> {
|
||||
ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
|
||||
context.responseSender().sendPacket(new FeaturePayload(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
||||
});
|
||||
ServerPlayNetworking.registerGlobalReceiver(ControlsModePayload.PACKET_ID, (payload, context) -> {
|
||||
ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.fabric.event;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
|
||||
import net.minecraft.client.gui.Click;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.clickInterceptor;
|
||||
|
||||
public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
|
||||
private final Screen screen;
|
||||
|
||||
public MouseClickListener(Screen screen) {
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowMouseClick(Screen screen, Click click) {
|
||||
if(MidnightControlsConfig.virtualKeyboard) {
|
||||
clickInterceptor.intercept(screen, click);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add equals and hashCode to prevent duplicate registrations
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof MouseClickListener) {
|
||||
return ((MouseClickListener) obj).screen == this.screen;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return screen.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,36 @@
|
||||
# Makes things faster
|
||||
org.gradle.parallel=true
|
||||
org.gradle.jvmargs=-Xmx2048M
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
minecraft_version=1.21.11
|
||||
supported_versions=
|
||||
yarn_mappings=1.21.11+build.2
|
||||
enabled_platforms=fabric,neoforge
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/use
|
||||
minecraft_version=1.20.1
|
||||
yarn_mappings=1.20.1+build.10
|
||||
loader_version=0.15.6
|
||||
|
||||
archives_base_name=midnightcontrols
|
||||
mod_version=1.11.4-alpha.1
|
||||
maven_group=eu.midnightdust
|
||||
release_type=beta
|
||||
# Mod Properties
|
||||
mod_version = 1.9.4
|
||||
maven_group = eu.midnightdust
|
||||
archives_base_name = midnightcontrols
|
||||
modrinth_id = bXX9h73M
|
||||
curseforge_id = 621768
|
||||
# Configure the IDs here after creating the projects on the websites
|
||||
changelog = See changes at: https://github.com/TeamMidnightDust/MidnightControls/commits/
|
||||
|
||||
midnightlib_version=1.9.2+1.21.11
|
||||
|
||||
fabric_loader_version=0.18.2
|
||||
fabric_api_version=0.139.4+1.21.11
|
||||
|
||||
neoforge_version=21.11.3-beta
|
||||
yarn_mappings_patch_neoforge_version = 1.21+build.4
|
||||
|
||||
quilt_loader_version=0.19.0-beta.18
|
||||
quilt_fabric_api_version=7.0.1+0.83.0-1.20
|
||||
|
||||
sodium_version=mc1.21-0.6.0-beta.1
|
||||
spruceui_version=9.0.0+1.21.9
|
||||
modmenu_version=10.0.0-beta.1
|
||||
emotecraft_version=2.5.5+1.21.4-fabric
|
||||
# Dependencies
|
||||
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
||||
fabric_version=0.91.0+1.20.1
|
||||
sodium_version=mc1.19.2-0.4.4
|
||||
spruceui_version=5.0.0+1.20
|
||||
midnightlib_version=1.4.1-fabric
|
||||
modmenu_version=7.0.0
|
||||
emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric
|
||||
bendylib_version=2.0.+
|
||||
emi_version=1.1.10+1.21+fabric
|
||||
emi_version=1.1.1+1.20.1+fabric
|
||||
libgui_version=6.0.0+1.19
|
||||
inventorytabs_version=inventorytabs-0.9.beta-1.19.x
|
||||
clothconfig_version=7.0.72
|
||||
yacl_version=2.2.0
|
||||
bedrockify_version=1.9+mc1.20
|
||||
|
||||
# Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions.
|
||||
# ok_zoomer_version=5.0.0-beta.3+1.17.1
|
||||
# libzoomer_version=0.3.0+1.17.1
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
10
gradlew
vendored
@@ -15,8 +15,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -57,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -86,7 +84,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -202,10 +200,10 @@ fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
186
gradlew.bat
vendored
@@ -1,94 +1,92 @@
|
||||
@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
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@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=.
|
||||
@rem This is normally unused
|
||||
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=-Dfile.encoding=UTF-8 "-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% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
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% equ 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!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@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=.
|
||||
@rem This is normally unused
|
||||
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% equ 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% equ 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!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
plugins {
|
||||
id 'com.github.johnrengelman.shadow'
|
||||
id "me.shedaniel.unified-publishing"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = 'NeoForged'
|
||||
url = 'https://maven.neoforged.net/releases'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
architectury {
|
||||
platformSetupLoomIde()
|
||||
neoForge()
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
||||
}
|
||||
|
||||
configurations {
|
||||
common {
|
||||
canBeResolved = true
|
||||
canBeConsumed = false
|
||||
}
|
||||
compileClasspath.extendsFrom common
|
||||
runtimeClasspath.extendsFrom common
|
||||
developmentNeoForge.extendsFrom common
|
||||
|
||||
// Files in this configuration will be bundled into your mod using the Shadow plugin.
|
||||
// Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
|
||||
shadowBundle {
|
||||
canBeResolved = true
|
||||
canBeConsumed = false
|
||||
}
|
||||
archivesBaseName = rootProject.archives_base_name + "-neoforge"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
neoForge "net.neoforged:neoforge:$rootProject.neoforge_version"
|
||||
modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-neoforge")
|
||||
modImplementation include ("maven.modrinth:obsidianui:${rootProject.obsidianui_version}-neoforge")
|
||||
shadowBundle('org.aperlambda:lambdajcommon:1.8.1') {
|
||||
exclude group: 'com.google.code.gson'
|
||||
exclude group: 'com.google.guava'
|
||||
}
|
||||
|
||||
common(project(path: ':common', configuration: 'namedElements')) { transitive false }
|
||||
shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge')
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property 'version', project.version
|
||||
|
||||
filesMatching('META-INF/neoforge.mods.toml') {
|
||||
expand version: project.version
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadowBundle]
|
||||
archiveClassifier = 'dev-shadow'
|
||||
}
|
||||
|
||||
remapJar {
|
||||
input.set shadowJar.archiveFile
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
def commonSources = project(":common").sourcesJar
|
||||
dependsOn commonSources
|
||||
from commonSources.archiveFile.map { zipTree(it) }
|
||||
}
|
||||
|
||||
components.java {
|
||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "MidnightControls $project.version - NeoForge $project.minecraft_version"
|
||||
releaseType = "$project.release_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = []
|
||||
gameLoaders = ["neoforge"]
|
||||
mainPublication remapJar
|
||||
relations {
|
||||
includes {
|
||||
curseforge = "midnightlib"
|
||||
modrinth = "midnightlib"
|
||||
}
|
||||
includes {
|
||||
curseforge = "obsidianui"
|
||||
modrinth = "obsidianui"
|
||||
}
|
||||
}
|
||||
|
||||
var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN")
|
||||
if (CURSEFORGE_TOKEN != null) {
|
||||
curseforge {
|
||||
token = CURSEFORGE_TOKEN
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 21", project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version-$project.name"
|
||||
gameVersions.addAll project.minecraft_version
|
||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
loom.platform=neoforge
|
||||
@@ -1,16 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform.neoforge;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of neoforge methods for
|
||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil
|
||||
*/
|
||||
public class ItemGroupUtilImpl {
|
||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||
return (screen.getCurrentPage().getVisibleTabs());
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package eu.midnightdust.midnightcontrols.client.util.platform.neoforge;
|
||||
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||
|
||||
/**
|
||||
* Implementation of neoforge methods for
|
||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil
|
||||
*/
|
||||
public class NetworkUtilImpl {
|
||||
private static final ClientPlayNetworkHandler handler = client.getNetworkHandler();
|
||||
|
||||
public static void sendPacketC2S(Packet<?> packet) {
|
||||
if (handler != null)
|
||||
handler.send(packet);
|
||||
}
|
||||
public static void sendPayloadC2S(CustomPayload payload) {
|
||||
if (handler != null && client.world != null) {
|
||||
try {
|
||||
handler.send(new CustomPayloadC2SPacket(payload));
|
||||
} catch (Exception e) {
|
||||
e.fillInStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||