Compare commits

..

No commits in common. "1.20" and "1.19.2-forge-windows-only" have entirely different histories.

375 changed files with 11135 additions and 12291 deletions

22
LICENSE
View File

@ -1,21 +1 @@
MIT License
Copyright (c) 2023 CinemaMod Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This mod and its source code is now in public domain. Feel free to do whatever you want with it; make forks, distribute it... whatever I would appreciate it, of course, if you credited me 😊 Thank you!

View File

@ -1,25 +1,18 @@
# WebDisplays
WebDisplays is a mod for creating and interacting with web browsers in Minecraft. You can create screens in your world and browse the internet.
# WebDisplays for Minecraft 1.12.2
This is the WebDisplays mod for Minecraft 1.12.2. I don't have time to maintain it anymore, so I changed the license recently and anybody is welcome to create forks and/or re-distribute it. For more info see [LICENSE](LICENSE).
WebDisplays was originally written by montoyo. It is currently maintained by CinemaMod Group.
### Wiki
* The Wiki that details all blocks/items can be found on my website https://montoyo.net/wdwiki/
Discussion: https://discord.gg/rNrh5kW8Ty
### Things before release
* Release ready. Targeted release date: 17/02/2018.
## Install
Download WebDisplays from either:
- CurseForge: https://legacy.curseforge.com/minecraft/mc-mods/webdisplays
- Modrinth: https://modrinth.com/mod/webdisplays
**WebDisplays Requires MCEF!** You must install MCEF in order for WebDisplays to work.
Download MCEF from either:
- CurseForge: https://legacy.curseforge.com/minecraft/mc-mods/mcef
- Modrinth: https://modrinth.com/mod/mcef
<img src='https://github.com/CinemaMod/webdisplays/assets/30220598/2acfd365-fa87-4adb-970a-33bb5c79f7ba' width='500'>
<img src='https://github.com/CinemaMod/webdisplays/assets/30220598/4e9985a3-d09f-4ab4-8016-37733d4f4a99' width='500'>
## Wiki
[Outdated Wiki from the original creator](https://montoyo.net/wdwiki/index.php?title=Main_Page)
[Outdated Getting Started](https://montoyo.net/wdwiki/index.php?title=Screen)
### Delayed things
* Plugin API
* The Shop
* CC Interface, if CC gets updated...
* Center camera to screen when using keyboard
* minePad management: check GuiContainer.draggedStack for minePad
* In-game command to add/remove blacklisted domains
* Config: RPMP (Real pixels per Minecraft pixels)
* Disable miniserv in solo

12
TODO.md
View File

@ -1,12 +0,0 @@
### Delayed things
* Plugin API
* Center camera to screen when using keyboard
* Allow actual cursor to be used via aiming it at the screen
* maybe aim at the focused element instead of the center of the screen, depends on if that information can be extracted
* minePad management: check GuiContainer.draggedStack for minePad
* In-game command to add/remove blacklisted domains
* CC Interface (for when it's actually possible, since the screens are client only currently, but a config option is planned to change that)
* Redstone controls (same reason as CC interface)
* Potentially redo minisrv logic?
* Perhaps hook it up to vanilla networking
* Maybe don't use it at all in single player

View File

@ -1,179 +1,101 @@
plugins {
id 'java'
id 'idea'
id 'dev.architectury.loom' version '0.12.0-SNAPSHOT'
id 'io.github.juuxel.loom-quiltflower' version '1.6.0'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'net.neoforged.moddev.legacyforge' version '2.0.103'
}
// Only add ProGuard if building with it
def enableProguard = project.hasProperty("enableProguard") && project.enableProguard.toBoolean()
if (enableProguard) {
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.7.0'
}
}
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
base {
archivesName = mod_id
}
group = mod_group_id
version = "${minecraft_version}-${mod_version}"
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
println "Java: ${System.getProperty 'java.version'}"
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
repositories {
mavenCentral()
maven { url = "https://libraries.minecraft.net/" }
maven { url = "https://cursemaven.com" }
maven { url = "https://maven.parchmentmc.org" }
maven { url = 'https://mcef-download.cinemamod.com/repositories/releases/' }
maven { url = "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" }
maven { url = "https://maven.theillusivec4.top/" }
maven { url = "https://repo.lucko.me/" }
maven { url = "https://maven.kosmx.dev/" }
maven { url = "https://modmaven.dev" }
flatDir { dir "libs" }
}
legacyForge {
version = "${minecraft_version}-${forge_version}"
// Access transformer
accessTransformers = files("src/main/resources/META-INF/accesstransformer.cfg")
// Parchment mappings
parchment {
minecraftVersion = minecraft_version
mappingsVersion = mapping_lasting_version
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven { url "https://maven.shedaniel.me/" }
maven { url 'https://jitpack.io' }
maven {
url = "https://maven.parchmentmc.org"
}
runs {
configureEach {
systemProperty 'forge.logging.console.level', 'debug'
logLevel = org.slf4j.event.Level.DEBUG
}
client {
client()
programArgument "-mixin.config=${mod_id}.mixins.json"
systemProperty 'mixin.debug.export', 'true'
}
server {
server()
programArgument "-mixin.config=${mod_id}.mixins.json"
}
data {
data()
programArguments.addAll '--mod', mod_id, '--all',
'--output', file('src/generated/resources/').absolutePath,
'--existing', file('src/main/resources/').absolutePath
}
}
mods {
"${mod_id}" {
sourceSet sourceSets.main
}
maven {
name = "cursemaven"
url = "https://www.cursemaven.com"
}
}
sourceSets.main.resources {
srcDir 'src/generated/resources'
loom {
accessWidenerPath = file("src/main/resources/webdisplays.accesswidener")
}
dependencies {
// MCEF dependency
modImplementation("com.cinemamod:mcef-forge:2.1.1-1.20.1") {
transitive = false
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-1.18.2:2022.05.02@zip")
}
forge "net.minecraftforge:forge:${project.forge_version}"
// Optional mods (make sure versions exist)
modRuntimeOnly "curse.maven:spark-361579:4738952"
modCompileOnly "curse.maven:vivecraft-667903:4794431"
modImplementation "software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}"
modCompileOnly "top.theillusivec4.curios:curios-forge:${curios_version}:api"
modRuntimeOnly "top.theillusivec4.curios:curios-forge:${curios_version}"
modImplementation "com.github.Mysticpasta1:mcef-forge:11826a2d11"
modImplementation "curse.maven:cloth_config_forge-348521:3546623"
// Uncomment the following line to enable the deprecated Fabric API modules.
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
// Mixin Extras
compileOnly annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")
modImplementation "io.github.llamalad7:mixinextras-forge:0.4.1"
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
}
tasks.named('jar', Jar) {
manifest {
attributes([
'Specification-Title': mod_name,
'Specification-Vendor': mod_authors,
'Specification-Version': '1',
'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Implementation-Vendor': mod_authors,
'MixinConfigs': "${mod_id}.mixins.json"
])
}
// Exclude ProGuard renamed files if ProGuard is used
if (enableProguard) {
exclude 'META-INF/versions/**'
loom {
forge {
mixinConfigs = [
"webdisplays.mixin.json"
]
}
}
// Generate sources jar
tasks.register('sourcesJar', Jar) {
dependsOn classes
archiveClassifier = 'sources'
from sourceSets.main.allSource
}
processResources {
inputs.property "version", project.version
// Reobfuscation handling
tasks.named('reobfJar') {
if (enableProguard) {
dependsOn 'proguard'
input = file("${buildDir}/libs/${mod_id}-${minecraft_version}-${mod_version}-proguard.jar")
} else {
dependsOn 'jar'
input = tasks.jar.archiveFile.get().asFile
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
// ProGuard configuration (if enabled)
if (enableProguard) {
tasks.register('proguard', proguard.gradle.ProGuardTask) {
dependsOn tasks.jar
configuration 'proguard.pro'
tasks.withType(JavaCompile).configureEach {
// Minecraft 1.18 (1.18-pre2) upwards uses Java 17.
it.options.release = 17
}
libraryjars "${System.getProperty('java.home')}/jmods"
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
def inputJar = tasks.jar.archiveFile.get().asFile
injars inputJar
outjars "${buildDir}/libs/${mod_id}-${minecraft_version}-${mod_version}-proguard.jar"
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = mod_id
artifact reobfJar
artifact sourcesJar
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
maven {
name = "local"
url = layout.buildDirectory.dir("repo")
}
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,36 +1,17 @@
# Gradle settings
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.caching=true
loom.platform=forge
# ProGuard
enableProguard=false
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.18.2
yarn_mappings=1.18.2+build.3
loader_version=0.14.8
# Mod properties
mod_id=webdisplays
mod_name=WebDisplays
mod_version=2.0.3
mod_group_id=com.cinemamod
mod_authors=CinemaMod Group
mod_description=Web browser displays for Minecraft
mod_license=All Rights Reserved
mod_credits=CinemaMod Group
# Mod Properties
mod_version = 1.0.0
maven_group = net.montoyo.wd
archives_base_name = webdisplays
# Minecraft/Forge versions
minecraft_version=1.20.1
forge_version=47.3.4
minecraft_version_range=[1.20.1,1.21)
forge_version_range=[47,)
loader_version_range=[47,)
# Parchment mappings
mapping_channel=parchment
mapping_version=2023.09.03-1.20.1
mapping_lasting_version=2023.09.03
# Other mod versions
jei_version=15.20.0.112
player_anim_version=1.0.2-rc1+1.20
geckolib_version=4.2.1
curios_version=5.5.0+1.20.1
# Dependencies
forge_version=1.18.2-40.1.52

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip

0
gradlew vendored Executable file → Normal file
View File

View File

@ -1,11 +1,23 @@
pluginManagement {
repositories {
mavenLocal()
pluginManagement {
repositories {
//jcenter() // jcenter will be stopped in 2022
mavenCentral()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
maven { url "https://maven.architectury.dev/" }
maven { url "https://files.minecraftforge.net/maven/" }
maven {
name = 'Cotton'
url = 'https://server.bbkr.space/artifactory/libs-release/'
}
gradlePluginPortal()
}
}
mavenCentral()
gradlePluginPortal()
maven { url = 'https://maven.neoforged.net/releases' }
maven { url = 'https://maven.parchmentmc.org' } // Add this line
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}

View File

@ -4,59 +4,40 @@
package net.montoyo.wd;
import com.cinemamod.mcef.MCEF;
import com.mojang.authlib.GameProfile;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkEvent;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraftforge.server.ServerLifecycleHooks;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.core.HasAdvancement;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.data.GuiData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import org.joml.Vector3d;
import javax.annotation.Nonnull;
import java.util.UUID;
import static net.minecraftforge.api.distmarker.Dist.CLIENT;
public class SharedProxy {
public void preInit() {
}
public void init() {
MCEF.scheduleForInit((cef) -> onCefInit());
}
public void postInit() {
}
public void onCefInit() {
}
@Deprecated(forRemoval = true)
public Level getWorld(ResourceKey<Level> dim) {
return getServer().getLevel(dim);
}
public BlockGetter getWorld(NetworkEvent.Context context) {
if (context.getSender() != null) return context.getSender().level();
return null;
}
public void enqueue(Runnable r) {
ServerLifecycleHooks.getCurrentServer().addTickable(r);
}
@ -65,7 +46,7 @@ public class SharedProxy {
Log.error("Called SharedProxy.displayGui() on server side...");
}
public void trackScreen(ScreenBlockEntity tes, boolean track) {
public void trackScreen(TileEntityScreen tes, boolean track) {
}
public void onAutocompleteResult(NameUUIDPair pairs[]) {
@ -84,11 +65,11 @@ public class SharedProxy {
public void screenUpdateAutoVolumeInGui(Vector3i pos, BlockSide side, boolean av) {
}
public void displaySetPadURLGui(ItemStack is, String padURL) {
public void displaySetPadURLGui(String padURL) {
Log.error("Called SharedProxy.displaySetPadURLGui() on server side...");
}
public void openMinePadGui(UUID padId) {
public void openMinePadGui(int padId) {
Log.error("Called SharedProxy.openMinePadGui() on server side...");
}
@ -129,20 +110,4 @@ public class SharedProxy {
return false;
}
public double distanceTo(ScreenBlockEntity tes, Vec3 position) {
double dist = Double.POSITIVE_INFINITY;
for (int i = 0; i < tes.screenCount(); i++) {
ScreenData scrn = tes.getScreen(i);
Vector3d pos = new Vector3d(
scrn.side.right.x * scrn.size.x / 2d + scrn.size.y * scrn.side.up.x / 2d,
scrn.side.right.y * scrn.size.x / 2d + scrn.size.y * scrn.side.up.y / 2d,
scrn.side.right.z * scrn.size.x / 2d + scrn.size.y * scrn.side.up.z / 2d
).add(tes.getBlockPos().getX(), tes.getBlockPos().getY(), tes.getBlockPos().getZ());
double dist2 = position.distanceToSqr(pos.x, pos.y, pos.z);
dist = Math.min(dist, dist2);
}
return dist;
}
}

View File

@ -5,11 +5,13 @@
package net.montoyo.wd;
import com.google.gson.Gson;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigHolder;
import me.shedaniel.autoconfig.serializer.Toml4jConfigSerializer;
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
@ -18,55 +20,59 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.montoyo.wd.block.WDBlockContainer;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.camera.KeyboardCamera;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.config.CommonConfig;
import net.montoyo.wd.controls.ScreenControlRegistry;
import net.montoyo.wd.client.gui.controls.*;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.core.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.init.TileInit;
import net.montoyo.wd.miniserv.server.Server;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageServerInfo;
import net.montoyo.wd.registry.BlockRegistry;
import net.montoyo.wd.registry.ItemRegistry;
import net.montoyo.wd.registry.TileRegistry;
import net.montoyo.wd.registry.WDTabs;
import net.montoyo.wd.utilities.DistSafety;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageServerInfo;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.serialization.Util;
import net.montoyo.wd.utilities.Util;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@Mod("webdisplays")
public class WebDisplays {
public static final String MOD_VERSION = "1.1";
public static WebDisplays INSTANCE;
public static SharedProxy PROXY = null;
public static SharedProxy PROXY = DistExecutor.<SharedProxy>runForDist(() -> ClientProxy::new, () -> SharedProxy::new);
public static WDCreativeTab CREATIVE_TAB;
public static final ResourceLocation ADV_PAD_BREAK = new ResourceLocation("webdisplays", "webdisplays/pad_break");
public static final String BLACKLIST_URL = "mod://webdisplays/blacklisted.html";
public static final Gson GSON = new Gson();
@ -88,40 +94,54 @@ public class WebDisplays {
//Config
public static final double PAD_RATIO = 59.0 / 30.0;
public String homePage;
public double padResX;
public double padResY;
private int lastPadId = 0;
public boolean doHardRecipe;
private boolean hasOC;
private boolean hasCC;
private List<String> blacklist;
public boolean disableOwnershipThief;
public double unloadDistance2;
public double loadDistance2;
public int maxResX;
public int maxResY;
public int maxScreenX;
public int maxScreenY;
public int miniservPort;
public long miniservQuota;
public boolean enableSoundDistance;
public float ytVolume;
public float avDist100;
public float avDist0;
// mod detection
private boolean hasOC;
private boolean hasCC;
public WebDisplays() {
INSTANCE = this;
if(FMLEnvironment.dist.isClient()) {
PROXY = DistSafety.createProxy();
} else {
PROXY = new SharedProxy();
}
if (FMLEnvironment.dist.isClient()) {
// proxies are annoying, so from now on, I'mma be just registering stuff in here
FMLJavaModLoadingContext.get().getModEventBus().addListener(ClientProxy::onKeybindRegistry);
MinecraftForge.EVENT_BUS.addListener(ClientProxy::onDrawSelection);
MinecraftForge.EVENT_BUS.addListener(KeyboardCamera::updateCamera);
MinecraftForge.EVENT_BUS.addListener(KeyboardCamera::gameTick);
ClientConfig.init();
}
CommonConfig.init();
AutoConfig.register(ModConfig.class, Toml4jConfigSerializer::new);
ConfigHolder<ModConfig> configHolder = AutoConfig.getConfigHolder(ModConfig.class);
ModConfig config = configHolder.getConfig();
configHolder.save();
this.blacklist = config.main.blacklist;
doHardRecipe = config.main.hardRecipes;
this.homePage = config.main.homepage;
disableOwnershipThief = config.main.disableOwnershipThief;
unloadDistance2 = config.client.unloadDistance * config.client.unloadDistance;
loadDistance2 = config.client.loadDistance * config.client.loadDistance;
this.maxResX = config.main.maxResolutionX;
this.maxResY = config.main.maxResolutionY;
this.miniservPort = config.main.miniservPort;
this.miniservQuota = config.main.miniservQuota * 1024L;
this.maxScreenX = config.main.maxScreenSizeX;
this.maxScreenY = config.main.maxScreenSizeY;
enableSoundDistance = config.client.autoVolumeControl.enableAutoVolume;
this.ytVolume = (float) config.client.autoVolumeControl.ytVolume;
avDist100 = (float) config.client.autoVolumeControl.dist100;
avDist0 = (float) config.client.autoVolumeControl.dist0;
CREATIVE_TAB = new WDCreativeTab();
//Criterions
criterionPadBreak = new Criterion("pad_break");
criterionUpgradeScreen = new Criterion("upgrade_screen");
@ -129,19 +149,23 @@ public class WebDisplays {
criterionKeyboardCat = new Criterion("keyboard_cat");
registerTrigger(criterionPadBreak, criterionUpgradeScreen, criterionLinkPeripheral, criterionKeyboardCat);
//Read configuration
padResY = config.main.padHeight;
padResX = padResY * PAD_RATIO;
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
WDNetworkRegistry.init();
SOUNDS.register(bus);
onRegisterSounds();
WDTabs.init(bus);
BlockRegistry.init(bus);
ItemRegistry.init(bus);
TileRegistry.init(bus);
bus.addListener(Messages::registryNetworkPackets);
BlockInit.init(bus);
ItemInit.init(bus);
ItemInit.registerUpgrade();
ItemInit.registerComponents();
TileInit.init(bus);
PROXY.preInit();
MinecraftForge.EVENT_BUS.register(this);
//Other things
PROXY.init();
@ -158,10 +182,6 @@ public class WebDisplays {
t.printStackTrace();
}
} */
if (!FMLEnvironment.production) {
ScreenControlRegistry.init();
}
}
@SubscribeEvent
@ -171,24 +191,23 @@ public class WebDisplays {
}
}
public void onRegisterSounds() {
soundTyping = registerSound("keyboard_type");
soundUpgradeAdd = registerSound("upgrade_add");
soundUpgradeDel = registerSound("upgrade_del");
soundScreenCfg = registerSound("screencfg_open");
soundServer = registerSound("server");
soundIronic = registerSound("ironic");
@SubscribeEvent
public void onRegisterSounds(RegistryEvent.Register<SoundEvent> ev) {
soundTyping = registerSound(ev, "keyboardType");
soundUpgradeAdd = registerSound(ev, "upgradeAdd");
soundUpgradeDel = registerSound(ev, "upgradeDel");
soundScreenCfg = registerSound(ev, "screencfgOpen");
soundServer = registerSound(ev, "server");
soundIronic = registerSound(ev, "ironic");
}
ArrayList<ResourceKey<Level>> serverStartedDimensions = new ArrayList<>();
@SubscribeEvent
public void onWorldLoad(LevelEvent.Load ev) {
if (ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldLoad(WorldEvent.Load ev) {
if (ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
File worldDir = Objects.requireNonNull(ev.getLevel().getServer()).getServerDirectory();
File worldDir = Objects.requireNonNull(ev.getWorld().getServer()).getServerDirectory();
File f = new File(worldDir, "wd_next.txt");
if (f.exists()) {
@ -212,34 +231,29 @@ public class WebDisplays {
if (miniservPort != 0) {
Server sv = Server.getInstance();
if(!serverStartedDimensions.contains(level.dimension())) {
sv.setPort(miniservPort);
sv.setDirectory(new File(worldDir, "wd_filehost"));
sv.start();
serverStartedDimensions.add(level.dimension());
}
sv.setPort(miniservPort);
sv.setDirectory(new File(worldDir, "wd_filehost"));
sv.start();
}
}
}
@SubscribeEvent
public void onWorldLeave(LevelEvent.Unload ev) throws IOException {
if(ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldLeave(WorldEvent.Unload ev) throws IOException {
if(ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
Server sw = Server.getInstance();
sw.stopServer();
serverStartedDimensions.remove(level.dimension());
}
}
@SubscribeEvent
public void onWorldSave(LevelEvent.Save ev) {
if(ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldSave(WorldEvent.Save ev) {
if(ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
File f = new File(Objects.requireNonNull(ev.getLevel().getServer()).getServerDirectory(), "wd_next.txt");
File f = new File(Objects.requireNonNull(ev.getWorld().getServer()).getServerDirectory(), "wd_next.txt");
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
@ -253,10 +267,10 @@ public class WebDisplays {
@SubscribeEvent
public void onToss(ItemTossEvent ev) {
if(!ev.getEntity().level().isClientSide) {
ItemStack is = ev.getEntity().getItem();
if(!ev.getEntityItem().getLevel().isClientSide) {
ItemStack is = ev.getEntityItem().getItem();
if(is.getItem() == ItemRegistry.MINEPAD.get()) {
if(is.getItem() == ItemInit.itemMinePad.get()) {
CompoundTag tag = is.getTag();
if(tag == null) {
@ -274,12 +288,12 @@ public class WebDisplays {
@SubscribeEvent
public void onPlayerCraft(PlayerEvent.ItemCraftedEvent ev) {
if(CommonConfig.hardRecipes && ItemRegistry.isCompCraftItem(ev.getCrafting().getItem()) && (CraftComponent.EXTCARD.makeItemStack().is(ev.getCrafting().getItem()))) {
if((ev.getEntity() instanceof ServerPlayer && !hasPlayerAdvancement((ServerPlayer) ev.getEntity(), ADV_PAD_BREAK)) || PROXY.hasClientPlayerAdvancement(ADV_PAD_BREAK) != HasAdvancement.YES) {
ev.getCrafting().setDamageValue(CraftComponent.BADEXTCARD.ordinal());
if(doHardRecipe && ev.getCrafting().getItem() == ItemInit.itemCraftComp.get() && (CraftComponent.EXTENSION_CARD.makeItemStack().is(ev.getCrafting().getItem()))) {
if((ev.getPlayer() instanceof ServerPlayer && !hasPlayerAdvancement((ServerPlayer) ev.getPlayer(), ADV_PAD_BREAK)) || PROXY.hasClientPlayerAdvancement(ADV_PAD_BREAK) != HasAdvancement.YES) {
ev.getCrafting().setDamageValue(CraftComponent.BAD_EXTENSION_CARD.ordinal());
if(!ev.getEntity().level().isClientSide)
ev.getEntity().level().playSound(null, ev.getEntity().getX(), ev.getEntity().getY(), ev.getEntity().getZ(), SoundEvents.ITEM_BREAK, SoundSource.MASTER, 1.0f, 1.0f);
if(!ev.getPlayer().getLevel().isClientSide)
ev.getPlayer().getLevel().playSound(null, ev.getPlayer().getX(), ev.getPlayer().getY(), ev.getPlayer().getZ(), SoundEvents.ITEM_BREAK, SoundSource.MASTER, 1.0f, 1.0f);
}
}
}
@ -291,35 +305,35 @@ public class WebDisplays {
@SubscribeEvent
public void onLogIn(PlayerEvent.PlayerLoggedInEvent ev) {
if (!CommonConfig.joinMessage) {
return;
}
if(!ev.getPlayer().getLevel().isClientSide && ev.getPlayer() instanceof ServerPlayer) {
IWDDCapability cap =
ev.getPlayer().getCapability(WDDCapability.Provider.cap, null).orElseThrow(RuntimeException::new);
if(!ev.getEntity().level().isClientSide && ev.getEntity() instanceof ServerPlayer) {
IWDDCapability cap = ev.getEntity().getCapability(WDDCapability.Provider.cap, null).orElseThrow(RuntimeException::new);
if(cap.isFirstRun()) {
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome1");
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome2");
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome3");
if(cap == null)
Log.warning("Player %s (%s) has null IWDDCapability!", ev.getPlayer().getName(), ev.getPlayer().getGameProfile().getId().toString());
else if(cap.isFirstRun()) {
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome1");
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome2");
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome3");
cap.clearFirstRun();
}
PacketDistributor.PacketTarget packetDistrutor = PacketDistributor.PLAYER.with(
() -> (ServerPlayer) ev.getEntity()
);
PacketDistributor.PacketTarget packetDistrutor = PacketDistributor.PLAYER
.with(
() ->
(ServerPlayer) ev.getPlayer());
S2CMessageServerInfo message = new S2CMessageServerInfo(miniservPort);
CMessageServerInfo message = new CMessageServerInfo(miniservPort);
WDNetworkRegistry.INSTANCE.send(packetDistrutor, message);
Messages.INSTANCE.send(packetDistrutor, message);
}
}
@SubscribeEvent
public void onLogOut(PlayerEvent.PlayerLoggedOutEvent ev) {
if(!ev.getEntity().level().isClientSide)
Server.getInstance().getClientManager().revokeClientKey(ev.getEntity().getGameProfile().getId());
if(!ev.getPlayer().getLevel().isClientSide)
Server.getInstance().getClientManager().revokeClientKey(ev.getPlayer().getGameProfile().getId());
}
@SubscribeEvent
@ -331,7 +345,7 @@ public class WebDisplays {
@SubscribeEvent
public void onPlayerClone(PlayerEvent.Clone ev) {
IWDDCapability src = ev.getOriginal().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
IWDDCapability dst = ev.getEntity().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
IWDDCapability dst = ev.getPlayer().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
if(src == null) {
Log.error("src is null");
@ -348,7 +362,7 @@ public class WebDisplays {
@SubscribeEvent
public void onServerChat(ServerChatEvent ev) {
String msg = ev.getMessage().getString().replaceAll("\\s+", " ").toLowerCase();
String msg = ev.getMessage().trim().replaceAll("\\s+", " ").toLowerCase();
StringBuilder sb = new StringBuilder(msg.length());
for(int i = 0; i < msg.length(); i++) {
char chr = msg.charAt(i);
@ -359,7 +373,7 @@ public class WebDisplays {
if(sb.toString().equals("ironic he could save others from death but not himself")) {
Player ply = ev.getPlayer();
ply.level().playSound(null, ply.getX(), ply.getY(), ply.getZ(), soundIronic, SoundSource.PLAYERS, 1.0f, 1.0f);
ply.getLevel().playSound(null, ply.getX(), ply.getY(), ply.getZ(), soundIronic, SoundSource.PLAYERS, 1.0f, 1.0f);
}
}
@ -382,13 +396,12 @@ public class WebDisplays {
return new WebDisplays().lastPadId++;
}
public static DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, "webdisplays");
private static SoundEvent registerSound(String resName) {
private static SoundEvent registerSound(RegistryEvent.Register<SoundEvent> ev, String resName) {
ResourceLocation resLoc = new ResourceLocation("webdisplays", resName);
SoundEvent ret = SoundEvent.createVariableRangeEvent(resLoc);
SoundEvent ret = new SoundEvent(resLoc);
ret.setRegistryName(resLoc);
SOUNDS.register(resName, () -> ret);
ev.getRegistry().register(ret);
return ret;
}
@ -408,9 +421,7 @@ public class WebDisplays {
public static boolean isSiteBlacklisted(String url) {
try {
URL url2 = new URL(Util.addProtocol(url));
for (String str : CommonConfig.Browser.blacklist)
if (str.equalsIgnoreCase(url2.getHost())) return true;
return false;
return new ModConfig.Main().blacklist.stream().anyMatch(str -> str.equalsIgnoreCase(url2.getHost()));
} catch(MalformedURLException ex) {
return false;
}
@ -419,5 +430,6 @@ public class WebDisplays {
public static String applyBlacklist(String url) {
return isSiteBlacklisted(url) ? BLACKLIST_URL : url;
}
}

View File

@ -0,0 +1,279 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockKeyboardLeft extends BlockPeripheral {
public static final EnumProperty<DefaultPeripheral> type = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] { type, facing };
public BlockKeyboardLeft() {
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
/*@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = state.getValue(type).getTEClass();
if(cls == null)
return null;
try {
return cls.create(pos, state);
} catch(Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
} */
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityKeyboard)
return ((TileEntityKeyboard) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return state.getValue(type) == DefaultPeripheral.KEYBOARD ? BlockKeyboardRight.KEYBOARD_AABB : Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(state.getValue(type) == DefaultPeripheral.KEYBOARD) {
//Keyboard special treatment
Direction f = state.getValue(facing);
Vec3i dir = f.getClockWise().getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if(!world.isEmptyBlock(pos.below()) && BlockKeyboardRight.checkNeighborhood(world, pos, null)) {
if(world.isEmptyBlock(right) && !world.isEmptyBlock(right.below()) && BlockKeyboardRight.checkNeighborhood(world, right, pos)) {
world.setBlock(right, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
world.setBlock(pos.offset(f.getNormal()), BlockInit.blockKeyBoard.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
} else if(world.isEmptyBlock(left) && !world.isEmptyBlock(left.below()) && BlockKeyboardRight.checkNeighborhood(world, left, pos)) {
world.setBlock(left, state, 3);
world.setBlock(pos.offset(f.getNormal()), BlockInit.blockKeyBoard.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
}
}
//Not good; remove this shit...
world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState());
if(!(placer instanceof Player) || !((Player) placer).isCreative()) {
// dropBlockAsItem(world, pos, state, 0); TODO: Loottable?
}
} else if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
private void removeRightPiece(Level world, BlockPos pos) {
for(Direction nf: Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
if(world.getBlockState(np).getBlock() instanceof BlockKeyboardRight) {
world.setBlock(np, Blocks.AIR.defaultBlockState(), 3);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide || state.getValue(type) != DefaultPeripheral.KEYBOARD)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
removeRightPiece(world, pos);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
if(state.getBlock() == this && state.getValue(type) == DefaultPeripheral.KEYBOARD)
removeRightPiece(world, pos);
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide && world.getBlockState(pos).getValue(type) == DefaultPeripheral.KEYBOARD) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -0,0 +1,208 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.core.IPeripheral;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.init.TileInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3i;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.CallbackI;
import java.util.List;
import java.util.Objects;
public class BlockKeyboardRight extends Block implements IPeripheral {
public static final DirectionProperty facing = BlockStateProperties.HORIZONTAL_FACING;
public static final VoxelShape KEYBOARD_AABB = Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0 / 16.0, 1.0);
public BlockKeyboardRight() {
super(Properties.of(Material.STONE)
.strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(facing);
}
@Override
public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) {
return false;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABB;
}
private TileEntityKeyboard getTileEntity(Level world, BlockPos pos) {
for (Direction nf : Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
BlockState ns = world.getBlockState(np);
if(ns.getBlock() instanceof BlockPeripheral && ns.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof TileEntityKeyboard)
return (TileEntityKeyboard) te;
break;
}
}
return null;
}
@Override
public boolean connect(Level world, BlockPos pos, BlockState state, Vector3i scrPos, BlockSide scrSide) {
TileEntityKeyboard keyboard = getTileEntity(world, pos);
return keyboard != null && keyboard.connect(world, pos, state, scrPos, scrSide);
}
public static boolean checkNeighborhood(Level world, BlockPos bp, BlockPos ignore) {
for (Direction neighbor : Direction.Plane.HORIZONTAL) {
BlockPos np = bp.offset(neighbor.getNormal());
if (ignore == null || !np.equals(ignore)) {
BlockState state = world.getBlockState(np);
if (state.getBlock() instanceof BlockPeripheral) {
if (state.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD)
return false;
} else if (state.getBlock() instanceof BlockKeyboardRight)
return false;
}
}
return true;
}
public void removeLeftPiece(Level world, BlockPos pos, boolean dropItem) {
for (Direction nf : Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
BlockState ns = world.getBlockState(np);
if (ns.getBlock() instanceof BlockPeripheral && ns.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD) {
/* if(dropItem)
if(world instanceof ServerLevel serverWorld) {
// ns.getBlock().getDrops(ns, serverWorld, np,0);
} */
world.setBlock(np, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL_IMMEDIATE);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos neighbor, boolean isMoving) {
if (world.isClientSide())
return;
if (neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ()) {
removeLeftPiece(world, pos, true);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL_IMMEDIATE);
}
}
@Override
public boolean onDestroyedByPlayer(BlockState state, Level world, BlockPos pos, Player ply, boolean willHarvest, FluidState fluid) {
if (!world.isClientSide)
removeLeftPiece(world, pos, !ply.isCreative());
return super.onDestroyedByPlayer(state, world, pos, ply, willHarvest, fluid);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
TileEntityKeyboard tek = getTileEntity(world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
if (!context.getItemInHand().isEmpty()) //Keyboard
return false;
//Special checks for the keyboard
BlockPos pos = context.getClickedPos().offset(context.getHorizontalDirection().getNormal());
if (context.getLevel().getBlockState(pos.below()) == Blocks.AIR.defaultBlockState() || !BlockKeyboardRight.checkNeighborhood(context.getLevel(), pos, null))
return true;
int f = (int) Math.floor(((double) (context.getPlayer().getYRot() * 4.0f / 360.0f)) + 2.5) & 3;
Vec3i dir = Direction.from2DDataValue(f).getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if (context.getLevel().getBlockState(right) == Blocks.AIR.defaultBlockState() && !(context.getLevel().getBlockState(right.below()) == Blocks.AIR.defaultBlockState()) && BlockKeyboardRight.checkNeighborhood(context.getLevel(), right, null))
return false;
else
return !(context.getLevel().getBlockState(left) == Blocks.AIR.defaultBlockState() && !(context.getLevel().getBlockState(left.below()) == Blocks.AIR.defaultBlockState()) && BlockKeyboardRight.checkNeighborhood(context.getLevel(), left, null));
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.isShiftKeyDown()) {
ItemStack itemStack = player.getItemInHand(hand);
if (canBeReplaced(state, new BlockPlaceContext(player, hand, itemStack, hit))) {
int f = (int) Math.floor(((double) (player.getYRot() * 4.0f / 360.0f)) + 2.5) & 3;
Vec3i dir = Direction.from2DDataValue(f).getNormal();
level.setBlock(pos.offset(dir), BlockInit.blockKeyBoard.get().defaultBlockState(), UPDATE_ALL_IMMEDIATE);
return InteractionResult.SUCCESS;
}
}
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
TileEntityKeyboard tek = getTileEntity(level, pos);
if(tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
}

View File

@ -0,0 +1,283 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockPeripheral extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] { type, facing };
public BlockPeripheral() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
// setName("peripheral");
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = state.getValue(type).getTEClass();
if(cls == null)
return null;
try {
return cls.create(pos, state);
} catch(Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityPeripheralBase)
return ((TileEntityPeripheralBase) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return state.getValue(type) == DefaultPeripheral.KEYBOARD ? BlockKeyboardRight.KEYBOARD_AABB : Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(state.getValue(type) == DefaultPeripheral.KEYBOARD) {
//Keyboard special treatment
Direction f = state.getValue(facing);
Vec3i dir = f.getClockWise().getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if(!world.isEmptyBlock(pos.below()) && BlockKeyboardRight.checkNeighborhood(world, pos, null)) {
if(world.isEmptyBlock(right) && !world.isEmptyBlock(right.below()) && BlockKeyboardRight.checkNeighborhood(world, right, pos)) {
world.setBlock(right, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
} else if(world.isEmptyBlock(left) && !world.isEmptyBlock(left.below()) && BlockKeyboardRight.checkNeighborhood(world, left, pos)) {
world.setBlock(left, state, 3);
world.setBlock(pos, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
}
}
//Not good; remove this shit...
world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState());
if(!(placer instanceof Player) || !((Player) placer).isCreative()) {
// dropBlockAsItem(world, pos, state, 0); TODO: Loottable?
}
} else if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
private void removeRightPiece(Level world, BlockPos pos) {
for(Direction nf: Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
if(world.getBlockState(np).getBlock() instanceof BlockKeyboardRight) {
world.setBlock(np, Blocks.AIR.defaultBlockState(), 3);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide || state.getValue(type) != DefaultPeripheral.KEYBOARD)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
removeRightPiece(world, pos);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
if(state.getBlock() == this && state.getValue(type) == DefaultPeripheral.KEYBOARD)
removeRightPiece(world, pos);
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide && world.getBlockState(pos).getValue(type) == DefaultPeripheral.KEYBOARD) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -0,0 +1,225 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockRCTRL extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockRCTRL() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityRCtrl(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
System.out.println(te);
if(te instanceof TileEntityRCtrl)
return ((TileEntityRCtrl) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -0,0 +1,225 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockRedCTRL extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockRedCTRL() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityRedCtrl(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityRedCtrl)
return ((TileEntityRedCtrl) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -12,158 +12,196 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.CommonConfig;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.core.DefaultUpgrade;
import net.montoyo.wd.core.IUpgrade;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.data.SetURLData;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.item.ItemLaserPointer;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.WDItem;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.Util;
import org.jetbrains.annotations.NotNull;
public class ScreenBlock extends BaseEntityBlock {
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockScreen extends BaseEntityBlock {
public static final BooleanProperty hasTE = BooleanProperty.create("haste");
public static final BooleanProperty emitting = BooleanProperty.create("emitting");
private static final Property<?>[] properties = new Property<?>[]{hasTE, emitting};
private static final Property<?>[] properties = new Property<?>[] { hasTE, emitting };
public static final DirectionProperty FACING = BlockStateProperties.FACING;
public ScreenBlock(Properties properties) {
private static final int BAR_BOT = 1;
private static final int BAR_RIGHT = 2;
private static final int BAR_TOP = 4;
private static final int BAR_LEFT = 8;
public BlockScreen(Properties properties) {
super(properties.strength(1.5f, 10.f));
// setCreativeTab(WebDisplays.CREATIVE_TAB);
// setName("screen");
this.registerDefaultState(this.defaultBlockState().setValue(hasTE, false).setValue(emitting, false));
}
@Override
public void onRemove(BlockState p_60515_, Level p_60516_, BlockPos p_60517_, BlockState p_60518_, boolean p_60519_) {
// TODO: make this also get called on client?
if (p_60518_.getBlock() == p_60515_.getBlock()) return;
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties).add(FACING);
}
for (BlockSide value : BlockSide.values()) {
Vector3i vec = new Vector3i(p_60517_.getX(), p_60517_.getY(), p_60517_.getZ());
Multiblock.findOrigin(p_60516_, vec, value, null);
BlockPos bp = new BlockPos(vec.x, vec.y, vec.z);
if (!bp.equals(p_60517_)) {
p_60516_.removeBlockEntity(bp);
p_60516_.setBlock(
bp, p_60516_.getBlockState(bp).setValue(hasTE, false),
11
);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
public static boolean isntScreenBlock(Level world, Vector3i pos) {
return world.getBlockState(pos.toBlock()).getBlock() != BlockInit.blockScreen.get();
}
@org.jetbrains.annotations.Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return super.getStateForPlacement(context);
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos currentPos, BlockPos neighborPos) {
return super.updateShape(state, direction, neighborState, level, currentPos, neighborPos);
}
/* @Override
@Nonnull
public BlockState getExtendedState(@Nonnull BlockState ret, Level world, BlockPos bpos) {
Vector3i pos = new Vector3i(bpos);
for(BlockSide side : BlockSide.values()) {
int icon = 0;
if(isntScreenBlock(world, side.up.clone().add(pos))) icon |= BAR_TOP;
if(isntScreenBlock(world, side.down.clone().add(pos))) icon |= BAR_BOT;
if(isntScreenBlock(world, side.left.clone().add(pos))) icon |= BAR_LEFT;
if(isntScreenBlock(world, side.right.clone().add(pos))) icon |= BAR_RIGHT;
ret = ret.setValue(sideFlags[side.ordinal()], icon);
}
super.onRemove(p_60515_, p_60516_, p_60517_, p_60518_, p_60519_);
return ret;
}*/
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// return getDefaultState().withProperty(hasTE, (meta & 1) != 0).withProperty(emitting, (meta & 2) != 0);
// }
//
public int getMetaFromState(BlockState state) {
int ret = 0;
if(state.getValue(hasTE))
ret |= 1;
if(state.getValue(emitting))
ret |= 2;
return ret;
}
@Override
public InteractionResult use(BlockState state, Level world, BlockPos position, Player player, InteractionHand hand, BlockHitResult hit) {
ItemStack heldItem = player.getItemInHand(hand);
boolean isUpgrade = false;
if (heldItem.isEmpty())
if(heldItem.isEmpty())
heldItem = null; //Easier to work with
else if (!(isUpgrade = heldItem.getItem() instanceof IUpgrade))
return InteractionResult.FAIL;
else if (heldItem.getItem() instanceof ItemLaserPointer)
return InteractionResult.FAIL; // laser pointer already handles stuff
// handling the off hand leads to double clicking
if (!isUpgrade && hand == InteractionHand.OFF_HAND)
else if(!(heldItem.getItem() instanceof IUpgrade))
return InteractionResult.FAIL;
if (world.isClientSide)
if(world.isClientSide)
return InteractionResult.FAIL;
boolean sneaking = player.isShiftKeyDown();
Vector3i pos = new Vector3i(position);
BlockSide side = BlockSide.values()[hit.getDirection().ordinal()];
Multiblock.findOrigin(world, pos, side, null);
ScreenBlockEntity te = (ScreenBlockEntity) world.getBlockEntity(pos.toBlock());
TileEntityScreen te = (TileEntityScreen) world.getBlockEntity(pos.toBlock());
if (te != null && te.getScreen(side) != null) {
ScreenData scr = te.getScreen(side);
if(te != null && te.getScreen(side) != null) {
TileEntityScreen.Screen scr = te.getScreen(side);
if (sneaking) { //Right Click
if ((scr.rightsFor(player) & ScreenRights.CHANGE_URL) == 0)
if(sneaking) { //Set URL
if((scr.rightsFor(player) & ScreenRights.CHANGE_URL) == 0)
Util.toast(player, "restrictions");
else
(new SetURLData(pos, scr.side, scr.url)).sendTo((ServerPlayer) player);
return InteractionResult.SUCCESS;
} else if (heldItem != null) {
if (!te.hasUpgrade(side, heldItem)) {
if ((scr.rightsFor(player) & ScreenRights.MANAGE_UPGRADES) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.CONSUME;
}
if (te.addUpgrade(side, heldItem, player, false)) {
if (!player.isCreative())
heldItem.shrink(1);
Util.toast(player, ChatFormatting.AQUA, "upgradeOk");
if (player instanceof ServerPlayer)
WebDisplays.INSTANCE.criterionUpgradeScreen.trigger(((ServerPlayer) player).getAdvancements());
} else
Util.toast(player, "upgradeError");
return InteractionResult.CONSUME;
}
} else {
if ((scr.rightsFor(player) & ScreenRights.INTERACT) == 0) {
} else if(heldItem != null && !te.hasUpgrade(side, heldItem)) { //Add upgrade
if((scr.rightsFor(player) & ScreenRights.MANAGE_UPGRADES) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.CONSUME;
return InteractionResult.SUCCESS;
}
if(te.addUpgrade(side, heldItem, player, false)) {
if(!player.isCreative())
heldItem.shrink(1);
Util.toast(player, ChatFormatting.AQUA, "upgradeOk");
if(player instanceof ServerPlayer)
WebDisplays.INSTANCE.criterionUpgradeScreen.trigger(((ServerPlayer) player).getAdvancements());
} else
Util.toast(player, "upgradeError");
return InteractionResult.SUCCESS;
} else { //Click
if((scr.rightsFor(player) & ScreenRights.CLICK) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.SUCCESS;
}
Vector2i tmp = new Vector2i();
float hitX = ((float) hit.getLocation().x) - (float) te.getBlockPos().getX();
float hitY = ((float) hit.getLocation().y) - (float) te.getBlockPos().getY();
float hitZ = ((float) hit.getLocation().z) - (float) te.getBlockPos().getZ();
if (hit2pixels(side, hit.getBlockPos(), new Vector3i(hit.getBlockPos()), scr, hitX, hitY, hitZ, tmp))
if(hit2pixels(side, hit.getBlockPos(), pos, scr, (float) hit.getLocation().x, (float) hit.getLocation().y, (float) hit.getLocation().z, tmp))
te.click(side, tmp);
return InteractionResult.CONSUME;
return InteractionResult.SUCCESS;
}
} else if(sneaking) {
Util.toast(player, "turnOn");
return InteractionResult.SUCCESS;
}
// else if(sneaking) {
// Util.toast(player, "turnOn");
// return InteractionResult.SUCCESS;
// }
Vector2i size = Multiblock.measure(world, pos, side);
if (size.x < 2 && size.y < 2) {
if(size.x < 2 || size.y < 2) {
Util.toast(player, "tooSmall");
return InteractionResult.SUCCESS;
}
if (size.x > CommonConfig.Screen.maxScreenSizeX || size.y > CommonConfig.Screen.maxScreenSizeY) {
Util.toast(player, "tooBig", CommonConfig.Screen.maxScreenSizeX, CommonConfig.Screen.maxScreenSizeY);
if(size.x > WebDisplays.INSTANCE.maxScreenX || size.y > WebDisplays.INSTANCE.maxScreenY) {
Util.toast(player, "tooBig", WebDisplays.INSTANCE.maxScreenX, WebDisplays.INSTANCE.maxScreenY);
return InteractionResult.SUCCESS;
}
Vector3i err = Multiblock.check(world, pos, size, side);
if (err != null) {
if(err != null) {
Util.toast(player, "invalid", err.toString());
return InteractionResult.SUCCESS;
}
@ -171,58 +209,60 @@ public class ScreenBlock extends BaseEntityBlock {
boolean created = false;
Log.info("Player %s (UUID %s) created a screen at %s of size %dx%d", player.getName(), player.getGameProfile().getId().toString(), pos.toString(), size.x, size.y);
if (te == null) {
if(te == null) {
BlockPos bp = pos.toBlock();
world.setBlockAndUpdate(bp, world.getBlockState(bp).setValue(hasTE, true));
te = (ScreenBlockEntity) world.getBlockEntity(bp);
te = (TileEntityScreen) world.getBlockEntity(bp);
created = true;
}
te.addScreen(side, size, null, player, true);
te.addScreen(side, size, null, player, !created);
return InteractionResult.SUCCESS;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos source,
boolean isMoving) {
if (block != this && !world.isClientSide && !state.getValue(emitting)) {
for (BlockSide side : BlockSide.values()) {
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos source, boolean isMoving) {
if(block != this && !world.isClientSide && !state.getValue(emitting)) {
for(BlockSide side: BlockSide.values()) {
Vector3i vec = new Vector3i(pos);
Multiblock.findOrigin(world, vec, side, null);
ScreenBlockEntity tes = (ScreenBlockEntity) world.getBlockEntity(vec.toBlock());
if (tes != null && tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
TileEntityScreen tes = (TileEntityScreen) world.getBlockEntity(vec.toBlock());
if(tes != null && tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
Direction facing = Direction.from2DDataValue(side.reverse().ordinal()); //Opposite face
vec.sub(pos.getX(), pos.getY(), pos.getZ()).neg();
// tes.updateJSRedstone(side, new Vector2i(vec.dot(side.right), vec.dot(side.up)), world.getSignal(pos, facing));
tes.updateJSRedstone(side, new Vector2i(vec.dot(side.right), vec.dot(side.up)), world.getSignal(pos, facing));
}
}
}
}
public static boolean hit2pixels(BlockSide side, BlockPos bpos, Vector3i pos, ScreenData scr, float hitX, float hitY, float hitZ, Vector2i dst) {
public static boolean hit2pixels(BlockSide side, BlockPos bpos, Vector3i pos, TileEntityScreen.Screen scr, float hitX, float hitY, float hitZ, Vector2i dst) {
if(side.right.x < 0)
hitX -= 1.f;
if(side.right.z < 0 || side == BlockSide.TOP || side == BlockSide.BOTTOM)
hitZ -= 1.f;
Vector3f rel = new Vector3f(hitX, hitY, hitZ);
Vector3f rel = new Vector3f(pos.toBlock().getX(), pos.toBlock().getY(), pos.toBlock().getZ());
rel.sub(hitX, hitY, hitZ);
// this dot is acting as a "get distance from plane" where the plane is the edge of the screen
float cx = rel.dot(side.right.toFloat()) - 2.f / 16.f;
float cy = rel.dot(side.up.toFloat()) - 2.f / 16.f;
float cx = Math.abs(rel.dot(side.right.toFloat()) - 2.f / 16.f);
float cy = Math.abs(rel.dot(side.up.toFloat()) - 2.f / 16.f);
float sw = ((float) scr.size.x) - 4.f / 16.f;
float sh = ((float) scr.size.y) - 4.f / 16.f;
cx /= sw;
cy /= sh;
if (cx >= 0.f && cx <= 1.0 && cy >= 0.f && cy <= 1.f) {
if (side != BlockSide.BOTTOM)
cx = cx - 0.05f;
cy = cy - 0.05f;
if(cx >= 0 && cx <= 1 && cy >= 0 && cy <= 1) {
if(side != BlockSide.BOTTOM)
cy = 1.f - cy;
switch (scr.rotation) {
switch(scr.rotation) {
case ROT_90:
cy = 1.0f - cy;
break;
@ -235,12 +275,15 @@ public class ScreenBlock extends BaseEntityBlock {
case ROT_270:
cx = 1.0f - cx;
break;
default:
break;
}
cx *= (float) scr.resolution.x;
cy *= (float) scr.resolution.y;
if (scr.rotation.isVertical) {
if(scr.rotation.isVertical) {
dst.x = (int) cy;
dst.y = (int) cx;
} else {
@ -254,41 +297,49 @@ public class ScreenBlock extends BaseEntityBlock {
return false;
}
@org.jetbrains.annotations.Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
int meta = getMetaFromState(state);
if((meta & 1) == 0)
return null;
return ((meta & 1) == 0) ? null : new TileEntityScreen(pos, state);
}
/************************************************* DESTRUCTION HANDLING *************************************************/
private void onDestroy(Level world, BlockPos pos, Player ply) {
if (!world.isClientSide) {
if(!world.isClientSide) {
Vector3i bp = new Vector3i(pos);
Multiblock.BlockOverride override = new Multiblock.BlockOverride(bp, Multiblock.OverrideAction.SIMULATE);
for (BlockSide bs : BlockSide.values())
for(BlockSide bs: BlockSide.values())
destroySide(world, bp.clone(), bs, override, ply);
}
}
private void destroySide(Level world, Vector3i pos, BlockSide side, Multiblock.BlockOverride override, Player
source) {
private void destroySide(Level world, Vector3i pos, BlockSide side, Multiblock.BlockOverride override, Player source) {
Multiblock.findOrigin(world, pos, side, override);
BlockPos bp = pos.toBlock();
BlockEntity te = world.getBlockEntity(bp);
if (te instanceof ScreenBlockEntity) {
((ScreenBlockEntity) te).onDestroy(source);
if(te != null && te instanceof TileEntityScreen) {
((TileEntityScreen) te).onDestroy(source);
world.setBlock(bp, world.getBlockState(bp).setValue(hasTE, false), Block.UPDATE_ALL_IMMEDIATE); //Destroy tile entity.
}
}
@Override
public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player,
boolean willHarvest, FluidState fluid) {
public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player, boolean willHarvest, FluidState fluid) {
onDestroy(level, pos, player);
return super.onDestroyedByPlayer(state, level, pos, player, willHarvest, fluid);
}
@Override
public void setPlacedBy(Level world, @NotNull BlockPos pos, @NotNull BlockState
state, @org.jetbrains.annotations.Nullable LivingEntity whoDidThisShit, @NotNull ItemStack stack) {
if (world.isClientSide)
public void setPlacedBy(Level world, @NotNull BlockPos pos, @NotNull BlockState state, @org.jetbrains.annotations.Nullable LivingEntity whoDidThisShit, @NotNull ItemStack stack) {
if(world.isClientSide)
return;
Multiblock.BlockOverride override = new Multiblock.BlockOverride(new Vector3i(pos), Multiblock.OverrideAction.IGNORE);
@ -301,16 +352,14 @@ public class ScreenBlock extends BaseEntityBlock {
neighbors[4] = new Vector3i(pos.getX(), pos.getY(), pos.getZ() + 1);
neighbors[5] = new Vector3i(pos.getX(), pos.getY(), pos.getZ() - 1);
for (Vector3i neighbor : neighbors) {
if (world.getBlockState(neighbor.toBlock()).getBlock() instanceof ScreenBlock) {
for (BlockSide bs : BlockSide.values())
for(Vector3i neighbor: neighbors) {
if(world.getBlockState(neighbor.toBlock()).getBlock() instanceof BlockScreen) {
for(BlockSide bs: BlockSide.values())
destroySide(world, neighbor.clone(), bs, override, (whoDidThisShit instanceof Player) ? ((Player) whoDidThisShit) : null);
}
}
}
/************************************************* STUFF THAT'S UNLIKELY TO BE TOUCHED BUT NEEDS TO BE HERE *************************************************/
@Override
public @NotNull PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
@ -326,18 +375,23 @@ public class ScreenBlock extends BaseEntityBlock {
return state.getValue(emitting);
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return state.getValue(hasTE) ? new ScreenBlockEntity(pos, state) : null;
// @Override //TODO: Add this
// protected BlockItem createItemBlock() {
// return new ItemBlockScreen(this);
// }
private static class ItemBlockScreen extends BlockItem implements WDItem {
public ItemBlockScreen(BlockScreen screen) {
super(screen, new Properties());
}
@Nullable
@Override
public String getWikiName(@Nonnull ItemStack is) {
return is.getItem().getName(is).getString();
}
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
}

View File

@ -0,0 +1,226 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockServer extends WDBlockContainer{
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockServer() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityServer(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -1,142 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import org.jetbrains.annotations.NotNull;
public class KeyboardBlockLeft extends PeripheralBlock {
public static final EnumProperty<DefaultPeripheral> TYPE = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty FACING = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
// public static final DirectionProperty HALF = DirectionProperty.create("facing", Direction.EAST, Direction.WEST);
public static final VoxelShape[] KEYBOARD_AABBS = new VoxelShape[]{
Shapes.box(0.0, 0.0, 3.0 / 16, 1.0, 1.0 / 16.0, 1.0),
Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0 / 16.0, 13 / 16.0),
Shapes.box(3.0 / 16, 0.0, 0.0, 1.0, 1.0 / 16.0, 1.0),
Shapes.box(0.0, 0.0, 0.0, 13 / 16.0, 1.0 / 16.0, 1.0),
};
private static final Property<?>[] properties = new Property<?>[] {TYPE, FACING};
public KeyboardBlockLeft() {
super(DefaultPeripheral.KEYBOARD);
}
// TODO: make non static (for extensibility purposes)
public static KeyboardBlockEntity getTileEntity(BlockState state, Level world, BlockPos pos) {
if (state.getBlock() instanceof KeyboardBlockLeft) {
BlockEntity te = world.getBlockEntity(pos); // TODO: check?
if (te instanceof KeyboardBlockEntity)
return (KeyboardBlockEntity) te;
}
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING).getOpposite()));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof PeripheralBlock) {
BlockEntity te = world.getBlockEntity(relative); // TODO: check?
if (te instanceof KeyboardBlockEntity)
return (KeyboardBlockEntity) te;
}
return null;
}
public static Direction mapDirection(Direction facing) {
return switch (facing) {
case NORTH -> Direction.EAST;
case EAST -> Direction.SOUTH;
case SOUTH -> Direction.WEST;
case WEST -> Direction.NORTH;
default -> facing;
};
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, level, pos);
if (tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABBS[state.getValue(FACING).ordinal() - 2];
}
@Override
public VoxelShape getOcclusionShape(BlockState arg, BlockGetter arg2, BlockPos arg3) {
return Shapes.empty();
}
private static void removeRightPiece(BlockState state, Level world, BlockPos pos) {
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING)));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof KeyboardBlockRight)
world.setBlock(relative, Blocks.AIR.defaultBlockState(), 3);
}
public static void remove(BlockState state, Level world, BlockPos pos, boolean setState, boolean drop) {
removeRightPiece(state, world, pos);
if (setState)
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
@Override
public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) {
if (!arg2.isClientSide)
remove(arg, arg2, arg3, false, false);
super.onRemove(arg, arg2, arg3, arg4, bl);
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.IPeripheral;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import org.jetbrains.annotations.NotNull;
import static net.montoyo.wd.block.KeyboardBlockLeft.KEYBOARD_AABBS;
import static net.montoyo.wd.block.PeripheralBlock.point;
// TODO: merge into KeyboardLeft
public class KeyboardBlockRight extends Block implements IPeripheral {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public KeyboardBlockRight() {
super(Properties.copy(Blocks.STONE)
.strength(1.5f, 10.f));
}
private static void removeLeftPiece(BlockState state, Level world, BlockPos pos) {
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING).getOpposite()));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof KeyboardBlockLeft)
world.setBlock(relative, Blocks.AIR.defaultBlockState(), 3);
}
public static void remove(BlockState state, Level world, BlockPos pos, boolean setState, boolean drop) {
removeLeftPiece(state, world, pos);
if (setState)
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
@Override
public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) {
if (!arg2.isClientSide)
remove(arg, arg2, arg3, false, false);
super.onRemove(arg, arg2, arg3, arg4, bl);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING);
}
@Override
public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) {
return false;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABBS[state.getValue(FACING).ordinal() - 2];
}
@Override
public boolean connect(Level world, BlockPos pos, BlockState state, Vector3i scrPos, BlockSide scrSide) {
KeyboardBlockEntity keyboard = KeyboardBlockLeft.getTileEntity(state, world, pos);
return keyboard != null && keyboard.connect(world, pos, state, scrPos, scrSide);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, level, pos);
if (tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
@Override
public VoxelShape getOcclusionShape(BlockState arg, BlockGetter arg2, BlockPos arg3) {
return Shapes.empty();
}
}

View File

@ -1,141 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.AbstractInterfaceBlockEntity;
import net.montoyo.wd.entity.AbstractPeripheralBlockEntity;
import net.montoyo.wd.entity.ServerBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import net.montoyo.wd.utilities.Log;
import org.jetbrains.annotations.Nullable;
public class PeripheralBlock extends WDContainerBlock {
DefaultPeripheral type;
public PeripheralBlock(DefaultPeripheral type) {
super(BlockBehaviour.Properties.copy(Blocks.STONE).strength(1.5f, 10.f));
this.type = type;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = type.getTEClass();
if (cls == null)
return null;
try {
return cls.create(pos, state);
} catch (Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.isShiftKeyDown())
return InteractionResult.FAIL;
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof AbstractPeripheralBlockEntity)
return ((AbstractPeripheralBlockEntity) te).onRightClick(player, hand);
else if (te instanceof ServerBlockEntity) {
((ServerBlockEntity) te).onPlayerRightClick(player);
return InteractionResult.SUCCESS;
} else
return InteractionResult.FAIL;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if (world.isClientSide)
return;
if (placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof ServerBlockEntity)
((ServerBlockEntity) te).setOwner((Player) placer);
else if (te instanceof AbstractInterfaceBlockEntity)
((AbstractInterfaceBlockEntity) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof AbstractPeripheralBlockEntity)
((AbstractPeripheralBlockEntity) te).onNeighborChange(neighborType, neighbor);
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if (!world.isClientSide) {
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
super.playerDestroy(world, player, pos, state, blockEntity, tool);
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
public static PacketDistributor.TargetPoint point(Player exclude, Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint((ServerPlayer) exclude, bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
public abstract class WDBlock extends Block {
protected BlockItem itemBlock;
public WDBlock(Properties properties) {
super(properties);
}
protected void setName(String name) {
setRegistryName(name);
}
public void makeItemBlock() {
if(itemBlock != null)
throw new RuntimeException("WDBlock.makeItemBlock() called twice!");
itemBlock = new BlockItem(this, new Item.Properties());
itemBlock.setRegistryName(getRegistryName());
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.montoyo.wd.WebDisplays;
public abstract class WDBlockContainer extends BaseEntityBlock {
protected static BlockItem itemBlock;
public WDBlockContainer(Properties arg) {
super(arg);
}
protected void setName(String name) {
// setRegistryName(name);
}
protected static BlockItem createItemBlock(Block block) {
return new BlockItem(block, new Item.Properties().tab(WebDisplays.CREATIVE_TAB));
}
public static void makeItemBlock(Block block) {
if(itemBlock != null)
throw new RuntimeException("WDBlockContainer.makeItemBlock() called twice!");
itemBlock = createItemBlock(block);
// itemBlock.setRegistryName(getName().getString());
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.level.block.BaseEntityBlock;
public abstract class WDContainerBlock extends BaseEntityBlock {
protected static BlockItem itemBlock;
public WDContainerBlock(Properties arg) {
super(arg);
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -1,54 +0,0 @@
package net.montoyo.wd.block.item;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.montoyo.wd.block.KeyboardBlockLeft;
import net.montoyo.wd.registry.BlockRegistry;
public class KeyboardItem extends BlockItem {
public KeyboardItem(Block arg, Properties arg2) {
super(arg, arg2);
}
@Override
protected boolean placeBlock(BlockPlaceContext arg, BlockState arg2) {
Direction facing = arg.getHorizontalDirection();
arg2 = arg2.setValue(KeyboardBlockLeft.FACING, facing);
Direction d = KeyboardBlockLeft.mapDirection(facing);
if (isValid(arg.getClickedPos(), arg.getLevel(), arg2, d)) {
Block kbRight = BlockRegistry.blockKbRight.get();
BlockState rightState = kbRight.defaultBlockState();
rightState = rightState.setValue(KeyboardBlockLeft.FACING, facing);
if (!arg.getLevel().setBlock(
arg.getClickedPos().relative(d),
rightState,
11
)) return false;
return arg.getLevel().setBlock(arg.getClickedPos(), arg2, 11);// 161
} else if (isValid(arg.getClickedPos().relative(d.getOpposite(), 2), arg.getLevel(), arg2, d)) {
Block kbRight = BlockRegistry.blockKbRight.get();
BlockState rightState = kbRight.defaultBlockState();
rightState = rightState.setValue(KeyboardBlockLeft.FACING, facing);
if (!arg.getLevel().setBlock(
arg.getClickedPos(),
rightState,
11
)) return false;
return arg.getLevel().setBlock(arg.getClickedPos().relative(d.getOpposite()), arg2, 11);// 161
}
return false;
}
private boolean isValid(BlockPos pos, Level level, BlockState state, Direction d) {
return level.getBlockState(pos.relative(d)).isAir();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,370 +1,371 @@
///*
// * Copyright (C) 2018 BARBOTIN Nicolas
// */
//
//package net.montoyo.wd.client;
//
//import net.minecraft.client.Minecraft;
//import net.minecraft.core.BlockPos;
//import net.minecraft.core.Direction;
//import net.minecraft.world.item.ItemStack;
//import net.minecraftforge.api.distmarker.Dist;
//import net.minecraftforge.api.distmarker.OnlyIn;
//import net.montoyo.wd.block.BlockScreen;
//import net.montoyo.wd.core.DefaultUpgrade;
//import net.montoyo.wd.core.IScreenQueryHandler;
//import net.montoyo.wd.core.IUpgrade;
//import net.montoyo.wd.core.JSServerRequest;
//import net.montoyo.wd.entity.TileEntityScreen;
//import net.montoyo.wd.net.WDNetworkRegistry;
//import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
//import net.montoyo.wd.utilities.*;
//
//import java.util.*;
//
//@OnlyIn(Dist.CLIENT)
//public final class JSQueryDispatcher {
//
// private static final class QueryData {
//
// private final IBrowser browser;
// private final String query;
// private final String args;
// private final IJSQueryCallback callback;
//
// private QueryData(IBrowser b, String q, String a, IJSQueryCallback cb) {
// browser = b;
// query = q;
// args = a;
// callback = cb;
// }
//
// }
//
// public static final class ServerQuery {
//
// private static int lastId = 0;
//
// private final TileEntityScreen tes;
// private final BlockSide side;
// private final IJSQueryCallback callback;
// private final int id;
//
// private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) {
// tes = t;
// side = s;
// callback = cb;
// id = lastId++;
// }
//
// public TileEntityScreen getTileEntity() {
// return tes;
// }
//
// public BlockSide getSide() {
// return side;
// }
//
// public TileEntityScreen.Screen getScreen() {
// return tes.getScreen(side);
// }
//
// public void success(String resp) {
// callback.success(resp);
// }
//
// public void error(int errId, String errStr) {
// callback.failure(errId, errStr);
// }
//
// }
//
// private final ClientProxy proxy;
// private final ArrayDeque<QueryData> queue = new ArrayDeque<>();
// private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair();
// private final HashMap<String, IScreenQueryHandler> handlers = new HashMap<>();
// private final ArrayList<ServerQuery> serverQueries = new ArrayList<>();
// private final Minecraft mc = Minecraft.getInstance();
//
// public JSQueryDispatcher(ClientProxy proxy) {
// this.proxy = proxy;
// registerDefaults();
// }
//
// public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) {
// synchronized(queue) {
// queue.offer(new QueryData(b, q, a, cb));
// }
// }
//
// public void handleQueries() {
// while(true) {
// QueryData next;
// synchronized(queue) {
// next = queue.poll();
// }
//
// if(next == null)
// break;
//
// if(proxy.findScreenFromBrowser(next.browser, lookupResult)) {
// Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args);
//
// if(args == null)
// next.callback.failure(400, "Malformed request parameters");
// else {
// try {
// handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args);
// } catch(Throwable t) {
// Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args);
// next.callback.failure(500, "Internal error");
// }
// }
// } else
// next.callback.failure(403, "A screen is required");
// }
// }
//
// public boolean canHandleQuery(String q) {
// return handlers.containsKey(q);
// }
//
// private static Object[] parseArgs(String args) {
// ArrayList<String> array = new ArrayList<>();
// int lastIdx = 0;
// boolean inString = false;
// boolean escape = false;
// boolean hadString = false;
//
// for(int i = 0; i < args.length(); i++) {
// char chr = args.charAt(i);
//
// if(inString) {
// if(escape)
// escape = false;
// else {
// if(chr == '\"')
// inString = false;
// else if(chr == '\\')
// escape = true;
// }
// } else if(chr == '\"') {
// if(hadString)
// return null;
//
// inString = true;
// hadString = true;
// } else if(chr == ',') {
// array.add(args.substring(lastIdx, i).trim());
// lastIdx = i + 1;
// hadString = false;
// }
// }
//
// if(inString)
// return null; //Non terminated string
//
// array.add(args.substring(lastIdx).trim());
// Object[] ret = new Object[array.size()];
//
// for(int i = 0; i < ret.length; i++) {
// String str = array.get(i);
// if(str.isEmpty())
// return null; //Nah...
//
// if(str.charAt(0) == '\"') //String
// ret[i] = str.substring(1, str.length() - 1);
// else {
// try {
// ret[i] = Double.parseDouble(str);
// } catch(NumberFormatException ex) {
// return null;
// }
// }
// }
//
// return ret;
// }
//
// public void register(String query, IScreenQueryHandler handler) {
// handlers.put(query.toLowerCase(), handler);
// }
//
// public ServerQuery fulfillQuery(int id) {
// int toRemove = -1;
//
// for(int i = 0; i < serverQueries.size(); i++) {
// ServerQuery sq = serverQueries.get(i);
//
// if(sq.id == id) {
// toRemove = i;
// break;
// }
// }
//
// if(toRemove < 0)
// return null;
// else
// return serverQueries.remove(toRemove);
// }
//
// private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) {
// ServerQuery ret = new ServerQuery(tes, side, cb);
// serverQueries.add(ret);
//
// WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data));
// }
//
// private void registerDefaults() {
// VideoType.registerQueries(this);
//
// register("GetSize", (cb, tes, side, args) -> {
// Vector2i size = tes.getScreen(side).size;
// cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}");
// });
//
// register("GetRedstoneAt", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
// TileEntityScreen.Screen scr = tes.getScreen(side);
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
//
// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
// cb.failure(403, "Out of range");
// else {
// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
// int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]);
// cb.success("{\"level\":" + level + "}");
// }
// } else
// cb.failure(400, "Wrong arguments");
// });
//
// register("GetRedstoneArray", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
// final Direction facing = Direction.values()[side.reverse().ordinal()];
// final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}");
//
// tes.forEachScreenBlocks(side, bp -> {
// if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting))
// resp.add("0");
// else
// resp.add("" + tes.getLevel().getSignal(bp, facing));
// });
//
// cb.success(resp.toString());
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("ClearRedstone", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()))
// makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE);
// else
// cb.success("{\"status\":\"notOwner\"}");
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("SetRedstoneAt", (cb, tes, side, args) -> {
// if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) {
// cb.failure(400, "Wrong arguments");
// return;
// }
//
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) {
// cb.success("{\"status\":\"notOwner\"}");
// return;
// }
//
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
// boolean state = ((Double) args[2]) > 0.0;
//
// Vector2i size = tes.getScreen(side).size;
// if(x < 0 || x >= size.x || y < 0 || y >= size.y) {
// cb.failure(403, "Out of range");
// return;
// }
//
// makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state);
// });
//
// register("IsEmitting", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
// TileEntityScreen.Screen scr = tes.getScreen(side);
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
//
// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
// cb.failure(403, "Out of range");
// else {
// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
// boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting);
// cb.success("{\"emitting\":" + (e ? "true" : "false") + "}");
// }
// } else
// cb.failure(400, "Wrong arguments");
// });
//
// register("GetEmissionArray", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}");
// tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0"));
// cb.success(resp.toString());
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("GetLocation", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// BlockPos bp = tes.getBlockPos();
// cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}");
// });
//
// register("GetUpgrades", (cb, tes, side, args) -> {
// final StringBuilder sb = new StringBuilder("{\"upgrades\":[");
// final ArrayList<ItemStack> upgrades = tes.getScreen(side).upgrades;
//
// for(int i = 0; i < upgrades.size(); i++) {
// if(i > 0)
// sb.append(',');
//
// sb.append('\"');
// sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i))));
// sb.append('\"');
// }
//
// cb.success(sb.append("]}").toString());
// });
//
// register("IsOwner", (cb, tes, side, args) -> {
// boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()));
// cb.success("{\"isOwner\":" + (res ? "true}" : "false}"));
// });
//
// register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}"));
// register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}"));
// }
//
//}
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.mcef.api.IBrowser;
import net.montoyo.mcef.api.IJSQueryCallback;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.block.BlockScreen;
import net.montoyo.wd.core.DefaultUpgrade;
import net.montoyo.wd.core.IScreenQueryHandler;
import net.montoyo.wd.core.IUpgrade;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.*;
import java.util.*;
@OnlyIn(Dist.CLIENT)
public final class JSQueryDispatcher {
private static final class QueryData {
private final IBrowser browser;
private final String query;
private final String args;
private final IJSQueryCallback callback;
private QueryData(IBrowser b, String q, String a, IJSQueryCallback cb) {
browser = b;
query = q;
args = a;
callback = cb;
}
}
public static final class ServerQuery {
private static int lastId = 0;
private final TileEntityScreen tes;
private final BlockSide side;
private final IJSQueryCallback callback;
private final int id;
private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) {
tes = t;
side = s;
callback = cb;
id = lastId++;
}
public TileEntityScreen getTileEntity() {
return tes;
}
public BlockSide getSide() {
return side;
}
public TileEntityScreen.Screen getScreen() {
return tes.getScreen(side);
}
public void success(String resp) {
callback.success(resp);
}
public void error(int errId, String errStr) {
callback.failure(errId, errStr);
}
}
private final ClientProxy proxy;
private final ArrayDeque<QueryData> queue = new ArrayDeque<>();
private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair();
private final HashMap<String, IScreenQueryHandler> handlers = new HashMap<>();
private final ArrayList<ServerQuery> serverQueries = new ArrayList<>();
private final Minecraft mc = Minecraft.getInstance();
public JSQueryDispatcher(ClientProxy proxy) {
this.proxy = proxy;
registerDefaults();
}
public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) {
synchronized(queue) {
queue.offer(new QueryData(b, q, a, cb));
}
}
public void handleQueries() {
while(true) {
QueryData next;
synchronized(queue) {
next = queue.poll();
}
if(next == null)
break;
if(proxy.findScreenFromBrowser(next.browser, lookupResult)) {
Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args);
if(args == null)
next.callback.failure(400, "Malformed request parameters");
else {
try {
handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args);
} catch(Throwable t) {
Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args);
next.callback.failure(500, "Internal error");
}
}
} else
next.callback.failure(403, "A screen is required");
}
}
public boolean canHandleQuery(String q) {
return handlers.containsKey(q);
}
private static Object[] parseArgs(String args) {
ArrayList<String> array = new ArrayList<>();
int lastIdx = 0;
boolean inString = false;
boolean escape = false;
boolean hadString = false;
for(int i = 0; i < args.length(); i++) {
char chr = args.charAt(i);
if(inString) {
if(escape)
escape = false;
else {
if(chr == '\"')
inString = false;
else if(chr == '\\')
escape = true;
}
} else if(chr == '\"') {
if(hadString)
return null;
inString = true;
hadString = true;
} else if(chr == ',') {
array.add(args.substring(lastIdx, i).trim());
lastIdx = i + 1;
hadString = false;
}
}
if(inString)
return null; //Non terminated string
array.add(args.substring(lastIdx).trim());
Object[] ret = new Object[array.size()];
for(int i = 0; i < ret.length; i++) {
String str = array.get(i);
if(str.isEmpty())
return null; //Nah...
if(str.charAt(0) == '\"') //String
ret[i] = str.substring(1, str.length() - 1);
else {
try {
ret[i] = Double.parseDouble(str);
} catch(NumberFormatException ex) {
return null;
}
}
}
return ret;
}
public void register(String query, IScreenQueryHandler handler) {
handlers.put(query.toLowerCase(), handler);
}
public ServerQuery fulfillQuery(int id) {
int toRemove = -1;
for(int i = 0; i < serverQueries.size(); i++) {
ServerQuery sq = serverQueries.get(i);
if(sq.id == id) {
toRemove = i;
break;
}
}
if(toRemove < 0)
return null;
else
return serverQueries.remove(toRemove);
}
private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) {
ServerQuery ret = new ServerQuery(tes, side, cb);
serverQueries.add(ret);
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data));
}
private void registerDefaults() {
register("GetSize", (cb, tes, side, args) -> {
Vector2i size = tes.getScreen(side).size;
cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}");
});
register("GetRedstoneAt", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
TileEntityScreen.Screen scr = tes.getScreen(side);
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
cb.failure(403, "Out of range");
else {
BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]);
cb.success("{\"level\":" + level + "}");
}
} else
cb.failure(400, "Wrong arguments");
});
register("GetRedstoneArray", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
final Direction facing = Direction.values()[side.reverse().ordinal()];
final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}");
tes.forEachScreenBlocks(side, bp -> {
if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting))
resp.add("0");
else
resp.add("" + tes.getLevel().getSignal(bp, facing));
});
cb.success(resp.toString());
} else
cb.failure(403, "Missing upgrade");
});
register("ClearRedstone", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()))
makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE);
else
cb.success("{\"status\":\"notOwner\"}");
} else
cb.failure(403, "Missing upgrade");
});
register("SetRedstoneAt", (cb, tes, side, args) -> {
if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) {
cb.failure(400, "Wrong arguments");
return;
}
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) {
cb.success("{\"status\":\"notOwner\"}");
return;
}
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
boolean state = ((Double) args[2]) > 0.0;
Vector2i size = tes.getScreen(side).size;
if(x < 0 || x >= size.x || y < 0 || y >= size.y) {
cb.failure(403, "Out of range");
return;
}
makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state);
});
register("IsEmitting", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
TileEntityScreen.Screen scr = tes.getScreen(side);
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
cb.failure(403, "Out of range");
else {
BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting);
cb.success("{\"emitting\":" + (e ? "true" : "false") + "}");
}
} else
cb.failure(400, "Wrong arguments");
});
register("GetEmissionArray", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}");
tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0"));
cb.success(resp.toString());
} else
cb.failure(403, "Missing upgrade");
});
register("GetLocation", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) {
cb.failure(403, "Missing upgrade");
return;
}
BlockPos bp = tes.getBlockPos();
cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}");
});
register("GetUpgrades", (cb, tes, side, args) -> {
final StringBuilder sb = new StringBuilder("{\"upgrades\":[");
final ArrayList<ItemStack> upgrades = tes.getScreen(side).upgrades;
for(int i = 0; i < upgrades.size(); i++) {
if(i > 0)
sb.append(',');
sb.append('\"');
sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i))));
sb.append('\"');
}
cb.success(sb.append("]}").toString());
});
register("IsOwner", (cb, tes, side, args) -> {
boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()));
cb.success("{\"isOwner\":" + (res ? "true}" : "false}"));
});
register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}"));
register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}"));
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.montoyo.wd.client.renderers.IModelBaker;
public class ResourceModelPair {
private final ModelResourceLocation resLoc;
private final IModelBaker model;
public ResourceModelPair(ModelResourceLocation rl, IModelBaker m) {
resLoc = rl;
model = m;
}
public ModelResourceLocation getResourceLocation() {
return resLoc;
}
public IModelBaker getModel() {
return model;
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
/*
package net.montoyo.wd.client;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nonnull;
public class StaticStateMapper {
private final ModelResourceLocation resLoc;
public StaticStateMapper(ModelResourceLocation rl) {
resLoc = rl;
}
@Override
@Nonnull
protected ModelResourceLocation getModelResourceLocation(@Nonnull BlockState state) {
return resLoc;
}
} */

View File

@ -4,127 +4,103 @@
package net.montoyo.wd.client;
import net.montoyo.mcef.api.IScheme;
import net.montoyo.mcef.api.ISchemeResponseData;
import net.montoyo.mcef.api.ISchemeResponseHeaders;
import net.montoyo.mcef.api.SchemePreResponse;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.miniserv.Constants;
import net.montoyo.wd.miniserv.client.Client;
import net.montoyo.wd.miniserv.client.ClientTaskGetFile;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.serialization.Util;
import org.cef.callback.CefCallback;
import org.cef.handler.CefResourceHandler;
import org.cef.misc.IntRef;
import org.cef.misc.StringRef;
import org.cef.network.CefRequest;
import org.cef.network.CefResponse;
import net.montoyo.wd.utilities.Util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class WDScheme implements CefResourceHandler {
public class WDScheme implements IScheme {
private static final String ERROR_PAGE = "<!DOCTYPE html><html><head></head><body><h1>%d %s</h1><hr /><i>Miniserv powered by WebDisplays</i></body></html>";
private ClientTaskGetFile task;
private boolean isErrorPage;
String url;
boolean onlyError = false;
public WDScheme(String url) {
this.url = url;
}
@Override
public boolean processRequest(CefRequest cefRequest, CefCallback cefCallback) {
url = cefRequest.getURL();
url = url.substring("webdisplays://".length());
public SchemePreResponse processRequest(String url) {
url = url.substring("wd://".length());
int pos = url.indexOf('/');
if (pos < 0)
return false;
if(pos < 0)
return SchemePreResponse.NOT_HANDLED;
String uuidStr = url.substring(0, pos);
String fileStr = url.substring(pos + 1);
fileStr = URLDecoder.decode(fileStr, StandardCharsets.UTF_8);
if (uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr)) {
// invalid URL or no UUID
onlyError = true;
cefCallback.Continue();
return true;
try {
fileStr = URLDecoder.decode(fileStr, "UTF-8");
} catch(UnsupportedEncodingException ex) {
Log.warningEx("UTF-8 isn't supported... yeah... and I'm a billionaire...", ex);
}
if(uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr))
return SchemePreResponse.NOT_HANDLED;
UUID uuid;
try {
uuid = UUID.fromString(uuidStr);
} catch (IllegalArgumentException ex) {
// invalid UUID
onlyError = true;
cefCallback.Continue();
return true;
} catch(IllegalArgumentException ex) {
return SchemePreResponse.NOT_HANDLED; //Invalid UUID
}
task = new ClientTaskGetFile(uuid, fileStr);
boolean doContinue = Client.getInstance().addTask(task);
if (doContinue) cefCallback.Continue();
return doContinue;
return Client.getInstance().addTask(task) ? SchemePreResponse.HANDLED_CONTINUE : SchemePreResponse.NOT_HANDLED;
}
@Override
public void getResponseHeaders(CefResponse cefResponse, IntRef contentLength, StringRef redir) {
int status;
if (onlyError) {
status = Constants.GETF_STATUS_BAD_NAME;
} else {
Log.info("Waiting for response...");
status = task.waitForResponse();
Log.info("Got response %d", status);
public void getResponseHeaders(ISchemeResponseHeaders resp) {
Log.info("Waiting for response...");
int status = task.waitForResponse();
Log.info("Got response %d", status);
if (status == 0) {
//OK
int extPos = task.getFileName().lastIndexOf('.');
if (extPos >= 0) {
String mime = mapMime(task.getFileName().substring(extPos + 1));
if(status == 0) {
//OK
int extPos = task.getFileName().lastIndexOf('.');
if(extPos >= 0) {
String mime = ((ClientProxy) WebDisplays.PROXY).getMCEF().mimeTypeFromExtension(task.getFileName().substring(extPos + 1));
if (mime != null)
cefResponse.setMimeType(mime);
}
cefResponse.setStatus(200);
cefResponse.setStatusText("OK");
contentLength.set(0);
return;
if(mime != null)
resp.setMimeType(mime);
}
resp.setStatus(200);
resp.setStatusText("OK");
resp.setResponseLength(-1);
return;
}
int errCode;
String errStr;
if (status == Constants.GETF_STATUS_NOT_FOUND) {
if(status == Constants.GETF_STATUS_NOT_FOUND) {
errCode = 404;
errStr = "Not Found";
} else if (status == Constants.GETF_STATUS_TIMED_OUT) {
errCode = 408;
errStr = "Timed Out";
} else if (status == Constants.GETF_STATUS_BAD_NAME) {
errCode = 418;
errStr = "I'm a teapot";
} else {
errCode = 500;
errStr = "Internal Server Error";
}
// reporting the actual status and text makes CEF not display the page
cefResponse.setStatus(200);
cefResponse.setStatusText("OK");
cefResponse.setMimeType("text/html");
resp.setStatus(errCode);
resp.setStatusText(errStr);
dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes(StandardCharsets.UTF_8);
dataOffset = 0;
amountToWrite = dataToWrite.length;
isErrorPage = true;
contentLength.set(0);
try {
dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes("UTF-8");
dataOffset = 0;
amountToWrite = dataToWrite.length;
isErrorPage = true;
resp.setResponseLength(amountToWrite);
} catch(UnsupportedEncodingException ex) {
resp.setResponseLength(0);
}
}
private byte[] dataToWrite;
@ -132,10 +108,10 @@ public class WDScheme implements CefResourceHandler {
private int amountToWrite;
@Override
public boolean readResponse(byte[] output, int bytesToRead, IntRef bytesRead, CefCallback cefCallback) {
if (dataToWrite == null) {
if (isErrorPage) {
bytesRead.set(0);
public boolean readResponse(ISchemeResponseData data) {
if(dataToWrite == null) {
if(isErrorPage) {
data.setAmountRead(0);
return false;
}
@ -143,25 +119,25 @@ public class WDScheme implements CefResourceHandler {
dataOffset = 3; //packet ID + size
amountToWrite = task.getDataLength();
if (amountToWrite <= 0) {
if(amountToWrite <= 0) {
dataToWrite = null;
bytesRead.set(0);
data.setAmountRead(0);
return false;
}
}
int toWrite = bytesToRead;
if (toWrite > amountToWrite)
int toWrite = data.getBytesToRead();
if(toWrite > amountToWrite)
toWrite = amountToWrite;
System.arraycopy(dataToWrite, dataOffset, output, 0, toWrite);
bytesRead.set(toWrite);
System.arraycopy(dataToWrite, dataOffset, data.getDataArray(), 0, toWrite);
data.setAmountRead(toWrite);
dataOffset += toWrite;
amountToWrite -= toWrite;
if (amountToWrite <= 0) {
if (!isErrorPage)
if(amountToWrite <= 0) {
if(!isErrorPage)
task.nextData();
dataToWrite = null;
@ -170,46 +146,4 @@ public class WDScheme implements CefResourceHandler {
return true;
}
@Override
public void cancel() {
Log.info("Scheme query canceled or finished.");
if (!onlyError)
task.cancel();
}
public static String mapMime(String ext) {
switch (ext) {
case "htm":
case "html":
return "text/html";
case "css":
return "text/css";
case "js":
return "text/javascript";
case "png":
return "image/png";
case "jpg":
case "jpeg":
return "image/jpeg";
case "gif":
return "image/gif";
case "svg":
return "image/svg+xml";
case "xml":
return "text/xml";
case "txt":
return "text/plain";
default:
return null;
}
}
}

View File

@ -1,116 +0,0 @@
package net.montoyo.wd.client.audio;
import net.minecraft.client.resources.sounds.Sound;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.client.sounds.AudioStream;
import net.minecraft.client.sounds.SoundBufferLibrary;
import net.minecraft.client.sounds.SoundManager;
import net.minecraft.client.sounds.WeighedSoundEvents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.SampledFloat;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class WDAudioSource implements SoundInstance {
private static final ResourceLocation location = new ResourceLocation("webdisplays:audio_source");
private static final WeighedSoundEvents events = new WeighedSoundEvents(
location, "webdisplays.browser"
);
private static final SampledFloat CONST_1 = new SampledFloat() {
@Override
public float sample(RandomSource pRandom) {
return 1.0f;
}
};
private final Sound sound = new Sound(
"unused",
CONST_1,
CONST_1,
1, Sound.Type.SOUND_EVENT,
true, false,
100
);
ScreenBlockEntity blockEntity;
ScreenData data;
public WDAudioSource(ScreenBlockEntity blockEntity, ScreenData data) {
this.blockEntity = blockEntity;
this.data = data;
}
@Override
public ResourceLocation getLocation() {
return location;
}
@Nullable
@Override
public WeighedSoundEvents resolve(SoundManager pManager) {
return events;
}
@Override
public CompletableFuture<AudioStream> getStream(SoundBufferLibrary soundBuffers, Sound sound, boolean looping) {
return null;
}
@Override
public Sound getSound() {
return sound;
}
@Override
public SoundSource getSource() {
return SoundSource.RECORDS;
}
@Override
public boolean isLooping() {
return true;
}
@Override
public boolean isRelative() {
return false;
}
@Override
public int getDelay() {
return 0;
}
@Override
public float getVolume() {
return blockEntity.ytVolume;
}
@Override
public float getPitch() {
return 1;
}
@Override
public double getX() {
return blockEntity.getBlockPos().getX();
}
@Override
public double getY() {
return blockEntity.getBlockPos().getY();
}
@Override
public double getZ() {
return blockEntity.getBlockPos().getZ();
}
@Override
public Attenuation getAttenuation() {
return Attenuation.LINEAR;
}
}

View File

@ -4,59 +4,53 @@
package net.montoyo.wd.client.gui;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.mojang.blaze3d.platform.InputConstants;
import com.sun.jna.platform.unix.X11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.loading.FMLPaths;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.gui.camera.KeyboardCamera;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.Control;
import net.montoyo.wd.client.gui.controls.Label;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.controls.builtin.ClickControl;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.serialization.TypeData;
import net.montoyo.wd.utilities.serialization.Util;
import org.cef.browser.CefBrowser;
import org.cef.misc.CefCursorType;
import org.joml.Matrix4f;
import org.joml.Vector4f;
import net.montoyo.wd.utilities.TypeData;
import net.montoyo.wd.utilities.Util;
import org.apache.commons.lang3.CharUtils;
import org.cef.browser.CefBrowserOsr;
import org.jline.utils.Display;
import org.lwjgl.glfw.GLFW;
import org.vivecraft.client_vr.gameplay.VRPlayer;
import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler;
import java.awt.event.KeyEvent;
import java.io.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import static com.mojang.blaze3d.platform.InputConstants.*;
import static java.awt.event.KeyEvent.*;
@OnlyIn(Dist.CLIENT)
public class GuiKeyboard extends WDScreen {
private static final String WARNING_FNAME = "wd_keyboard_warning.txt";
private ScreenBlockEntity tes;
private TileEntityScreen tes;
private BlockSide side;
private ScreenData data;
private final ArrayList<TypeData> evStack = new ArrayList<>();
private BlockPos kbPos;
private boolean showWarning = true;
@ -71,7 +65,7 @@ public class GuiKeyboard extends WDScreen {
super(Component.nullToEmpty(null));
}
public GuiKeyboard(ScreenBlockEntity tes, BlockSide side, BlockPos kbPos) {
public GuiKeyboard(TileEntityScreen tes, BlockSide side, BlockPos kbPos) {
this();
this.tes = tes;
this.side = side;
@ -83,30 +77,6 @@ public class GuiKeyboard extends WDScreen {
vars.put("showWarning", showWarning ? 1.0 : 0.0);
}
private static final boolean vivecraftPresent;
static {
boolean vivePres = false;
if (ModList.get().isLoaded("vivecraft")) vivePres = true;
// I believe the non-mixin version of vivecraft is not a proper mod, so
// detect the mod reflectively if the mod is not found
else {
try {
Class<?> clazz = Class.forName("org.vivecraft.gameplay.screenhandlers.KeyboardHandler");
//noinspection ConstantConditions
if (clazz == null) vivePres = false;
else {
Method m = clazz.getMethod("setOverlayShowing", boolean.class);
//noinspection ConstantConditions
vivePres = m != null;
}
} catch (Throwable ignored) {
vivePres = false;
}
}
vivecraftPresent = vivePres;
}
@Override
public void init() {
super.init();
@ -152,77 +122,64 @@ public class GuiKeyboard extends WDScreen {
defaultBackground = showWarning;
syncTicks = 5;
if (vivecraftPresent)
if (VRPlayer.get() != null)
KeyboardHandler.setOverlayShowing(true);
KeyboardCamera.focus(tes, side);
data = tes.getScreen(side);
CefBrowser browser = data.browser;
((MCEFBrowser) browser).setCursor(CefCursorType.fromId(data.mouseType));
((MCEFBrowser) browser).setCursorChangeListener((id) -> {
data.mouseType = id;
((MCEFBrowser) browser).setCursor(CefCursorType.fromId(id));
});
}
@Override
public void removed() {
super.removed();
if (vivecraftPresent)
if (VRPlayer.get() != null)
KeyboardHandler.setOverlayShowing(false);
KeyboardCamera.focus(null, null);
CefBrowser browser = data.browser;
if (browser instanceof MCEFBrowser mcef) {
mcef.setCursor(CefCursorType.POINTER);
mcef.setCursorChangeListener((cursor) -> data.mouseType = cursor);
}
}
@Override
public void onClose() {
removed();
super.onClose();
this.minecraft.popGuiLayer();
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (quitOnEscape && keyCode == GLFW.GLFW_KEY_ESCAPE) {
onClose();
return true;
}
addKey(new TypeData(TypeData.Action.PRESS, keyCode, modifiers, scanCode));
key(keyCode, scanCode, true, modifiers);
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
public boolean charTyped(char codePoint, int modifiers) {
addKey(new TypeData(TypeData.Action.TYPE, codePoint, modifiers, 0));
return super.charTyped(codePoint, modifiers);
}
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
addKey(new TypeData(TypeData.Action.RELEASE, keyCode, modifiers, scanCode));
key(keyCode, scanCode, false, modifiers);
return super.keyPressed(keyCode, scanCode, modifiers);
}
void addKey(TypeData data) {
tes.type(side, "[" + WebDisplays.GSON.toJson(data) + "]", kbPos);
public void key(int keyCode, int scanCode, boolean pressed, int mod) {
if (pressed) {
if(quitOnEscape && keyCode == GLFW.GLFW_KEY_ESCAPE) {
Minecraft.getInstance().setScreen(null);
}
evStack.add(data);
if (!evStack.isEmpty() && !syncRequested())
requestSync();
int chr = getChar(keyCode, scanCode);
evStack.add(new TypeData(TypeData.Action.PRESS, chr, mod));
evStack.add(new TypeData(TypeData.Action.RELEASE, chr, mod));
if (keyCode != 0)
evStack.add(new TypeData(TypeData.Action.TYPE, chr, mod));
if (!evStack.isEmpty() && !syncRequested())
requestSync();
}
}
public int getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if(keystr == null){
keystr = "\0";
}
if(keyCode == GLFW.GLFW_KEY_ENTER){
return 13;
}
if (keyCode == GLFW.GLFW_KEY_SPACE) {
return 32;
}
if(keystr.length() == 0){
return -1;
}
if(hasShiftDown()) {
keystr = keystr.toUpperCase(Locale.ROOT);
return CefBrowserOsr.remapKeycode(keyCode, keystr.charAt(keystr.length() - 1));
} else {
return CefBrowserOsr.remapKeycode(keyCode, keystr.charAt(keystr.length() - 1));
}
}
@Override
protected void sync() {
if(!evStack.isEmpty()) {
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.type(tes, side, WebDisplays.GSON.toJson(evStack), kbPos));
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.type(tes, side, WebDisplays.GSON.toJson(evStack), kbPos));
evStack.clear();
}
}
@ -250,7 +207,7 @@ public class GuiKeyboard extends WDScreen {
private boolean hasUserReadWarning() {
try {
File f = new File(FMLPaths.GAMEDIR.get().toString(), WARNING_FNAME);
File f = new File(FMLPaths.GAMEDIR.name(), WARNING_FNAME);
if(f.exists()) {
BufferedReader br = new BufferedReader(new FileReader(f));
@ -268,7 +225,7 @@ public class GuiKeyboard extends WDScreen {
private void writeUserAcknowledge() {
try {
File f = new File(FMLPaths.GAMEDIR.get().toString(), WARNING_FNAME);
File f = new File(FMLPaths.GAMEDIR.name(), WARNING_FNAME);
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write("read\n");
@ -283,89 +240,4 @@ public class GuiKeyboard extends WDScreen {
return bp.equals(kbPos) || (bp.equals(tes.getBlockPos()) && side == this.side);
}
protected void mouse(double mouseX, double mouseY, Consumer<Vector2i> func) {
float pct = Minecraft.getInstance().getPartialTick();
double fov = Minecraft.getInstance().gameRenderer.getFov(
Minecraft.getInstance().getEntityRenderDispatcher().camera,
pct, true
);
mouseX /= width;
mouseY /= height;
mouseX -= 0.5;
mouseY -= 0.5;
mouseY = -mouseY;
Matrix4f proj = Minecraft.getInstance().gameRenderer.getProjectionMatrix(fov);
Entity e = Minecraft.getInstance().getEntityRenderDispatcher().camera.getEntity();
PoseStack camera = new PoseStack();
float[] angle = KeyboardCamera.getAngle(e, pct);
camera.mulPose(Axis.XP.rotationDegrees(angle[0]));
camera.mulPose(Axis.YP.rotationDegrees(angle[1] + 180.0F));
Vector4f coord = new Vector4f(2f * (float) mouseX, 2 * (float) mouseY, 0, 1f);
coord.add(proj.invert().transform(coord));
coord = camera.last().pose().invert().transform(coord);
Vec3 vec3 = e.getEyePosition(pct);
Vec3 vec31 = new Vec3(coord.x, coord.y, coord.z).normalize();
BlockHitResult result = tes.trace(side, vec3, vec31);
if (result.getType() != HitResult.Type.MISS) {
tes.interact(result, func);
}
}
@Override
public void mouseMoved(double mouseX, double mouseY) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserMove(tes, side, hit));
});
super.mouseMoved(mouseX, mouseY);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
tes.handleMouseEvent(side, ClickControl.ControlType.DOWN, hit, button);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserDown(tes, side, hit, button));
});
KeyboardCamera.setMouse(button, true);
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
tes.handleMouseEvent(side, ClickControl.ControlType.UP, hit, button);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserUp(tes, side, button));
});
KeyboardCamera.setMouse(button, false);
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public void tick() {
double mouseX = Minecraft.getInstance().mouseHandler.xpos() / Minecraft.getInstance().getWindow().getWidth();
double mouseY = Minecraft.getInstance().mouseHandler.ypos() / Minecraft.getInstance().getWindow().getHeight();
mouse(mouseX * width, mouseY * height, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserMove(tes, side, hit));
});
super.tick();
}
}

View File

@ -4,354 +4,180 @@
package net.montoyo.wd.client.gui;
import com.cinemamod.mcef.MCEFBrowser;
import com.google.gson.JsonObject;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.core.BlockPos;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.utilities.browser.WDBrowser;
import net.montoyo.wd.utilities.browser.handlers.js.Scripts;
import net.montoyo.wd.utilities.data.BlockSide;
import org.cef.misc.CefCursorType;
import net.montoyo.wd.utilities.BlockSide;
import org.lwjgl.glfw.GLFW;
import java.util.Optional;
import static net.minecraftforge.api.distmarker.Dist.CLIENT;
import static org.lwjgl.opengl.GL11.glColor4f;
@OnlyIn(CLIENT)
public class GuiMinePad extends WDScreen {
private ClientProxy.PadData pad;
private double vx;
private double vy;
private double vw;
private double vh;
private ClientProxy.PadData pad;
private double vx;
private double vy;
private double vw;
private double vh;
public GuiMinePad() {
super(Component.nullToEmpty(null));
}
public GuiMinePad() {
super(Component.nullToEmpty(null));
}
public GuiMinePad(ClientProxy.PadData pad) {
this();
this.pad = pad;
}
public GuiMinePad(ClientProxy.PadData pad) {
this();
this.pad = pad;
}
int trueWidth, trueHeight;
@Override
public void init() {
super.init();
@Override
public void init() {
vw = ((double) width) - 32.0f;
vh = vw / WebDisplays.PAD_RATIO;
vx = 16.0f;
vy = (((double) height) - vh) / 2.0f;
vw = ((double) width) - 32.0f;
vh = vw / WebDisplays.PAD_RATIO;
vx = 16.0f;
vy = (((double) height) - vh) / 2.0f;
}
trueWidth = width;
trueHeight = height;
private static void addRect(BufferBuilder bb, double x, double y, double w, double h) {
bb.vertex(x, y, 0.0).endVertex();
bb.vertex(x + w, y, 0.0).endVertex();
bb.vertex(x + w, y + h, 0.0).endVertex();
bb.vertex(x, y + h, 0.0).endVertex();
}
this.width = (int) vw;
this.height = (int) vh;
@Override
public void render(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
renderBackground(poseStack);
super.init();
RenderSystem.disableTexture();
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.73f, 0.73f, 0.73f, 1.0f);
((MCEFBrowser) pad.view).setCursor(CefCursorType.fromId(pad.activeCursor));
((MCEFBrowser) pad.view).setCursorChangeListener((id) -> {
pad.activeCursor = id;
((MCEFBrowser) pad.view).setCursor(CefCursorType.fromId(id));
});
}
Tesselator t = Tesselator.getInstance();
BufferBuilder bb = t.getBuilder();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
addRect(bb, vx, vy - 16, vw, 16);
addRect(bb, vx, vy + vh, vw, 16);
addRect(bb, vx - 16, vy, 16, vh);
addRect(bb, vx + vw, vy, 16, vh);
t.end();
private static void addRect(BufferBuilder bb, double x, double y, double w, double h) {
bb.vertex(x, y, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x + w, y, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x + w, y + h, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x, y + h, 0.0).color(255, 255, 255, 255).endVertex();
}
RenderSystem.enableTexture();
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float ptt) {
width = trueWidth;
height = trueHeight;
renderBackground(graphics);
width = (int) vw;
height = (int) vh;
if (pad.view != null) {
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
pad.view.draw(poseStack, vx, vy + vh, vx + vw, vy);
}
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.73f, 0.73f, 0.73f, 1.0f);
RenderSystem.enableCull();
}
Tesselator t = Tesselator.getInstance();
BufferBuilder bb = t.getBuilder();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
addRect(bb, vx, vy - 16, vw, 16);
addRect(bb, vx, vy + vh, vw, 16);
addRect(bb, vx - 16, vy, 16, vh);
addRect(bb, vx + vw, vy, 16, vh);
t.end();
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, true);
return super.keyPressed(keyCode, scanCode, modifiers);
}
if (pad.view != null) {
// pad.view.draw(poseStack, vx, vy + vh, vx + vw, vy);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem.setShaderTexture(0, ((MCEFBrowser) pad.view).getRenderer().getTextureID());
t = Tesselator.getInstance();
BufferBuilder buffer = t.getBuilder();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
double x1 = vx;
double y1 = vy;
double x2 = vx + vw;
double y2 = vy + vh;
buffer.vertex(graphics.pose().last().pose(), (float) x1, (float) y1, 0.0f).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x2, (float) y1, 0.0f).uv(1.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x2, (float) y2, 0.0f).uv(1.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x1, (float) y2, 0.0f).uv(0.0F, 1.0F).color(255, 255, 255, 255).endVertex();
t.end();
RenderSystem.enableDepthTest();
}
RenderSystem.enableCull();
graphics.drawString(
minecraft.font, Language.getInstance().getOrDefault(
"webdisplays.gui.minepad.close"
), (int) vx + 4, (int) vy - minecraft.font.lineHeight - 3, 16777215, true
);
}
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, false);
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
return this.keyChanged(keyCode, scanCode, modifiers, true) || super.keyPressed(keyCode, scanCode, modifiers);
}
public void key(int keyCode, int scanCode, boolean pressed) {
Optional<Character> key = getChar(keyCode, scanCode);
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
return this.keyChanged(keyCode, scanCode, modifiers, false) || super.keyReleased(keyCode, scanCode, modifiers);
}
if (pad.view != null && key.isPresent()) {
char c = key.get();
@Override
public boolean charTyped(char codePoint, int modifiers) {
if (pad.view != null) {
((MCEFBrowser) pad.view).sendKeyTyped(codePoint, modifiers);
return true;
} else {
return super.charTyped(codePoint, modifiers);
}
}
if (pressed)
pad.view.injectKeyPressedByKeyCode(keyCode, c, 0);
else
pad.view.injectKeyReleasedByKeyCode(keyCode, c, 0);
/* copied from MCEF */
public boolean keyChanged(int keyCode, int scanCode, int modifiers, boolean pressed) {
assert minecraft != null;
if ((modifiers & GLFW.GLFW_MOD_SHIFT) == GLFW.GLFW_MOD_SHIFT && keyCode == GLFW.GLFW_KEY_ESCAPE) {
onClose();
return true;
}
if (c != 0)
pad.view.injectKeyTyped(c, 0);
}
InputConstants.Key iuKey = InputConstants.getKey(keyCode, scanCode);
String keystr = iuKey.getDisplayName().getString();
// System.out.println("KEY STR " + keystr);
if (keystr.length() == 0)
return false;
}
char key = keystr.charAt(keystr.length() - 1);
@Override
public void mouseMoved(double mouseX, double mouseY) {
super.mouseMoved(mouseX, mouseY);
mouse(-1, false, (int) mouseX, (int) mouseY);
}
if (keystr.equals("Enter")) {
keyCode = 10;
key = '\n';
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(button, true, (int) mouseX, (int) mouseY);
return super.mouseClicked(mouseX, mouseY, button);
}
if (pad.view != null) {
if (pressed)
((MCEFBrowser) pad.view).sendKeyPress(keyCode, scanCode, modifiers);
else
((MCEFBrowser) pad.view).sendKeyRelease(keyCode, scanCode, modifiers);
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(button, false, (int) mouseX, (int) mouseY);
return super.mouseReleased(mouseX, mouseY, button);
}
if (pressed && key == '\n')
if (modifiers != 0) ((MCEFBrowser) pad.view).sendKeyTyped('\r', modifiers);
return true;
}
public void mouse(int btn, boolean pressed, int sx, int sy) {
return false;
}
int vx = screen2DisplayX((int) this.vx);
int vy = screen2DisplayY((int) this.vy);
int vh = screen2DisplayX((int) this.vh);
int vw = screen2DisplayY((int) this.vw);
@Override
public void mouseMoved(double mouseX, double mouseY) {
super.mouseMoved(mouseX, mouseY);
mouse(-1, false, (int) mouseX, (int) mouseY, 0);
}
if (pad.view != null && sx >= vx && sx <= vx + vw && sy >= vy && sy <= vy + vh) {
sx -= vx;
sy -= vy;
sy = vh - sy;
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(button, true, (int) mouseX, (int) mouseY, 0);
return super.mouseClicked(mouseX, mouseY, button);
}
//Scale again according to the webview
sx = (int) (((double) sx) / ((double) vw) * WebDisplays.INSTANCE.padResX);
sy = (int) (((double) sy) / ((double) vh) * WebDisplays.INSTANCE.padResY);
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(button, false, (int) mouseX, (int) mouseY, 0);
return super.mouseReleased(mouseX, mouseY, button);
}
if (btn == -1)
pad.view.injectMouseMove(sx, sy, 0, false);
else
pad.view.injectMouseButton(sx, sy, 0, btn + 1, pressed, 1);
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
double mx = (mouseX - vx) / vw;
double my = (mouseY - vy) / vh;
int sx = (int) (mx * WebDisplays.INSTANCE.padResX);
int sy = (int) (my * WebDisplays.INSTANCE.padResY);
// TODO: this doesn't work, and I don't understand why?
((MCEFBrowser) pad.view).sendMouseWheel(sx, sy, amount, (hasControlDown() && !hasAltDown() && !hasShiftDown()) ? GLFW.GLFW_MOD_CONTROL : 0);
}
}
return super.mouseScrolled(mouseX, mouseY, amount);
}
public static Optional<Character> getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if(keystr == null){
keystr = "\0";
}
if(keyCode == GLFW.GLFW_KEY_ENTER){
keystr = "\n";
}
if(keystr.length() == 0){
return Optional.empty();
}
public void capturedMouse(double scaledX, double scaledY, int sx, int sy) {
double centerX = (int) (0.5 * (double) this.minecraft.getWindow().getGuiScaledWidth());
double centerY = (int) (0.5 * (double) this.minecraft.getWindow().getGuiScaledHeight());
return Optional.of(keystr.charAt(keystr.length() - 1));
}
if (sx == (int) centerX && sy == (int) centerY) return;
@Override
public void tick() {
if(pad.view == null)
minecraft.setScreen(null); //In case the user dies with the pad in the hand
}
double mx = (centerX - vx) / vw;
double my = (centerY - vy) / vh;
double scaledCentX = (mx * WebDisplays.INSTANCE.padResX);
double scaledCentY = (my * WebDisplays.INSTANCE.padResY);
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return false;
}
double deltX = scaledX - scaledCentX;
double deltY = scaledY - scaledCentY;
String scr = Scripts.MOUSE_EVENT;
pad.view.executeJavaScript(
scr
.replace("%xCoord%", "" + (int) centerX)
.replace("%yCoord%", "" + (int) centerY)
.replace("%xDelta%", "" + (deltX))
.replace("%yDelta%", "" + (deltY)),
"WebDisplays", 0
);
// lock mouse
try {
double xpos = (this.minecraft.getWindow().getScreenWidth() / 2);
double ypos = (this.minecraft.getWindow().getScreenHeight() / 2);
GLFW.glfwSetCursorPos(minecraft.getWindow().getWindow(), xpos, ypos);
} catch (Throwable ignored) {
}
}
public void mouse(int btn, boolean pressed, int sx, int sy, double scrollAmount) {
double mx = (sx - vx) / vw;
double my = (sy - vy) / vh;
if (pad.view != null && mx >= 0 && mx <= 1) {
//Scale again according to the webview
int scaledX = (int) (mx * WebDisplays.INSTANCE.padResX);
int scaledY = (int) (my * WebDisplays.INSTANCE.padResY);
if (btn == -1) {
if (locked)
capturedMouse(mx * WebDisplays.INSTANCE.padResX, my * WebDisplays.INSTANCE.padResY, sx, sy);
else ((MCEFBrowser) pad.view).sendMouseMove(scaledX, scaledY);
} else if (pressed)
((MCEFBrowser) pad.view).sendMousePress(scaledX, scaledY, btn);
else ((MCEFBrowser) pad.view).sendMouseRelease(scaledX, scaledY, btn);
pad.view.setFocus(true);
}
}
public static Optional<Character> getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if (keystr == null) {
keystr = "\0";
}
if (keyCode == GLFW.GLFW_KEY_ENTER) {
keystr = "\n";
}
if (keystr.length() == 0) {
return Optional.empty();
}
return Optional.of(keystr.charAt(keystr.length() - 1));
}
@Override
public void tick() {
if (pad.view == null)
minecraft.setScreen(null); //In case the user dies with the pad in the hand
pollElement();
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return false;
}
@Override
public void removed() {
super.removed();
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
Minecraft.getInstance().options.rawMouseInput().get()
);
if (pad.view instanceof MCEFBrowser browser) {
browser.setCursor(CefCursorType.POINTER);
browser.setCursorChangeListener((cursor) -> {
pad.activeCursor = cursor;
});
}
}
@Override
public void onClose() {
super.onClose();
removed();
this.minecraft.popGuiLayer();
}
boolean locked = false;
double lockCenterX = -1;
double lockCenterY = -1;
protected void updateCrd(JsonObject obj) {
if (obj.getAsJsonPrimitive("exists").getAsBoolean()) {
locked = true;
RenderSystem.recordRenderCall(() -> {
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
obj.getAsJsonPrimitive("unadjust").getAsBoolean()
);
GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), 208897, GLFW.GLFW_CURSOR_DISABLED);
});
lockCenterX = obj.getAsJsonPrimitive("x").getAsDouble() + obj.getAsJsonPrimitive("w").getAsDouble() / 2;
lockCenterY = obj.getAsJsonPrimitive("y").getAsDouble() + obj.getAsJsonPrimitive("h").getAsDouble() / 2;
} else {
if (locked) {
locked = false;
RenderSystem.recordRenderCall(()->{
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
Minecraft.getInstance().options.rawMouseInput().get()
);
GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), 208897, GLFW.GLFW_CURSOR_NORMAL);
GLFW.glfwSetCursor(Minecraft.getInstance().getWindow().getWindow(), CefCursorType.fromId(pad.activeCursor).glfwId);
});
}
}
}
protected void pollElement() {
if (pad.view instanceof WDBrowser browser) {
JsonObject object = browser.pointerLockElement().getObj();
if (object != null) updateCrd(object);
}
}
}

View File

@ -7,11 +7,17 @@ package net.montoyo.wd.client.gui;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.montoyo.mcef.api.API;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.TextField;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageRedstoneCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
import javax.annotation.Nullable;
@ -47,18 +53,18 @@ public class GuiRedstoneCtrl extends WDScreen {
tfFallingEdge.setText(fallingEdgeURL);
}
// @GuiSubscribe
// public void onClick(Button.ClickEvent ev) {
// if(ev.getSource() == btnOk) {
// API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF();
//
// String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText()));
// String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText()));
// WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageRedstoneCtrl(pos, rising, falling));
// }
//
// minecraft.setScreen(null);
// }
@GuiSubscribe
public void onClick(Button.ClickEvent ev) {
if(ev.getSource() == btnOk) {
API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF();
String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText()));
String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText()));
Messages.INSTANCE.sendToServer(new SMessageRedstoneCtrl(dimension, pos, rising, falling));
}
minecraft.setScreen(null);
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {

View File

@ -15,17 +15,11 @@ import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.gui.controls.*;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.item.WDItem;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -35,7 +29,7 @@ import java.util.UUID;
public class GuiScreenConfig extends WDScreen {
//Screen data
private final ScreenBlockEntity tes;
private final TileEntityScreen tes;
private final BlockSide side;
private NameUUIDPair owner;
private NameUUIDPair[] friends;
@ -124,7 +118,7 @@ public class GuiScreenConfig extends WDScreen {
private CheckBox[] friendBoxes;
private CheckBox[] otherBoxes;
public GuiScreenConfig(Component component, ScreenBlockEntity tes, BlockSide side, NameUUIDPair[] friends, int fr, int or) {
public GuiScreenConfig(Component component, TileEntityScreen tes, BlockSide side, NameUUIDPair[] friends, int fr, int or) {
super(component);
this.tes = tes;
this.side = side;
@ -139,20 +133,20 @@ public class GuiScreenConfig extends WDScreen {
loadFrom(new ResourceLocation("webdisplays", "gui/screencfg.json"));
friendBoxes = new CheckBox[] { boxFResolution, boxFUpgrades, boxFOthers, boxFFriends, boxFClick, boxFSetUrl };
boxFResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxFResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION);
boxFUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxFOthers.setUserdata(ScreenRights.MANAGE_OTHER_RIGHTS);
boxFFriends.setUserdata(ScreenRights.MANAGE_FRIEND_LIST);
boxFClick.setUserdata(ScreenRights.INTERACT);
boxFClick.setUserdata(ScreenRights.CLICK);
boxFSetUrl.setUserdata(ScreenRights.CHANGE_URL);
otherBoxes = new CheckBox[] { boxOResolution, boxOUpgrades, boxOClick, boxOSetUrl };
boxOResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxOResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION);
boxOUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxOClick.setUserdata(ScreenRights.INTERACT);
boxOClick.setUserdata(ScreenRights.CLICK);
boxOSetUrl.setUserdata(ScreenRights.CHANGE_URL);
ScreenData scr = tes.getScreen(side);
TileEntityScreen.Screen scr = tes.getScreen(side);
if(scr != null) {
owner = scr.owner;
rotation = scr.rotation;
@ -196,7 +190,7 @@ public class GuiScreenConfig extends WDScreen {
}
private void clickSetRes() {
ScreenData scr = tes.getScreen(side);
TileEntityScreen.Screen scr = tes.getScreen(side);
if(scr == null)
return; //WHATDAFUQ?
@ -207,7 +201,7 @@ public class GuiScreenConfig extends WDScreen {
throw new NumberFormatException(); //I'm lazy
if(x != scr.resolution.x || y != scr.resolution.y)
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.resolution(tes, side, new Vector2i(x, y)));
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.vec2(tes, side, SMessageScreenCtrl.CTRL_SET_RESOLUTION, new Vector2i(x, y)));
} catch(NumberFormatException ex) {
//Roll back
tfResX.setText("" + scr.resolution.x);
@ -225,7 +219,7 @@ public class GuiScreenConfig extends WDScreen {
clickSetRes();
else if(ev.getSource() == btnChangeRot) {
Rotation[] rots = Rotation.values();
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, rots[(rotation.ordinal() + 1) % rots.length]));
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, rots[(rotation.ordinal() + 1) % rots.length]));
}
}
@ -288,7 +282,7 @@ public class GuiScreenConfig extends WDScreen {
@GuiSubscribe
public void onRemovePlayer(List.EntryClick ev) {
if(ev.getSource() == lstFriends)
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, (NameUUIDPair) ev.getUserdata(), true));
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, (NameUUIDPair) ev.getUserdata(), true));
}
@GuiSubscribe
@ -318,12 +312,13 @@ public class GuiScreenConfig extends WDScreen {
} catch(NumberFormatException ex) {
cbLockRatio.setChecked(false);
}
} else if(ev.getSource() == cbAutoVolume) WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.autoVol(tes, side, ev.isChecked()));
} else if(ev.getSource() == cbAutoVolume)
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.autoVol(tes, side, ev.isChecked()));
}
@GuiSubscribe
public void onRemoveUpgrade(UpgradeGroup.ClickEvent ev) {
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, ev.getMouseOverStack()));
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, ev.getMouseOverStack()));
}
public boolean isFriendCheckbox(CheckBox cb) {
@ -344,7 +339,7 @@ public class GuiScreenConfig extends WDScreen {
if(adding) {
if(!hasFriend(pairs[0]))
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, pairs[0], false));
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, pairs[0], false));
tfFriend.setDisabled(false);
tfFriend.clear();
@ -433,7 +428,7 @@ public class GuiScreenConfig extends WDScreen {
@Override
protected void sync() {
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, friendRights, otherRights));
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, friendRights, otherRights));
Log.info("Sent sync packet");
}
@ -461,7 +456,7 @@ public class GuiScreenConfig extends WDScreen {
flag = (myRights & ScreenRights.MANAGE_OTHER_RIGHTS) == 0;
grpOthers.setDisabled(flag);
flag = (myRights & ScreenRights.MODIFY_SCREEN) == 0;
flag = (myRights & ScreenRights.CHANGE_RESOLUTION) == 0;
tfResX.setDisabled(flag);
tfResY.setDisabled(flag);
btnChangeRot.setDisabled(flag);
@ -508,16 +503,5 @@ public class GuiScreenConfig extends WDScreen {
return "Screen_Configurator";
}
// reason: allow closing the UI, lol
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
Minecraft.getInstance().setScreen(null);
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,147 +7,125 @@ package net.montoyo.wd.client.gui;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.Event;
import net.montoyo.wd.client.gui.controls.TextField;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.item.ItemMinePad2;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageMinepadUrl;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.Util;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessagePadCtrl;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
@Mod.EventBusSubscriber(Dist.CLIENT)
@Mod.EventBusSubscriber
public class GuiSetURL2 extends WDScreen {
//Screen data
private ScreenBlockEntity tileEntity;
private BlockSide screenSide;
private Vector3i remoteLocation;
//Pad data
private ItemStack stack;
private final boolean isPad;
//Common
private final String screenURL;
@FillControl
private TextField tfURL;
@FillControl
private Button btnShutDown;
@FillControl
private Button btnCancel;
@FillControl
private Button btnOk;
public GuiSetURL2(ScreenBlockEntity tes, BlockSide side, String url, Vector3i rl) {
super(Component.nullToEmpty(null));
tileEntity = tes;
screenSide = side;
remoteLocation = rl;
isPad = false;
screenURL = url;
}
public GuiSetURL2(ItemStack is, String url) {
super(Component.nullToEmpty(null));
isPad = true;
stack = is;
screenURL = url;
}
@Override
public void init() {
super.init();
loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json"));
tfURL.setText(screenURL);
}
@Override
protected void addLoadCustomVariables(Map<String, Double> vars) {
vars.put("isPad", isPad ? 1.0 : 0.0);
}
protected UUID getUUID() {
if (stack == null || !(stack.getItem() instanceof ItemMinePad2))
throw new RuntimeException("Get UUID is being called for a non-minepad UI");
if (!stack.hasTag() || !stack.getTag().contains("PadID"))
stack.getOrCreateTag().putUUID("PadID", UUID.randomUUID());
return stack.getTag().getUUID("PadID");
}
@GuiSubscribe
public void onButtonClicked(Button.ClickEvent ev) {
if (ev.getSource() == btnCancel)
minecraft.setScreen(null);
else if (ev.getSource() == btnOk)
validate(tfURL.getText());
else if (ev.getSource() == btnShutDown) {
if (isPad) {
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageMinepadUrl(
getUUID(),
""
));
stack.getTag().remove("PadID");
}
minecraft.setScreen(null);
}
}
@GuiSubscribe
public void onEnterPressed(TextField.EnterPressedEvent ev) {
validate(ev.getText());
}
private void validate(String url) {
if (!url.isEmpty()) {
try {
ScreenBlockEntity.url(url);
} catch (IOException e) {
throw new RuntimeException(e);
}
url = Util.addProtocol(url);
// url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url);
if (isPad) {
UUID uuid = getUUID();
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageMinepadUrl(uuid, url));
stack.getTag().putString("PadURL", url);
ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(uuid);
if (pd != null && pd.view != null) {
pd.view.loadURL(WebDisplays.applyBlacklist(url));
}
} else
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation));
}
minecraft.setScreen(null);
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide);
}
//Screen data
private TileEntityScreen tileEntity;
private BlockSide screenSide;
private Vector3i remoteLocation;
//Pad data
private final boolean isPad;
//Common
private final String screenURL;
@FillControl
private TextField tfURL;
@FillControl
private Button btnShutDown;
@FillControl
private Button btnCancel;
@FillControl
private Button btnOk;
public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url, Vector3i rl) {
super(Component.nullToEmpty(null));
tileEntity = tes;
screenSide = side;
remoteLocation = rl;
isPad = false;
screenURL = url;
}
public GuiSetURL2(String url) {
super(Component.nullToEmpty(null));
isPad = true;
screenURL = url;
}
@Override
public void init() {
super.init();
loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json"));
tfURL.setText(screenURL);
}
@Override
protected void addLoadCustomVariables(Map<String, Double> vars) {
vars.put("isPad", isPad ? 1.0 : 0.0);
}
@GuiSubscribe
public void onButtonClicked(Button.ClickEvent ev) {
if(ev.getSource() == btnCancel)
minecraft.setScreen(null);
else if(ev.getSource() == btnOk)
validate(tfURL.getText());
else if(ev.getSource() == btnShutDown) {
if(isPad)
Messages.INSTANCE.sendToServer(new SMessagePadCtrl(""));
minecraft.setScreen(null);
}
}
@GuiSubscribe
public void onEnterPressed(TextField.EnterPressedEvent ev) {
validate(ev.getText());
}
private void validate(String url) {
if(!url.isEmpty()) {
url = Util.addProtocol(url);
url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url);
if(isPad) {
Messages.INSTANCE.sendToServer(new SMessagePadCtrl(url));
ItemStack held = minecraft.player.getItemInHand(InteractionHand.MAIN_HAND);
if(held.getItem().equals(ItemInit.itemMinePad.get()) && held.getTag() != null && held.getTag().contains("PadID")) {
ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(held.getTag().getInt("PadID"));
if(pd != null && pd.view != null)
pd.view.loadURL(WebDisplays.applyBlacklist(url));
}
} else
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation));
}
minecraft.setScreen(null);
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide);
}
}

View File

@ -7,7 +7,6 @@ package net.montoyo.wd.client.gui;
import com.mojang.blaze3d.platform.Lighting;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.language.I18n;
@ -78,16 +77,15 @@ public class RenderRecipe extends Screen {
Log.info("Loaded %d recipes", recipes.size());
nextRecipe();
}
@Override
public void render(GuiGraphics context, int mouseX, int mouseY, float partialTick) {
// renderBackground(poseStack);
renderBackground(context);
public void render(PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
renderBackground(poseStack);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, CRAFTING_TABLE_GUI_TEXTURES);
// context.blit(x, y, 0, 0, SIZE_X, SIZE_Y);
// font.draw(poseStack, I18n.get("container.crafting"), x + 28, y + 6, 0x404040);
blit(poseStack, x, y, 0, 0, SIZE_X, SIZE_Y);
font.draw(poseStack, I18n.get("container.crafting"), x + 28, y + 6, 0x404040);
Lighting.setupForFlatItems();
// RenderSystem.disableLighting(); //TODO: Need this?
@ -100,15 +98,15 @@ public class RenderRecipe extends Screen {
int x = this.x + 30 + sx * 18;
int y = this.y + 17 + sy * 18;
context.renderItem(is, x, y);
context.renderItemDecorations(font, is, x, y);
renderItem.renderAndDecorateItem(minecraft.player, is, x, y, 0);
renderItem.renderGuiItemDecorations(font, is, x, y, null);
}
}
}
if(recipeResult != null) {
context.renderItem(recipeResult, x, y);
context.renderItemDecorations(font, recipeResult, x, y);
renderItem.renderAndDecorateItem(minecraft.player, recipeResult, x + 124, y + 35, 0);
renderItem.renderGuiItemDecorations(font, recipeResult, x + 124, y + 35, null);
}
// GlStateManager.enableLighting();
@ -129,7 +127,7 @@ public class RenderRecipe extends Screen {
}
}
// recipeResult = recipe.getResultItem();
recipeResult = recipe.getResultItem();
}
private void nextRecipe() {

View File

@ -7,12 +7,12 @@ package net.montoyo.wd.client.gui;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FormattedCharSequence;
@ -23,13 +23,10 @@ import net.montoyo.wd.client.gui.controls.Event;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.client.gui.loading.GuiLoader;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageACQuery;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageACQuery;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.data.Bounds;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.io.IOException;
@ -116,19 +113,17 @@ public abstract class WDScreen extends Screen {
}
@Override
public void render(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void render(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(defaultBackground)
renderBackground(poseStack);
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
for(Control ctrl: controls)
ctrl.draw(poseStack, mouseX, mouseY, ptt);
for(Control ctrl: postDrawList)
ctrl.postDraw(poseStack, mouseX, mouseY, ptt);
}
@Override
public boolean charTyped(char codePoint, int modifiers) {
boolean typed = false;
@ -143,21 +138,8 @@ public abstract class WDScreen extends Screen {
public boolean mouseClicked(double mouseX, double mouseY, int button) {
boolean clicked = false;
Control clickedEl = null;
for(Control ctrl: controls) {
clicked = ctrl.mouseClicked(mouseX, mouseY, button);
if (clicked) {
clickedEl = ctrl;
break; // don't assume the compiler will optimize stuff
}
}
if (clicked) {
for (Control control : controls) {
if (control != clickedEl)
control.unfocus();
}
}
for(Control ctrl: controls)
clicked = clicked || ctrl.mouseClicked(mouseX, mouseY, button);
return clicked;
}
@ -169,7 +151,7 @@ public abstract class WDScreen extends Screen {
for(Control ctrl: controls)
mouseReleased = mouseReleased || ctrl.mouseReleased(mouseX, mouseY, button);
return mouseReleased;
return mouseReleased || mouseClicked(mouseX, mouseY, button);
}
@Override
@ -185,7 +167,7 @@ public abstract class WDScreen extends Screen {
@Override
protected void init() {
CURRENT_SCREEN = this;
// minecraft.keyboardHandler.setSendRepeatsToGui(true);
minecraft.keyboardHandler.setSendRepeatsToGui(true);
}
@Override
@ -198,7 +180,7 @@ public abstract class WDScreen extends Screen {
for(Control ctrl : controls)
ctrl.destroy();
// Minecraft.getInstance().keyboardHandler.setSendRepeatsToGui(false);
Minecraft.getInstance().keyboardHandler.setSendRepeatsToGui(false);
CURRENT_SCREEN = null;
}
@ -227,9 +209,9 @@ public abstract class WDScreen extends Screen {
boolean down = false;
for (Control ctrl : controls)
down = down || ctrl.keyDown(keyCode, scanCode, modifiers);
down = down || ctrl.keyDown(keyCode);
if (this instanceof GuiKeyboard) {
if (Minecraft.getInstance().screen instanceof GuiKeyboard) {
return down;
} else {
return new GuiServer(new Vector3i(), new NameUUIDPair()).keyPressed(keyCode, scanCode, modifiers);
@ -241,7 +223,7 @@ public abstract class WDScreen extends Screen {
boolean up = false;
for(Control ctrl : controls)
up = up || ctrl.keyUp(keyCode, scanCode, modifiers);
up = up || ctrl.keyUp(keyCode);
return up || super.keyReleased(keyCode, scanCode, modifiers);
}
@ -282,9 +264,7 @@ public abstract class WDScreen extends Screen {
}
public void loadFrom(ResourceLocation resLoc) {
try {
JsonObject root = GuiLoader.getJson(resLoc);
JsonObject root = GuiLoader.getJson(resLoc);
if(root == null)
throw new RuntimeException("Could not load GUI file " + resLoc.toString());
@ -332,10 +312,6 @@ public abstract class WDScreen extends Screen {
if(root.has("center") && root.get("center").getAsBoolean())
centerControls();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
@ -348,7 +324,7 @@ public abstract class WDScreen extends Screen {
}
protected void requestAutocomplete(String beginning, boolean matchExact) {
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageACQuery(beginning, matchExact));
Messages.INSTANCE.sendToServer(new SMessageACQuery(beginning, matchExact));
}
public void onAutocompleteResult(NameUUIDPair pairs[]) {
@ -380,12 +356,12 @@ public abstract class WDScreen extends Screen {
}
}
public void drawItemStackTooltip(GuiGraphics poseStack, ItemStack is, int x, int y) {
poseStack.renderTooltip(Minecraft.getInstance().font, is, x, y); //Since it's protected...
public void drawItemStackTooltip(PoseStack poseStack, ItemStack is, int x, int y) {
renderTooltip(poseStack, is, x, y); //Since it's protected...
}
public void drawTooltip(GuiGraphics poseStack, List<String> lines, int x, int y) {
poseStack.renderTooltip(Minecraft.getInstance().font, lines.stream().map(a -> FormattedCharSequence.forward(a, Style.EMPTY)).collect(Collectors.toList()), x, y); //This is also protected...
public void drawTooltip(PoseStack poseStack, List<String> lines, int x, int y) {
renderTooltip(poseStack, lines.stream().map(a -> FormattedCharSequence.forward(a, Style.EMPTY)).collect(Collectors.toList()), x, y, font); //This is also protected...
}
public void requirePostDraw(Control ctrl) {

View File

@ -1,273 +0,0 @@
package net.montoyo.wd.client.gui.camera;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.event.ViewportEvent;
import net.minecraftforge.event.TickEvent;
import net.montoyo.wd.client.gui.GuiKeyboard;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.utilities.browser.WDBrowser;
import net.montoyo.wd.utilities.browser.handlers.js.queries.ElementCenterQuery;
import net.montoyo.wd.utilities.data.BlockSide;
public class KeyboardCamera {
private static ScreenBlockEntity tes;
private static BlockSide side;
private static double oxCrd = -1;
private static double xCrd = -1;
private static double nxCrd = -1;
private static double oyCrd = -1;
private static double yCrd = -1;
private static double nyCrd = -1;
private static double nextX = -1;
private static double nextY = -1;
private static double focalX = -1;
private static double focalY = -1;
private static final boolean[] mouseStatus = new boolean[2];
protected static Vec2 pxToHit(ScreenData scr, Vec2 dst) {
float cx, cy;
if (scr.rotation.isVertical) {
cy = dst.x;
cx = dst.y;
} else {
cx = dst.x;
cy = dst.y;
}
cx /= (float) scr.resolution.x;
cy /= (float) scr.resolution.y;
switch (scr.rotation) {
case ROT_270:
cx = 1.0f - cx;
break;
case ROT_180:
cx = 1.0f - cx;
cy = 1.0f - cy;
break;
case ROT_90:
cy = 1.0f - cy;
break;
}
if (side != BlockSide.BOTTOM)
cy = 1.0f - cy;
float swInverse = (((float) scr.size.x) - 4.f / 16.f);
float shInverse = (((float) scr.size.y) - 4.f / 16.f);
cx *= swInverse;
cy *= shInverse;
if (side.right.x > 0 || side.right.z > 0)
cx += 1.f;
if (side == BlockSide.TOP || side == BlockSide.BOTTOM)
cy -= 1.f;
return new Vec2(cx + (2 / 16f), cy + (2 / 16f));
}
protected static void updateCrd(ElementCenterQuery lock) {
ScreenData scr = tes.getScreen(side);
if (scr != null) {
Vec2 c;
if (!mouseStatus[0] && !mouseStatus[1]) {
if (lock.hasFocused()) {
if (ClientConfig.Input.keyboardCamera) {
nextX = lock.getX();
nextY = lock.getY();
c = pxToHit(scr, new Vec2((float) nextX, (float) nextY));
} else c = new Vec2(scr.size.x / 2f, scr.size.y / 2f);
} else c = new Vec2(scr.size.x / 2f, scr.size.y / 2f);
// } else c = new Vec2((float) focalX, (float) focalY);
} else return;
focalX = c.x;
focalY = c.y;
nextX = c.x;
nextY = c.y;
if (nextX < 0) nextX = 0;
else if (nextX > scr.size.x) nextX = scr.size.x;
if (nextY < 0) nextY = 0;
else if (nextY > scr.size.y) nextY = scr.size.y;
float scl = Math.max(scr.size.x, scr.size.y);
double mx = Minecraft.getInstance().mouseHandler.xpos();
mx /= Minecraft.getInstance().getWindow().getWidth();
double my = Minecraft.getInstance().mouseHandler.ypos();
my /= Minecraft.getInstance().getWindow().getHeight();
Vec2 v2 = new Vec2((float) mx, (float) my).add(-0.5f);
nextX += v2.x * scl;
nextY -= v2.y * scl;
}
}
protected static void pollElement() {
ScreenBlockEntity teTmp = tes;
BlockSide sdTmp = side;
// async nonsense can occur here
if (teTmp == null || sdTmp == null) return;
ScreenData scr = teTmp.getScreen(sdTmp);
if (scr != null) {
if (scr.browser instanceof WDBrowser wdBrowser) {
wdBrowser.focusedElement().dispatch(scr.browser);
updateCrd(((WDBrowser) scr.browser).focusedElement());
}
}
}
public static float[] getAngle(Entity e, double pct) {
BlockEntity tes = KeyboardCamera.tes;
BlockSide side = KeyboardCamera.side;
if (tes == null) return new float[]{Float.NaN, 0};
if (side == null) return new float[]{Float.NaN, 0};
double coxCrd = Mth.lerp(0.5 * pct, oxCrd, xCrd);
double coyCrd = Mth.lerp(0.5 * pct, oyCrd, yCrd);
double focalX = tes.getBlockPos().getX() +
side.right.x * (coxCrd - 1) + side.up.x * coyCrd + Math.abs(side.forward.x) * 0.5;
double focalY = tes.getBlockPos().getY() +
side.right.y * (coxCrd - 1) + side.up.y * coyCrd + Math.abs(side.forward.y) * 0.5;
double focalZ = tes.getBlockPos().getZ() +
side.right.z * (coxCrd - 1) + side.up.z * coyCrd + Math.abs(side.forward.z) * 0.5;
focalX += side.forward.x * 0.5f;
focalY += side.forward.y * 0.5f;
focalZ += side.forward.z * 0.5f;
float[] angle = lookAt(
e, EntityAnchorArgument.Anchor.EYES,
new Vec3(focalX, focalY, focalZ)
);
return angle;
}
public static void setMouse(int side, boolean pressed) {
mouseStatus[side] = pressed;
}
public static void updateCamera(ViewportEvent.ComputeCameraAngles event) {
if (tes == null) {
xCrd = -1;
yCrd = -1;
return; // nothing to do
}
if (xCrd == -1) return;
if (yCrd == -1) return;
float[] angle = getAngle(event.getCamera().getEntity(), event.getPartialTick());
if (Float.isNaN(angle[0])) return;
// float xRot = event.getYaw(); // left right
// float yRot = event.getPitch(); // up down
// TODO: smooth in/out
event.setYaw(angle[1]);
event.setPitch(angle[0]);
}
public static void focus(ScreenBlockEntity screen, BlockSide side) {
KeyboardCamera.tes = screen;
KeyboardCamera.side = side;
}
public static float[] lookAt(Entity entity, EntityAnchorArgument.Anchor pAnchor, Vec3 pTarget) {
Vec3 vec3 = pAnchor.apply(entity);
double d0 = pTarget.x - vec3.x;
double d1 = pTarget.y - vec3.y;
double d2 = pTarget.z - vec3.z;
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
float xr = (Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * (double) (180F / (float) Math.PI)))));
float yr = (Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * (double) (180F / (float) Math.PI)) - 90.0F));
return new float[]{xr, yr};
}
protected static int delay = 8;
public static void gameTick(TickEvent.ClientTickEvent event) {
if (mouseStatus[0] || mouseStatus[1]) {
oxCrd = Mth.lerp(0.5, oxCrd, xCrd);
oyCrd = Mth.lerp(0.5, oyCrd, yCrd);
return;
}
if (event.phase.equals(TickEvent.Phase.END)) {
if (side == null) {
delay = 1;
oxCrd = -1;
oyCrd = -1;
xCrd = -1;
yCrd = -1;
nxCrd = -1;
nyCrd = -1;
return;
}
if (!(Minecraft.getInstance().screen instanceof GuiKeyboard)) {
tes = null;
side = null;
return;
}
pollElement();
double anxx = nextX;
double anxy = nextY;
if (
anxx == -1 || anxy == -1 ||
nxCrd == -1 || nyCrd == -1 ||
oxCrd == -1 || oyCrd == -1 ||
xCrd == -1 || yCrd == -1
) {
ScreenData data = tes.getScreen(side);
if (data == null)
return;
anxx = data.size.x / 2.0;
anxy = data.size.y / 2.0;
if (nxCrd == -1) {
oxCrd = xCrd = anxx;
oyCrd = yCrd = anxy;
}
}
nxCrd = anxx;
nyCrd = anxy;
oxCrd = Mth.lerp(0.5, oxCrd, xCrd);
xCrd = Mth.lerp(0.15, xCrd, nxCrd);
oyCrd = Mth.lerp(0.5, oyCrd, yCrd);
yCrd = Mth.lerp(0.15, yCrd, nyCrd);
}
}
}

View File

@ -5,16 +5,10 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.glfw.GLFW;
import java.util.function.Supplier;
public class Button extends Control {
protected final net.minecraft.client.gui.components.Button btn;
@ -37,23 +31,17 @@ public class Button extends Control {
}
}
public Button() {
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(""), a -> {})
.bounds(0, 0, 0, 0)
.build();
btn = new net.minecraft.client.gui.components.Button(0,0, 0, 0, Component.nullToEmpty(null), a -> {});
}
public Button(String text, int x, int y, int width) {
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(text), a -> {})
.bounds(x, y, width, 20)
.build();
btn = new net.minecraft.client.gui.components.Button(x, y, width, 20, Component.nullToEmpty(text), a -> {});
}
public Button(String text, int x, int y) {
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(text), a -> {})
.bounds(0, 0, x, y)
.build();
btn = new net.minecraft.client.gui.components.Button(0, 0, x, y, Component.nullToEmpty(text), a -> {});
}
@Override
@ -83,8 +71,7 @@ public class Button extends Control {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
btn.setFGColor(16777215);
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
btn.render(poseStack, mouseX, mouseY, ptt);
}
@ -116,17 +103,18 @@ public class Button extends Control {
@Override
public void setPos(int x, int y) {
btn.setPosition(x, y);
btn.x = x;
btn.y = y;
}
@Override
public int getX() {
return btn.getX();
return btn.x;
}
@Override
public int getY() {
return btn.getY();
return btn.y;
}
public net.minecraft.client.gui.components.Button getMcButton() {
@ -170,7 +158,7 @@ public class Button extends Control {
}
@Override
public boolean keyUp(int key, int scanCode, int modifiers) {
public boolean keyUp(int key) {
if(key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT) {
shiftDown = false;
btn.setFGColor(originalColor);
@ -182,7 +170,7 @@ public class Button extends Control {
}
@Override
public boolean keyDown(int key, int scanCode, int modifiers) {
public boolean keyDown(int key) {
if(key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT) {
shiftDown = true;
btn.setFGColor(shiftColor);
@ -216,13 +204,11 @@ public class Button extends Control {
@Override
public void load(JsonOWrapper json) {
super.load(json);
btn.setPosition(
json.getInt("x", 0),
json.getInt("y", 0)
);
btn.x = json.getInt("x", 0);
btn.y = json.getInt("y", 0);
btn.setWidth(json.getInt("width", 200));
btn.setHeight(json.getInt("height", 20));
btn.setMessage(Component.nullToEmpty(tr(json.getString("label", btn.getMessage().getContents().toString()))));
btn.setMessage(Component.nullToEmpty(tr(json.getString("label", btn.getMessage().getContents()))));
btn.active = json.getBool("active", btn.active);
btn.visible = json.getBool("visible", btn.visible);

View File

@ -7,14 +7,17 @@ package net.montoyo.wd.client.gui.controls;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CheckBox extends BasicControl {
private static final ResourceLocation texUnchecked = new ResourceLocation("webdisplays", "textures/gui/checkbox.png");
@ -69,28 +72,29 @@ public class CheckBox extends BasicControl {
checked = !checked;
mc.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
parent.actionPerformed(new CheckedEvent(this));
return true;
}
return true;
}
return false;
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(visible) {
// GlStateManager.disableAlpha();
poseStack.pose().pushPose();
poseStack.pushPose();
RenderSystem.setShaderTexture(2, checked ? texChecked : texUnchecked);
RenderSystem.bindTexture(2);
RenderSystem.enableBlend();
poseStack.blit(
checked ? texChecked : texUnchecked, x, y, 0, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT
);
fillTexturedRect(poseStack, x, y, WIDTH, HEIGHT, 0.0, 0.0, 1.0, 1.0);
RenderSystem.disableBlend();
RenderSystem.bindTexture(-1);
poseStack.pose().popPose();
poseStack.popPose();
boolean inside = (!disabled && mouseX >= x && mouseX <= x + WIDTH + 2 + labelW && mouseY >= y && mouseY < y + HEIGHT);
poseStack.drawString(Minecraft.getInstance().font, label, x + WIDTH + 2, y + 4, inside ? 0xFF0080FF : COLOR_WHITE, false);
font.draw(poseStack, label, x + WIDTH + 2, y + 4, inside ? 0xFF0080FF : COLOR_WHITE);
}
}
@ -136,7 +140,7 @@ public class CheckBox extends BasicControl {
}
@Override
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(tooltip != null && !disabled && mouseX >= x && mouseX <= x + WIDTH + 2 + labelW && mouseY >= y && mouseY < y + HEIGHT)
parent.drawTooltip(poseStack, tooltip, mouseX, mouseY);
}

View File

@ -5,10 +5,10 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.GuiLoader;
import net.montoyo.wd.client.gui.loading.JsonAWrapper;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
@ -36,24 +36,24 @@ public abstract class Container extends BasicControl {
}
@Override
public boolean keyUp(int key, int scanCode, int modifiers) {
public boolean keyUp(int key) {
boolean up = false;
if(!disabled) {
for(Control ctrl : childs)
up = up || ctrl.keyUp(key, scanCode, modifiers);
up = up || ctrl.keyUp(key);
}
return up;
}
@Override
public boolean keyDown(int key, int scanCode, int modifiers) {
public boolean keyDown(int key) {
boolean down = false;
if(!disabled) {
for(Control ctrl : childs)
down = down || ctrl.keyDown(key, scanCode, modifiers);
down = down || ctrl.keyDown(key);
}
return down;
@ -67,10 +67,8 @@ public abstract class Container extends BasicControl {
mouseX -= x + paddingX;
mouseY -= y + paddingY;
for(Control ctrl : childs) {
clicked = ctrl.mouseClicked(mouseX, mouseY, mouseButton);
if (clicked) break; // don't assume compiler optimizations
}
for(Control ctrl : childs)
clicked = clicked || ctrl.mouseClicked(mouseX, mouseY, mouseButton);
}
return clicked;
@ -138,13 +136,13 @@ public abstract class Container extends BasicControl {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(visible) {
mouseX -= x + paddingX;
mouseY -= y + paddingY;
poseStack.pose().pushPose();
poseStack.pose().translate(x + paddingX, y + paddingY, 0.0);
poseStack.pushPose();
poseStack.translate(x + paddingX, y + paddingY, 0.0);
if(disabled) {
for(Control ctrl : childs)
@ -154,7 +152,7 @@ public abstract class Container extends BasicControl {
ctrl.draw(poseStack, mouseX, mouseY, ptt);
}
poseStack.pose().popPose();
poseStack.popPose();
}
}
@ -189,10 +187,4 @@ public abstract class Container extends BasicControl {
return null;
}
@Override
public void unfocus() {
for (Control control : childs) {
control.unfocus();
}
}
}

View File

@ -8,26 +8,20 @@ import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import net.minecraft.client.KeyboardHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.client.gui.WDScreen;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.data.Bounds;
import org.joml.Matrix4f;
import net.montoyo.wd.utilities.Bounds;
import org.lwjgl.glfw.GLFW;
import java.util.Arrays;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glEnable;
import static com.mojang.math.Axis.XP;
@OnlyIn(Dist.CLIENT)
public abstract class Control {
public static final int COLOR_BLACK = 0xFF000000;
@ -67,11 +61,11 @@ public abstract class Control {
return false;
}
public boolean keyUp(int key, int scanCode, int modifiers) {
public boolean keyUp(int key) {
return false;
}
public boolean keyDown(int key, int scanCode, int modifiers) {
public boolean keyDown(int key) {
return false;
}
@ -79,9 +73,6 @@ public abstract class Control {
return false;
}
public void unfocus() {
}
public boolean mouseReleased(double mouseX, double mouseY, int state) {
return false;
}
@ -98,10 +89,10 @@ public abstract class Control {
return false;
}
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
}
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
}
public void destroy() {
@ -117,7 +108,7 @@ public abstract class Control {
public abstract int getHeight();
public abstract void setPos(int x, int y);
public void fillRect(MultiBufferSource.BufferSource source, int x, double y, int w, int h, int color) {
public void fillRect(int x, double y, int w, int h, int color) {
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
@ -127,38 +118,34 @@ public abstract class Control {
int g = (color >> 8 ) & 0xFF;
int b = color & 0xFF;
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
RenderSystem.setShaderColor(1, 1, 1, 1f);
// RenderSystem.disableTexture();
RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f);
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
VertexConsumer consumer = source.getBuffer(RenderType.gui());
consumer.vertex(x1, y2, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x2, y2, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x2, y1, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x1, y1, 0.0).color(r, g, b, a).endVertex();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
vBuffer.vertex(x1, y2, 0.0).endVertex();
vBuffer.vertex(x2, y2, 0.0).endVertex();
vBuffer.vertex(x2, y1, 0.0).endVertex();
vBuffer.vertex(x1, y1, 0.0).endVertex();
tessellator.end();
RenderSystem.disableBlend();
// RenderSystem.enableTexture();
RenderSystem.enableTexture();glEnable(GL_TEXTURE_2D);
}
public void fillTexturedRect(PoseStack poseStack, int x, int y, int w, int h, double u1, double v1, double u2, double v2) {
float x1 = x;
float y1 = y;
float x2 = (x + w);
float y2 = (y + h);
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
double y2 = (double) (y + h);
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
Matrix4f p = poseStack.last().pose();
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
vBuffer.vertex(p, x1, y2, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v2).endVertex();
vBuffer.vertex(p, x2, y2, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v2).endVertex();
vBuffer.vertex(p, x2, y1, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v1).endVertex();
vBuffer.vertex(p, x1, y1, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v1).endVertex();
BufferUploader.drawWithShader(vBuffer.end());
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
vBuffer.vertex(x1, y2, 0.0).uv((float) u1, (float) v2).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x2, y2, 0.0).uv((float) u2, (float) v2).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x2, y1, 0.0).uv((float) u2, (float) v1).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x1, y1, 0.0).uv((float) u1, (float) v1).color(255, 255, 255, 255).endVertex();
tessellator.end();
}
public static void blend(boolean enable) {
@ -176,11 +163,11 @@ public abstract class Control {
RenderSystem.setShaderTexture(0, resLoc);
}
public void drawBorder(GuiGraphics poseStack, int x, int y, int w, int h, int color) {
public void drawBorder(PoseStack poseStack, int x, int y, int w, int h, int color) {
drawBorder(poseStack, x, y, w, h, color, 1.0);
}
public void drawBorder(GuiGraphics poseStack, int x, int y, int w, int h, int color, double sz) {
public void drawBorder(PoseStack poseStack, int x, int y, int w, int h, int color, double sz) {
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
@ -190,9 +177,8 @@ public abstract class Control {
int g = (color >> 8 ) & 0xFF;
int b = color & 0xFF;
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f);
// RenderSystem.enableTexture();
RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
@ -222,46 +208,36 @@ public abstract class Control {
vBuffer.vertex(x2 - sz, y1, 0.0).endVertex();
tessellator.end();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
RenderSystem.disableBlend();
// RenderSystem.enableTexture();
RenderSystem.enableTexture();
}
public GuiGraphics beginFramebuffer(RenderTarget fbo, float vpW, float vpH) {
GuiGraphics tmpGraphics = new GuiGraphics(Minecraft.getInstance(), Minecraft.getInstance().renderBuffers().bufferSource());
public PoseStack beginFramebuffer(RenderTarget fbo, float vpW, float vpH) {
fbo.bindWrite(true);
RenderSystem.backupProjectionMatrix();
RenderSystem.setProjectionMatrix(new Matrix4f().ortho(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f), VertexSorting.ORTHOGRAPHIC_Z);
RenderSystem.setProjectionMatrix(Matrix4f.orthographic(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f));
tmpGraphics.pose().last().pose().set(RenderSystem.getModelViewStack().last().pose());
tmpGraphics.pose().last().normal().set(RenderSystem.getModelViewStack().last().normal());
PoseStack poseStack = tmpGraphics.pose();
PoseStack poseStack = RenderSystem.getModelViewStack();
poseStack.pushPose();
poseStack.setIdentity();
poseStack.mulPose(XP.rotationDegrees(180.0f));
RenderSystem.getModelViewStack().pushPose();
RenderSystem.getModelViewStack().last().pose().set(poseStack.last().pose());
RenderSystem.getModelViewStack().last().normal().set(poseStack.last().normal());
// poseStack.mulPose(Vector3f.XP.rotationDegrees(180.0f));
RenderSystem.applyModelViewMatrix();
if(!fbo.useDepth)
RenderSystem.disableDepthTest();
return tmpGraphics;
return poseStack;
}
public void endFramebuffer(GuiGraphics poseStack, RenderTarget fbo) {
public void endFramebuffer(PoseStack poseStack, RenderTarget fbo) {
if(!fbo.useDepth)
RenderSystem.enableDepthTest();
RenderSystem.colorMask(true, true, true, true);
RenderSystem.restoreProjectionMatrix();
poseStack.pose().popPose();
RenderSystem.getModelViewStack().popPose();
poseStack.popPose();
RenderSystem.applyModelViewMatrix();
fbo.unbindWrite();
mc.getMainRenderTarget().bindWrite(true);

View File

@ -7,13 +7,12 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.data.Bounds;
import net.montoyo.wd.utilities.Bounds;
import java.util.Arrays;
import static org.lwjgl.opengl.GL11.*;
public class ControlGroup extends Container {
@ -95,23 +94,22 @@ public class ControlGroup extends Container {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
super.draw(poseStack, mouseX, mouseY, ptt);
if(visible) {
poseStack.pose().pushPose();
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
poseStack.pushPose();
RenderSystem.setShaderColor(0.5f, 0.5f, 0.5f, 1.f);
// RenderSystem.disableTexture();
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
double x1 = x;
double y1 = y;
double x2 = (x + width);
double y2 = (y + height);
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + width);
double y2 = (double) (y + height);
double bp = 4.0;
double lw = labelW;
double lw = (double) labelW;
x1 += bp;
y1 += bp;
@ -160,14 +158,12 @@ public class ControlGroup extends Container {
vBuffer.vertex(x2 - 1.0, y1, 0.0).endVertex();
tessellator.end();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
RenderSystem.disableBlend();
// RenderSystem.enableTexture();
poseStack.pose().popPose();
RenderSystem.enableTexture();
poseStack.popPose();
if(labelW != 0)
poseStack.drawString(Minecraft.getInstance().font, label, x + 10 + ((int) bp), y, labelColor, labelShadowed);
font.drawShadow(poseStack, label, x + 10 + ((int) bp), y, labelColor, labelShadowed);
}
}
@ -180,13 +176,6 @@ public class ControlGroup extends Container {
height = bounds.getHeight() + paddingY * 2;
}
@Override
public void unfocus() {
for (Control control : childs) {
control.unfocus();
}
}
@Override
public void load(JsonOWrapper json) {
super.load(json);

View File

@ -6,10 +6,8 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
public class Icon extends BasicControl {
@ -46,17 +44,17 @@ public class Icon extends BasicControl {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(texture != null) {
poseStack.pose().pushPose();
// RenderSystem.enableTexture();
poseStack.pushPose();
RenderSystem.enableTexture();
RenderSystem.setShaderTexture(1, texture);
RenderSystem.bindTexture(1);
RenderSystem.enableBlend();
fillTexturedRect(poseStack.pose(), x, y, width, height, u1, v1, u2, v2);
fillTexturedRect(poseStack, x, y, width, height, u1, v1, u2, v2);
RenderSystem.disableBlend();
RenderSystem.bindTexture(-1);
poseStack.pose().popPose();
poseStack.popPose();
}
}

View File

@ -5,8 +5,6 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
public class Label extends BasicControl {
@ -74,12 +72,9 @@ public class Label extends BasicControl {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(visible)
poseStack.drawString(
Minecraft.getInstance().font,
label, x, y, color, shadowed
);
font.drawShadow(poseStack, label, x, y, color, shadowed);
}
@Override

View File

@ -9,13 +9,8 @@ import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.network.chat.TextComponent;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import java.util.ArrayList;
@ -101,21 +96,19 @@ public class List extends BasicControl {
if(fbo != null)
fbo.destroyBuffers();
fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), true, Minecraft.ON_OSX);
fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), false, Minecraft.ON_OSX);
fbo.setFilterMode(GL_NEAREST);
fbo.bindWrite(true);
fbo.bindWrite(false);
RenderSystem.clearColor(0.0f, 0.0f, 0.0f, 1.f); //Set alpha to 1
RenderSystem.clearDepth(GL_COLOR_BUFFER_BIT);
fbo.unbindWrite();
mc.getMainRenderTarget().bindWrite(true);
update = true;
}
private void renderToFBO(MultiBufferSource.BufferSource source) {
GuiGraphics graphics = beginFramebuffer(fbo, width, height);
GL11.glColorMask(true, true, true, true);
RenderSystem.applyModelViewMatrix();
graphics.fill(0, 0, width, height, COLOR_BLACK);
private void renderToFBO() {
PoseStack poseStack = beginFramebuffer(fbo, width, height);
poseStack.pushPose();
fillRect(0, 0, width, height, COLOR_BLACK);
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
int offset = 4 - getYOffset();
@ -127,13 +120,13 @@ public class List extends BasicControl {
break;
int color = (i == selected) ? selColor : COLOR_WHITE;
graphics.drawString(font, content.get(i).text, 4, i * 12 + offset, color);
font.draw(poseStack, content.get(i).text, 4, i * 12 + offset, color);
}
}
graphics.renderOutline(0, 0, width, height, 0xFF808080);
graphics.flush();
endFramebuffer(graphics, fbo);
drawBorder(poseStack, 0, 0, width, height, 0xFF808080);
endFramebuffer(poseStack, fbo);
poseStack.popPose();
}
@Override
@ -248,16 +241,13 @@ public class List extends BasicControl {
if(isInScrollbar(mouseX, mouseY)) {
scrolling = true;
scrollGrab = mouseY - (y + 1 + scrollPos);
return true;
} else if(selected >= 0) {
System.out.println(parent.actionPerformed(new EntryClick(this)));
return true;
}
} else if(selected >= 0)
parent.actionPerformed(new EntryClick(this));
return false;
return true;
}
return false;
return true;
}
@Override
@ -318,18 +308,19 @@ public class List extends BasicControl {
}
@Override
public void draw(GuiGraphics graphics, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(visible) {
if(update) {
renderToFBO(graphics.bufferSource());
renderToFBO();
update = false;
}
RenderSystem.setShaderTexture(0, fbo.getColorTextureId());
fbo.bindRead(); //TODO: Make sure is right
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
fillTexturedRect(graphics.pose(), x, y, width, height, 0.0, 1.0, 1.0, 0.0);
fillTexturedRect(poseStack, x, y, width, height, 0.0, 1.0, 1.0, 0.0);
fbo.unbindRead();
fillRect(graphics.bufferSource(), x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040);
fillRect(x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040);
}
}

View File

@ -5,18 +5,13 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.Component;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.cef.browser.CefBrowserOsr;
import org.lwjgl.glfw.GLFW;
import java.util.ArrayList;
import static java.awt.event.KeyEvent.VK_ENTER;
import static org.lwjgl.glfw.GLFW.*;
public class TextField extends Control {
public static class EnterPressedEvent extends Event<TextField> {
@ -99,48 +94,40 @@ public class TextField extends Control {
public TextField() {
field = new EditBox(font, 1, 1, 198, 20, Component.nullToEmpty(""));
setFocused(false);
}
public TextField(int x, int y, int width, int height) {
field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty(""));
setFocused(false);
}
public TextField(int x, int y, int width, int height, String text) {
field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty(""));
field.setValue(text);
setFocused(false);
}
// TODO: make this public static in CefBrowserOSR
private long mapScanCode(int key, char c) {
if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL) return 29;
return switch (key) {
case GLFW_KEY_DELETE -> 83;
case GLFW_KEY_LEFT -> 75;
case GLFW_KEY_DOWN -> 80;
case GLFW_KEY_UP -> 72;
case GLFW_KEY_RIGHT -> 77;
case GLFW_KEY_PAGE_DOWN -> 81;
case GLFW_KEY_PAGE_UP -> 73;
case GLFW_KEY_END -> 79;
case GLFW_KEY_HOME -> 71;
case VK_ENTER, GLFW_KEY_ENTER, GLFW_KEY_KP_ENTER -> 28;
default -> GLFW.glfwGetKeyScancode(key);
};
}
@Override
public boolean keyDown(int key, int scanCode, int modifiers) {
return field.keyPressed(key, scanCode, modifiers);
public boolean keyDown(int key) {
if(key == GLFW.GLFW_KEY_BACKSPACE) {
String old;
if(enabled && field.isFocused())
old = field.getValue();
else
old = null;
if(field.getValue().length() > 0)
field.setValue(field.getValue().substring(0, field.getValue().length() - 1));
if(enabled && field.isFocused() && !field.getValue().equals(old)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, field.getValue());
parent.actionPerformed(new TextChangedEvent(this, old));
}
}
return false;
}
@Override
public boolean keyUp(int key, int scanCode, int modifiers) {
return field.keyReleased(key, scanCode, modifiers);
}
@Override
public boolean keyTyped(int keyCode, int modifier) {
if(keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER)
@ -154,56 +141,26 @@ public class TextField extends Control {
else
old = null;
field.charTyped((char) keyCode, modifier);
if(enabled && field.isFocused() && !field.getValue().equals(old)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, field.getValue());
parent.actionPerformed(new TextChangedEvent(this, old));
}
return field.charTyped((char) keyCode, modifier);
}
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
if (field.mouseClicked(mouseX, mouseY, mouseButton)) {
setFocused(true);
return true;
}
return false;
return field.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override
public void unfocus() {
setFocused(false);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
return field.mouseReleased(mouseX, mouseY, state);
}
@Override
public boolean mouseClickMove(double mouseX, double mouseY, int button, double dragX, double dragY) {
return field.mouseClicked(mouseX, mouseY, 0);
}
@Override
public boolean mouseMove(double mouseX, double mouseY) {
field.mouseMoved(mouseX, mouseY);
return true;
}
@Override
public boolean mouseScroll(double mouseX, double mouseY, double amount) {
return field.mouseScrolled(mouseX, mouseY, amount);
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
field.render(poseStack, mouseX, mouseY, ptt);
}
@ -254,26 +211,23 @@ public class TextField extends Control {
@Override
public void setPos(int x, int y) {
field.setPosition(
x + 1,
y + 1
);
field.x = x + 1;
field.y = y + 1;
}
@Override
public int getX() {
return field.getX() - 1;
return field.x - 1;
}
@Override
public int getY() {
return field.getY() - 1;
return field.y - 1;
}
public void setDisabled(boolean en) {
enabled = !en;
if (!en)
field.setFocused(false);
field.setFocus(enabled);
}
public boolean isDisabled() {
@ -281,11 +235,12 @@ public class TextField extends Control {
}
public void enable() {
field.setFocus(true);
enabled = true;
}
public void disable() {
field.setFocused(false);
field.setFocus(false);
enabled = false;
}
@ -306,7 +261,7 @@ public class TextField extends Control {
}
public void setFocused(boolean val) {
field.setFocused(val);
field.setFocus(val);
}
public boolean hasFocus() {
@ -314,7 +269,15 @@ public class TextField extends Control {
}
public void focus() {
field.setFocused(true);
field.setFocus(true);
}
public void setMaxLength(int len) {
field.setMaxLength(len);
}
public int getMaxLength() {
return field.getMaxLength(); //TODO: access transformer
}
public void setTextColor(int color) {
@ -351,10 +314,8 @@ public class TextField extends Control {
@Override
public void load(JsonOWrapper json) {
super.load(json);
field.setPosition(
json.getInt("x", 0) + 1,
json.getInt("y", 0) + 1
);
field.x = json.getInt("x", 0) + 1;
field.y = json.getInt("y", 0) + 1;
field.setWidth(json.getInt("width", 200) - 2);
field.setHeight(json.getInt("height", 22) - 2);
field.setValue(tr(json.getString("text", "")));
@ -367,7 +328,7 @@ public class TextField extends Control {
field.setTextColor(textColor);
field.setTextColorUneditable(disabledColor);
setFocused(false);
field.setFocus(enabled);
}
}

View File

@ -6,10 +6,9 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.IEventBus;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import java.util.ArrayList;
@ -28,23 +27,23 @@ public class UpgradeGroup extends BasicControl {
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(upgrades != null) {
int x = this.x;
for(ItemStack is: upgrades) {
if(is == overStack && !disabled)
fillRect(poseStack.bufferSource(), x, y, 16, 16, 0x80FF0000);
fillRect(x, y, 16, 16, 0x80FF0000);
poseStack.renderItem(is, x, y);
poseStack.renderItemDecorations(font, is, x, y);
renderItem.renderAndDecorateItem(mc.player, is, x, y, 0);
renderItem.renderAndDecorateItem(is, font.lineHeight, x, y); //TODO is lineHeight right?
x += 18;
}
}
}
@Override
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
if(overStack != null)
parent.drawItemStackTooltip(poseStack, overStack, mouseX, mouseY);
}
@ -104,15 +103,9 @@ public class UpgradeGroup extends BasicControl {
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
if(mouseButton == 0) {
// don't process the click if it's not inbounds, lol
if (
mouseX >= x && mouseX <= x + width &&
mouseY >= y && mouseX <= y + height
) {
clickStack = overStack;
return true;
}
clickStack = overStack;
return true;
}
return false;

View File

@ -6,7 +6,7 @@ package net.montoyo.wd.client.gui.controls;
import net.minecraft.network.chat.Component;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.serialization.Util;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.VideoType;
import java.net.MalformedURLException;

View File

@ -62,15 +62,24 @@ public class GuiLoader {
return ret;
}
public static JsonObject getJson(ResourceLocation resLoc) throws IOException {
public static JsonObject getJson(ResourceLocation resLoc) {
JsonObject ret = RESOURCES.get(resLoc);
if(ret == null) {
Resource resource;
resource = Minecraft.getInstance().getResourceManager().getResource(resLoc).get();
try {
resource = Minecraft.getInstance().getResourceManager().getResource(resLoc);
} catch(IOException e) {
Log.errorEx("Couldn't load JSON UI from file", e);
throw new RuntimeException(e);
}
JsonParser parser = new JsonParser();
ret = parser.parse(new InputStreamReader(resource.open())).getAsJsonObject();
ret = parser.parse(new InputStreamReader(resource.getInputStream())).getAsJsonObject();
try {
resource.close();
} catch(IOException e) {}
RESOURCES.put(resLoc, ret);
}

View File

@ -9,17 +9,7 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.item.ItemStack;
public interface IItemRenderer {
/**
* @param pose the pose stack
* @param stack the item stack
* @param handSideSign TODO:
* @param swingProgress TODO:
* @param equipProgress TODO:
* @param multiBufferSource the buffer source
* @param packedLight packed light
* @return whether or not to cancel vanilla rendering
*/
boolean render(PoseStack pose, ItemStack stack, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight);
void render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight);
}

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client.renderers;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
public interface IModelBaker extends IDynamicBakedModel{
void loadTextures(TextureAtlas texMap);
}

View File

@ -4,127 +4,112 @@
package net.montoyo.wd.client.renderers;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.registry.ItemRegistry;
import net.montoyo.wd.item.ItemLaserPointer;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import static com.mojang.math.Axis.*;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
@OnlyIn(Dist.CLIENT)
public final class LaserPointerRenderer implements IItemRenderer {
private final Tesselator t = Tesselator.getInstance();
private final BufferBuilder bb = t.getBuilder();
public LaserPointerRenderer() {
}
public static boolean isOn() {
if (Minecraft.getInstance().screen != null) return false;
Minecraft mc = Minecraft.getInstance();
return mc.player != null && mc.level != null &&
(
ClientProxy.mouseOn ||
ItemLaserPointer.isOn()
) &&
mc.player.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemRegistry.LASER_POINTER.get()) &&
(mc.hitResult == null || mc.hitResult.getType() == HitResult.Type.BLOCK || mc.hitResult.getType() == HitResult.Type.MISS);
}
@Override
public boolean render(PoseStack poseStack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
RenderSystem.disableCull();
// RenderSystem.disableTexture();
RenderSystem.enableDepthTest();
RenderSystem.enableBlend();
float PI = (float) Math.PI;
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
float sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
RenderSystem.setShader(GameRenderer::getPositionColorShader);
var matrix0 = poseStack.last().pose();
//Laser pointer
poseStack.pushPose();
poseStack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, (float) (0.2f * Math.sin(sqrtSwingProg * PI * 2.0f)), (float) (-0.2f * Math.sin(swingProgress * PI)));
poseStack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
poseStack.mulPose(YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f))));
poseStack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
poseStack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
poseStack.mulPose(YP.rotationDegrees(handSideSign * -30.0f));
poseStack.translate(0.0f, 0.2f, 0.0f);
poseStack.mulPose(XP.rotationDegrees(10.0f));
poseStack.scale(1.0f / 16.0f, 1.0f / 16.0f, 1.0f / 16.0f);
var matrix = poseStack.last().pose();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
bb.vertex(matrix, 0.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
if (isOn()) drawLineBetween(bb, matrix0, matrix, new Vec3(0.5f, -0.5f, 0.5f), new Vec3(-40.0f, 4000.5f, -100.0f));
t.end();
RenderSystem.disableBlend();
RenderSystem.disableDepthTest();
// RenderSystem.enableTexture(); //Fix for shitty minecraft fire
RenderSystem.enableCull();
poseStack.popPose();
return true;
}
private static void drawLineBetween(BufferBuilder bb, Matrix4f matrix0, Matrix4f matrix, Vec3 local, Vec3 target) {
//Calculate distance between points -> length of the line
float distance = (float) local.distanceTo(target) / 2;
float quarterWidth = 0.25f;
float biggerWidth = 10;
bb.vertex(matrix, 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, 0.25f, -quarterWidth - 0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, -biggerWidth + 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -quarterWidth - 0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, -biggerWidth + 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
}
private static final float PI = (float) Math.PI;
private final Tesselator t = Tesselator.getInstance();
private final BufferBuilder bb = t.getBuilder();
private final VertexBuffer vb = new VertexBuffer();
private final FloatBuffer matrix1 = BufferUtils.createFloatBuffer(16);
private final FloatBuffer renderBuffer = BufferUtils.createFloatBuffer(8);
public boolean isOn = false;
public LaserPointerRenderer() {
for(int i = 0; i < 8; i++)
renderBuffer.put(0.0f);
renderBuffer.position(0);
}
@Override
public void render(PoseStack poseStack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//This whole method is a fucking hack
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
float sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
RenderSystem.disableCull();
RenderSystem.disableTexture();
poseStack.pushPose();
//Laser pointer
poseStack.pushPose();
poseStack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, (float) (0.2f * Math.sin(sqrtSwingProg * PI * 2.0f)), (float) (-0.2f * Math.sin(swingProgress * PI)));
poseStack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
poseStack.mulPose(Vector3f.YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f))));
poseStack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
poseStack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
poseStack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -30.0f));
poseStack.translate(0.0f, 0.2f, 0.0f);
poseStack.mulPose(Vector3f.XP.rotationDegrees(10.0f));
poseStack.scale(1.0f / 16.0f, 1.0f / 16.0f, 1.0f / 16.0f);
RenderSystem.setShaderColor(0.5f, 0.5f, 0.5f, 1.0f);
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bb.vertex(0.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 0.0).endVertex();
bb.vertex(0.0, -1.0, 0.0).endVertex();
bb.vertex(0.0, -1.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, -1.0, 0.0).endVertex();
bb.vertex(1.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
t.end();
if(isOn) {
poseStack.translate(0.5f, -0.5f, 0.0f);
matrix1.position(0);
RenderSystem.getModelViewMatrix(); //Hax to get that damn position
}
poseStack.popPose();
if(isOn) {
//Actual laser
poseStack.pushPose();
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.DST_ALPHA);
RenderSystem.setShaderColor(1.0f, 0.0f, 0.0f, 0.5f);
RenderSystem.lineWidth(3.0f);
matrix1.position(12);
renderBuffer.put(matrix1.get());
renderBuffer.put(matrix1.get());
renderBuffer.put(matrix1.get() - 0.02f); //I know this is stupid, but it's the only thing that worked...
renderBuffer.put(matrix1.get());
renderBuffer.position(0);
RenderSystem.drawElements(GL_LINES, 0, GL_UNSIGNED_INT);
poseStack.popPose();
}
RenderSystem.enableTexture(); //Fix for shitty minecraft fire
RenderSystem.enableCull();
}
}

View File

@ -4,161 +4,132 @@
package net.montoyo.wd.client.renderers;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.item.ItemMinePad2;
import static com.mojang.math.Axis.*;
import static org.lwjgl.opengl.GL12.GL_RESCALE_NORMAL;
@OnlyIn(Dist.CLIENT)
public final class MinePadRenderer implements IItemRenderer {
private static final float PI = (float) Math.PI;
private final Minecraft mc = Minecraft.getInstance();
private final ResourceLocation tex = new ResourceLocation("webdisplays", "textures/item/model/minepad.png");
private final ModelMinePad model = new ModelMinePad();
private final ClientProxy clientProxy = (ClientProxy) WebDisplays.PROXY;
private float sinSqrtSwingProg1;
private float sinSqrtSwingProg2;
private float sinSwingProg1;
private float sinSwingProg2;
public static boolean renderAtSide(float handSideSign) {
float relSide = handSideSign;
if (Minecraft.getInstance().player.getMainArm() == HumanoidArm.LEFT) relSide *= -1;
// by default, the player holds the device off to the side
// if they are crouching, they hold it infront of them
// however, if they are holding two at once, then it once again should just be held off to the side
boolean sideHold = Minecraft.getInstance().player.isShiftKeyDown() != ClientConfig.sidePad;
if (
(relSide < 0 && Minecraft.getInstance().player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof ItemMinePad2) ||
(relSide > 0 && Minecraft.getInstance().player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof ItemMinePad2)
) sideHold = true;
return sideHold;
}
@Override
public final boolean render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//Pre-compute values
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
sinSqrtSwingProg2 = (float) Math.sin(sqrtSwingProg * PI * 2.0f);
sinSwingProg1 = (float) Math.sin(swingProgress * PI);
sinSwingProg2 = (float) Math.sin(swingProgress * swingProgress * PI);
boolean sideHold = renderAtSide(handSideSign);
//Render arm
stack.pushPose();
renderArmFirstPerson(stack, multiBufferSource, packedLight, equipProgress, handSideSign);
stack.popPose();
// if (!sideHold && handSideSign == 1 && mc.player.getItemInHand(InteractionHand.OFF_HAND).isEmpty()) {
// stack.pushPose();
// renderArmFirstPerson(stack, multiBufferSource, packedLight, 0, -handSideSign);
// stack.popPose();
// }
//Prepare minePad transform
stack.pushPose();
stack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, 0.2f * sinSqrtSwingProg2, -0.2f * sinSwingProg1);
stack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
stack.mulPose(YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f)));
stack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
stack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * -45.0f));
if (sideHold) {
stack.translate(0.0f, 0.0f, -0.2f);
stack.mulPose(YP.rotationDegrees(20.0f * -handSideSign));
float total = 0.475f;
float off = -0.025f; // gotta love magic numbers
stack.translate(-(total - off) + (off * handSideSign), -0.1f, 0.0f);
stack.mulPose(ZP.rotationDegrees(1.0f));
} else if (handSideSign >= 0) // right hand
stack.translate(-1.065f, 0.0f, 0.0f);
else // left hand
stack.translate(0.065f, 0.0f, 0.0f);
//Render model
stack.translate(0.063f, 0.28f, 0.001f);
model.render(multiBufferSource, stack);
stack.translate(-0.063f, -0.28f, -0.001f);
// force draw so the browser can be drawn ontop of the model
multiBufferSource.getBuffer(RenderType.LINES);
if (is.getTag() != null && is.getTag().contains("PadID")) {
ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getUUID("PadID"));
//Render web view
if (pd != null) {
double x1 = 0.0;
double y1 = 0.0;
double x2 = 27.65 / 32.0 + 0.01;
double y2 = 14.0 / 32.0 + 0.002;
stack.translate(0.063f, 0.28f, 0.001f);
// RenderSystem.setShaderTexture(0, tex);
RenderSystem.disableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem.setShaderTexture(0, ((MCEFBrowser) pd.view).getRenderer().getTextureID());
Tesselator t = Tesselator.getInstance();
BufferBuilder buffer = t.getBuilder();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
buffer.vertex(stack.last().pose(), (float) x1, (float) y1, 0.0f).uv(0.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x2, (float) y1, 0.0f).uv(1.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x2, (float) y2, 0.0f).uv(1.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x1, (float) y2, 0.0f).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex();
t.end();
RenderSystem.enableDepthTest();
}
}
stack.popPose();
RenderSystem.enableCull();
return true;
}
private void renderArmFirstPerson(PoseStack stack, MultiBufferSource buffer, int combinedLight, float equipProgress, float handSideSign) {
float tx = -0.3f * sinSqrtSwingProg1;
float ty = 0.4f * sinSqrtSwingProg2;
float tz = -0.4f * sinSwingProg1;
stack.translate(handSideSign * (tx + 0.64000005f), ty - 0.6f - equipProgress * 0.6f, tz - 0.71999997f);
stack.mulPose(YP.rotationDegrees(handSideSign * 45.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f));
stack.mulPose(ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f));
stack.translate(-handSideSign, 3.6f, 3.5f);
stack.mulPose(ZP.rotationDegrees(handSideSign * 120.0f));
stack.mulPose(XP.rotationDegrees(200.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * -135.0f));
stack.translate(handSideSign * 5.6f, 0.0f, 0.0f);
PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(mc.player);
RenderSystem.setShaderTexture(0, mc.player.getSkinTextureLocation());
if (handSideSign >= 0.0f)
playerRenderer.renderRightHand(stack, buffer, combinedLight, mc.player);
else
playerRenderer.renderLeftHand(stack, buffer, combinedLight, mc.player);
}
private static final float PI = (float) Math.PI;
private final Minecraft mc = Minecraft.getInstance();
private final ResourceLocation tex = new ResourceLocation("webdisplays", "textures/models/minepad.png");
// private final ModelMinePad model = new ModelMinePad();
private final ClientProxy clientProxy = (ClientProxy) WebDisplays.PROXY;
private float sinSqrtSwingProg1;
private float sinSqrtSwingProg2;
private float sinSwingProg1;
private float sinSwingProg2;
// public static void drawAxis() {
// glDisable(GL_TEXTURE_2D);
// glBegin(GL_LINES);
// glColor4f(1.f, 0.f, 0.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(1.f, 0.f, 0.f, 1.f); glVertex3d(5.0, 0.0, 0.0);
// glColor4f(0.f, 1.f, 0.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(0.f, 1.f, 0.f, 1.f); glVertex3d(0.0, 5.0, 0.0);
// glColor4f(0.f, 0.f, 1.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(0.f, 0.f, 1.f, 1.f); glVertex3d(0.0, 0.0, 5.0);
// glEnd();
// glEnable(GL_TEXTURE_2D);
// }
@Override
public final void render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//Pre-compute values
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
sinSqrtSwingProg2 = (float) Math.sin(sqrtSwingProg * PI * 2.0f);
sinSwingProg1 = (float) Math.sin(swingProgress * PI);
sinSwingProg2 = (float) Math.sin(swingProgress * swingProgress * PI);
RenderSystem.disableCull();
// glEnable(GL_RESCALE_NORMAL);
//Render arm
stack.pushPose();
renderArmFirstPerson(stack, multiBufferSource, packedLight, equipProgress, handSideSign);
stack.popPose();
//Prepare minePad transform
stack.pushPose();
stack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, 0.2f * sinSqrtSwingProg2, -0.2f * sinSwingProg1);
stack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f)));
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
stack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -45.0f));
if(handSideSign >= 0.0f)
stack.translate(-1.065f, 0.0f, 0.0f);
else {
stack.translate(0.0f, 0.0f, -0.2f);
stack.mulPose(Vector3f.YP.rotationDegrees(20.0f));
stack.translate(-0.475f, -0.1f, 0.0f);
stack.mulPose(Vector3f.ZP.rotationDegrees(1.0f));
}
//Render model
stack.pushPose();
stack.mulPose(Vector3f.XP.rotationDegrees(-90.0f));
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, tex);
// model.render(1.f / 16.f);
stack.popPose();
//Render web view
if(is.getTag() != null && is.getTag().contains("PadID")) {
ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getInt("PadID"));
if(pd != null) {
stack.translate(0.063f, 0.28f, 0.001f);
RenderSystem.disableTexture();
pd.view.draw(stack,0.0, 0.0, 27.65 / 32.0 + 0.01, 14.0 / 32.0 + 0.002);
}
}
stack.popPose();
// glDisable(GL_RESCALE_NORMAL);
RenderSystem.enableCull();
}
private void renderArmFirstPerson(PoseStack stack, MultiBufferSource buffer, int combinedLight, float equipProgress, float handSideSign) {
float tx = -0.3f * sinSqrtSwingProg1;
float ty = 0.4f * sinSqrtSwingProg2;
float tz = -0.4f * sinSwingProg1;
stack.translate(handSideSign * (tx + 0.64000005f), ty - 0.6f - equipProgress * 0.6f, tz - 0.71999997f);
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * 45.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f));
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f));
stack.translate(-handSideSign, 3.6f, 3.5f);
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * 120.0f));
stack.mulPose(Vector3f.XP.rotationDegrees(200.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -135.0f));
stack.translate(handSideSign * 5.6f, 0.0f, 0.0f);
PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(mc.player);
RenderSystem.setShaderTexture(0, mc.player.getSkinTextureLocation());
if(handSideSign >= 0.0f)
playerRenderer.renderRightHand(stack, buffer, combinedLight, mc.player);
else
playerRenderer.renderLeftHand(stack, buffer, combinedLight, mc.player);
}
}

View File

@ -4,70 +4,60 @@
package net.montoyo.wd.client.renderers;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
/*import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
@OnlyIn(Dist.CLIENT)
public final class ModelMinePad {
public void render(MultiBufferSource buffers, PoseStack stack) {
// TODO: this needs completing
// TODO: I'd like this to be able to load a model from a JSON if possible
double x1 = 0.0;
double y1 = 0.0;
double x2 = 27.65 / 32.0 + 0.01;
double y2 = 14.0 / 32.0 + 0.002;
Matrix4f positionMatrix = stack.last().pose();
Tesselator t = Tesselator.getInstance();
BufferBuilder vb = t.getBuilder();
RenderSystem.setShader(GameRenderer::getPositionColorShader);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
vb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
vb.vertex(positionMatrix, (float) x1, (float) y1, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x2, (float) y1, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x2, (float) y2, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x1, (float) y2, 0.0f).color(0, 0, 0, 255).endVertex();
t.end();
int width = 32;
int height = 32;
float padding = 1f / 23;
float padding1 = 1f / 21;
float z = 0;
VertexConsumer consumer = buffers.getBuffer(RenderType.entityCutout(new ResourceLocation("webdisplays:textures/item/model/minepad_item.png")));
consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 12f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z).color(255, 255, 255, 255).uv(19f / width, 12f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z).color(255, 255, 255, 255).uv(19f / width, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
public final class ModelMinePad extends Model {
consumer.vertex(positionMatrix, (float) x1 - padding1, (float) y1, z).color(255, 255, 255, 255).uv(0f / width, 10f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2 + padding1, (float) y1, z).color(255, 255, 255, 255).uv(20f / width, 10f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2 + padding1, (float) y2, z).color(255, 255, 255, 255).uv(20f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x1 - padding1, (float) y2, z).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
//
// consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
}
}
// fields
private final ModelPart base;
private final ModelPart left;
private final ModelPart right;
public ModelMinePad() {
super();
textureWidth = 64;
textureHeight = 32;
base = new ModelPart(this, 0, 0);
base.addBox(0F, 0F, 0F, 14, 1, 9);
base.setRotationPoint(1F, 0F, 3.5F);
base.setTextureSize(64, 32);
base.mirror = true;
clearRotation(base);
left = new ModelRenderer(this, 0, 10);
left.addBox(0F, 0F, 0F, 1, 1, 7);
left.setRotationPoint(0F, 0F, 4.5F);
left.setTextureSize(64, 32);
left.mirror = true;
clearRotation(left);
right = new ModelRenderer(this, 30, 10);
right.addBox(0F, 0F, 0F, 1, 1, 7);
right.setRotationPoint(15F, 0F, 4.5F);
right.setTextureSize(64, 32);
right.mirror = true;
clearRotation(right);
}
public final void render(float f5) {
base.render(f5);
left.render(f5);
right.render(f5);
}
private void clearRotation(ModelPart model) {
model.rotateAngleX = 0.0f;
model.rotateAngleY = 0.0f;
model.rotateAngleZ = 0.0f;
}
@Override
public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
}
}*/

View File

@ -5,232 +5,164 @@
package net.montoyo.wd.client.renderers;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.Material;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import net.minecraftforge.client.model.data.IModelData;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3f;
import net.montoyo.wd.utilities.Vector3i;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
public class ScreenBaker implements BakedModel {
private static final List<BakedQuad> noQuads = ImmutableList.of();
private final TextureAtlasSprite[] texs = new TextureAtlasSprite[16];
private final BlockSide[] blockSides = BlockSide.values();
private final Direction[] blockFacings = Direction.values();
private final ModelState modelState;
private final Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter;
private final ItemOverrides overrides;
private final ItemTransforms itemTransforms;
IntegerModelProperty[] TEXTURES = new IntegerModelProperty[6];
public ScreenBaker(ModelState modelState, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ItemOverrides overrides, ItemTransforms itemTransforms) {
this.modelState = modelState;
this.spriteGetter = spriteGetter;
this.overrides = overrides;
this.itemTransforms = itemTransforms;
for (int i = 0; i < texs.length; i++) {
texs[i] = spriteGetter.apply(ScreenModelLoader.MATERIALS_SIDES[i]);
}
for (int i = 0; i < TEXTURES.length; i++) {
TEXTURES[i] = new IntegerModelProperty();
}
}
private void putVertex(int[] buf, int pos, Vector3f vpos, TextureAtlasSprite tex, Vector3f uv, Vector3i normal) {
pos *= 8;
buf[pos] = Float.floatToRawIntBits(vpos.x);
buf[pos + 1] = Float.floatToRawIntBits(vpos.y);
buf[pos + 2] = Float.floatToRawIntBits(vpos.z);
buf[pos + 3] = 0xFFFFFFFF; //Color, let this white...
buf[pos + 4] = Float.floatToRawIntBits(tex.getU(uv.x));
buf[pos + 5] = Float.floatToRawIntBits(tex.getV(uv.y));
int nx = (normal.x * 127) & 0xFF;
int ny = (normal.y * 127) & 0xFF;
int nz = (normal.z * 127) & 0xFF;
buf[pos + 7] = nx | (ny << 8) | (nz << 16);
}
private Vector3f rotateVec(Vector3f vec, BlockSide side) {
return switch (side) {
case BOTTOM -> new Vector3f(vec.x, 1.0f, 1.0f - vec.z);
case TOP -> new Vector3f(vec.x, 0.0f, vec.z);
case NORTH -> new Vector3f(vec.x, vec.z, 1.0f);
case SOUTH -> new Vector3f(vec.x, 1.0f - vec.z, 0.0f);
case WEST -> new Vector3f(1.f, vec.x, vec.z);
case EAST -> new Vector3f(0.0f, 1.0f - vec.x, vec.z);
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
}
private Vector3f rotateTex(BlockSide side, float u, float v) {
return switch (side) {
case BOTTOM, NORTH -> new Vector3f(16.f - u, 16.f - v, 0.0f);
case TOP -> new Vector3f(16.f - u, v, 0.0f);
case SOUTH -> new Vector3f(u, v, 0.0f);
case WEST -> new Vector3f(16.f - v, u, 0.0f);
case EAST -> new Vector3f(v, 16.f - u, 0.0f);
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
}
private BakedQuad bakeSide(BlockSide side, TextureAtlasSprite tex) {
int[] data = new int[8 * 4];
// I have no idea
int rotation = switch (side) {
case NORTH, TOP, BOTTOM -> 2;
case SOUTH -> 0;
case EAST -> 1;
case WEST -> 3;
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
putVertex(data, (rotation + 3) % 4, rotateVec(new Vector3f(0.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 16.0f, 0.0f), side.backward);
putVertex(data, (rotation + 2) % 4, rotateVec(new Vector3f(0.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 16.0f, 16.0f), side.backward);
putVertex(data, (rotation + 1) % 4, rotateVec(new Vector3f(1.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 0.0f, 16.0f), side.backward);
putVertex(data, (rotation) % 4, rotateVec(new Vector3f(1.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 0.0f, 0.0f), side.backward);
return new BakedQuad(data, 0xFFFFFFFF, blockFacings[side.ordinal()].getOpposite(), tex, true);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource random) {
return getQuads(state, side, random, ModelData.EMPTY, null);
}
@Override
public @NotNull List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @NotNull RandomSource rand, @NotNull ModelData data, @Nullable RenderType renderType) {
if (side == null)
return noQuads;
List<BakedQuad> ret = new ArrayList<>();
int sid = BlockSide.reverse(side.ordinal());
BlockSide s = blockSides[sid];
TextureAtlasSprite tex = texs[15];
if (data.has(TEXTURES[side.ordinal()]))
tex = texs[data.get(TEXTURES[side.ordinal()])];
ret.add(bakeSide(s, tex));
return ret;
}
protected byte check(BlockState state, BlockAndTintGetter level, BlockPos pos, Vector3i dir) {
BlockState u = level.getBlockState(pos.offset(dir.x, dir.y, dir.z));
BlockState d = level.getBlockState(pos.offset(-dir.x, -dir.y, -dir.z));
if (
u.getBlock() == state.getBlock() &&
d.getBlock() != state.getBlock()
) return (byte) 1; // away
else if (
d.getBlock() == state.getBlock() &&
u.getBlock() != state.getBlock()
) return (byte) 2; // to
else if (
d.getBlock() != state.getBlock() &&
u.getBlock() != state.getBlock()
) return (byte) 3; // both
return (byte) 0; // none
}
@Override
public @NotNull ModelData getModelData(@NotNull BlockAndTintGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull ModelData modelData) {
ModelData.Builder builder = ModelData.builder();
final int BAR_BOTTOM = 1;
final int BAR_RIGHT = 2;
final int BAR_TOP = 4;
final int BAR_LEFT = 8;
for (int i = 0; i < TEXTURES.length; i++) {
BlockSide side = blockSides[i];
// check up and down
int res = switch (check(state, level, pos, side.up)) {
case 1 -> BAR_BOTTOM;
case 2 -> BAR_TOP;
case 3 -> BAR_TOP | BAR_BOTTOM;
default -> 0;
};
// check left and right
res |= switch (check(state, level, pos, side.right)) {
case 1 -> BAR_LEFT;
case 2 -> BAR_RIGHT;
case 3 -> BAR_LEFT | BAR_RIGHT;
default -> 0;
};
builder.with(TEXTURES[i], res);
}
return builder.build();
}
@Override
public boolean useAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean usesBlockLight() {
return false;
}
@Override
public boolean isCustomRenderer() {
return false;
}
@Override
@Nonnull
public TextureAtlasSprite getParticleIcon() {
return texs[15];
}
@Override
@Nonnull
public ItemTransforms getTransforms() {
return ItemTransforms.NO_TRANSFORMS;
}
@Override
@Nonnull
public ItemOverrides getOverrides() {
return ItemOverrides.EMPTY;
}
//@formatter:off
public static final class IntegerModelProperty extends ModelProperty<Integer> {}
//@formatter:on
public class ScreenBaker implements IModelBaker {
private static final List<BakedQuad> noQuads = ImmutableList.of();
private final TextureAtlasSprite[] texs = new TextureAtlasSprite[16];
private final BlockSide[] blockSides = BlockSide.values();
private final Direction[] blockFacings = Direction.values();
private final ModelState modelState;
private final Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter;
private final ItemOverrides overrides;
private final ItemTransforms itemTransforms;
public ScreenBaker(ModelState modelState, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ItemOverrides overrides, ItemTransforms itemTransforms) {
this.modelState = modelState;
this.spriteGetter = spriteGetter;
this.overrides = overrides;
this.itemTransforms = itemTransforms;
}
@Override
public void loadTextures(TextureAtlas texMap) {
for(int i = 0; i < texs.length; i++)
texs[i] = texMap.getSprite(new ResourceLocation("webdisplays", "blocks/screen" + i));
}
private void putVertex(int[] buf, int pos, Vector3f vpos, TextureAtlasSprite tex, Vector3f uv, Vector3i normal) {
buf[pos * 7 + 0] = Float.floatToRawIntBits(vpos.x);
buf[pos * 7 + 1] = Float.floatToRawIntBits(vpos.y);
buf[pos * 7 + 2] = Float.floatToRawIntBits(vpos.z);
buf[pos * 7 + 3] = 0xFFFFFFFF; //Color, let this white...
buf[pos * 7 + 4] = Float.floatToRawIntBits(tex.getU(uv.x));
buf[pos * 7 + 5] = Float.floatToRawIntBits(tex.getV(uv.y));
int nx = (normal.x * 127) & 0xFF;
int ny = (normal.y * 127) & 0xFF;
int nz = (normal.z * 127) & 0xFF;
buf[pos * 7 + 6] = nx | (ny << 8) | (nz << 16);
}
private Vector3f rotateVec(Vector3f vec, BlockSide side) {
switch(side) {
case BOTTOM: return new Vector3f(vec.x, 1.0f, 1.0f - vec.z);
case TOP: return new Vector3f(vec.x, 0.0f, vec.z);
case NORTH: return new Vector3f(vec.x, vec.z, 1.0f);
case SOUTH: return new Vector3f(vec.x, 1.0f - vec.z, 0.0f);
case WEST: return new Vector3f(1.f , vec.x, vec.z);
case EAST: return new Vector3f(0.0f, 1.0f - vec.x, vec.z);
}
throw new RuntimeException("Unknown block side " + side);
}
private Vector3f rotateTex(BlockSide side, float u, float v) {
switch(side) {
case BOTTOM: return new Vector3f(u, 16.f - v, 0.0f);
case TOP: return new Vector3f(u, v, 0.0f);
case NORTH: return new Vector3f(16.f - u, 16.f - v, 0.0f);
case SOUTH: return new Vector3f(u, v, 0.0f);
case WEST: return new Vector3f(v, 16.f - u, 0.0f);
case EAST: return new Vector3f(16.f - v, u, 0.0f);
}
throw new RuntimeException("Unknown block side " + side);
}
private BakedQuad bakeSide(BlockSide side, TextureAtlasSprite tex) {
int[] data = new int[7 * 4];
putVertex(data, 3, rotateVec(new Vector3f(0.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 0.0f, 0.0f ), side.backward);
putVertex(data, 2, rotateVec(new Vector3f(0.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 0.0f, 16.0f ), side.backward);
putVertex(data, 1, rotateVec(new Vector3f(1.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 16.0f, 16.0f), side.backward);
putVertex(data, 0, rotateVec(new Vector3f(1.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 16.0f, 0.0f ), side.backward);
return new BakedQuad(data, 0xFFFFFFFF, blockFacings[side.ordinal()], tex, true);
}
@NotNull
@Override
public List<BakedQuad> getQuads(@org.jetbrains.annotations.Nullable BlockState state, @org.jetbrains.annotations.Nullable Direction side, @NotNull Random random, @NotNull IModelData iModelData) {
if(side == null)
return noQuads;
BlockState bs = state;
List<BakedQuad> ret = new ArrayList<>();
int sid = BlockSide.reverse(side.ordinal());
BlockSide s = blockSides[sid];
TextureAtlasSprite tex = texs[15];
if(bs != null) {
IntegerProperty[] sideFlags = new IntegerProperty[6];
for(int i = 0; i < sideFlags.length; i++)
sideFlags[i] = IntegerProperty.create("neighbor" + i, 0, 15);
tex = texs[bs.getValue(sideFlags[sid])];
}
ret.add(bakeSide(s, tex));
return ret;
}
@Override
public boolean useAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean usesBlockLight() {
return false;
}
@Override
public boolean isCustomRenderer() {
return false;
}
@Override
@Nonnull
public TextureAtlasSprite getParticleIcon() {
return texs[15];
}
@Override
@Nonnull
public ItemTransforms getTransforms() {
return ItemTransforms.NO_TRANSFORMS;
}
@Override
@Nonnull
public ItemOverrides getOverrides() {
return ItemOverrides.EMPTY;
}
}

View File

@ -2,65 +2,56 @@ package net.montoyo.wd.client.renderers;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.IModelLoader;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
public class ScreenModelLoader implements IGeometryLoader<ScreenModelLoader.ScreenModelGeometry> {
public class ScreenModelLoader implements IModelLoader<ScreenModelLoader.ScreenModelGeometry> {
public static final ResourceLocation SCREEN_LOADER = new ResourceLocation("webdisplays", "screen_loader");
public static final ResourceLocation SCREEN_SIDE = new ResourceLocation("webdisplays", "block/screen");
private static final ResourceLocation[] SIDES = new ResourceLocation[16];
public static final Material[] MATERIALS_SIDES = new Material[16];
static {
for (int i = 0; i < SIDES.length; i++) {
SIDES[i] = new ResourceLocation(SCREEN_SIDE.getNamespace(), SCREEN_SIDE.getPath() + i);
MATERIALS_SIDES[i] = ForgeHooksClient.getBlockMaterial(SIDES[i]);
}
}
public static final Material MATERIAL_SIDE = ForgeHooksClient.getBlockMaterial(SCREEN_SIDE);
@Override
public ScreenModelGeometry read(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
public void onResourceManagerReload(ResourceManager resourceManager) {
}
@Override
public ScreenModelGeometry read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
return new ScreenModelGeometry();
}
public static class ScreenModelGeometry implements IUnbakedGeometry<ScreenModelGeometry> {
@Override
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) {
return new ScreenBaker(modelState, spriteGetter, overrides, context.getTransforms());
}
// @Override
// public void resolveParents(Function<ResourceLocation, UnbakedModel> modelGetter, IGeometryBakingContext context) {
// IUnbakedGeometry.super.resolveParents(modelGetter, context);
// }
// @Override
// public Set<String> getConfigurableComponentNames() {
// return IUnbakedGeometry.super.getConfigurableComponentNames();
// }
// TODO: ?
// @Override
// public Collection<Material> getMaterials(IGeometryBakingContext iGeometryBakingContext, Function<ResourceLocation, UnbakedModel> function, Set<Pair<String, String>> set) {
// return Arrays.asList(MATERIALS_SIDES);
// }
public static class ScreenModelGeometry implements IModelGeometry<ScreenModelGeometry> {
@Override
public BakedModel bake(IModelConfiguration owner, ModelBakery modelBakery, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides itemOverrides, ResourceLocation resourceLocation) {
return new ScreenBaker(modelState, spriteGetter, itemOverrides, owner.getCameraTransforms());
}
@Override
public Collection<net.minecraft.client.resources.model.Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return List.of(MATERIAL_SIDE);
}
}
}

View File

@ -4,186 +4,205 @@
package net.montoyo.wd.client.renderers;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.world.phys.AABB;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.Vector3f;
import net.montoyo.wd.utilities.Vector3i;
import org.jetbrains.annotations.NotNull;
import static com.mojang.math.Axis.*;
import static com.mojang.math.Vector3f.*;
import static org.lwjgl.opengl.GL11.*;
public class ScreenRenderer implements BlockEntityRenderer<ScreenBlockEntity> {
public ScreenRenderer() {
}
public static class ScreenRendererProvider implements BlockEntityRendererProvider<ScreenBlockEntity> {
@Override
public @NotNull BlockEntityRenderer<ScreenBlockEntity> create(@NotNull Context arg) {
return new ScreenRenderer();
}
}
private final Vector3f mid = new Vector3f();
private final Vector3i tmpi = new Vector3i();
private final Vector3f tmpf = new Vector3f();
@Override
public void render(ScreenBlockEntity te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
if (!te.isLoaded())
return;
public class ScreenRenderer implements BlockEntityRenderer<TileEntityScreen> {
//Disable lighting
// RenderSystem.enableTexture();
// RenderSystem.disableCull();
RenderSystem.disableBlend();
for (int i = 0; i < te.screenCount(); i++) {
ScreenData scr = te.getScreen(i);
if (scr.browser == null) {
double dist = WebDisplays.PROXY.distanceTo(te, Minecraft.getInstance().getEntityRenderDispatcher().camera.getPosition());
if (dist <= WebDisplays.INSTANCE.loadDistance2 * 16)
scr.createBrowser(te, true);
else continue;
}
// TODO: manually backface cull the screens
tmpi.set(scr.side.right);
tmpi.mul(scr.size.x);
tmpi.addMul(scr.side.up, scr.size.y);
tmpf.set(tmpi);
mid.set(0.5, 0.5, 0.5);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.left);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.down);
mid.addMul(tmpf, 0.5f);
poseStack.pushPose();
poseStack.translate(mid.x, mid.y, mid.z);
switch (scr.side) {
case BOTTOM:
poseStack.mulPose(XP.rotation(90.f + 49.8f));
break;
case TOP:
poseStack.mulPose(XN.rotation(90.f + 49.8f));
break;
case NORTH:
poseStack.mulPose(YN.rotationDegrees(180.f));
break;
case SOUTH:
break;
case WEST:
poseStack.mulPose(YN.rotationDegrees(90.f));
break;
case EAST:
poseStack.mulPose(YP.rotationDegrees(90.f));
break;
}
if (scr.doTurnOnAnim) {
long lt = System.currentTimeMillis() - scr.turnOnTime;
float ft = ((float) lt) / 100.0f;
if (ft >= 1.0f) {
ft = 1.0f;
scr.doTurnOnAnim = false;
}
poseStack.scale(ft, ft, 1.0f);
}
if (!scr.rotation.isNull)
poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle));
float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f;
float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f;
if (scr.rotation.isVertical) {
float tmp = sw;
sw = sh;
sh = tmp;
}
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder();
//TODO: don't use tesselator
RenderSystem.enableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem._setShaderTexture(0, ((MCEFBrowser) scr.browser).getRenderer().getTextureID());
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
builder.vertex(poseStack.last().pose(), -sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), -sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
tesselator.end();//Minecraft does shit with mah texture otherwise...
RenderSystem.disableDepthTest();
// TODO: it'd be neat to draw a mouse cursor on the screen
// // debug hit2pixels
// HitResult result = Minecraft.getInstance().hitResult;
// VertexConsumer consumer = bufferSource.getBuffer(RenderType.lines());
// poseStack.translate(-sw, -sh, 0);
// if (result instanceof BlockHitResult hit) {
// BlockPos bpos = hit.getBlockPos();
//
// Vector3i pos = new Vector3i(hit.getBlockPos());
// float hitX = ((float) result.getLocation().x) - (float) te.getBlockPos().getX();
// float hitY = ((float) result.getLocation().y) - (float) te.getBlockPos().getY();
// float hitZ = ((float) result.getLocation().z) - (float) te.getBlockPos().getZ();
// Vector2i tmp = new Vector2i();
//
// if (BlockScreen.hit2pixels(scr.side, bpos, pos, scr, hitX, hitY, hitZ, tmp)) {
// float x = tmp.x / (float) scr.resolution.x * scr.size.x;
// float y = tmp.y / (float) scr.resolution.y * scr.size.y;
// y = scr.size.y - y;
//
// x /= scr.size.x;
// y /= scr.size.y;
// x *= sw * 2;
// y *= sh * 2;
//
// LevelRenderer.renderLineBox(
// poseStack,
// consumer, new AABB(
// x - 0.01, y - 0.01, 0.5 - 0.01,
// x + 0.01, y + 0.01, 0.5 + 0.01
// ),
// 1f, 0, 0, 1f
// );
// }
// }
poseStack.popPose();
}
public static class ScreenRendererProvider implements BlockEntityRendererProvider<TileEntityScreen> {
@Override
public @NotNull BlockEntityRenderer<TileEntityScreen> create(@NotNull Context arg) {
return new ScreenRenderer();
}
}
private final Vector3f mid = new Vector3f();
private final Vector3i tmpi = new Vector3i();
private final Vector3f tmpf = new Vector3f();
@Override
public void render(TileEntityScreen te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
if(!te.isLoaded())
return;
//Disable lighting
RenderSystem.enableTexture();
RenderSystem.disableCull();
RenderSystem.disableBlend();
for(int i = 0; i < te.screenCount(); i++) {
TileEntityScreen.Screen scr = te.getScreen(i);
if(scr.browser == null) {
scr.browser = ((ClientProxy) WebDisplays.PROXY).getMCEF().createBrowser(WebDisplays.applyBlacklist(scr.url));
if(scr.rotation.isVertical)
scr.browser.resize(scr.resolution.y, scr.resolution.x);
else
scr.browser.resize(scr.resolution.x, scr.resolution.y);
scr.doTurnOnAnim = true;
scr.turnOnTime = System.currentTimeMillis();
}
tmpi.set(scr.side.right);
tmpi.mul(scr.size.x);
tmpi.addMul(scr.side.up, scr.size.y);
tmpf.set(tmpi);
mid.set(0.5, 0.5, 0.5);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.left);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.down);
mid.addMul(tmpf, 0.5f);
poseStack.pushPose();
poseStack.translate(mid.x, mid.y, mid.z);
switch(scr.side) {
case BOTTOM:
poseStack.mulPose(XP.rotation(90.f + 49.8f));
break;
case TOP:
poseStack.mulPose(XN.rotation(90.f + 49.8f));
break;
case NORTH:
poseStack.mulPose(YN.rotationDegrees(180.f));
break;
case SOUTH:
break;
case WEST:
poseStack.mulPose(YN.rotationDegrees(90.f));
break;
case EAST:
poseStack.mulPose(YP.rotationDegrees(90.f));
break;
}
if(scr.doTurnOnAnim) {
long lt = System.currentTimeMillis() - scr.turnOnTime;
float ft = ((float) lt) / 100.0f;
if(ft >= 1.0f) {
ft = 1.0f;
scr.doTurnOnAnim = false;
}
poseStack.scale(ft, ft, 1.0f);
}
if(!scr.rotation.isNull)
poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle));
float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f;
float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f;
if(scr.rotation.isVertical) {
float tmp = sw;
sw = sh;
sh = tmp;
}
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder();
//TODO: Use tesselator
RenderSystem.enableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem._setShaderTexture(0, scr.browser.getTextureID());
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
builder.vertex(poseStack.last().pose(),-sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(),-sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
tesselator.end();//Minecraft does shit with mah texture otherwise...
RenderSystem.disableDepthTest();
poseStack.popPose();
}
// //Bounding box debugging
// poseStack.pushPose();
// poseStack.translate(-te.getBlockPos().getX(), -te.getBlockPos().getY(), -te.getBlockPos().getZ());
// LevelRenderer.renderLineBox(
// poseStack, bufferSource.getBuffer(RenderType.LINES),
// te.getRenderBoundingBox(), 1, 1, 1, 1f
// );
// poseStack.popPose();
//Re-enable lighting
// RenderSystem.enableCull();
}
//Bounding box debugging
/*poseStack.pushPose();
poseStack.translate(-te.getBlockPos().getX(), -te.getBlockPos().getY(), -te.getBlockPos().getZ());
renderAABB(te.getRenderBoundingBox());
poseStack.popPose();*/
//Re-enable lighting
RenderSystem.enableCull();
}
public void renderAABB(AABB bb) {
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.f, 0.5f, 1.f, 0.75f);
RenderSystem.depthMask(false);
Tesselator t = new Tesselator();
BufferBuilder vb = t.getBuilder();
VertexBuffer tb = new VertexBuffer();
vb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
//Bottom
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
//Top
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
//Left
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
//Right
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
//Front
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
//Back
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
tb.draw();
RenderSystem.depthMask(true);
RenderSystem.enableCull();
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}
}

View File

@ -1,133 +0,0 @@
package net.montoyo.wd.config;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.annoconfg.AnnoCFG;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.DoubleRange;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
@Config(type = ModConfig.Type.CLIENT)
public class ClientConfig {
@SuppressWarnings("unused")
private static final AnnoCFG CFG = new AnnoCFG(FMLJavaModLoadingContext.get().getModEventBus(), ClientConfig.class);
public static void init() {
// loads the class
}
@Name("load_distance")
@Comment("How far (in blocks) you can be before a screen starts rendering")
@Translation("config.webdisplays.load_distance")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 30)
public static double loadDistance = 30.0;
@Name("unload_distance")
@Comment("How far you can be before a screen stops rendering")
@Translation("config.webdisplays.unload_distance")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 32)
public static double unloadDistance = 32.0;
@Name("pad_resolution")
@Comment({
"The resolution that minePads should use",
"Smaller values produce lower qualities, higher values produce higher qualities",
"Due to how web browsers work however, the larger this value is, the smaller text is",
"Also, higher values will invariably lag more",
"A good goto value for this would be the height of your monitor, in pixels",
"A standard monitor is (at least currently) 1080",
})
@Translation("config.webdisplays.pad_res")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 720)
public static int padResolution = 720;
@Name("side_pad")
@Comment({
"When this is true, the minePad is placed off to the side of the screen when held, so it's visible but doesn't take up too much of the screen",
"When this is false, the minePad is placed closer to the center of the screen, allow it to be seen better, but taking up more of your view",
})
@Translation("config.webdisplays.side_pad")
@Default(valueBoolean = true)
public static boolean sidePad = true;
@Comment({
"Options relating to input handling"
})
@CFGSegment("input")
public static class Input {
@Name("keyboard_camera")
@Comment({
"If this is on, then the camera will try to focus on the selected element while a keyboard is in use",
"Elsewise, it'll try to focus on the center of the screen",
})
@Translation("config.webdisplays.keyboard_camera")
@Default(valueBoolean = true)
public static boolean keyboardCamera = true;
@Name("switch_buttons")
@Comment("If the left and right buttons should be swapped when using a laser")
@Translation("config.webdisplays.switch_buttons")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 30)
public static boolean switchButtons = true;
}
// @Comment({
// "AutoVolume makes audio fade off based on distance",
// "Currently, this seems to not work"
// })
// @CFGSegment("auto_volume")
// public static class AutoVolumeControl {
// @Name("enabled")
// @Comment("Whether or not auto volume should be enabled")
// @Translation("config.webdisplays.auto_vol")
// @Default(valueBoolean = true)
// public static boolean enableAutoVolume = true;
//
// @Name("youtube_volume")
// @Comment("How loud youtube should be by default")
// @Translation("config.webdisplays.yt_vol")
// @DoubleRange(minV = 0, maxV = 100)
// @Default(valueD = 100)
// public static double ytVolume = 100.0;
//
// @Name("dist0")
// @Comment("Distance after which you can't hear anything (in blocks)")
// @Translation("config.webdisplays.d0")
// @DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
// @Default(valueD = 30)
// public static double dist0 = 30.0;
//
// @Name("dist100")
// @Comment("Distance after which the sound starts dropping (in blocks)")
// @Translation("config.webdisplays.d100")
// @DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
// @Default(valueD = 10)
// public static double dist100 = 10.0;
// }
@SuppressWarnings("unused")
public static void postLoad() {
if (unloadDistance < loadDistance + 2.0)
unloadDistance = loadDistance + 2.0;
// if (AutoVolumeControl.dist0 < AutoVolumeControl.dist100 + 0.1)
// AutoVolumeControl.dist0 = AutoVolumeControl.dist100 + 0.1;
// cache pad resolution
WebDisplays.INSTANCE.padResY = padResolution;
WebDisplays.INSTANCE.padResX = WebDisplays.INSTANCE.padResY * WebDisplays.PAD_RATIO;
// cache unload/load distances
WebDisplays.INSTANCE.unloadDistance2 = unloadDistance * unloadDistance;
WebDisplays.INSTANCE.loadDistance2 = loadDistance * loadDistance;
// WebDisplays.INSTANCE.ytVolume = (float) AutoVolumeControl.ytVolume;
// WebDisplays.INSTANCE.avDist100 = (float) AutoVolumeControl.dist100;
// WebDisplays.INSTANCE.avDist0 = (float) AutoVolumeControl.dist0;
}
}

View File

@ -1,127 +0,0 @@
package net.montoyo.wd.config;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.annoconfg.AnnoCFG;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
import net.montoyo.wd.config.annoconfg.annotation.value.LongRange;
@SuppressWarnings("DefaultAnnotationParam")
@Config(type = ModConfig.Type.COMMON)
public class CommonConfig {
@SuppressWarnings("unused")
private static final AnnoCFG CFG = new AnnoCFG(FMLJavaModLoadingContext.get().getModEventBus(), CommonConfig.class);
public static void init() {
// loads the class
}
@Name("hard_recipes")
@Comment("If true, breaking the minePad is required to craft upgrades.")
@Translation("config.webdisplays.hard_recipes")
@Default(valueBoolean = true)
public static boolean hardRecipes = true;
@Name("join_message")
@Comment("Whether or not webdisplays should thank the user for using the mod")
@Translation("config.webdisplays.join_message")
@Default(valueBoolean = true)
public static boolean joinMessage = true;
@Name("disable_ownership_thief")
@Comment("If true, the ownership thief item will be disabled")
@Translation("config.webdisplays.disable_thief")
@Default(valueBoolean = false)
public static boolean disableOwnershipThief = false;
@Comment("Options for the browsers (both the minePad and the screens)")
@CFGSegment("browser_options")
public static class Browser {
@Name("blacklist")
@Comment("The page which screens should open up to when turning on")
@Translation("config.webdisplays.blacklist")
@Default(valueStr = "")
public static String[] blacklist = new String[0];
@Name("home_page")
@Comment("The page which screens should open up to when turning on")
@Translation("config.webdisplays.home_page")
@Default(valueStr = "mod://webdisplays/main.html")
public static String homepage = "mod://webdisplays/main.html";
}
@Comment("Options for the in world screen blocks")
@CFGSegment("screen_options")
public static class Screen {
@Name("max_resolution_x")
@Comment("The maximum value screen's horizontal resolution, in pixels")
@Translation("config.webdisplays.max_res_x")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 1920)
public static int maxResolutionX = 1920;
@Name("max_resolution_y")
@Comment("The maximum value screen's vertical resolution, in pixels")
@Translation("config.webdisplays.max_res_y")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 1080)
public static int maxResolutionY = 1080;
@Name("max_width")
@Comment("The maximum width for the screen multiblock, in blocks")
@Translation("config.webdisplays.max_width")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 16)
public static int maxScreenSizeX = 16;
@Name("max_height")
@Comment("The maximum height for the screen multiblock, in blocks")
@Translation("config.webdisplays.max_height")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 16)
public static int maxScreenSizeY = 16;
}
@Comment("Options for the miniserver")
@CFGSegment("mini_server")
public static class MiniServ {
@Name("miniserv_port")
@Comment("The port used by miniserv. 0 to disable")
@Translation("config.webdisplays.miniserv_port")
@IntRange(minV = 0, maxV = Short.MAX_VALUE)
@Default(valueI = 25566)
public static int miniservPort = 25566;
@Name("miniserv_quota")
@Comment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)")
@Translation("config.webdisplays.miniserv_quota")
@LongRange(minV = 0, maxV = Long.MAX_VALUE)
@Default(valueL = 1920)
public static long miniservQuota = 1024; //It's stored as a string anyway
}
@SuppressWarnings("unused")
public static void postLoad() {
WebDisplays.INSTANCE.miniservPort = MiniServ.miniservPort;
WebDisplays.INSTANCE.miniservQuota = MiniServ.miniservQuota * 1024L;
}
// //Comments & shit
// blacklist.setComment("An array of domain names you don't want to load.");
// padHeight.setComment("The minePad Y resolution in pixels. padWidth = padHeight * " + PAD_RATIO);
// hardRecipe.setComment("If true, breaking the minePad is required to craft upgrades.");
// homePage.setComment("The URL that will be loaded each time you create a screen");
// disableOT.setComment("If true, the ownership thief item will be disabled");
// loadDistance.setComment("All screens outside this range will be unloaded");
// unloadDistance.setComment("All unloaded screens inside this range will be loaded");
// maxResX.setComment("Maximum horizontal screen resolution, in pixels");
// maxResY.setComment("Maximum vertical screen resolution, in pixels");
// miniservPort.setComment("The port used by miniserv. 0 to disable.");
// miniservPort.setMaxValue(Short.MAX_VALUE);
// miniservQuota.setComment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)");
// maxScreenX.setComment("Maximum screen width, in blocks. Resolution will be clamped by maxResolutionX.");
// maxScreenY.setComment("Maximum screen height, in blocks. Resolution will be clamped by maxResolutionY.");
}

View File

@ -0,0 +1,121 @@
package net.montoyo.wd.config;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
import me.shedaniel.autoconfig.annotation.ConfigEntry;
import net.minecraft.util.Mth;
import net.montoyo.mcef.easy_forge_compat.Configuration;
import java.util.List;
@Config(name = "webdisplays")
public class ModConfig implements ConfigData {
@ConfigEntry.Category("main")
public Main main = new Main();
@ConfigEntry.Category("client")
public Client client = new Client();
public static class Main {
@ConfigEntry.Gui.Tooltip
public List<String> blacklist = List.of();
@ConfigEntry.Gui.Tooltip
public int padHeight = 480;
@ConfigEntry.Gui.Tooltip
public boolean hardRecipes = true;
@ConfigEntry.Gui.Tooltip
public String homepage = "https://www.google.com";
@ConfigEntry.Gui.Tooltip
public boolean disableOwnershipThief = false;
@ConfigEntry.Gui.Tooltip
public int maxResolutionX = 1920;
@ConfigEntry.Gui.Tooltip
public int maxResolutionY = 1080;
@ConfigEntry.Gui.Tooltip
@ConfigEntry.BoundedDiscrete(max = Short.MAX_VALUE)
public int miniservPort = 25566;
@ConfigEntry.Gui.Tooltip
public long miniservQuota = 1024; //It's stored as a string anyway
@ConfigEntry.Gui.Tooltip
public int maxScreenSizeX = 16;
@ConfigEntry.Gui.Tooltip
public int maxScreenSizeY = 16;
}
public static class Client {
@ConfigEntry.Gui.Tooltip
public double loadDistance = 30.0;
@ConfigEntry.Gui.Tooltip
public double unloadDistance = 32.0;
@ConfigEntry.Gui.CollapsibleObject()
public AutoVolumeControl autoVolumeControl = new AutoVolumeControl();
public static class AutoVolumeControl {
@ConfigEntry.Gui.Tooltip
public boolean enableAutoVolume = true;
@ConfigEntry.Gui.Tooltip
public double ytVolume = 100.0;
@ConfigEntry.Gui.Tooltip
public double dist100 = 10.0;
@ConfigEntry.Gui.Tooltip
public double dist0 = 30.0;
}
}
@Override
public void validatePostLoad() throws ValidationException {
ConfigData.super.validatePostLoad();
main.miniservPort = Mth.clamp(main.miniservPort, 0, Short.MAX_VALUE);
client.autoVolumeControl.ytVolume = Mth.clamp(client.autoVolumeControl.ytVolume, 0.0, 100.0);
client.autoVolumeControl.dist0 = Mth.clamp(client.autoVolumeControl.dist0, 0.0, Double.MAX_VALUE);
client.autoVolumeControl.ytVolume = Mth.clamp(client.autoVolumeControl.dist100, 0.0, Double.MAX_VALUE);
if(client.unloadDistance < client.loadDistance + 2.0) {
client.unloadDistance = client.loadDistance + 2.0;
}
if(client.autoVolumeControl.dist0 < client.autoVolumeControl.dist100 + 0.1) {
client.autoVolumeControl.dist0 = client.autoVolumeControl.dist100 + 0.1;
}
}
// //Comments & shit
// blacklist.setComment("An array of domain names you don't want to load.");
// padHeight.setComment("The minePad Y resolution in pixels. padWidth = padHeight * " + PAD_RATIO);
// hardRecipe.setComment("If true, breaking the minePad is required to craft upgrades.");
// homePage.setComment("The URL that will be loaded each time you create a screen");
// disableOT.setComment("If true, the ownership thief item will be disabled");
// loadDistance.setComment("All screens outside this range will be unloaded");
// unloadDistance.setComment("All unloaded screens inside this range will be loaded");
// maxResX.setComment("Maximum horizontal screen resolution, in pixels");
// maxResY.setComment("Maximum vertical screen resolution, in pixels");
// miniservPort.setComment("The port used by miniserv. 0 to disable.");
// miniservPort.setMaxValue(Short.MAX_VALUE);
// miniservQuota.setComment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)");
// maxScreenX.setComment("Maximum screen width, in blocks. Resolution will be clamped by maxResolutionX.");
// maxScreenY.setComment("Maximum screen height, in blocks. Resolution will be clamped by maxResolutionY.");
// enableAutoVol.setComment("If true, the volume of YouTube videos will change depending on how far you are");
// ytVolume.setComment("Volume for YouTube videos. This will have no effect if enableSoundDistance is set to false");
// ytVolume.setMinValue(0.0);
// ytVolume.setMaxValue(100.0);
// dist100.setComment("Distance after which the sound starts dropping (in blocks)");
// dist100.setMinValue(0.0);
// dist0.setComment("Distance after which you can't hear anything (in blocks)");
// dist0.setMinValue(0.0);
}

View File

@ -1,219 +0,0 @@
package net.montoyo.wd.config.annoconfg;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.DoubleRange;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
import net.montoyo.wd.config.annoconfg.annotation.value.LongRange;
import net.montoyo.wd.config.annoconfg.handle.UnsafeHandle;
import net.montoyo.wd.config.annoconfg.util.EnumType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.function.Supplier;
public class AnnoCFG {
private ForgeConfigSpec mySpec;
private final HashMap<String, ConfigEntry> handles = new HashMap<>();
private static final ArrayList<AnnoCFG> configs = new ArrayList<>();
private final Method postInit;
public AnnoCFG(IEventBus bus, Class<?> clazz) {
bus.addListener(this::onConfigChange);
ForgeConfigSpec.Builder configBuilder = new ForgeConfigSpec.Builder();
setup("", configBuilder, clazz);
configs.add(this);
Method m = null;
try {
m = clazz.getDeclaredMethod("postLoad");
} catch (Throwable ignored) {
}
postInit = m;
Config configDescriptor = clazz.getAnnotation(Config.class);
if (configDescriptor != null) {
String pth = configDescriptor.path();
if (!pth.isEmpty()) pth = pth + "/";
switch (configDescriptor.type()) {
case SERVER -> create(ModConfig.Type.SERVER, pth + ModLoadingContext.get().getActiveNamespace() + "_server.toml");
case CLIENT -> create(ModConfig.Type.CLIENT, pth + ModLoadingContext.get().getActiveNamespace() + "_client.toml");
case COMMON -> create(ModConfig.Type.COMMON, pth + ModLoadingContext.get().getActiveNamespace() + "_common.toml");
default -> throw new RuntimeException("wat");
}
}
}
protected void setupCommentsAndTranslations(AnnotatedElement element, ForgeConfigSpec.Builder builder, String... additionalLines) {
Translation translation = element.getAnnotation(Translation.class);
Comment comment = element.getAnnotation(Comment.class);
StringBuilder builder1 = new StringBuilder();
if (comment != null) {
for (int i = 0; i < comment.value().length; i++) {
String s = comment.value()[i];
builder1.append(s);
if (i != comment.value().length - 1)
builder1.append("\n");
}
}
for (String additionalLine : additionalLines) builder1.append(additionalLine);
if (!builder1.isEmpty())
builder.comment(builder1.toString());
if (translation != null)
builder.translation(translation.value());
}
public void setup(String dir, ForgeConfigSpec.Builder builder, Class<?> clazz) {
if (dir.startsWith(".")) dir = dir.substring(1);
for (Field field : clazz.getFields()) {
if (field.canAccess(null)) {
Skip skip = field.getAnnotation(Skip.class);
if (skip != null) continue;
Name name = field.getAnnotation(Name.class);
String nameStr = field.getName();
if (name != null) nameStr = name.value();
setupCommentsAndTranslations(field, builder);
Supplier<?> value;
Default defaultValue = field.getAnnotation(Default.class);
try {
switch (EnumType.forClass(field.getType())) {
case INT -> {
IntRange range = field.getAnnotation(IntRange.class);
int v = defaultValue.valueI();
if (range != null) {
int min = range.minV();
int max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case LONG -> {
LongRange range = field.getAnnotation(LongRange.class);
long v = defaultValue.valueL();
if (range != null) {
long min = range.minV();
long max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case DOUBLE -> {
DoubleRange range = field.getAnnotation(DoubleRange.class);
double v = defaultValue.valueD();
if (range != null) {
double min = range.minV();
double max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case BOOLEAN -> {
boolean b = defaultValue.valueBoolean();
value = builder.define(nameStr, b);
}
case OTHER -> {
Class<?> fieldType = field.getType();
if (fieldType.equals(String[].class)) {
Supplier<String> sup = builder.define(nameStr, defaultValue.valueStr());
value = () -> {
String v = sup.get();
return v.split(",");
};
} else if (fieldType.equals(String.class)) {
value = builder.define(nameStr, defaultValue.valueStr());
} else
throw new RuntimeException("NYI " + field.getType());
}
default -> throw new RuntimeException("NYI " + field.getType());
}
} catch (NullPointerException npe) {
String inf = "";
if (npe.getMessage().contains("\"value.Default\""))
inf = " this is likely due to a missing default.";
throw new RuntimeException("A null pointer occurred on " + field.getName() + inf, npe);
}
Object o;
try {
// without this line, this system freaks out due to using theUnsafe
//noinspection UnusedAssignment
o = field.get(null);
} catch (Throwable ignored) {
}
UnsafeHandle handle = new UnsafeHandle(field);
o = handle.get();
handle.set(o);
//noinspection FunctionalExpressionCanBeFolded
handles.put(dir + "." + nameStr, new ConfigEntry(
handle, value::get
));
}
}
// TODO: check if the nested class is a direct nesting
for (Class<?> nestMember : clazz.getClasses()) {
if (nestMember == clazz) continue;
if (!nestMember.getName().startsWith(clazz.getName())) continue;
CFGSegment segment = nestMember.getAnnotation(CFGSegment.class);
if (segment == null) {
System.out.println(nestMember);
throw new RuntimeException("NYI: default name");
}
String name = segment.value();
setupCommentsAndTranslations(nestMember, builder);
builder.push(name);
setup(dir + "." + name, builder, nestMember);
builder.pop();
}
mySpec = builder.build();
}
public void onConfigChange(ModConfigEvent event) {
if (
event.getConfig().getSpec().equals(mySpec) ||
event.getConfig().getSpec() == mySpec
) {
for (String s : handles.keySet()) {
ConfigEntry entry = handles.get(s);
entry.handle.set(entry.supplier.get());
}
}
try {
postInit.invoke(null);
} catch (Throwable err) {
err.printStackTrace();
}
}
public void create(ModConfig.Type type, String file) {
ModLoadingContext.get().registerConfig(type, mySpec, file);
}
}

View File

@ -1,15 +0,0 @@
package net.montoyo.wd.config.annoconfg;
import net.montoyo.wd.config.annoconfg.handle.UnsafeHandle;
import java.util.function.Supplier;
public class ConfigEntry {
UnsafeHandle handle;
Supplier<?> supplier;
public ConfigEntry(UnsafeHandle handle, Supplier<?> supplier) {
this.handle = handle;
this.supplier = supplier;
}
}

View File

@ -1,9 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface CFGSegment {
String value();
}

View File

@ -1,9 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Comment {
String[] value();
}

View File

@ -1,12 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import net.minecraftforge.fml.config.ModConfig;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {
ModConfig.Type type();
String path() default "";
}

View File

@ -1,9 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}

View File

@ -1,8 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Skip {
}

View File

@ -1,9 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Translation {
String value();
}

View File

@ -1,16 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Default {
byte valueB() default 0;
short valueS() default 0;
int valueI() default 0;
long valueL() default 0;
float valueF() default 0;
double valueD() default 0;
boolean valueBoolean() default false;
String valueStr() default "";
}

View File

@ -1,10 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface DoubleRange {
double minV();
double maxV();
}

View File

@ -1,10 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface IntRange {
int minV();
int maxV();
}

View File

@ -1,10 +0,0 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface LongRange {
long minV();
long maxV();
}

View File

@ -1,86 +0,0 @@
package net.montoyo.wd.config.annoconfg.handle;
import net.montoyo.wd.config.annoconfg.util.EnumType;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class UnsafeHandle {
private static final Unsafe theUnsafe;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
theUnsafe = (Unsafe) f.get(null);
} catch (Throwable ignored) {
throw new RuntimeException("AnnoConfg: Failed to acquire an instance of the unsafe.");
}
}
private final long offset;
private final Consumer<Object> uploader;
private final Supplier<Object> getter;
public UnsafeHandle(Field f) {
this(null, f);
}
public UnsafeHandle(Object relative, Field f) {
offset = theUnsafe.staticFieldOffset(f);
if (relative == null) relative = theUnsafe.staticFieldBase(f);
Object finalRelative = relative;
if (f.getType().isPrimitive()) {
switch (EnumType.forClass(f.getType())) {
case BYTE -> {
uploader = (v) -> theUnsafe.putByte(finalRelative, offset, (byte) v);
getter = () -> theUnsafe.getByte(finalRelative, offset);
}
case SHORT -> {
uploader = (v) -> theUnsafe.putShort(finalRelative, offset, (short) v);
getter = () -> theUnsafe.getShort(finalRelative, offset);
}
case INT -> {
uploader = (v) -> theUnsafe.putInt(finalRelative, offset, (int) v);
getter = () -> theUnsafe.getInt(finalRelative, offset);
}
case LONG -> {
uploader = (v) -> theUnsafe.putLong(finalRelative, offset, (long) v);
getter = () -> theUnsafe.getLong(finalRelative, offset);
}
case FLOAT -> {
uploader = (v) -> theUnsafe.putFloat(finalRelative, offset, (float) v);
getter = () -> theUnsafe.getFloat(finalRelative, offset);
}
case DOUBLE -> {
uploader = (v) -> theUnsafe.putDouble(finalRelative, offset, (double) v);
getter = () -> theUnsafe.getDouble(finalRelative, offset);
}
case BOOLEAN -> {
uploader = (v) -> theUnsafe.putBoolean(finalRelative, offset, (boolean) v);
getter = () -> theUnsafe.getBoolean(finalRelative, offset);
}
default -> {
// TODO: check that I have all primitives?
uploader = null;
getter = () -> null;
}
}
} else {
uploader = (v) -> theUnsafe.putObject(finalRelative, offset, v);
getter = () -> theUnsafe.getObject(finalRelative, offset);
}
}
public void set(Object o) {
uploader.accept(o);
// System.out.println(getter.get());
}
public Object get() {
return getter.get();
}
}

View File

@ -1,25 +0,0 @@
package net.montoyo.wd.config.annoconfg.util;
public enum EnumType {
BYTE(byte.class),
SHORT(short.class),
INT(int.class),
LONG(long.class),
FLOAT(float.class),
DOUBLE(double.class),
BOOLEAN(boolean.class),
OTHER(Object.class),
;
Class<?> clazz;
EnumType(Class<?> clazz) {
this.clazz = clazz;
}
public static EnumType forClass(Class<?> clazz) {
for (EnumType value : EnumType.values())
if (value.clazz.equals(clazz)) return value;
return OTHER;
}
}

View File

@ -1,38 +0,0 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.Objects;
import java.util.function.Function;
public abstract class ScreenControl {
private final ResourceLocation id;
public ScreenControl(ResourceLocation id) {
this.id = id;
}
public abstract void write(FriendlyByteBuf buf);
public abstract void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException;
@OnlyIn(Dist.CLIENT)
public abstract void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx);
public void checkPerms(int perms, Function<Integer, Boolean> checker, ServerPlayer player) throws MissingPermissionException {
if (!checker.apply(perms)) {
throw new MissingPermissionException(perms, Objects.requireNonNull(player));
}
}
public final ResourceLocation getId() {
return id;
}
}

View File

@ -1,77 +0,0 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.builtin.*;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.Log;
import java.lang.reflect.Method;
import java.util.HashMap;
// TODO: enable deferred registry of these
public class ScreenControlRegistry {
private static final HashMap<ResourceLocation, ScreenControlType<?>> CONTROL_TYPES = new HashMap<>();
public static void register(ResourceLocation name, ScreenControlType<?> type) {
if (CONTROL_TYPES.containsKey(name)) {
Log.warning("ScreenControlRegistry#CONTROL_TYPES already contains an entry with name " + name);
throw new IllegalArgumentException("Cannot have two entries with the same name.");
}
CONTROL_TYPES.put(name, type);
// lil thing for sanity
// avoids the pain the dist cleaner causes, hopefully
if (!FMLEnvironment.production) {
if (FMLEnvironment.dist.isClient()) {
boolean shouldThrow = false;
try {
Method m = type.clazz.getMethod("handleClient", BlockPos.class, BlockSide.class, ScreenBlockEntity.class, NetworkEvent.Context.class);
OnlyIn onlyIn = m.getAnnotation(OnlyIn.class);
if (onlyIn == null) shouldThrow = true;
Dist d = onlyIn.value(); // idc if this throws, lol
if (d != Dist.CLIENT) shouldThrow = true;
} catch (Throwable ignored) {
}
if (shouldThrow) {
Log.warning("handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz);
throw new IllegalStateException(
"handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz
);
}
}
}
}
// if needed, the old code
// https://github.com/Mysticpasta1/webdisplays/blob/ff55cbf1b27773c15f44f17ad3364da3a16b6ed9/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java#L281-L364
// https://github.com/Mysticpasta1/webdisplays/blob/5ce9e4574df356910645b0382628f74d1401e26d/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java#L261-L284
static {
register(SetURLControl.id, new ScreenControlType<>(SetURLControl.class, SetURLControl::new));
register(KeyTypedControl.id, new ScreenControlType<>(KeyTypedControl.class, KeyTypedControl::new));
register(AutoVolumeControl.id, new ScreenControlType<>(AutoVolumeControl.class, AutoVolumeControl::new));
register(JSRequestControl.id, new ScreenControlType<>(JSRequestControl.class, JSRequestControl::new));
register(LaserControl.id, new ScreenControlType<>(LaserControl.class, LaserControl::new));
register(ScreenModifyControl.id, new ScreenControlType<>(ScreenModifyControl.class, ScreenModifyControl::new));
register(ModifyFriendListControl.id, new ScreenControlType<>(ModifyFriendListControl.class, ModifyFriendListControl::new));
register(ManageRightsAndUpdgradesControl.id, new ScreenControlType<>(ManageRightsAndUpdgradesControl.class, ManageRightsAndUpdgradesControl::new));
register(ClickControl.id, new ScreenControlType<>(ClickControl.class, ClickControl::new));
register(OwnerControl.id, new ScreenControlType<>(OwnerControl.class, OwnerControl::new));
register(TurnOffControl.id, new ScreenControlType<>(TurnOffControl.class, (buf) -> TurnOffControl.INSTANCE));
}
public static ScreenControl parse(FriendlyByteBuf buf) {
return CONTROL_TYPES.get(new ResourceLocation(buf.readUtf()))
.deserializer.apply(buf);
}
public static void init() {
/* NO-OP: allows static init to run during mod init in dev env */
}
}

View File

@ -1,15 +0,0 @@
package net.montoyo.wd.controls;
import net.minecraft.network.FriendlyByteBuf;
import java.util.function.Function;
public class ScreenControlType<T extends ScreenControl> {
Class<T> clazz;
Function<FriendlyByteBuf, ScreenControl> deserializer;
public ScreenControlType(Class<T> clazz, Function<FriendlyByteBuf, ScreenControl> deserializer) {
this.clazz = clazz;
this.deserializer = deserializer;
}
}

View File

@ -1,49 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class AutoVolumeControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:auto_volume");
boolean autoVol;
public AutoVolumeControl(boolean autoVol) {
super(id);
this.autoVol = autoVol;
}
public AutoVolumeControl(FriendlyByteBuf buf) {
super(id);
autoVol = buf.readBoolean();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(autoVol);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// I feel like there's probably a better permission category
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
tes.setAutoVolume(side, autoVol);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.setAutoVolume(side, autoVol);
}
}

View File

@ -1,62 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class ClickControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:click");
public enum ControlType {
CLICK, MOVE, DOWN, UP
}
ControlType type;
Vector2i coord;
public ClickControl(ControlType type, Vector2i coord) {
this(type, coord, -1);
this.type = type;
}
public ClickControl(ControlType type, Vector2i coord, int button) {
super(id);
this.coord = coord;
}
public ClickControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
coord = new Vector2i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
coord.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot call click control on server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (coord != null)
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, coord, -1);
tes.handleMouseEvent(side, type, coord, 1);
}
}

View File

@ -1,62 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class JSRequestControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:js_req");
int reqId;
JSServerRequest reqType;
Object[] data;
public JSRequestControl(int reqId, JSServerRequest reqType, Object[] data) {
super(id);
this.reqId = reqId;
this.reqType = reqType;
this.data = data;
}
public JSRequestControl(FriendlyByteBuf buf) {
super(id);
reqId = buf.readInt();
reqType = JSServerRequest.fromID(buf.readByte());
if (reqType != null)
data = reqType.deserialize(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeInt(reqId);
buf.writeByte(reqType.ordinal());
if (!reqType.serialize(buf, data))
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + reqType);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
// if (reqType == null || data == null) Log.warning("Caught invalid JS request from player %s (UUID %s)", player.getName(), player.getGameProfile().getId().toString());
// else tes.handleJSRequest(player, side, reqId, reqType, data);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -1,52 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class KeyTypedControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:type");
String text;
BlockPos soundPos;
public KeyTypedControl(String text, BlockPos soundPos) {
super(id);
this.text = text;
this.soundPos = soundPos;
}
public KeyTypedControl(FriendlyByteBuf buf) {
super(id);
text = buf.readUtf();
soundPos = buf.readBlockPos();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(text);
buf.writeBlockPos(soundPos);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
tes.type(side, text, soundPos, ctx.getSender());
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.type(side, text, soundPos);
}
}

View File

@ -1,79 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class LaserControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:laser");
public enum ControlType {
MOVE, DOWN, UP
}
ControlType type;
Vector2i coord;
int button;
public LaserControl(ControlType type, Vector2i coord) {
this(type, coord, -1);
}
public LaserControl(ControlType type, Vector2i coord, int button) {
super(id);
this.type = type;
this.coord = coord;
this.button = button;
}
public LaserControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (!type.equals(ControlType.UP))
coord = new Vector2i(buf);
if (!type.equals(ControlType.MOVE))
button = buf.readInt();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (coord != null) coord.writeTo(buf);
if (type != ControlType.MOVE) buf.writeInt(button);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// feel like this makes sense, but I wanna get opinions first
// checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
ServerPlayer sender = ctx.getSender();
switch (type) {
case UP -> tes.laserUp(side, sender, button);
case DOWN -> tes.laserDownMove(side, sender, coord, true, button);
case MOVE -> tes.laserDownMove(side, sender, coord, false, button);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (coord != null)
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, coord, -1);
switch (type) {
case UP -> tes.handleMouseEvent(side, ClickControl.ControlType.UP, coord, button);
case DOWN -> tes.handleMouseEvent(side, ClickControl.ControlType.DOWN, coord, button);
}
}
}

View File

@ -1,125 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
/**
* TODO: I'm considering merging this with {@link ModifyFriendListControl} to make ManageScreenControl
*/
@Deprecated
public class ManageRightsAndUpdgradesControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_rights_upgrades");
public enum ControlType {
RIGHTS, UPGRADES
}
ControlType type;
boolean adding;
ItemStack toRemove;
private int friendRights;
private int otherRights;
public ManageRightsAndUpdgradesControl(boolean adding, ItemStack toRemove) {
super(id);
this.adding = adding;
type = ControlType.UPGRADES;
this.toRemove = toRemove;
}
public ManageRightsAndUpdgradesControl(int friendRights, int otherRights) {
super(id);
type = ControlType.RIGHTS;
this.friendRights = friendRights;
this.otherRights = otherRights;
}
public ManageRightsAndUpdgradesControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
switch (type) {
case UPGRADES -> {
adding = buf.readBoolean();
toRemove = buf.readItem();
}
case RIGHTS -> {
friendRights = buf.readInt();
otherRights = buf.readInt();
}
}
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
switch (type) {
case UPGRADES -> {
buf.writeBoolean(adding);
buf.writeItem(toRemove);
}
case RIGHTS -> {
buf.writeInt(friendRights);
buf.writeInt(otherRights);
}
}
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
switch (type) {
case UPGRADES -> {
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
if (adding)
throw new RuntimeException("Cannot add an upgrade from the client");
else tes.removeUpgrade(side, toRemove, player);
}
case RIGHTS -> {
ScreenData scr = tes.getScreen(side);
int fr = scr.owner.uuid.equals(player.getGameProfile().getId()) ? friendRights : scr.friendRights;
int or = (scr.rightsFor(player) & ScreenRights.MANAGE_OTHER_RIGHTS) == 0 ? scr.otherRights : otherRights;
if(scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
ServerPlayer player = ctx.getSender();
switch (type) {
case UPGRADES -> {
if (adding)
tes.addUpgrade(side, toRemove, player, true);
else tes.removeUpgrade(side, toRemove, player);
}
case RIGHTS -> {
ScreenData scr = tes.getScreen(side);
int fr = friendRights;
int or = otherRights;
if(scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
}
}
}

View File

@ -1,56 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import java.util.function.Function;
public class ModifyFriendListControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_friend_list");
boolean adding;
NameUUIDPair friend;
public ModifyFriendListControl(NameUUIDPair pair, boolean adding) {
super(id);
this.adding = adding;
this.friend = pair;
}
public ModifyFriendListControl(FriendlyByteBuf buf) {
super(id);
adding = buf.readBoolean();
friend = new NameUUIDPair(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(adding);
friend.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
checkPerms(ScreenRights.MANAGE_FRIEND_LIST, permissionChecker, ctx.getSender());
if (adding) tes.addFriend(player, side, friend);
else tes.removeFriend(player, side, friend);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -1,47 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import java.util.function.Function;
public class OwnerControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:set_owner");
NameUUIDPair owner;
public OwnerControl(NameUUIDPair pair) {
super(id);
this.owner = pair;
}
public OwnerControl(FriendlyByteBuf buf) {
super(id);
owner = new NameUUIDPair(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
owner.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot handle ownership theft packet from server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.getScreen(side).owner = owner;
}
}

View File

@ -1,74 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class ScreenModifyControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_screen");
public enum ControlType {
RESOLUTION, ROTATION
}
ControlType type;
Vector2i res;
Rotation rotation;
public ScreenModifyControl(Vector2i res) {
super(id);
this.type = ControlType.RESOLUTION;
this.res = res;
}
public ScreenModifyControl(Rotation rotation) {
super(id);
this.type = ControlType.ROTATION;
this.rotation = rotation;
}
public ScreenModifyControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (type.equals(ControlType.RESOLUTION))
res = new Vector2i(buf);
else rotation = Rotation.values()[buf.readByte()];
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (res != null) res.writeTo(buf);
else if (rotation != null) buf.writeByte(rotation.ordinal());
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.MODIFY_SCREEN, permissionChecker, ctx.getSender());
switch (type) {
case RESOLUTION -> tes.setResolution(side, res);
case ROTATION -> tes.setRotation(side, rotation);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
switch (type) {
case RESOLUTION -> tes.setResolution(side, res);
case ROTATION -> tes.setRotation(side, rotation);
}
}
}

View File

@ -1,63 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import java.util.function.Function;
public class SetURLControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:set_url");
String url;
Vector3i remoteLocation;
public SetURLControl(String url, Vector3i remoteLocation) {
super(id);
this.url = url;
this.remoteLocation = remoteLocation;
}
public SetURLControl(FriendlyByteBuf buf) {
super(id);
url = buf.readUtf();
if (buf.readBoolean()) remoteLocation = new Vector3i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(url);
buf.writeBoolean(remoteLocation != null);
if (remoteLocation != null) remoteLocation.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// TODO: deal with remote
checkPerms(ScreenRights.CHANGE_URL, permissionChecker, ctx.getSender());
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
}

View File

@ -1,48 +0,0 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class TurnOffControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:deactivate");
public static final TurnOffControl INSTANCE = new TurnOffControl();
public TurnOffControl() {
super(id);
}
@Override
public void write(FriendlyByteBuf buf) {
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot handle deactivation packet from server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (side != null) {
WebDisplays.PROXY.closeGui(pos, side);
tes.disableScreen(side);
} else {
for (BlockSide value : BlockSide.values()) {
WebDisplays.PROXY.closeGui(pos, value);
tes.disableScreen(value);
}
}
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.core;
public enum AdvancementIcon {
WEB_DISPLAYS("wd"),
BROKEN_PAD("brokenpad"),
PIGEON("pigeon");
private final String name;
AdvancementIcon(String n) {
name = n;
}
@Override
public String toString() {
return name;
}
}

View File

@ -7,7 +7,6 @@ package net.montoyo.wd.core;
import java.util.List;
import java.util.Map;
// TODO: bring this back when SSR is implemented
public class CCArguments implements IComputerArgs {
private final Object[] args;

View File

@ -5,18 +5,20 @@
package net.montoyo.wd.core;
import net.minecraft.world.item.ItemStack;
import net.montoyo.wd.registry.ItemRegistry;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.init.ItemInit;
public enum CraftComponent {
STONEKEY("stonekey", "StoneKey"),
UPGRADE("upgrade", "Upgrade"),
PERIPHERAL("peripheral", "Peripheral"),
BATCELL("batcell", "BatCell"),
BATPACK("batpack", "BatPack"),
LASERDIODE("laserdiode", "LaserDiode"),
STONE_KEY("stonekey", "Stone_Key"),
BLANK_UPGRADE("upgrade", "Blank_Upgrade"),
PERIPHERAL_BASE("peripheral", "Peripheral_Base"),
BATTERY_CELL("batcell", "Battery_Cell"),
BATTERY_PACK("batpack", "Battery_Pack"),
LASER_DIODE("laserdiode", "Laser_Diode"),
BACKLIGHT("backlight", "Backlight"),
EXTCARD("extcard", "ExtCard"),
BADEXTCARD("badextcard", "BadExtCard");
EXTENSION_CARD("extcard", "Blank_Upgrade"),
BAD_EXTENSION_CARD("badextcard", "Bad_Extension_Card");
private final String name;
private final String wikiName;
@ -32,6 +34,7 @@ public enum CraftComponent {
}
public ItemStack makeItemStack() {
return new ItemStack(ItemRegistry.getComputerCraftItem(ordinal()).get(), 1);
return new ItemStack(ItemInit.itemCraftComp.get(), 1);
}
}

View File

@ -7,7 +7,6 @@ package net.montoyo.wd.core;
import com.google.gson.JsonObject;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance;
import net.minecraft.advancements.critereon.ContextAwarePredicate;
import net.minecraft.advancements.critereon.DeserializationContext;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.resources.ResourceLocation;
@ -20,8 +19,10 @@ import java.util.Arrays;
import java.util.HashMap;
public class Criterion implements CriterionTrigger<Criterion.Instance> {
public static class Instance extends AbstractCriterionTriggerInstance {
public Instance(ResourceLocation id, ContextAwarePredicate arg2) {
public Instance(ResourceLocation id, EntityPredicate.Composite arg2) {
super(id, arg2);
}
}
@ -59,15 +60,16 @@ public class Criterion implements CriterionTrigger<Criterion.Instance> {
@Override
public @NotNull Instance createInstance(JsonObject json, DeserializationContext context) {
return new Instance(id, EntityPredicate.fromJson(json, "instance", context));
return new Instance(id, EntityPredicate.Composite.fromJson(json, "instance", context));
}
public void trigger(PlayerAdvancements ply) {
ArrayList<Listener<Instance>> listeners = map.get(ply);
if (listeners != null) {
if(listeners != null) {
Listener[] copy = listeners.toArray(new Listener[0]); //We need to make a copy, otherwise we get a ConcurrentModificationException
Arrays.stream(copy).forEach(l -> l.run(ply));
}
}
}

View File

@ -8,22 +8,22 @@ import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.entity.RemoteControlBlockEntity;
import net.montoyo.wd.entity.RedstoneControlBlockEntity;
import net.montoyo.wd.entity.ServerBlockEntity;
import net.montoyo.wd.registry.BlockRegistry;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityRCtrl;
import net.montoyo.wd.entity.TileEntityRedCtrl;
import net.montoyo.wd.entity.TileEntityServer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public enum DefaultPeripheral implements StringRepresentable {
KEYBOARD("keyboard", "Keyboard", KeyboardBlockEntity::new, BlockRegistry.KEYBOARD_BLOCK), //WITH FACING (< 3)
KEYBOARD("keyboard", "Keyboard", TileEntityKeyboard::new, TileEntityKeyboard::getBlockFromTE), //WITH FACING (< 3)
// CC_INTERFACE("ccinterface", "ComputerCraft_Interface", TileEntityCCInterface.class),
// OC_INTERFACE("cointerface", "OpenComputers_Interface", TileEntityOCInterface.class),
REMOTE_CONTROLLER("remotectrl", "Remote_Controller", RemoteControlBlockEntity::new , BlockRegistry.REMOTE_CONTROLLER_BLOCK), //WITHOUT FACING (>= 3)
REDSTONE_CONTROLLER("redstonectrl", "Redstone_Controller", RedstoneControlBlockEntity::new , BlockRegistry.REDSTONE_CONTROL_BLOCK),
SERVER("server", "Server", ServerBlockEntity::new, BlockRegistry.SERVER_BLOCK);
REMOTE_CONTROLLER("remotectrl", "Remote_Controller", TileEntityRCtrl::new ,TileEntityRCtrl::getBlockFromTE), //WITHOUT FACING (>= 3)
REDSTONE_CONTROLLER("redstonectrl", "Redstone_Controller", TileEntityRedCtrl::new ,TileEntityRedCtrl::getBlockFromTE),
SERVER("server", "Server", TileEntityServer::new, TileEntityServer::getBlockFromTE);
private final String name;
private final String wikiName;

View File

@ -5,16 +5,19 @@
package net.montoyo.wd.core;
import net.minecraft.world.item.ItemStack;
import net.montoyo.wd.item.ItemUpgrade;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.init.ItemInit;
public enum DefaultUpgrade {
LASERMOUSE("lasermouse", "LaserMouse"),
REDINPUT("redinput", "RedInput"),
REDOUTPUT("redoutput", "RedOutput"),
GPS("gps", "GPS");
public final String name;
public final String wikiName;
LASER_MOUSE("lasermouse", "Laser_Sensor"),
REDSTONE_INPUT("redinput", "Redstone_Input_Port"),
REDSTONE_OUTPUT("redoutput", "Redstone_Output_Port"),
GPS("gps", "GPS_Module");
private final String name;
private final String wikiName;
DefaultUpgrade(String n, String wn) {
name = n;
@ -26,25 +29,7 @@ public enum DefaultUpgrade {
return name;
}
protected static boolean matches(ItemStack stack, DefaultUpgrade upgrade) {
if (stack.getItem() instanceof ItemUpgrade upgrade1)
return upgrade1.type == upgrade;
return false;
}
public boolean matchesLaserMouse(ItemStack is) {
return matches(is, LASERMOUSE);
}
public boolean matchesRedInput(ItemStack is) {
return matches(is, REDINPUT);
}
public boolean matchesRedOutput(ItemStack is) {
return matches(is, REDOUTPUT);
}
public boolean matchesGps(ItemStack is) {
return matches(is, GPS);
public boolean matches(ItemStack is) {
return is.getItem() == ItemInit.itemUpgrade.get();
}
}

View File

@ -5,7 +5,9 @@
package net.montoyo.wd.core;
public enum HasAdvancement {
DONT_KNOW,
YES,
NO
}

View File

@ -7,8 +7,10 @@ package net.montoyo.wd.core;
import java.util.Map;
public interface IComputerArgs {
String checkString(int i);
int checkInteger(int i);
Map checkTable(int i);
int count();
}

View File

@ -7,9 +7,11 @@ package net.montoyo.wd.core;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3i;
public interface IPeripheral {
boolean connect(Level world, BlockPos blockPos, BlockState blockState, Vector3i screenPos, BlockSide screenSide);
}

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