Merge pull request #5 from NorbiPeti/directvb
Directly using VirtualBox from Java
This commit is contained in:
commit
04053f9b13
89 changed files with 3032 additions and 3148 deletions
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
libpxc.so
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
|
@ -466,4 +468,3 @@ TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar
|
|||
*.iml
|
||||
*.name
|
||||
.idea/compiler.xml
|
||||
*.xml
|
||||
|
|
89
README.md
89
README.md
|
@ -1,49 +1,50 @@
|
|||
# The Computer
|
||||
A working modern computer in Minecraft made using VirtualBox, jni4net, C# and Java. No clientside mods required.
|
||||
A working modern computer in Minecraft made using VirtualBox and Java. No clientside mods required.
|
||||
|
||||
I started working on this project on 2015. december 5. However I did not write much code in that time as I had to figure out how things work.
|
||||
I plan on making a series where I show the whole process of creating this project.
|
||||
## Video
|
||||
|
||||
##Video
|
||||
|
||||
[![Original video](https://img.youtube.com/vi/VxSyDfxPd3s/0.jpg)](https://www.youtube.com/watch?v=VxSyDfxPd3s)
|
||||
[![Video](https://img.youtube.com/vi/K4t98YUIm4M/0.jpg)](https://www.youtube.com/watch?v=K4t98YUIm4M)
|
||||
|
||||
## Installation requirements
|
||||
*Note: only the server host has to meet these requirements.*
|
||||
|
||||
### Currently compiled for (and tested on):
|
||||
*If you don't meet these requirements, you will need to compile the files for yourself. Please help by sending the compiled version to me so more people can download it.*
|
||||
* A non-Windows OS supported by VirtualBox
|
||||
* Root (sudo) privileges
|
||||
* Enough resources to run another OS
|
||||
|
||||
* Windows 7 64-bit
|
||||
* VirtualBox 5
|
||||
* Spgiot/Bukkit 1.8/1.9 (with Movecraft for the mouse craft type)
|
||||
* Microsoft .NET Framework 4.5
|
||||
### Tested versions:
|
||||
*If you don't meet these requirements, you may need to compile the files for yourself. If you do please send the compiled version to me so more people can download it.*
|
||||
|
||||
* OS X; Ubuntu 16.04/18.04
|
||||
* VirtualBox 6.0
|
||||
* Spgiot/Bukkit 1.12
|
||||
* Java 8
|
||||
|
||||
### Possibly works with (untested):
|
||||
* Any version of Windows which supports .NET 4.5
|
||||
* Other VirtualBox versions (code modifications are probably necessary)
|
||||
* Other Spigot/Bukkit versions
|
||||
* Microsoft .NET Framework 4 (code modifications *are* necessary)
|
||||
* Other Java versions
|
||||
*The fast rendering method currently only supports 1.12.2.*
|
||||
|
||||
*Due to jni4net support limitations the plugin does not support other operating systems.*
|
||||
### Tested on:
|
||||
*The requirements vary greatly depending on what OS you want to run ingame but here are my specs that can run Overwatch in Minecraft.*
|
||||
|
||||
* CPU: Intel® Pentium(R) CPU G3460 @ 3.50GHz × 2
|
||||
* RAM: 8 GB
|
||||
* GPU: NVidia GeForce GTX 650 1 GB
|
||||
|
||||
*Due to VirtualBox Java binding support limitations the plugin does not support Windows currently.*
|
||||
|
||||
## Installation
|
||||
**Warning:** The first loaded world on the server (the one specified in server.properties) will **lose** the first 20 maps, though it might be only a temporary effect, it might restore after the server starts up without the plugin. *(Untested.)*
|
||||
**Warning:** The first loaded world on the server (the one specified in server.properties) will temporarily **lose** the first 20 maps, although it will be back to normal if the server is loaded without the plugin.
|
||||
|
||||
* Install all the requirements
|
||||
* Add a virtual PC if you don't have any (the first one will be started)
|
||||
* Install VirtualBox
|
||||
* *Using sudo,* add a virtual PC if you don't have any (the first one will be started by default)
|
||||
* Install an OS and Guest Additions, if you haven't already
|
||||
* Put the jar file into <server>/plugins directory
|
||||
* Make sure your server is set to a world that you don't mind your maps deleted from
|
||||
* Start your server
|
||||
* *Using sudo,* start your server
|
||||
|
||||
## Usage
|
||||
*Please give appropriate credit and link to this page if you use this machine in one of your videos/creations/etc. You can also send me your video so I can put it here.*
|
||||
*Please give appropriate credit and link to this page if you use this machine in one of your videos/creations/etc.*
|
||||
|
||||
### Display
|
||||
*Note:* You can create as many displays as you want, but all of them will show the same.
|
||||
*Note: You can create as many displays as you want, but all of them will show the same currently.*
|
||||
|
||||
To create a display, make a 5 wide 4 high wall of item frames, then put the maps 0-19 on them starting from the top left and going downwards. You can give the maps with this command:
|
||||
|
||||
|
@ -54,22 +55,40 @@ Where you'll need to increment 0 for each map.
|
|||
It is also recommended to start the virtual machine first so you can distinguish the different parts of the display while placing it.
|
||||
|
||||
#### Keyboard
|
||||
You can either open the chat keyboard using /computer input key, or you can use /computer key \<keyname\>. You can find key names [here](https://github.com/NorbiPeti/VirtualComputer/blob/master/VirtualComputerSender/VirtualKeys.cs). Note that not all keys are currently supported.
|
||||
You can either open the chat keyboard using /computer input key, or you can use /computer key \<keyname\>. You can find key names [here](https://github.com/NorbiPeti/VirtualComputer/blob/directvb/VirtualComputer/src/sznp/virtualcomputer/Scancode.java).
|
||||
|
||||
#### Mouse
|
||||
You can "lock" the physical mouse to the virtual one with /computer input mouse, or you can move the mouse (including scrolling) with /computer mouse \<dx\> \<dy\> \<dz\> \<dw\>, where dx specifies the amount of pixels to move right, and dy specifies the amount of pixels to move down, while dz and dw specify the scrolling vertically (positive values scroll down) and horizontally.
|
||||
|
||||
To set the locked mouse speed, use /computer input mspeed \<integer\>. The difference in look position will be multiplied with this number. Recommended values are between 1 and 10 (inclusive). Default: 1.
|
||||
|
||||
You can also use the "mouse" Movecraft craft type to move the mouse, though it's a bit unreliable.
|
||||
|
||||
You can press a mouse button with /computer mouse <buttonname>. For example: /computer mouse leftbutton. You can find all the button names [here](https://github.com/NorbiPeti/VirtualComputer/blob/master/VirtualComputerSender/MouseBS.cs).
|
||||
You can press a mouse button with /computer mouse <buttonname>. For example: /computer mouse leftbutton. Usable key names:
|
||||
* LeftButton
|
||||
* RightButton
|
||||
* MiddleButton
|
||||
* WheelUp
|
||||
* WheelDown
|
||||
* XButton1
|
||||
* XButton2
|
||||
|
||||
#### Sounds
|
||||
Due to the way it works, it automatically plays every sound from the virtual machine **on the host computer**. This is built into VBoxHeadless, it seems. In order to make the sounds play for every connected player, we'd need a clientside mod.
|
||||
Due to the way it works, it automatically plays every sound from the virtual machine **on the host computer**. This is built into the VM, it seems. In order to make the sounds play for every connected player, we'd need a clientside mod.
|
||||
|
||||
### Special thanks:
|
||||
* The creators of VirtualBox for making it open-source and easy to use (though I had minor issues but those was because .NET had a few marshaling errors with booleans and that I needed to learn how machines work - especially keyboards)
|
||||
* The creators of jni4net, after I figured it out, it was quite easy to use
|
||||
* Minecraft player iie for testing and suggesting the Movecraft mouse and other ideas not related to this project
|
||||
* The creator(s) of SketchMap, a plugin which I edited to create the display
|
||||
* The creators of VirtualBox for making it open-source and kind of easy to use (though I had minor issues as the documentation doesn't really tell me how to write a new frontend :P and that I needed to learn how machines work - especially keyboards)
|
||||
* @iiegit for testing and more testing for the non-Windows version and helping a lot to get it on /r/sequence
|
||||
|
||||
# Known issues
|
||||
## Port remains open (cannot bind to port)
|
||||
**Fix:** Close all VirtualBox instances and wait 10 seconds.
|
||||
|
||||
**Cause:** Possibly it happens because the plugin creates the VBoxSVC process, which thus inherits file descriptors such as the open server port.
|
||||
|
||||
## OpenCL error
|
||||
|
||||
```
|
||||
Check your environment. Failed to load codegen native library or possibly failed to locate opencl native library (opencl.dll/opencl.so). Ensure that OpenCL is in your PATH (windows) or in LD_LIBRARY_PATH (linux).
|
||||
```
|
||||
|
||||
**Fix:** On Ubuntu you can install the needed library with `sudo apt install ocl-icd-opencl-dev`
|
||||
|
||||
|
|
|
@ -16,6 +16,5 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="VirtualComputerSender.j4n.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
144
VirtualComputer/dependency-reduced-pom.xml
Normal file
144
VirtualComputer/dependency-reduced-pom.xml
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.NorbiPeti</groupId>
|
||||
<artifactId>VirtualComputer</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArgs>
|
||||
<arg>-g</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration />
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>XPCOM</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.virtualbox:VirtualBox-MSCOM</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>MSCOM</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.virtualbox:VirtualBox</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>repo</id>
|
||||
<url>file://${basedir}/repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>commons-lang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<groupId>org.yaml</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<groupId>net.md-5</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||
<version>6.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
BIN
VirtualComputer/fix/IDisplaySourceBitmap.class
Normal file
BIN
VirtualComputer/fix/IDisplaySourceBitmap.class
Normal file
Binary file not shown.
3
VirtualComputer/fix/README
Normal file
3
VirtualComputer/fix/README
Normal file
|
@ -0,0 +1,3 @@
|
|||
If a new version is released, copy this to the JAR into org/mozilla/interfaces
|
||||
This fixes the source bitmap pointer return type in the Java API.
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
VirtualComputer/lombok.config
Normal file
1
VirtualComputer/lombok.config
Normal file
|
@ -0,0 +1 @@
|
|||
lombok.var.flagUsage = ALLOW
|
|
@ -1,8 +0,0 @@
|
|||
name: VirtualComputer
|
||||
main: sznp.virtualcomputer.PluginMain
|
||||
version: 1.1
|
||||
commands:
|
||||
computer:
|
||||
usage: Use /computer start|stop
|
||||
alias: c
|
||||
softdepend: [Movecraft]
|
|
@ -3,24 +3,8 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.NorbiPeti</groupId>
|
||||
<artifactId>VirtualComputer</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>.</directory>
|
||||
<includes>
|
||||
<include>*.dll</include>
|
||||
<include>*.yml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
@ -28,6 +12,9 @@
|
|||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArgs>
|
||||
<arg>-g</arg> <!-- LocalVariableTable -->
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@ -41,16 +28,6 @@
|
|||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>org.virtualbox:VirtualBox</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<pluginExecution>
|
||||
<action>
|
||||
<execute />
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
@ -71,24 +48,103 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.9.2-R0.1-SNAPSHOT</version>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.countercraft</groupId>
|
||||
<artifactId>Movecraft</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.jni4net</groupId>
|
||||
<artifactId>jni4net.j</artifactId>
|
||||
<version>0.8.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox</artifactId>
|
||||
<version>5.1</version>
|
||||
<version>6.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||
<version>6.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
|
||||
<dependency>
|
||||
<groupId>com.github.jnr</groupId>
|
||||
<artifactId>jnr-ffi</artifactId>
|
||||
<version>2.1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aparapi</groupId>
|
||||
<artifactId>aparapi</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.16</version>
|
||||
</dependency>
|
||||
<dependency> <!-- javax.annotations.Nullable -->
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>XPCOM</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.virtualbox:VirtualBox-MSCOM</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>MSCOM</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.virtualbox:VirtualBox</exclude>
|
||||
</excludes>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||
<version>6.0</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox-MSCOM</artifactId>
|
||||
<versioning>
|
||||
<release>6.0</release>
|
||||
<versions>
|
||||
<version>6.0</version>
|
||||
</versions>
|
||||
<lastUpdated>20190405225845</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
Binary file not shown.
Binary file not shown.
|
@ -2,8 +2,8 @@
|
|||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.NorbiPeti</groupId>
|
||||
<artifactId>SenderBridge</artifactId>
|
||||
<version>1.0</version>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox</artifactId>
|
||||
<version>5.1</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
Binary file not shown.
9
VirtualComputer/repo/org/virtualbox/VirtualBox/5.2/VirtualBox-5.2.pom
Executable file
9
VirtualComputer/repo/org/virtualbox/VirtualBox/5.2/VirtualBox-5.2.pom
Executable file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox</artifactId>
|
||||
<version>5.2</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox</artifactId>
|
||||
<version>6.0</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>org.virtualbox</groupId>
|
||||
<artifactId>VirtualBox</artifactId>
|
||||
<versioning>
|
||||
<release>6.0</release>
|
||||
<versions>
|
||||
<version>5.1</version>
|
||||
<version>5.2</version>
|
||||
<version>6.0</version>
|
||||
</versions>
|
||||
<lastUpdated>20181221211412</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
|
@ -1,217 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap;
|
||||
|
||||
/*
|
||||
* This file was originally taken from https://github.com/slipswhitley/SketchMap
|
||||
*/
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.mcplugindev.slipswhitley.sketchmap.file.SketchMapFileException;
|
||||
import com.mcplugindev.slipswhitley.sketchmap.map.RelativeLocation;
|
||||
import com.mcplugindev.slipswhitley.sketchmap.map.SketchMap;
|
||||
|
||||
//import com.mcplugindev.slipswhitley.sketchmap.map.SketchMap.BaseFormat;
|
||||
|
||||
public class SketchMapAPI
|
||||
{
|
||||
|
||||
public static SketchMap getMapByID(String id)
|
||||
{
|
||||
for (SketchMap map : SketchMap.getLoadedMaps())
|
||||
{
|
||||
if (map.getID().equalsIgnoreCase(id))
|
||||
{
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<ItemStack> getOrderedItemSet(SketchMap map)
|
||||
{
|
||||
List<ItemStack> items = new ArrayList<ItemStack>();
|
||||
|
||||
for (int y = 0; y < map.getLengthY(); y++)
|
||||
{
|
||||
for (int x = 0; x < map.getLengthX(); x++)
|
||||
{
|
||||
for (RelativeLocation loc : map.getMapCollection().keySet())
|
||||
{
|
||||
if (loc.getX() != x || loc.getY() != y)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack iStack = new ItemStack(Material.MAP, 1);
|
||||
iStack.setDurability(SketchMapUtils.getMapID(map
|
||||
.getMapCollection().get(loc)));
|
||||
|
||||
ItemMeta iMeta = iStack.getItemMeta();
|
||||
iMeta.setDisplayName(ChatColor.GREEN + "SketchMap ID: "
|
||||
+ ChatColor.GOLD + map.getID() + ChatColor.GREEN
|
||||
+ " Pos-X: " + ChatColor.GOLD + (x + 1)
|
||||
+ ChatColor.GREEN + " Pos-Y: " + ChatColor.GOLD
|
||||
+ (y + 1));
|
||||
|
||||
iMeta.setLore(Arrays.asList(new String[] { ChatColor.GRAY
|
||||
+ "SketchMap ID: " + map.getID()
|
||||
|
||||
}));
|
||||
|
||||
iStack.setItemMeta(iMeta);
|
||||
items.add(iStack);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public static SketchMap loadSketchMapFromFile(File file)
|
||||
throws SketchMapFileException
|
||||
{
|
||||
|
||||
YamlConfiguration config = null;
|
||||
try
|
||||
{
|
||||
config = YamlConfiguration.loadConfiguration(file);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
throw new SketchMapFileException("Invalid SketchMap File \""
|
||||
+ file.getName() + "\"");
|
||||
}
|
||||
|
||||
String[] fieldSet = { "x-panes", "y-panes", "public-protected",
|
||||
"map-collection", "base-format", "map-image", };
|
||||
|
||||
for (String field : fieldSet)
|
||||
{
|
||||
if (!config.isSet(field))
|
||||
{
|
||||
throw new SketchMapFileException(
|
||||
"Unable to load SketchMap file \"" + file.getName()
|
||||
+ "\" missing field \"" + field + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
Integer xPanes = config.getInt("x-panes");
|
||||
if (xPanes == null || xPanes < 1)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName() + "\" invalid field \"x-panes\"");
|
||||
}
|
||||
|
||||
Integer yPanes = config.getInt("y-panes");
|
||||
if (yPanes == null || yPanes < 1)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName() + "\" invalid field \"y-panes\"");
|
||||
}
|
||||
|
||||
Boolean publicProtected = config.getBoolean("public-protected");
|
||||
if (publicProtected == null)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName() + "\" invalid field \"public-protected\"");
|
||||
}
|
||||
|
||||
List<String> mapList = config.getStringList("map-collection");
|
||||
if (mapList == null)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName() + "\" invalid field \"map-collection\"");
|
||||
}
|
||||
|
||||
Map<Short, RelativeLocation> mapCollection = new HashMap<Short, RelativeLocation>();
|
||||
|
||||
for (String map : mapList)
|
||||
{
|
||||
String[] split = map.split(" ");
|
||||
if (split.length != 2)
|
||||
{
|
||||
throw new SketchMapFileException(
|
||||
"Unable to load SketchMap file \"" + file.getName()
|
||||
+ "\" cannot parse field in \"map-colection\"");
|
||||
}
|
||||
|
||||
RelativeLocation loc = RelativeLocation.fromString(split[0]);
|
||||
|
||||
if (loc == null)
|
||||
{
|
||||
throw new SketchMapFileException(
|
||||
"Unable to load SketchMap file \"" + file.getName()
|
||||
+ "\" cannot parse field in \"map-colection\"");
|
||||
}
|
||||
|
||||
Short id = null;
|
||||
try
|
||||
{
|
||||
id = Short.parseShort(split[1]);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
throw new SketchMapFileException(
|
||||
"Unable to load SketchMap file \"" + file.getName()
|
||||
+ "\" cannot parse field in \"map-colection\"");
|
||||
}
|
||||
|
||||
mapCollection.put(id, loc);
|
||||
}
|
||||
|
||||
//BaseFormat format = null;
|
||||
/*
|
||||
* try {
|
||||
* format = BaseFormat.valueOf(config.getString("base-format"));
|
||||
* }
|
||||
* catch (Exception ex) {
|
||||
* throw new SketchMapFileException("Unable to load SketchMap file \"" +
|
||||
* file.getName()
|
||||
* + "\" cannot parse BaseFormat from field \"base-format\"");
|
||||
* }
|
||||
*/
|
||||
|
||||
String b64Img = config.getString("map-image");
|
||||
if (b64Img == null)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName() + "\" invalid field \"map-image\"");
|
||||
}
|
||||
|
||||
BufferedImage image = null;
|
||||
|
||||
try
|
||||
{
|
||||
image = SketchMapUtils.base64StringToImg(b64Img);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName()
|
||||
+ "\" parse image from field \"map-image\"");
|
||||
}
|
||||
|
||||
String imageID = file.getName().substring(0,
|
||||
file.getName().lastIndexOf("."));
|
||||
if (getMapByID(imageID) != null)
|
||||
{
|
||||
throw new SketchMapFileException("Unable to load SketchMap file \""
|
||||
+ file.getName()
|
||||
+ "\" A SketchMap by that ID already exists.");
|
||||
}
|
||||
|
||||
return new SketchMap(image, imageID, yPanes, yPanes, publicProtected);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap;
|
||||
|
||||
/*
|
||||
* This file was originally taken from https://github.com/slipswhitley/SketchMap
|
||||
*/
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.mcplugindev.slipswhitley.sketchmap.listener.PlayerListener;
|
||||
|
||||
public class SketchMapPlugin extends JavaPlugin
|
||||
{
|
||||
private static SketchMapPlugin plugin;
|
||||
|
||||
public void onEnable()
|
||||
{
|
||||
plugin = this;
|
||||
|
||||
setupListeners();
|
||||
|
||||
sendEnabledMessage();
|
||||
}
|
||||
|
||||
private void sendEnabledMessage()
|
||||
{
|
||||
SketchMapUtils.sendColoredConsoleMessage(ChatColor.GREEN
|
||||
+ "| |");
|
||||
|
||||
SketchMapUtils.sendColoredConsoleMessage(ChatColor.GREEN + "| "
|
||||
+ ChatColor.AQUA + "SketchMap "
|
||||
+ this.getDescription().getVersion() + " has been Enabled!"
|
||||
+ ChatColor.GREEN + " |");
|
||||
|
||||
SketchMapUtils.sendColoredConsoleMessage(ChatColor.GREEN + "| "
|
||||
+ ChatColor.AQUA + " Authors: SlipsWhitley & Fyrinlight"
|
||||
+ ChatColor.GREEN + " |");
|
||||
|
||||
SketchMapUtils.sendColoredConsoleMessage(ChatColor.GREEN
|
||||
+ "| |");
|
||||
}
|
||||
|
||||
private void setupListeners()
|
||||
{
|
||||
Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
|
||||
}
|
||||
|
||||
public static SketchMapPlugin getPlugin()
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap;
|
||||
|
||||
/*
|
||||
* This file was originally taken from https://github.com/slipswhitley/SketchMap
|
||||
*/
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Base64;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
public class SketchMapUtils
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Image Utils
|
||||
*
|
||||
*/
|
||||
|
||||
public static BufferedImage resize(Image img, Integer width, Integer height)
|
||||
{
|
||||
|
||||
img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
|
||||
|
||||
if (img instanceof BufferedImage)
|
||||
{
|
||||
return (BufferedImage) img;
|
||||
}
|
||||
|
||||
BufferedImage bimage = new BufferedImage(img.getWidth(null),
|
||||
img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D bGr = bimage.createGraphics();
|
||||
bGr.drawImage(img, 0, 0, null);
|
||||
bGr.dispose();
|
||||
|
||||
return bimage;
|
||||
}
|
||||
|
||||
public static BufferedImage base64StringToImg(final String base64String)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder()
|
||||
.decode(base64String)));
|
||||
} catch (final IOException ioe)
|
||||
{
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendColoredConsoleMessage(String msg)
|
||||
{
|
||||
ConsoleCommandSender sender = Bukkit.getConsoleSender();
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated Methods Here :'c
|
||||
*/
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static short getMapID(MapView map)
|
||||
{
|
||||
return map.getId();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static MapView getMapView(short id)
|
||||
{
|
||||
MapView map = Bukkit.getMap(id);
|
||||
if (map != null)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
return Bukkit.createMap(getDefaultWorld());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
public static Block getTargetBlock(Player player, int i)
|
||||
{
|
||||
return player.getTargetBlock((HashSet<Material>) null, i);
|
||||
}
|
||||
|
||||
public static World getDefaultWorld()
|
||||
{
|
||||
return Bukkit.getWorlds().get(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap.file;
|
||||
|
||||
public class SketchMapFileException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SketchMapFileException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap.listener;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class PlayerListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEntityEvent event) {
|
||||
if(!(event.getRightClicked() instanceof ItemFrame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemFrame iFrame = (ItemFrame) event.getRightClicked();
|
||||
ItemStack iHand = event.getPlayer().getItemInHand();
|
||||
|
||||
if(iHand.getType() != Material.MAP) {
|
||||
return;
|
||||
}
|
||||
|
||||
String lore = iHand.getItemMeta().getLore().get(0);
|
||||
|
||||
if(!ChatColor.stripColor(lore).startsWith("SketchMap ID:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(iFrame.getItem().getType() != Material.AIR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
|
||||
ItemStack frameItem = iHand.clone();
|
||||
frameItem.setAmount(1);
|
||||
ItemMeta frameIMeta = frameItem.getItemMeta();
|
||||
|
||||
frameIMeta.setDisplayName("");
|
||||
frameItem.setItemMeta(frameIMeta);
|
||||
|
||||
iFrame.setItem(frameItem);
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if(player.getGameMode() == GameMode.CREATIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(iHand.getAmount() == 1) {
|
||||
player.getInventory().setItemInHand(new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
|
||||
iHand.setAmount(iHand.getAmount() - 1);
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap.map;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapCanvas;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
public class ImageRenderer extends MapRenderer
|
||||
{
|
||||
|
||||
private BufferedImage image;
|
||||
|
||||
public ImageRenderer(BufferedImage image)
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
private int progress = 0;
|
||||
public static int updatepixels = 15;
|
||||
|
||||
@Override
|
||||
public void render(MapView view, MapCanvas canvas, Player player)
|
||||
{
|
||||
long time = System.nanoTime();
|
||||
|
||||
try
|
||||
{
|
||||
canvas.drawImage(0, progress * updatepixels, image.getSubimage(0,
|
||||
progress * updatepixels, 128, (progress * updatepixels
|
||||
+ updatepixels >= 128 ? 128 - progress
|
||||
* updatepixels : updatepixels)));
|
||||
if (progress < 128 / updatepixels)
|
||||
progress++;
|
||||
else
|
||||
progress = 0;
|
||||
|
||||
long diff = System.nanoTime() - time;
|
||||
if (TimeUnit.NANOSECONDS.toMillis(diff) > 40)
|
||||
{
|
||||
System.out.println("Map rendering took "
|
||||
+ TimeUnit.NANOSECONDS.toMillis(diff) + " ms");
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("Progess: " + progress);
|
||||
System.out.println("UpdatePixels: " + updatepixels);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap.map;
|
||||
|
||||
public class RelativeLocation {
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public RelativeLocation (int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return x + ":" + y;
|
||||
}
|
||||
|
||||
public static RelativeLocation fromString(String str) {
|
||||
String[] args = str.split(":");
|
||||
if(args.length != 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
try {
|
||||
x = Integer.parseInt(args[0]);
|
||||
y = Integer.parseInt(args[1]);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RelativeLocation (x, y);
|
||||
}
|
||||
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
package com.mcplugindev.slipswhitley.sketchmap.map;
|
||||
|
||||
/*
|
||||
* This file was originally taken from https://github.com/slipswhitley/SketchMap
|
||||
*/
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import com.mcplugindev.slipswhitley.sketchmap.SketchMapUtils;
|
||||
|
||||
public class SketchMap
|
||||
{
|
||||
|
||||
public BufferedImage image;
|
||||
private String mapID;
|
||||
private Integer xPanes;
|
||||
private Integer yPanes;
|
||||
private Boolean publicProtected;
|
||||
//private BaseFormat format;
|
||||
|
||||
private Map<RelativeLocation, MapView> mapCollection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Create SketchMap using New Maps
|
||||
*
|
||||
*/
|
||||
|
||||
public SketchMap(BufferedImage image, String mapID, int xPanes, int yPanes,
|
||||
boolean publicProtected)
|
||||
{
|
||||
|
||||
this.image = SketchMapUtils.resize(image, xPanes * 128, yPanes * 128);
|
||||
this.mapID = mapID;
|
||||
this.xPanes = xPanes;
|
||||
this.yPanes = yPanes;
|
||||
this.publicProtected = publicProtected;
|
||||
//this.format = format;
|
||||
|
||||
this.mapCollection = new HashMap<RelativeLocation, MapView>();
|
||||
|
||||
getLoadedMaps().add(this);
|
||||
loadSketchMap();
|
||||
}
|
||||
|
||||
private void loadSketchMap()
|
||||
{
|
||||
for (int x = 0; x < xPanes; x++)
|
||||
{
|
||||
for (int y = 0; y < yPanes; y++)
|
||||
{
|
||||
initMap(x, y,
|
||||
Bukkit.createMap(SketchMapUtils.getDefaultWorld()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Create SketchMap using Specified Maps
|
||||
*
|
||||
*/
|
||||
|
||||
public SketchMap(BufferedImage image, String mapID, int xPanes, int yPanes,
|
||||
boolean publicProtected, Map<Short, RelativeLocation> mapCollection)
|
||||
{
|
||||
|
||||
this.image = SketchMapUtils.resize(image, xPanes * 128, yPanes * 128);
|
||||
this.mapID = mapID;
|
||||
this.xPanes = xPanes;
|
||||
this.yPanes = yPanes;
|
||||
this.publicProtected = publicProtected;
|
||||
//this.format = format;
|
||||
|
||||
this.mapCollection = new HashMap<RelativeLocation, MapView>();
|
||||
|
||||
getLoadedMaps().add(this);
|
||||
loadSketchMap(mapCollection);
|
||||
}
|
||||
|
||||
private void loadSketchMap(Map<Short, RelativeLocation> mapCollection)
|
||||
{
|
||||
for (Short mapID : mapCollection.keySet())
|
||||
{
|
||||
RelativeLocation loc = mapCollection.get(mapID);
|
||||
|
||||
initMap(loc.getX(), loc.getY(), SketchMapUtils.getMapView(mapID));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
private void initMap(int x, int y, MapView mapView)
|
||||
{
|
||||
BufferedImage subImage = image.getSubimage(x * 128, y * 128, 128, 128);
|
||||
mapView.getRenderers().clear();
|
||||
mapView.addRenderer(new ImageRenderer(subImage));
|
||||
|
||||
mapCollection.put(new RelativeLocation(x, y), mapView);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get Object information
|
||||
*
|
||||
*/
|
||||
|
||||
public String getID()
|
||||
{
|
||||
return mapID;
|
||||
}
|
||||
|
||||
public BufferedImage getImage()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
public int getLengthX()
|
||||
{
|
||||
return xPanes;
|
||||
}
|
||||
|
||||
public int getLengthY()
|
||||
{
|
||||
return yPanes;
|
||||
}
|
||||
|
||||
public boolean isPublicProtected()
|
||||
{
|
||||
return publicProtected;
|
||||
}
|
||||
|
||||
public Map<RelativeLocation, MapView> getMapCollection()
|
||||
{
|
||||
return mapCollection;
|
||||
}
|
||||
|
||||
/*
|
||||
* public BaseFormat getBaseFormat() {
|
||||
* return format;
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* Map Functions
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public void delete()
|
||||
{
|
||||
getLoadedMaps().remove(this);
|
||||
|
||||
try
|
||||
{
|
||||
this.finalize();
|
||||
} catch (Throwable e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Static Methods
|
||||
*
|
||||
*/
|
||||
|
||||
private static Set<SketchMap> sketchMaps;
|
||||
|
||||
public static Set<SketchMap> getLoadedMaps()
|
||||
{
|
||||
if (sketchMaps == null)
|
||||
{
|
||||
sketchMaps = new HashSet<SketchMap>();
|
||||
}
|
||||
|
||||
return sketchMaps;
|
||||
}
|
||||
|
||||
/*
|
||||
* public enum BaseFormat {
|
||||
* PNG,
|
||||
* JPEG;
|
||||
*
|
||||
* public String getExtension() {
|
||||
* if(this == BaseFormat.PNG) {
|
||||
* return "png";
|
||||
* }
|
||||
* if(this == BaseFormat.JPEG) {
|
||||
* return "jpg";
|
||||
* }
|
||||
* return null;
|
||||
* }
|
||||
*
|
||||
* public static BaseFormat fromExtension(String ext) {
|
||||
* if(ext.equalsIgnoreCase("png")) {
|
||||
* return BaseFormat.PNG;
|
||||
*
|
||||
* }
|
||||
* if(ext.equalsIgnoreCase("jpg")) {
|
||||
* return BaseFormat.JPEG;
|
||||
* }
|
||||
* return null;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
}
|
162
VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java
Normal file
162
VirtualComputer/src/main/java/sznp/virtualcomputer/Commands.java
Normal file
|
@ -0,0 +1,162 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.virtualbox_6_0.VBoxException;
|
||||
|
||||
public class Commands implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (args.length == 0)
|
||||
return false;
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "start":
|
||||
case "poweron":
|
||||
case "on":
|
||||
case "startup":
|
||||
int c = getMachineIndex(args);
|
||||
if (c == -1) {
|
||||
sender.sendMessage("§cUsage: /" + label + " start [index]");
|
||||
return true;
|
||||
}
|
||||
Computer.getInstance().Start(sender, c);
|
||||
break;
|
||||
case "stop":
|
||||
case "poweroff":
|
||||
case "off":
|
||||
case "shutdown":
|
||||
case "kill":
|
||||
Computer.getInstance().Stop(sender);
|
||||
break;
|
||||
case "powerbutton":
|
||||
case "pwrbtn":
|
||||
case "powerbtn":
|
||||
c = getMachineIndex(args);
|
||||
if (c == -1) {
|
||||
sender.sendMessage("§cUsage: /" + label + " powerbutton [index]");
|
||||
return true;
|
||||
}
|
||||
Computer.getInstance().PowerButton(sender, c);
|
||||
break;
|
||||
case "reset":
|
||||
case "restart":
|
||||
Computer.getInstance().Reset(sender);
|
||||
break;
|
||||
case "fix":
|
||||
case "fixscreen":
|
||||
Computer.getInstance().FixScreen(sender);
|
||||
break;
|
||||
case "key":
|
||||
case "press":
|
||||
case "presskey":
|
||||
case "keypress":
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage("§cUsage: /computer key <key> [down/up|duration(ticks)]");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 3)
|
||||
Computer.getInstance().PressKey(sender, args[1], "");
|
||||
else
|
||||
Computer.getInstance().PressKey(sender, args[1], args[2]);
|
||||
break;
|
||||
case "mouse":
|
||||
boolean showusage = true;
|
||||
if (args.length < 6) {
|
||||
try {
|
||||
// Command overloading, because I can :P
|
||||
if (args.length > 4) // 4<x<6
|
||||
{
|
||||
Computer.getInstance().UpdateMouse(sender, Integer.parseInt(args[1]), Integer.parseInt(args[2]),
|
||||
Integer.parseInt(args[3]), Integer.parseInt(args[4]), "", false);
|
||||
showusage = false;
|
||||
} else {
|
||||
if (args.length == 3) {
|
||||
Computer.getInstance().UpdateMouse(sender, 0, 0, 0, 0, args[1], args[2].equals("down"));
|
||||
showusage = false;
|
||||
} else if (args.length == 2) {
|
||||
Computer.getInstance().UpdateMouse(sender, 0, 0, 0, 0, args[1]);
|
||||
showusage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (VBoxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (Exception ignored) { //It will show the usage here
|
||||
}
|
||||
}
|
||||
if (showusage) {
|
||||
sender.sendMessage("§cUsage: /computer mouse <relx> <rely> <relz> <relw>");
|
||||
sender.sendMessage("§cOr: /computer mouse <button> [up/down]");
|
||||
}
|
||||
break;
|
||||
case "input":
|
||||
case "show":
|
||||
case "showinput":
|
||||
case "shinput": {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage("§cError: Only players can use this command.");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage("§cUsage: /computer input <key|mouse>");
|
||||
return true;
|
||||
}
|
||||
switch (args[1].toLowerCase()) {
|
||||
case "key":
|
||||
case "keyboard":
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName()
|
||||
+ " [\"\",{\"text\":\" [0]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D0\"}},{\"text\":\" [1]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D1\"}},{\"text\":\" [2]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D2\"}},{\"text\":\" [3]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D3\"}},{\"text\":\" [4]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D4\"}},{\"text\":\" [5]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D5\"}},{\"text\":\" [6]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D6\"}},{\"text\":\" [7]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D7\"}},{\"text\":\" [8]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D8\"}},{\"text\":\" [9]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D9\"}}]");
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Tab]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Tab\"}},{\"text\":\" [Q]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Q\"}},{\"text\":\" [W]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key W\"}},{\"text\":\" [E]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key E\"}},{\"text\":\" [R]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key R\"}},{\"text\":\" [T]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key T\"}},{\"text\":\" [Y]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Y\"}},{\"text\":\" [U]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key U\"}},{\"text\":\" [I]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key I\"}},{\"text\":\" [O]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key O\"}},{\"text\":\" [P]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key P\"}}]");
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName()
|
||||
+ " [\"\",{\"text\":\" [CapsLock]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key CapsLock\"}},{\"text\":\" [A]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key A\"}},{\"text\":\" [S]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key S\"}},{\"text\":\" [D]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D\"}},{\"text\":\" [F]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key F\"}},{\"text\":\" [G]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key G\"}},{\"text\":\" [H]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key H\"}},{\"text\":\" [J]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key J\"}},{\"text\":\" [K]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key K\"}},{\"text\":\" [L]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key L\"}},{\"text\":\" [Enter]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Enter\"}}]");
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Z]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Z\"}},{\"text\":\" [X]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key X\"}},{\"text\":\" [C]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key C\"}},{\"text\":\" [V]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key V\"}},{\"text\":\" [B]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key B\"}},{\"text\":\" [N]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key N\"}},{\"text\":\" [M]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key M\"}}]");
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlLeft\"}},{\"text\":\" [Alt]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltLeft\"}},{\"text\":\" [Space]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Space\"}},{\"text\":\" [AltGr]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltRight\"}},{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlRight\"}}]");
|
||||
break;
|
||||
case "mouse":
|
||||
MouseLockerPlayerListener.toggleLock((Player) sender);
|
||||
break;
|
||||
case "mspeed":
|
||||
case "mousespeed":
|
||||
if (args.length < 3) {
|
||||
sender.sendMessage("§cUsage: /computer input mspeed <number>");
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
MouseLockerPlayerListener.LockedSpeed = Float.parseFloat(args[2]);
|
||||
} catch(NumberFormatException e) {
|
||||
sender.sendMessage("§cThe speed must be a number.");
|
||||
break;
|
||||
}
|
||||
sender.sendMessage("§aMouse speed set to " + MouseLockerPlayerListener.LockedSpeed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the 2nd parameter
|
||||
*
|
||||
* @return The index of the machine or -1 on usage error
|
||||
*/
|
||||
private int getMachineIndex(String[] args) {
|
||||
int c = 0;
|
||||
if (args.length >= 2) {
|
||||
try {
|
||||
c = Integer.parseInt(args[1]);
|
||||
} catch (Exception ignored) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
235
VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java
Normal file
235
VirtualComputer/src/main/java/sznp/virtualcomputer/Computer.java
Normal file
|
@ -0,0 +1,235 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.virtualbox_6_0.*;
|
||||
import sznp.virtualcomputer.events.MachineEventHandler;
|
||||
import sznp.virtualcomputer.events.VBoxEventHandler;
|
||||
import sznp.virtualcomputer.renderer.GPURenderer;
|
||||
import sznp.virtualcomputer.renderer.MCFrameBuffer;
|
||||
import sznp.virtualcomputer.util.Scancode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class Computer {
|
||||
@Getter
|
||||
private static Computer instance;
|
||||
|
||||
private final PluginMain plugin;
|
||||
private ISession session;
|
||||
private IVirtualBox vbox;
|
||||
private IMachine machine;
|
||||
private MachineEventHandler handler;
|
||||
private IEventListener listener;
|
||||
private VirtualBoxManager manager;
|
||||
|
||||
@java.beans.ConstructorProperties({"plugin"})
|
||||
public Computer(PluginMain plugin, VirtualBoxManager manager, IVirtualBox vbox) {
|
||||
this.plugin = plugin;
|
||||
this.manager = manager;
|
||||
session = manager.getSessionObject();
|
||||
this.vbox = vbox;
|
||||
if (instance != null) throw new IllegalStateException("A computer already exists!");
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void Start(CommandSender sender, int index) {// TODO: Add touchscreen support (#2)
|
||||
if (session.getState() == SessionState.Locked) {
|
||||
sender.sendMessage("§cThe machine is already running!");
|
||||
return;
|
||||
}
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
if (vbox.getMachines().size() <= index) {
|
||||
sendMessage(sender, "§cMachine not found!");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sendMessage(sender, "§eStarting computer...");
|
||||
machine = vbox.getMachines().get(index);
|
||||
session.setName("minecraft");
|
||||
// machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); - This creates a *process*, we don't want that anymore
|
||||
machine.lockMachine(session, LockType.VM); // We want the machine inside *our* process <-- Need the VM type to have console access
|
||||
VBoxEventHandler.getInstance().setup(machine.getId(), sender); //TODO: Sometimes null
|
||||
} catch (VBoxException e) {
|
||||
if (e.getResultCode() == 0x80070005) { //lockMachine: "The object functionality is limited"
|
||||
sendMessage(sender, "§6Cannot start computer, the machine may be inaccessible");
|
||||
sendMessage(sender, "§6Make sure that the server is running as root (sudo)");
|
||||
//TODO: If we have VirtualBox open, it won't close the server's port
|
||||
//TODO: "The object in question already exists." on second start
|
||||
//machine.launchVMProcess(session, "headless", "").waitForCompletion(10000); //No privileges, start the 'old' way
|
||||
//session.getConsole().getDisplay().attachFramebuffer(0L, new IFramebuffer(new MCFrameBuffer(session.getConsole().getDisplay(), false)));
|
||||
//sendMessage(sender, "§6Computer started with slower screen. Run as root to use a faster method.");
|
||||
} else {
|
||||
sendMessage(sender, "§cFailed to start computer: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called when the machine is locked after {@link #Start(CommandSender, int)}
|
||||
*
|
||||
* @param sender The sender which started the machine
|
||||
*/
|
||||
public void onLock(CommandSender sender) {
|
||||
machine = session.getMachine(); // This is the Machine object we can work with
|
||||
final IConsole console = session.getConsole();
|
||||
if (handler != null)
|
||||
handler.disable();
|
||||
handler = new MachineEventHandler(Computer.this, sender);
|
||||
listener = handler.registerTo(console.getEventSource());
|
||||
IProgress progress = console.powerUp(); // https://marc.info/?l=vbox-dev&m=142780789819967&w=2
|
||||
handler.setProgress(progress);
|
||||
handler.registerTo(progress.getEventSource()); //TODO: Show progress bar some way?
|
||||
console.getDisplay().attachFramebuffer(0L,
|
||||
new IFramebuffer(new MCFrameBuffer(console.getDisplay(), true)));
|
||||
}
|
||||
|
||||
private void sendMessage(@Nullable CommandSender sender, String message) {
|
||||
if (sender != null)
|
||||
sender.sendMessage(message);
|
||||
plugin.getLogger().warning((sender == null ? "" : sender.getName() + ": ") + ChatColor.stripColor(message));
|
||||
}
|
||||
|
||||
public void Stop(CommandSender sender) {
|
||||
if (checkMachineNotRunning(sender)) {
|
||||
if (session.getState().equals(SessionState.Locked)) {
|
||||
onMachineStop(sender); //Needed for session reset
|
||||
sendMessage(sender, "§eComputer was already off, released it.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
sendMessage(sender, "§eStopping computer...");
|
||||
session.getConsole().powerDown();
|
||||
}
|
||||
|
||||
public void PowerButton(CommandSender sender, int index) {
|
||||
sendMessage(sender, "§ePressing powerbutton...");
|
||||
Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (session.getState() != SessionState.Locked || session.getMachine() == null) {
|
||||
Start(sender, index);
|
||||
} else {
|
||||
session.getConsole().powerButton();
|
||||
sendMessage(sender, "§ePowerbutton pressed.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Reset(CommandSender sender) {
|
||||
if (checkMachineNotRunning(sender))
|
||||
return;
|
||||
sendMessage(sender, "§eResetting computer...");
|
||||
session.getConsole().reset();
|
||||
sendMessage(sender, "§eComputer reset.");
|
||||
}
|
||||
|
||||
public void FixScreen(CommandSender sender) {
|
||||
if (checkMachineNotRunning(sender))
|
||||
return;
|
||||
sendMessage(sender, "§eFixing screen...");
|
||||
session.getConsole().getDisplay().setSeamlessMode(false);
|
||||
session.getConsole().getDisplay().setVideoModeHint(0L, true, false, 0, 0, 640L, 480L, 32L);
|
||||
sendMessage(sender, "§eScreen fixed.");
|
||||
}
|
||||
|
||||
public boolean checkMachineNotRunning(@Nullable CommandSender sender) {
|
||||
if (session.getState() != SessionState.Locked || machine.getState() != MachineState.Running) {
|
||||
if (sender != null)
|
||||
sender.sendMessage("§cMachine isn't running.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void PressKey(CommandSender sender, String key, String stateorduration) {
|
||||
if (checkMachineNotRunning(sender))
|
||||
return;
|
||||
int durationorstate;
|
||||
if (stateorduration.length() == 0)
|
||||
durationorstate = 0;
|
||||
else if (stateorduration.equalsIgnoreCase("down"))
|
||||
durationorstate = -1;
|
||||
else if (stateorduration.equalsIgnoreCase("up"))
|
||||
durationorstate = -2;
|
||||
else
|
||||
durationorstate = Short.parseShort(stateorduration);
|
||||
int code = Scancode.getCode("sc_" + key.toLowerCase());
|
||||
if (code == -1) {
|
||||
sender.sendMessage("§cUnknown key: " + key);
|
||||
return;
|
||||
}
|
||||
// Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD())
|
||||
// +128
|
||||
if (durationorstate != -2)
|
||||
session.getConsole().getKeyboard().putScancode(code);
|
||||
Runnable sendrelease = () -> session.getConsole().getKeyboard().putScancodes(Lists.newArrayList(code + 128,
|
||||
Scancode.sc_controlLeft.Code + 128, Scancode.sc_shiftLeft.Code + 128, Scancode.sc_altLeft.Code + 128));
|
||||
if (durationorstate == 0 || durationorstate == -2)
|
||||
sendrelease.run();
|
||||
if (durationorstate > 0) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, sendrelease, durationorstate);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs, boolean down) throws Exception {
|
||||
if (checkMachineNotRunning(sender))
|
||||
return;
|
||||
int state = 0;
|
||||
if (mbs.length() > 0 && down)
|
||||
state = Arrays.stream(MouseButtonState.values()).filter(mousebs -> mousebs.name().equalsIgnoreCase(mbs))
|
||||
.findAny().orElseThrow(() -> new Exception("Unknown mouse button")).value();
|
||||
session.getConsole().getMouse().putMouseEvent(x, y, z, w, state);
|
||||
}
|
||||
|
||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs) throws Exception {
|
||||
if (checkMachineNotRunning(sender))
|
||||
return;
|
||||
UpdateMouse(sender, x, y, z, w, mbs, true);
|
||||
UpdateMouse(sender, x, y, z, w, mbs, false);
|
||||
}
|
||||
|
||||
public void onMachineStart(CommandSender sender) {
|
||||
sendMessage(sender, "§eComputer started.");
|
||||
}
|
||||
|
||||
public void onMachineStop(CommandSender sender) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
if (session.getState() == SessionState.Locked) {
|
||||
session.unlockMachine(); //Needs to be outside of the event handler
|
||||
handler = null;
|
||||
machine = null;
|
||||
session = manager.getSessionObject();
|
||||
sendMessage(sender, "§eComputer powered off."); //This block runs later
|
||||
}
|
||||
});
|
||||
GPURenderer.update(new byte[1], 0, 0, 0, 0, 640, 480); //Black screen
|
||||
stopEvents();
|
||||
MouseLockerPlayerListener.computerStop();
|
||||
}
|
||||
|
||||
public void stopEvents() {
|
||||
/*if(session!=null && listener!=null)
|
||||
session.getConsole().getEventSource().unregisterListener(listener);*/
|
||||
if (listener != null)
|
||||
handler.disable();
|
||||
listener = null;
|
||||
}
|
||||
|
||||
public void pluginDisable(CommandSender ccs) {
|
||||
stopEvents();
|
||||
if (session.getState() == SessionState.Locked) {
|
||||
if (session.getMachine().getState().equals(MachineState.Running)) {
|
||||
ccs.sendMessage("§aSaving machine state...");
|
||||
session.getMachine().saveState().waitForCompletion(10000);
|
||||
}
|
||||
session.unlockMachine();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MouseLockerPlayerListener implements Runnable, Listener {
|
||||
private static final Map<Player, Location> LockedPlayers = new HashMap<>();
|
||||
public static float LockedSpeed = 5;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (Entry<Player, Location> entry : LockedPlayers.entrySet()) {
|
||||
float yaw1 = entry.getValue().getYaw();
|
||||
float pitch1 = entry.getValue().getPitch();
|
||||
float yaw2 = entry.getKey().getLocation().getYaw();
|
||||
float pitch2 = entry.getKey().getLocation().getPitch();
|
||||
if (yaw2 - yaw1 == 0 || pitch2 - pitch1 == 0)
|
||||
return;
|
||||
|
||||
try {
|
||||
Computer.getInstance().UpdateMouse(null, (int) ((yaw2 - yaw1) * LockedSpeed),
|
||||
(int) ((pitch2 - pitch1) * LockedSpeed), 0, 0, "");
|
||||
} catch (Exception e) { //Should not happen
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
entry.getKey().teleport(entry.getValue(), TeleportCause.PLUGIN);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerLeave(PlayerQuitEvent event) {
|
||||
LockedPlayers.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
public static void toggleLock(Player player) {
|
||||
if (!MouseLockerPlayerListener.LockedPlayers.containsKey(player)) {
|
||||
MouseLockerPlayerListener.LockedPlayers.put(player, player.getLocation());
|
||||
player.sendMessage("§aMouse locked.");
|
||||
} else {
|
||||
MouseLockerPlayerListener.LockedPlayers.remove(player);
|
||||
player.sendMessage("§bMouse unlocked.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void computerStop() {
|
||||
LockedPlayers.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import jnr.ffi.LibraryLoader;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.virtualbox_6_0.IEventListener;
|
||||
import org.virtualbox_6_0.IVirtualBox;
|
||||
import org.virtualbox_6_0.VirtualBoxManager;
|
||||
import sznp.virtualcomputer.events.VBoxEventHandler;
|
||||
import sznp.virtualcomputer.renderer.BukkitRenderer;
|
||||
import sznp.virtualcomputer.renderer.GPURenderer;
|
||||
import sznp.virtualcomputer.renderer.IRenderer;
|
||||
import sznp.virtualcomputer.util.Utils;
|
||||
import sznp.virtualcomputer.util.VBoxLib;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PluginMain extends JavaPlugin {
|
||||
private static final int MCX = 5;
|
||||
private static final int MCY = 4;
|
||||
private BukkitTask mousetask;
|
||||
private IEventListener listener;
|
||||
|
||||
public static PluginMain Instance;
|
||||
//public static ByteBuffer allpixels = ByteBuffer.allocate(640 * 480 * 4); // It's set on each change
|
||||
/**
|
||||
* Only used if {@link #direct} is false.
|
||||
*/
|
||||
public static ByteBuffer allpixels; // It's set on each change
|
||||
private static ArrayList<IRenderer> renderers = new ArrayList<>();
|
||||
/*
|
||||
* Only used if {@link #direct} is true.
|
||||
*/
|
||||
//public static PXCLib pxc;
|
||||
public static boolean direct;
|
||||
public static boolean sendAll;
|
||||
|
||||
// Fired when plugin is first enabled
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Instance = this;
|
||||
try {
|
||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||
this.getCommand("computer").setExecutor(new Commands());
|
||||
sendAll = getConfig().getBoolean("sendAll", true);
|
||||
ccs.sendMessage("§bInitializing VirtualBox...");
|
||||
String vbpath = System.getProperty("os.name").toLowerCase().contains("mac")
|
||||
? "/Applications/VirtualBox.app/Contents/MacOS"
|
||||
: "/opt/virtualbox";
|
||||
//noinspection ConstantConditions
|
||||
Predicate<File> notGoodDir= ff->!ff.isDirectory() || Arrays.stream(ff.list()).noneMatch(s -> s.contains("xpcom"));
|
||||
if (notGoodDir.test(new File(vbpath)))
|
||||
vbpath = "/usr/lib/virtualbox";
|
||||
if(notGoodDir.test(new File(vbpath)))
|
||||
error("Could not find VirtualBox! Download from https://www.virtualbox.org/wiki/Downloads");
|
||||
if (System.getProperty("vbox.home") == null || System.getProperty("vbox.home").isEmpty())
|
||||
System.setProperty("vbox.home", vbpath);
|
||||
if (System.getProperty("sun.boot.library.path") == null
|
||||
|| System.getProperty("sun.boot.library.path").isEmpty())
|
||||
System.setProperty("sun.boot.library.path", vbpath);
|
||||
if (System.getProperty("java.library.path") == null || System.getProperty("java.library.path").isEmpty())
|
||||
System.setProperty("java.library.path", vbpath);
|
||||
Utils.addLibraryPath(vbpath);
|
||||
final VirtualBoxManager manager = VirtualBoxManager.createInstance(getDataFolder().getAbsolutePath());
|
||||
VBoxLib vbl = LibraryLoader.create(VBoxLib.class).load("vboxjxpcom"); //TODO: Test for MSCOM
|
||||
vbl.RTR3InitExe(0, "", 0);
|
||||
IVirtualBox vbox = manager.getVBox();
|
||||
listener = new VBoxEventHandler().registerTo(vbox.getEventSource());
|
||||
new Computer(this, manager, vbox); //Saves itself
|
||||
ccs.sendMessage("§bLoading Screen...");
|
||||
try {
|
||||
//throw new NoClassDefFoundError("Test error pls ignore");
|
||||
for (short i = 0; i < MCX; i++)
|
||||
for (short j = 0; j < MCY; j++)
|
||||
renderers.add(new GPURenderer((short) (j * 5 + i), Bukkit.getWorlds().get(0), i, j));
|
||||
//pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc");
|
||||
direct=true;
|
||||
ccs.sendMessage("§bUsing Direct Renderer, all good");
|
||||
} catch (NoClassDefFoundError | Exception e) {
|
||||
for (short i = 0; i < 20; i++)
|
||||
renderers.add(new BukkitRenderer(i, Bukkit.getWorlds().get(0), i * 128 * 128 * 4));
|
||||
direct=false;
|
||||
e.printStackTrace();
|
||||
ccs.sendMessage("§6Compatibility error, using slower renderer");
|
||||
}
|
||||
ccs.sendMessage("§bLoaded!");
|
||||
val mlpl = new MouseLockerPlayerListener();
|
||||
mousetask = getServer().getScheduler().runTaskTimer(this, mlpl, 0, 0);
|
||||
getServer().getPluginManager().registerEvents(mlpl, this);
|
||||
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void error(String message) {
|
||||
getLogger().severe("A fatal error occured, disabling plugin!");
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
// Fired when plugin is disabled
|
||||
@Override
|
||||
public void onDisable() {
|
||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||
if (mousetask != null)
|
||||
mousetask.cancel();
|
||||
/*try {
|
||||
source.unregisterListener(listener);
|
||||
} catch (VBoxException e) { //"Listener was never registered"
|
||||
e.printStackTrace(); - VBox claims the listener was never registered (can double register as well)
|
||||
}*/
|
||||
if (listener != null)
|
||||
((VBoxEventHandler) listener.getTypedWrapped()).disable(); //The save progress wait locks with the event
|
||||
if (Computer.getInstance() != null)
|
||||
Computer.getInstance().pluginDisable(ccs);
|
||||
ccs.sendMessage("§aHuh.");
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
}
|
107
VirtualComputer/src/main/java/sznp/virtualcomputer/Test.java
Normal file
107
VirtualComputer/src/main/java/sznp/virtualcomputer/Test.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import com.aparapi.Kernel;
|
||||
import com.aparapi.Range;
|
||||
import com.sun.jna.Pointer;
|
||||
import jnr.ffi.LibraryLoader;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.map.MapPalette;
|
||||
import sznp.virtualcomputer.util.PXCLib;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Test {
|
||||
private int[] x = new int[]{10};
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void main(String[] args) {
|
||||
/*System.out.println(new File("").getAbsolutePath());
|
||||
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(2);
|
||||
long[] x = new long[]{Pointer.nativeValue(Native.getDirectBufferPointer(bb))};
|
||||
pxc.convert(new int[]{5, 10}, x);
|
||||
System.out.println(bb.get(0)); //19 AYY //TO!DO: Use setSource, we don't want to wrap the native array*/
|
||||
//final int[] a={5,6,8,2,3,10,5,26,5,416,41,85,416,41};
|
||||
//final int[] b={10,80,10,3,32,20,56,85,51,968,156,5894,10,60,52};
|
||||
//final int[] a={5,6};
|
||||
//final int[] b={10,80};
|
||||
int[] a = IntStream.range(0, 640 * 480).toArray();
|
||||
final int[] res = new int[a.length];
|
||||
//java.awt.Color tc=new java.awt.Color(0);
|
||||
/*GPURenderer gr;
|
||||
try {
|
||||
gr=new GPURenderer((short) 0, null, 0, 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}*/
|
||||
//gr.pixels=new byte[1];
|
||||
int[] x = new Test().x;
|
||||
Kernel kernel=new Kernel() {
|
||||
@Override
|
||||
public void run() {
|
||||
int i=getGlobalId();
|
||||
//System.out.println(i);
|
||||
//res[i]=a[i]+b[i];
|
||||
//res[i]= MapPalette.matchColor(a[i] & 0x0000FF, a[i] & 0x00FF00 >> 8, a[i] & 0xFF0000 >> 16);
|
||||
//res[i] = a[i];
|
||||
//res[i]=tc.getBlue();
|
||||
//gr.pixels[0]=5;
|
||||
res[i] = x[0];
|
||||
//GPURenderer.px[0]=10;
|
||||
//GPURendererInternal.test[0]=10; - LAMBDAS
|
||||
}
|
||||
};
|
||||
long t = System.nanoTime();
|
||||
kernel.put(a).execute(Range.create(res.length)).get(res);
|
||||
//System.out.println(Arrays.toString(res));
|
||||
System.out.println(a[10]);
|
||||
System.out.println("OpenCL time: "+(System.nanoTime()-t)/1000000f+"ms");
|
||||
a[50] = 652; //Massive speedups after the fist pass
|
||||
t = System.nanoTime();
|
||||
kernel.put(a).execute(Range.create(res.length)).get(res);
|
||||
System.out.println(a[10]);
|
||||
System.out.println("Second OpenCL time: " + (System.nanoTime() - t) / 1000000f + "ms");
|
||||
|
||||
t=System.nanoTime();
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
Color c = Color.fromBGR(a[i]);
|
||||
res[i]= MapPalette.matchColor(c.getRed(), c.getGreen(), c.getBlue());
|
||||
}
|
||||
System.out.println("For loop time: "+(System.nanoTime()-t)/1000000f+"ms");
|
||||
|
||||
t=System.nanoTime();
|
||||
System.arraycopy(a, 0, res, 0, res.length);
|
||||
System.out.println("Sys time: "+(System.nanoTime()-t)/1000000f+"ms");
|
||||
|
||||
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(640 * 480 * 4);
|
||||
try {
|
||||
Field f=Buffer.class.getDeclaredField("address");
|
||||
f.setAccessible(true);
|
||||
long addr= (long) f.get(bb);
|
||||
pxc.setSource(addr, 640, 480, 5, 4);
|
||||
t = System.nanoTime();
|
||||
long p = pxc.updateAndGetMap(0, 0, 640, 480, null);
|
||||
if (p == 0) return;
|
||||
byte[] img = new Pointer(p).getByteArray(0, 128 * 128);
|
||||
System.out.println("img[50]: " + img[50]);
|
||||
System.out.println("Native time: " + (System.nanoTime() - t) / 1000000f + "ms");
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
kernel = new Kernel() {
|
||||
@Override
|
||||
public void run() {
|
||||
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
||||
pxc.updateAndGetMap(0, 0, 0, 0, null);
|
||||
}
|
||||
};
|
||||
kernel.execute(Range.create(1));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package sznp.virtualcomputer.events;
|
||||
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.mozilla.interfaces.IEvent;
|
||||
import org.mozilla.interfaces.IEventListener;
|
||||
import org.virtualbox_6_0.IEventSource;
|
||||
import org.virtualbox_6_0.VBoxEventType;
|
||||
import sznp.virtualcomputer.util.COMObjectBase;
|
||||
import sznp.virtualcomputer.util.Utils;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Bukkit-like event system which calls the appropriate methods on an event.
|
||||
*/
|
||||
public abstract class EventHandlerBase extends COMObjectBase implements IEventListener {
|
||||
/**
|
||||
* The events to listen for. It will only look for these handlers.
|
||||
*/
|
||||
private final Map<VBoxEventType, Class<? extends org.virtualbox_6_0.IEvent>> eventMap;
|
||||
private boolean enabled = true;
|
||||
|
||||
protected EventHandlerBase(Map<VBoxEventType, Class<? extends org.virtualbox_6_0.IEvent>> eventMap) {
|
||||
//this.eventMap = eventMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().value(), Map.Entry::getValue));
|
||||
this.eventMap = eventMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleEvent(IEvent iEvent) {
|
||||
//val cl=eventMap.get((int)iEvent.getType()); - We can afford to search through the events for this handler
|
||||
if (!enabled)
|
||||
return;
|
||||
val kv = eventMap.entrySet().stream().filter(e -> e.getKey().value() == iEvent.getType()).findAny();
|
||||
if (!kv.isPresent()) return; //Event not supported
|
||||
val cl = kv.get().getValue();
|
||||
for (Method method : getClass().getMethods()) {
|
||||
if (method.isAnnotationPresent(org.bukkit.event.EventHandler.class)
|
||||
&& method.getParameterCount() == 1 && method.getParameterTypes()[0] == cl) {
|
||||
try {
|
||||
method.invoke(this, Utils.getEvent(iEvent, cl));
|
||||
return;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
Bukkit.getLogger().warning("Error while handling VirtualBox event!");
|
||||
e.getCause().printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends EventHandlerBase> org.virtualbox_6_0.IEventListener registerTo(IEventSource source) {
|
||||
return Utils.registerListener(source, this, new ArrayList<>(eventMap.keySet()));
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package sznp.virtualcomputer.events;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.var;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.virtualbox_6_0.IProgress;
|
||||
import org.virtualbox_6_0.IStateChangedEvent;
|
||||
import org.virtualbox_6_0.VBoxEventType;
|
||||
import sznp.virtualcomputer.Computer;
|
||||
import sznp.virtualcomputer.PluginMain;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MachineEventHandler extends EventHandlerBase {
|
||||
private final Computer computer;
|
||||
private final CommandSender sender;
|
||||
private boolean starting = false;
|
||||
@Setter
|
||||
private IProgress progress;
|
||||
|
||||
public MachineEventHandler(Computer computer, CommandSender sender) {
|
||||
super(ImmutableMap.of(VBoxEventType.OnStateChanged, IStateChangedEvent.class));
|
||||
//VBoxEventType.OnProgressPercentageChanged, IProgressPercentageChangedEvent.class)); - Doesn't fire at all, the complete event only fires on success
|
||||
this.computer = computer;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void handleStateChange(IStateChangedEvent event) { //https://www.virtualbox.org/sdkref/_virtual_box_8idl.html#a80b08f71210afe16038e904a656ed9eb
|
||||
switch (event.getState()) {
|
||||
case Stuck:
|
||||
computer.Stop(null);
|
||||
break;
|
||||
case PoweredOff:
|
||||
case Saved:
|
||||
if (starting) {
|
||||
sender.sendMessage("§cFailed to start computer! See the console for more details.");
|
||||
sender.sendMessage("§cMake sure that 2D and 3D acceleration is disabled.");
|
||||
starting = false;
|
||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||
progress.waitForCompletion(-1);
|
||||
if (progress != null && progress.getCompleted() && progress.getResultCode() != 0) {
|
||||
Logger l = PluginMain.Instance.getLogger();
|
||||
l.warning("Result code: " + Integer.toHexString(progress.getResultCode()));
|
||||
for (var info = progress.getErrorInfo(); info != null; info = info.getNext()) {
|
||||
l.warning("----------------");
|
||||
l.warning("VBox: " + info.getText());
|
||||
l.warning("Component: " + info.getComponent());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
computer.onMachineStop(sender);
|
||||
break;
|
||||
case Starting:
|
||||
starting = true;
|
||||
break;
|
||||
case Running:
|
||||
starting = false;
|
||||
computer.onMachineStart(sender);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package sznp.virtualcomputer.events;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.virtualbox_6_0.ISessionStateChangedEvent;
|
||||
import org.virtualbox_6_0.SessionState;
|
||||
import org.virtualbox_6_0.VBoxEventType;
|
||||
import sznp.virtualcomputer.Computer;
|
||||
|
||||
public class VBoxEventHandler extends EventHandlerBase {
|
||||
public VBoxEventHandler() {
|
||||
super(ImmutableMap.of(VBoxEventType.OnSessionStateChanged, ISessionStateChangedEvent.class));
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static VBoxEventHandler instance;
|
||||
private String machineID;
|
||||
private CommandSender sender;
|
||||
|
||||
@EventHandler
|
||||
public void onSessionStateChange(ISessionStateChangedEvent event) {
|
||||
if (!event.getMachineId().equals(machineID)) return;
|
||||
if (event.getState() == SessionState.Locked) //Need to check here, because we can't access the console yet
|
||||
Computer.getInstance().onLock(sender);
|
||||
}
|
||||
|
||||
public void setup(String machineID, CommandSender sender) {
|
||||
this.machineID = machineID;
|
||||
this.sender = sender;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package sznp.virtualcomputer.renderer;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapCanvas;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BukkitRenderer extends MapRenderer implements IRenderer {
|
||||
private ByteBuffer allpixels;
|
||||
private BufferedImage image;
|
||||
private int startindex;
|
||||
|
||||
/**
|
||||
* The raw pixel data from the machine in BGRA format
|
||||
*/
|
||||
public void setAllPixels(ByteBuffer allpixels) {
|
||||
this.allpixels = allpixels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic implementation, should work on most versions
|
||||
*
|
||||
* @param id
|
||||
* The ID of the current map
|
||||
* @param world
|
||||
* The world to create new maps in
|
||||
* @param startindex
|
||||
* The index to start from in allpixels
|
||||
*/
|
||||
public BukkitRenderer(short id, World world, int startindex) {
|
||||
MapView map = IRenderer.prepare(id, world);
|
||||
map.addRenderer(this);
|
||||
this.startindex = startindex;
|
||||
image = new BufferedImage(128, 128, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
private int progress = 0;
|
||||
public static int updatepixels = 15;
|
||||
|
||||
@Override
|
||||
public void render(MapView view, MapCanvas canvas, Player player) {
|
||||
if (allpixels == null)
|
||||
return;
|
||||
long time = System.nanoTime();
|
||||
|
||||
final int[] a = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); // Directly update the bytes of the image
|
||||
|
||||
// (byte) bgra to rgb (int)
|
||||
for (int i = startindex, j = 0; i < startindex + 128 * 128; i = i + 4, j++) {
|
||||
int b, g, r;
|
||||
|
||||
b = allpixels.get(i) & 0xFF; //TODO: <-- IndexOutOfBoundsException sometimes
|
||||
g = allpixels.get(i + 1) & 0xFF;
|
||||
r = allpixels.get(i + 2) & 0xFF;
|
||||
|
||||
a[j] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
try {
|
||||
canvas.drawImage(0, progress * updatepixels, image.getSubimage(0, progress * updatepixels, 128,
|
||||
(progress * updatepixels + updatepixels >= 128 ? 128 - progress * updatepixels : updatepixels)));
|
||||
if (progress < 128 / updatepixels)
|
||||
progress++;
|
||||
else
|
||||
progress = 0;
|
||||
|
||||
long diff = System.nanoTime() - time;
|
||||
if (TimeUnit.NANOSECONDS.toMillis(diff) > 40) {
|
||||
System.out.println("Map rendering took " + TimeUnit.NANOSECONDS.toMillis(diff) + " ms");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Progess: " + progress);
|
||||
System.out.println("UpdatePixels: " + updatepixels);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package sznp.virtualcomputer.renderer;
|
||||
|
||||
import net.minecraft.server.v1_12_R1.WorldMap;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.map.MapCanvas;
|
||||
import org.bukkit.map.MapPalette;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
import org.bukkit.map.MapView;
|
||||
import sznp.virtualcomputer.PluginMain;
|
||||
import sznp.virtualcomputer.util.Timing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GPURenderer extends MapRenderer implements IRenderer {
|
||||
private byte[] buffer;
|
||||
private final GPURendererInternal kernel;
|
||||
private WorldMap wmap;
|
||||
private int mapx, mapy;
|
||||
//Store at central location after conversion
|
||||
private static int[] colors_;
|
||||
private int changedX = 0, changedY = 0, changedWidth = 640, changedHeight = 480;
|
||||
private static ArrayList<GPURenderer> renderers = new ArrayList<>();
|
||||
|
||||
public GPURenderer(short id, World world, int mapx, int mapy) throws Exception {
|
||||
MapView map = IRenderer.prepare(id, world);
|
||||
if (map == null) {
|
||||
kernel = null;
|
||||
return; //Testing
|
||||
}
|
||||
|
||||
if (colors_ == null) {
|
||||
Field field = MapPalette.class.getDeclaredField("colors");
|
||||
field.setAccessible(true);
|
||||
Color[] cs = (Color[]) field.get(null);
|
||||
colors_ = new int[cs.length];
|
||||
for (int i = 0; i < colors_.length; i++) {
|
||||
colors_[i] = cs[i].getRGB();
|
||||
}
|
||||
}
|
||||
this.mapx = mapx;
|
||||
this.mapy = mapy;
|
||||
Field field = map.getClass().getDeclaredField("worldMap");
|
||||
field.setAccessible(true);
|
||||
wmap = (WorldMap) field.get(map);
|
||||
kernel = new GPURendererInternal(mapx, mapy, colors_);
|
||||
renderers.add(this);
|
||||
|
||||
map.addRenderer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MapView map, MapCanvas canvas, Player player) {
|
||||
Timing t = new Timing();
|
||||
try {
|
||||
if (kernel.isRendered()) return;
|
||||
if (buffer == null) { //The buffer remains the same, as the canvas remains the same
|
||||
Field field = canvas.getClass().getDeclaredField("buffer");
|
||||
field.setAccessible(true);
|
||||
buffer = (byte[]) field.get(canvas);
|
||||
}
|
||||
if (!PluginMain.sendAll) {
|
||||
synchronized (kernel) {
|
||||
if (changedX >= (mapx + 1) * 128 || changedY >= (mapy + 1) * 128
|
||||
|| changedX + changedWidth < mapx * 128 || changedY + changedHeight < mapy * 128) {
|
||||
kernel.ignoreChange();
|
||||
return; //No change for this map
|
||||
}
|
||||
}
|
||||
//System.out.println("changed: (" + changedX + ", " + changedY + ") " + changedWidth + "x" + changedHeight);
|
||||
//System.out.println("map: (" + mapx + ", " + mapy + ")");
|
||||
int x = changedX - mapx * 128;
|
||||
int y = changedY - mapy * 128;
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) y = 0;
|
||||
int xx = x + changedWidth >= 128 ? 127 : x + changedWidth;
|
||||
int yy = y + changedHeight >= 128 ? 127 : y + changedHeight;
|
||||
//System.out.println("local: ("+x+", "+y+") "+w+"x"+h);
|
||||
kernel.render(buffer);
|
||||
wmap.flagDirty(x, y);
|
||||
wmap.flagDirty(xx, yy); // Send the changes only
|
||||
changedX = Integer.MAX_VALUE; //Finished rendering
|
||||
changedY = Integer.MAX_VALUE; //TODO: Render as soon as we receive new image
|
||||
changedWidth = -1; //Finished rendering
|
||||
changedHeight = -1;
|
||||
} else {
|
||||
kernel.render(buffer);
|
||||
wmap.flagDirty(0, 0);
|
||||
wmap.flagDirty(127, 127); // Send everything
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (t.elapsedMS() > 60)
|
||||
System.out.println("Map rendering took " + t.elapsedMS() + "ms");
|
||||
}
|
||||
|
||||
public static void update(byte[] pixels, int width, int height, int changedX, int changedY, int changedWidth, int changedHeight) {
|
||||
for (GPURenderer r : renderers) {
|
||||
synchronized (r.kernel) {
|
||||
if (!PluginMain.sendAll) {
|
||||
if (changedX < r.changedX)
|
||||
r.changedX = changedX;
|
||||
if (changedY < r.changedY)
|
||||
r.changedY = changedY;
|
||||
if (changedWidth > r.changedWidth)
|
||||
r.changedWidth = changedWidth;
|
||||
if (changedHeight > r.changedHeight)
|
||||
r.changedHeight = changedHeight;
|
||||
}
|
||||
r.kernel.setPixels(pixels, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package sznp.virtualcomputer.renderer;
|
||||
|
||||
import com.aparapi.Kernel;
|
||||
import com.aparapi.Range;
|
||||
import lombok.Getter;
|
||||
|
||||
//Accessing the GPURenderer results in ArrayIndexOutOfBoundsExceptions - IT'S THE LAMBDAS
|
||||
public class GPURendererInternal extends Kernel {
|
||||
private int mapx;
|
||||
private int mapy;
|
||||
private int width;
|
||||
private int height;
|
||||
private byte[] pixels;
|
||||
//Can't use static fields because it leads to incorrect CL code
|
||||
private int[] colors;
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
private byte[] buffer; //References the map buffer
|
||||
private Range range;
|
||||
@Getter
|
||||
private boolean rendered;
|
||||
|
||||
//public static byte[] test=new byte[1]; - LAMBDAS
|
||||
public GPURendererInternal(int mapx, int mapy, int[] colors) {
|
||||
this.mapx = mapx;
|
||||
this.mapy = mapy;
|
||||
this.colors = colors;
|
||||
range = Range.create2D(128, 128);
|
||||
|
||||
//Do an intial draw of a black screen with Aparapi so it doesn't lag at start
|
||||
pixels = new byte[1];
|
||||
width = height = 0;
|
||||
rendered = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//Single booleans not found (no such field error)
|
||||
int mx = getGlobalId(0);
|
||||
int my = getGlobalId(1);
|
||||
int imgx = mx + mapx * 128;
|
||||
int imgy = my + mapy * 128;
|
||||
int imgi = (imgy * width + imgx) * 4;
|
||||
if (imgx >= width || imgy >= height) { //Array length check --> Unhandled exception string
|
||||
buffer[my * 128 + mx] = matchColor(0, 0, 0);
|
||||
//buffer[my*128+mx]=10; - LAMBDAS
|
||||
return;
|
||||
}
|
||||
buffer[my * 128 + mx] = matchColor(pixels[imgi] & 0xFF, pixels[imgi + 1] & 0xFF, pixels[imgi + 2] & 0xFF); //Byte.toUnsignedInt
|
||||
//buffer[my*128+mx]=10; - LAMBDAS
|
||||
//Unhandled exception string (used & 255, after using toUnsignedInt on the blue color) - Not that, see above
|
||||
}
|
||||
|
||||
//Modified version of MapPalette.matchColor
|
||||
private byte matchColor(int b, int g, int r) {
|
||||
int index = 0;
|
||||
double best = -1;
|
||||
|
||||
for (int i = 4; i < colors.length; i++) {
|
||||
double distance = distance(b, g, r, colors[i]);
|
||||
if (distance < best || best == -1) {
|
||||
best = distance;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Minecraft has 143 colors, some of which have negative byte representations
|
||||
return (byte) (index < 128 ? index : -129 + (index - 127));
|
||||
}
|
||||
|
||||
//Can't use getXY prefix because it treats it as a getter
|
||||
private double distance(int b1, int g1, int r1, int c2) {
|
||||
int red2 = color(c2, RED);
|
||||
double rmean = (r1 + red2) / 2.0;
|
||||
double r = r1 - red2;
|
||||
double g = g1 - color(c2, GREEN);
|
||||
int b = b1 - color(c2, BLUE);
|
||||
double weightR = 2 + rmean / 256.0;
|
||||
double weightG = 4.0;
|
||||
double weightB = 2 + (255 - rmean) / 256.0;
|
||||
return weightR * r * r + weightG * g * g + weightB * b * b;
|
||||
}
|
||||
|
||||
private static int color(int bgra, int oc) {
|
||||
return (bgra >> (oc * 8)) & 0xFF;
|
||||
}
|
||||
|
||||
private static final int RED = 2;
|
||||
private static final int GREEN = 1;
|
||||
private static final int BLUE = 0;
|
||||
|
||||
//Aparapi fails with lambdas
|
||||
void setPixels(byte[] pixels, int width, int height) {
|
||||
this.pixels = pixels;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
rendered = false;
|
||||
}
|
||||
|
||||
void render(byte[] buffer) {
|
||||
if (pixels == null || rendered) return;
|
||||
this.buffer = buffer;
|
||||
put(buffer).put(pixels).execute(range).get(buffer);
|
||||
rendered = true;
|
||||
}
|
||||
|
||||
void ignoreChange() {
|
||||
rendered = true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package sznp.virtualcomputer.renderer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
public interface IRenderer {
|
||||
static MapView prepare(short id, World world) {
|
||||
if (world == null) return null; //Testing
|
||||
@SuppressWarnings("deprecation")
|
||||
MapView map = Bukkit.getMap(id);
|
||||
if (map == null)
|
||||
map = Bukkit.createMap(world);
|
||||
map.getRenderers().clear();
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package sznp.virtualcomputer.renderer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.mozilla.interfaces.IFramebuffer;
|
||||
import org.mozilla.interfaces.IFramebufferOverlay;
|
||||
import org.mozilla.interfaces.nsISupports;
|
||||
import org.mozilla.xpcom.Mozilla;
|
||||
import org.virtualbox_6_0.*;
|
||||
import sznp.virtualcomputer.PluginMain;
|
||||
import sznp.virtualcomputer.util.Timing;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class MCFrameBuffer implements IFramebuffer {
|
||||
private IDisplay display;
|
||||
private Holder<IDisplaySourceBitmap> holder = new Holder<>();
|
||||
|
||||
public MCFrameBuffer(IDisplay display, boolean VBoxDirect) { //TODO: Implement param
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public nsISupports queryInterface(String id) {
|
||||
return Mozilla.queryInterface(this, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBitsPerPixel() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBytesPerLine() {
|
||||
return 640L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getCapabilities(long[] arg0) {
|
||||
try {
|
||||
System.out.println("Capabilities queried");
|
||||
System.out.println("Capabilities: " + Arrays.toString(arg0));
|
||||
return new long[]{FramebufferCapabilities.UpdateImage.value()};
|
||||
}
|
||||
catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
return new long[]{};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getHeight() {
|
||||
return 480;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getHeightReduction() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFramebufferOverlay getOverlay() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPixelFormat() {
|
||||
return BitmapFormat.BGRA.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVisibleRegion(byte arg0, long arg1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getWidth() {
|
||||
return 640;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getWinId() {
|
||||
return 0; // Zero means no win id
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notify3DEvent(long arg0, byte[] arg1) {
|
||||
}
|
||||
|
||||
private BukkitTask tt;
|
||||
private Pointer pointer;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
@Override
|
||||
public void notifyChange(long screenId, long xOrigin, long yOrigin, long width, long height) {
|
||||
if (tt != null)
|
||||
tt.cancel();
|
||||
tt = Bukkit.getScheduler().runTaskAsynchronously(PluginMain.Instance, () -> {
|
||||
try {
|
||||
display.querySourceBitmap(0L, holder);
|
||||
long[] ptr = new long[1], w = new long[1], h = new long[1], bpp = new long[1], bpl = new long[1], pf = new long[1];
|
||||
holder.value.getTypedWrapped().queryBitmapInfo(ptr, w, h, bpp, bpl, pf);
|
||||
if (PluginMain.direct) {
|
||||
pointer = new Pointer(ptr[0]);
|
||||
this.width = (int) w[0];
|
||||
this.height = (int) h[0];
|
||||
GPURenderer.update(pointer.getByteArray(0L, (int) (w[0] * h[0] * 4)), (int) w[0], (int) h[0], 0, 0, this.width, this.height);
|
||||
} else {
|
||||
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
||||
if (width * height > 640 * 480)
|
||||
PluginMain.allpixels.limit(640 * 480 * 4);
|
||||
else
|
||||
PluginMain.allpixels.limit((int) (width * height * 4));
|
||||
}
|
||||
} catch (VBoxException e) {
|
||||
if (e.getResultCode() == 0x80070005)
|
||||
return; // Machine is being powered down
|
||||
if (e.getResultCode() == 0x80004005) //The function "querySourceBitmap" returned an error condition: "Operation failed (NS_ERROR_FAILURE)"
|
||||
System.out.println("I don't know why this happens, but stopping the computer helps.");
|
||||
e.printStackTrace();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUpdate(long x, long y, long width, long height) {
|
||||
Timing t = new Timing();
|
||||
GPURenderer.update(pointer.getByteArray(0L, this.width * this.height * 4), this.width, this.height, (int) x, (int) y, (int) width, (int) height);
|
||||
if (t.elapsedMS() > 60) //Typically 1ms max
|
||||
System.out.println("Update took " + t.elapsedMS() + "ms");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUpdateImage(long arg0, long arg1, long arg2, long arg3, byte[] arg4) {
|
||||
System.out.println("Update image!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisibleRegion(byte arg0, long arg1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processVHWACommand(byte b, int i, boolean b1) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean videoModeSupported(long arg0, long arg1, long arg2) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
import org.mozilla.interfaces.nsISupports;
|
||||
import org.mozilla.xpcom.Mozilla;
|
||||
|
||||
public abstract class COMObjectBase implements nsISupports {
|
||||
public nsISupports queryInterface(String id) {
|
||||
return Mozilla.queryInterface(this, id);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
import jnr.ffi.Pointer;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public interface PXCLib {
|
||||
/**
|
||||
* Testing only
|
||||
* @param px Input array
|
||||
* @param out Output array
|
||||
* @return 0
|
||||
*/
|
||||
int convert(int[] px, long[] out);
|
||||
|
||||
/**
|
||||
* Set source bitmap
|
||||
* @param address Bitmap address from VirtualBox
|
||||
* @param w Width of the screen
|
||||
* @param h Height of the screen
|
||||
* @param mcx Width of the screen in maps
|
||||
* @param mcy Height of the screen in maps
|
||||
*/
|
||||
void setSource(long address, int w, int h, int mcx, int mcy);
|
||||
|
||||
/**
|
||||
* Updates map and returns it's content, where affected
|
||||
* @return Partial map data [mapc][data]
|
||||
*/
|
||||
long updateAndGetMap(int x, int y, int width, int height, Pointer out_changed); //TODO: Only update parts that actually updated and return them per-map (flagDirty)
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
/*
|
||||
The scancode values come from:
|
||||
- http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc (March 16), 2000).
|
||||
- http://www.computer-engineering.org/ps2keyboard/scancodes1.html
|
||||
- using MapVirtualKeyEx( VK_*), MAPVK_VK_TO_VSC_EX), 0 ) with the english us keyboard layout
|
||||
- reading win32 WM_INPUT keyboard messages.
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public enum Scancode { // https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names
|
||||
|
||||
sc_escape(0x01), sc_1(0x02), sc_2(0x03), sc_3(0x04), sc_4(0x05), sc_5(0x06), sc_6(0x07), sc_7(0x08), sc_8(
|
||||
0x09), sc_9(0x0A), sc_0(0x0B), sc_minus(0x0C), sc_equals(0x0D), sc_backspace(0x0E), sc_tab(0x0F), sc_q(
|
||||
0x10), sc_w(0x11), sc_e(0x12), sc_r(0x13), sc_t(0x14), sc_y(0x15), sc_u(0x16), sc_i(0x17), sc_o(
|
||||
0x18), sc_p(0x19), sc_bracketLeft(0x1A), sc_bracketRight(0x1B), sc_enter(
|
||||
0x1C), sc_controlLeft(0x1D), sc_a(0x1E), sc_s(0x1F), sc_d(
|
||||
0x20), sc_f(0x21), sc_g(0x22), sc_h(0x23), sc_j(0x24), sc_k(0x25), sc_l(
|
||||
0x26), sc_semicolon(0x27), sc_apostrophe(0x28), sc_grave(
|
||||
0x29), sc_shiftLeft(0x2A), sc_backslash(0x2B), sc_z(
|
||||
0x2C), sc_x(0x2D), sc_c(0x2E), sc_v(0x2F), sc_b(
|
||||
0x30), sc_n(0x31), sc_m(0x32), sc_comma(
|
||||
0x33), sc_period(0x34), sc_slash(
|
||||
0x35), sc_shiftRight(
|
||||
0x36), sc_numpad_multiply(
|
||||
0x37), sc_altLeft(
|
||||
0x38), sc_space(
|
||||
0x39), sc_capsLock(
|
||||
0x3A), sc_f1(
|
||||
0x3B), sc_f2(
|
||||
0x3C), sc_f3(
|
||||
0x3D), sc_f4(
|
||||
0x3E), sc_f5(
|
||||
0x3F), sc_f6(
|
||||
0x40), sc_f7(
|
||||
0x41), sc_f8(
|
||||
0x42), sc_f9(
|
||||
0x43), sc_f10(
|
||||
0x44), sc_numLock(
|
||||
0x45), sc_scrollLock(
|
||||
0x46), sc_numpad_7(
|
||||
0x47), sc_numpad_8(
|
||||
0x48), sc_numpad_9(
|
||||
0x49), sc_numpad_minus(
|
||||
0x4A), sc_numpad_4(
|
||||
0x4B), sc_numpad_5(
|
||||
0x4C), sc_numpad_6(
|
||||
0x4D), sc_numpad_plus(
|
||||
0x4E), sc_numpad_1(
|
||||
0x4F), sc_numpad_2(
|
||||
0x50), sc_numpad_3(
|
||||
0x51), sc_numpad_0(
|
||||
0x52), sc_numpad_period(
|
||||
0x53), sc_alt_printScreen(
|
||||
0x54), /*
|
||||
* Alt
|
||||
* +
|
||||
* print
|
||||
* screen.
|
||||
* MapVirtualKeyEx(
|
||||
* VK_SNAPSHOT
|
||||
* )
|
||||
* ,
|
||||
* MAPVK_VK_TO_VSC_EX
|
||||
* )
|
||||
* ,
|
||||
* 0
|
||||
* )
|
||||
* returns
|
||||
* scancode
|
||||
* 0x54.
|
||||
*/
|
||||
sc_bracketAngle(0x56), /* Key between the left shift and Z. */
|
||||
sc_f11(0x57), sc_f12(0x58), sc_oem_1(0x5a), /* VK_OEM_WSCTRL */
|
||||
sc_oem_2(0x5b), /* VK_OEM_FINISH */
|
||||
sc_oem_3(0x5c), /* VK_OEM_JUMP */
|
||||
sc_eraseEOF(0x5d), sc_oem_4(0x5e), /* VK_OEM_BACKTAB */
|
||||
sc_oem_5(0x5f), /* VK_OEM_AUTO */
|
||||
sc_zoom(0x62), sc_help(0x63), sc_f13(0x64), sc_f14(0x65), sc_f15(0x66), sc_f16(0x67), sc_f17(0x68), sc_f18(
|
||||
0x69), sc_f19(
|
||||
0x6a), sc_f20(0x6b), sc_f21(0x6c), sc_f22(0x6d), sc_f23(0x6e), sc_oem_6(0x6f), /* VK_OEM_PA3 */
|
||||
sc_katakana(0x70), sc_oem_7(0x71), /* VK_OEM_RESET */
|
||||
sc_f24(0x76), sc_sbcschar(0x77), sc_convert(0x79), sc_nonconvert(0x7B), /* VK_OEM_PA1 */
|
||||
|
||||
sc_media_previous(0xE010), sc_media_next(0xE019), sc_numpad_enter(0xE01C), sc_controlRight(0xE01D), sc_volume_mute(
|
||||
0xE020), sc_launch_app2(0xE021), sc_media_play(0xE022), sc_media_stop(
|
||||
0xE024), sc_volume_down(0xE02E), sc_volume_up(
|
||||
0xE030), sc_browser_home(0xE032), sc_numpad_divide(0xE035), sc_printScreen(0xE037),
|
||||
/*
|
||||
* sc_printScreen: - make: 0xE02A 0xE037 - break: 0xE0B7 0xE0AA - MapVirtualKeyEx( VK_SNAPSHOT), MAPVK_VK_TO_VSC_EX), 0 ) returns scancode 0x54; - There is no VK_KEYDOWN with VK_SNAPSHOT.
|
||||
*/
|
||||
sc_altRight(0xE038), sc_cancel(0xE046), /* CTRL + Pause */
|
||||
sc_home(0xE047), sc_arrowUp(0xE048), sc_pageUp(0xE049), sc_arrowLeft(0xE04B), sc_arrowRight(0xE04D), sc_end(
|
||||
0xE04F), sc_arrowDown(0xE050), sc_pageDown(0xE051), sc_insert(0xE052), sc_delete(0xE053), sc_metaLeft(
|
||||
0xE05B), sc_metaRight(0xE05C), sc_application(0xE05D), sc_power(0xE05E), sc_sleep(0xE05F), sc_wake(
|
||||
0xE063), sc_browser_search(0xE065), sc_browser_favorites(0xE066), sc_browser_refresh(
|
||||
0xE067), sc_browser_stop(0xE068), sc_browser_forward(0xE069), sc_browser_back(
|
||||
0xE06A), sc_launch_app1(
|
||||
0xE06B), sc_launch_email(0xE06C), sc_launch_media(0xE06D),
|
||||
|
||||
sc_pause(0xE11D45);
|
||||
/*
|
||||
* sc_pause: - make: 0xE11D 45 0xE19D C5 - make in raw input: 0xE11D 0x45 - break: none - No repeat when you hold the key down - There are no break so I don't know how the key down/up is expected
|
||||
* to work. Raw input sends "keydown" and "keyup" messages), and it appears that the keyup message is sent directly after the keydown message (you can't hold the key down) so depending on when
|
||||
* GetMessage or PeekMessage will return messages), you may get both a keydown and keyup message "at the same time". If you use VK messages most of the time you only get keydown messages), but
|
||||
* some times you get keyup messages too. - when pressed at the same time as one or both control keys, generates a 0xE046 (sc_cancel) and the string for that scancode is "break".
|
||||
*/
|
||||
|
||||
private static final HashMap<String, Integer> scanCodes = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Scancode sc : values())
|
||||
scanCodes.put(sc.toString().toLowerCase(), sc.Code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scancode from a lowercased string (O(1))
|
||||
*
|
||||
* @param keyLowerCased The key name, lowercased (sc_...)
|
||||
* @return The code or -1 if not found
|
||||
*/
|
||||
public static int getCode(String keyLowerCased) {
|
||||
Integer code = scanCodes.get(keyLowerCased);
|
||||
if (code == null) return -1;
|
||||
return code;
|
||||
}
|
||||
|
||||
public int Code;
|
||||
|
||||
Scancode(int code) {
|
||||
Code = code;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
public class Timing {
|
||||
private long start = System.nanoTime();
|
||||
|
||||
public long elapsedMS() {
|
||||
return (System.nanoTime() - start) / 1000000L;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
import lombok.val;
|
||||
import org.mozilla.interfaces.IEventListener;
|
||||
import org.virtualbox_6_0.IEvent;
|
||||
import org.virtualbox_6_0.IEventSource;
|
||||
import org.virtualbox_6_0.VBoxEventType;
|
||||
import org.virtualbox_6_0.xpcom.IUnknown;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Utils {
|
||||
/**
|
||||
* Adds the specified path to the java library path
|
||||
*
|
||||
* @param pathToAdd the path to add
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void addLibraryPath(String pathToAdd) throws Exception {
|
||||
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
|
||||
usrPathsField.setAccessible(true);
|
||||
|
||||
// get array of paths
|
||||
final String[] paths = (String[]) usrPathsField.get(null);
|
||||
|
||||
// check if the path to add is already present
|
||||
for (String path : paths) {
|
||||
if (path.equals(pathToAdd)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// add the new path
|
||||
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
|
||||
newPaths[newPaths.length - 1] = pathToAdd;
|
||||
usrPathsField.set(null, newPaths);
|
||||
}
|
||||
|
||||
//public static void registerListener(IEventSource source, IEventListener listener, VBoxEventType... types) {
|
||||
public static org.virtualbox_6_0.IEventListener registerListener(IEventSource source, IEventListener listener, List<VBoxEventType> types) {
|
||||
val ret = new org.virtualbox_6_0.IEventListener(listener);
|
||||
source.registerListener(ret, types, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends IEvent> T getEvent(org.mozilla.interfaces.IEvent event, Class<T> cl) {
|
||||
//if (event.getType() != type.value()) return null;
|
||||
//return (T) T.queryInterface(new IEvent(event)); - Probably won't work
|
||||
try {
|
||||
val method = cl.getMethod("queryInterface", IUnknown.class);
|
||||
return (T) method.invoke(null, new IEvent(event));
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
5
VirtualComputer/src/main/java/sznp/virtualcomputer/util/VBoxLib.java
Executable file
5
VirtualComputer/src/main/java/sznp/virtualcomputer/util/VBoxLib.java
Executable file
|
@ -0,0 +1,5 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
public interface VBoxLib {
|
||||
void RTR3InitExe(int argc, String argv, int somethingzero);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package sznp.virtualcomputer.util;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
public interface WinLib extends Library {
|
||||
WinLib INSTANCE = Native.loadLibrary("VirtualComputerWin", WinLib.class);
|
||||
|
||||
public void init();
|
||||
}
|
7
VirtualComputer/src/main/resources/plugin.yml
Normal file
7
VirtualComputer/src/main/resources/plugin.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
name: VirtualComputer
|
||||
main: sznp.virtualcomputer.PluginMain
|
||||
version: 2.0
|
||||
commands:
|
||||
computer:
|
||||
usage: Use /computer start|stop|reset|key|mouse|input|fix
|
||||
aliases: c
|
|
@ -1,201 +0,0 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import net.countercraft.movecraft.craft.Craft;
|
||||
import net.countercraft.movecraft.craft.CraftManager;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class Commands implements CommandExecutor
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||
String[] args)
|
||||
{
|
||||
switch (cmd.getName().toLowerCase())
|
||||
{
|
||||
case "computer":
|
||||
{
|
||||
if (args.length == 0)
|
||||
return false;
|
||||
switch (args[0].toLowerCase())
|
||||
{
|
||||
case "start":
|
||||
PluginMain.getPlugin(PluginMain.class).Start(sender);
|
||||
break;
|
||||
case "stop":
|
||||
PluginMain.getPlugin(PluginMain.class).Stop(sender);
|
||||
break;
|
||||
case "debug":
|
||||
World w = Bukkit.getWorlds().get(0);
|
||||
Craft[] crafts = CraftManager.getInstance().getCraftsInWorld(w);
|
||||
sender.sendMessage("World: " + w);
|
||||
sender.sendMessage("Crafts: " + crafts);
|
||||
sender.sendMessage("Craft type: "
|
||||
+ crafts[0].getType().getCraftName());
|
||||
sender.sendMessage("DX: " + crafts[0].getLastDX());
|
||||
sender.sendMessage("DY: " + crafts[0].getLastDY());
|
||||
sender.sendMessage("DZ: " + crafts[0].getLastDZ());
|
||||
sender.sendMessage("MouseSpeed: " + PluginMain.MouseSpeed);
|
||||
sender.sendMessage("Block: "
|
||||
+ Bukkit.getWorlds()
|
||||
.get(0)
|
||||
.getBlockAt(crafts[0].getMinX(),
|
||||
crafts[0].getMinY() - 1,
|
||||
crafts[0].getMinZ()).getType()); // Block:
|
||||
// AIR
|
||||
break;
|
||||
case "powerbutton":
|
||||
PluginMain.getPlugin(PluginMain.class).PowerButton(sender);
|
||||
break;
|
||||
case "reset":
|
||||
PluginMain.getPlugin(PluginMain.class).Reset(sender);
|
||||
break;
|
||||
case "fix":
|
||||
PluginMain.getPlugin(PluginMain.class).FixScreen(sender);
|
||||
break;
|
||||
case "key":
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage("§cUsage: /computer key <key> [down/up|interval]");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 3)
|
||||
PluginMain.getPlugin(PluginMain.class).PressKey(sender,
|
||||
args[1], "");
|
||||
else
|
||||
PluginMain.getPlugin(PluginMain.class).PressKey(sender,
|
||||
args[1], args[2]);
|
||||
break;
|
||||
case "mouse":
|
||||
boolean showusage = true;
|
||||
if (args.length < 6)
|
||||
{
|
||||
// Command overloading, because I can :P
|
||||
if (args.length > 4) // 4<x<6
|
||||
{
|
||||
PluginMain.getPlugin(PluginMain.class).UpdateMouse(
|
||||
sender, Integer.parseInt(args[1]),
|
||||
Integer.parseInt(args[2]),
|
||||
Integer.parseInt(args[3]),
|
||||
Integer.parseInt(args[4]), "", false);
|
||||
showusage = false;
|
||||
} else
|
||||
{
|
||||
if (args.length == 3)
|
||||
{
|
||||
PluginMain.getPlugin(PluginMain.class).UpdateMouse(
|
||||
sender, 0, 0, 0, 0, args[1],
|
||||
(args[2].equals("down")));
|
||||
showusage = false;
|
||||
} else if (args.length == 2)
|
||||
{
|
||||
PluginMain.getPlugin(PluginMain.class).UpdateMouse(
|
||||
sender, 0, 0, 0, 0, args[1]);
|
||||
showusage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (showusage)
|
||||
{
|
||||
sender.sendMessage("§cUsage: /computer mouse <relx> <rely> <relz> <relw>");
|
||||
sender.sendMessage("§cOr: /computer mouse <button> [up/down]");
|
||||
}
|
||||
break;
|
||||
case "mspeed":
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage("§cUsage: /computer mspeed <speed>");
|
||||
return true;
|
||||
}
|
||||
PluginMain.MouseSpeed = Integer.parseInt(args[1]);
|
||||
sender.sendMessage("Mouse speed set to " + args[1]);
|
||||
break;
|
||||
case "input":
|
||||
{
|
||||
if (!(sender instanceof Player))
|
||||
{
|
||||
sender.sendMessage("§cError: Only players can use this command.");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 2)
|
||||
{
|
||||
sender.sendMessage("§cUsage: /computer input <key|mouse>");
|
||||
return true;
|
||||
}
|
||||
if (args[1].equalsIgnoreCase("key"))
|
||||
{
|
||||
Bukkit.getServer()
|
||||
.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw "
|
||||
+ sender.getName()
|
||||
+ " [\"\",{\"text\":\" [0]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D0\"}},{\"text\":\" [1]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D1\"}},{\"text\":\" [2]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D2\"}},{\"text\":\" [3]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D3\"}},{\"text\":\" [4]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D4\"}},{\"text\":\" [5]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D5\"}},{\"text\":\" [6]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D6\"}},{\"text\":\" [7]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D7\"}},{\"text\":\" [8]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D8\"}},{\"text\":\" [9]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D9\"}}]");
|
||||
Bukkit.getServer()
|
||||
.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw "
|
||||
+ sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Tab]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Tab\"}},{\"text\":\" [Q]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Q\"}},{\"text\":\" [W]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key W\"}},{\"text\":\" [E]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key E\"}},{\"text\":\" [R]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key R\"}},{\"text\":\" [T]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key T\"}},{\"text\":\" [Y]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Y\"}},{\"text\":\" [U]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key U\"}},{\"text\":\" [I]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key I\"}},{\"text\":\" [O]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key O\"}},{\"text\":\" [P]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key P\"}}]");
|
||||
Bukkit.getServer()
|
||||
.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw "
|
||||
+ sender.getName()
|
||||
+ " [\"\",{\"text\":\" [CapsLock]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key CapsLock\"}},{\"text\":\" [A]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key A\"}},{\"text\":\" [S]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key S\"}},{\"text\":\" [D]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key D\"}},{\"text\":\" [F]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key F\"}},{\"text\":\" [G]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key G\"}},{\"text\":\" [H]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key H\"}},{\"text\":\" [J]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key J\"}},{\"text\":\" [K]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key K\"}},{\"text\":\" [L]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key L\"}},{\"text\":\" [Return]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Return\"}}]");
|
||||
Bukkit.getServer()
|
||||
.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw "
|
||||
+ sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Z]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Z\"}},{\"text\":\" [X]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key X\"}},{\"text\":\" [C]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key C\"}},{\"text\":\" [V]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key V\"}},{\"text\":\" [B]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key B\"}},{\"text\":\" [N]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key N\"}},{\"text\":\" [M]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key M\"}}]");
|
||||
Bukkit.getServer()
|
||||
.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw "
|
||||
+ sender.getName()
|
||||
+ " [\"\",{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlLeft\"}},{\"text\":\" [Alt]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltLeft\"}},{\"text\":\" [Space]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key Space\"}},{\"text\":\" [AltGr]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key AltRight\"}},{\"text\":\" [Ctrl]\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/computer key ControlRight\"}}]");
|
||||
} else if (args[1].equalsIgnoreCase("mouse"))
|
||||
{
|
||||
if (!(sender instanceof Player))
|
||||
{
|
||||
sender.sendMessage("§cOnly ingame players can use this command.");
|
||||
return true;
|
||||
}
|
||||
if (!MouseLockerPlayerListener.LockedPlayers
|
||||
.contains(sender))
|
||||
{
|
||||
MouseLockerPlayerListener.LockedPlayers
|
||||
.add((Player) sender);
|
||||
sender.sendMessage("§aMouse locked.");
|
||||
} else
|
||||
{
|
||||
MouseLockerPlayerListener.LockedPlayers.remove(sender);
|
||||
sender.sendMessage("§bMouse unlocked.");
|
||||
}
|
||||
} else if (args[1].equalsIgnoreCase("mspeed"))
|
||||
{
|
||||
if (args.length < 3)
|
||||
{
|
||||
sender.sendMessage("§cUsage: /computer input mspeed <integer>");
|
||||
return true;
|
||||
}
|
||||
MouseLockerPlayerListener.LockedSpeed = Float
|
||||
.parseFloat(args[2]);
|
||||
sender.sendMessage("§aMouse speed set to "
|
||||
+ MouseLockerPlayerListener.LockedSpeed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class JarUtils {
|
||||
|
||||
public static boolean extractFromJar(final String fileName,
|
||||
final String dest) throws IOException {
|
||||
if (getRunningJar() == null) {
|
||||
return false;
|
||||
}
|
||||
final File file = new File(dest);
|
||||
if (file.isDirectory()) {
|
||||
file.mkdir();
|
||||
return false;
|
||||
}
|
||||
if (!file.exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
final JarFile jar = getRunningJar();
|
||||
final Enumeration<JarEntry> e = jar.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
final JarEntry je = e.nextElement();
|
||||
if (!je.getName().contains(fileName)) {
|
||||
continue;
|
||||
}
|
||||
final InputStream in = new BufferedInputStream(
|
||||
jar.getInputStream(je));
|
||||
final OutputStream out = new BufferedOutputStream(
|
||||
new FileOutputStream(file));
|
||||
copyInputStream(in, out);
|
||||
jar.close();
|
||||
return true;
|
||||
}
|
||||
jar.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
private final static void copyInputStream(final InputStream in,
|
||||
final OutputStream out) throws IOException {
|
||||
try {
|
||||
final byte[] buff = new byte[4096];
|
||||
int n;
|
||||
while ((n = in.read(buff)) > 0) {
|
||||
out.write(buff, 0, n);
|
||||
}
|
||||
} finally {
|
||||
out.flush();
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static URL getJarUrl(final File file) throws IOException {
|
||||
return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/");
|
||||
}
|
||||
|
||||
public static JarFile getRunningJar() throws IOException {
|
||||
if (!RUNNING_FROM_JAR) {
|
||||
return null; // null if not running from jar
|
||||
}
|
||||
String path = new File(JarUtils.class.getProtectionDomain()
|
||||
.getCodeSource().getLocation().getPath()).getAbsolutePath();
|
||||
path = URLDecoder.decode(path, "UTF-8");
|
||||
return new JarFile(path);
|
||||
}
|
||||
|
||||
private static boolean RUNNING_FROM_JAR = false;
|
||||
|
||||
static {
|
||||
final URL resource = JarUtils.class.getClassLoader().getResource(
|
||||
"plugin.yml");
|
||||
if (resource != null) {
|
||||
RUNNING_FROM_JAR = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public class MouseLockerPlayerListener implements Listener
|
||||
{
|
||||
public static List<Player> LockedPlayers = new ArrayList<Player>();
|
||||
public static float LockedSpeed = 1;
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMoveMouse(PlayerMoveEvent e)
|
||||
{
|
||||
if (!LockedPlayers.contains(e.getPlayer()))
|
||||
return;
|
||||
float yaw1 = e.getFrom().getYaw();
|
||||
float pitch1 = e.getFrom().getPitch();
|
||||
float yaw2 = e.getTo().getYaw();
|
||||
float pitch2 = e.getTo().getPitch();
|
||||
if (yaw2 - yaw1 == 0 || pitch2 - pitch1 == 0)
|
||||
return;
|
||||
|
||||
PluginMain.Instance.UpdateMouse(null,
|
||||
(int) ((yaw2 - yaw1) * LockedSpeed),
|
||||
(int) ((pitch2 - pitch1) * LockedSpeed), 0, 0, "");
|
||||
|
||||
e.setTo(e.getFrom());
|
||||
}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
package sznp.virtualcomputer;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.countercraft.movecraft.craft.Craft;
|
||||
import net.countercraft.movecraft.craft.CraftManager;
|
||||
import net.sf.jni4net.Bridge;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import virtualcomputersender.Computer;
|
||||
|
||||
import com.mcplugindev.slipswhitley.sketchmap.map.RelativeLocation;
|
||||
import com.mcplugindev.slipswhitley.sketchmap.map.SketchMap;
|
||||
|
||||
public class PluginMain extends JavaPlugin {
|
||||
private Computer computer;
|
||||
private SketchMap smap;
|
||||
|
||||
public static PluginMain Instance;
|
||||
|
||||
// Fired when plugin is first enabled
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Instance = this;
|
||||
try {
|
||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||
this.getCommand("computer").setExecutor(new Commands());
|
||||
ccs.sendMessage("§bExtracting necessary libraries...");
|
||||
final File[] libs = new File[] {
|
||||
// new File(getDataFolder(), "jni4net.j-0.8.8.0.jar"),
|
||||
new File(getDataFolder(), "jni4net.n-0.8.8.0.dll"),
|
||||
new File(getDataFolder(), "jni4net.n.w64.v40-0.8.8.0.dll"),
|
||||
// new File(getDataFolder(), "VirtualComputerSender.j4n.jar"),
|
||||
new File(getDataFolder(), "VirtualComputerSender.j4n.dll"),
|
||||
new File(getDataFolder(), "VirtualComputerSender.dll"),
|
||||
new File(getDataFolder(), "Interop.VirtualBox.dll") };
|
||||
|
||||
for (final File lib : libs) {
|
||||
if (!lib.exists()) {
|
||||
JarUtils.extractFromJar(lib.getName(), lib.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
ccs.sendMessage("§bInitializing bridge...");
|
||||
Bridge.init(new File(getDataFolder(), "jni4net.n.w64.v40-0.8.8.0.dll").getAbsoluteFile());
|
||||
Bridge.LoadAndRegisterAssemblyFrom(new File(getDataFolder(), "VirtualComputerSender.j4n.dll"));
|
||||
ccs.sendMessage("§bInititalizing VirtualBox interface...");
|
||||
computer = new Computer();
|
||||
ccs.sendMessage("§bLoading SketchMap...");
|
||||
img = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
|
||||
HashMap<Short, RelativeLocation> map = new HashMap<>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
map.put((short) (i * 4 + j), new RelativeLocation(i, j));
|
||||
smap = new SketchMap(img, "Screen", 5, 4, false, map);
|
||||
ccs.sendMessage("§bLoaded!");
|
||||
getServer().getPluginManager().registerEvents(new MouseLockerPlayerListener(), this);
|
||||
DoStart();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Fired when plugin is disabled
|
||||
@Override
|
||||
public void onDisable() {
|
||||
ConsoleCommandSender ccs = getServer().getConsoleSender();
|
||||
ccs.sendMessage("§aHuh.");
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
private volatile BufferedImage img;
|
||||
private volatile BukkitTask task = null;
|
||||
|
||||
public void Start(CommandSender sender) {
|
||||
sender.sendMessage("§eStarting computer...");
|
||||
computer.Start();
|
||||
sender.sendMessage("§eComputer started.");
|
||||
DoStart();
|
||||
}
|
||||
|
||||
public static int MouseSpeed = 1;
|
||||
|
||||
private void DoStart() {
|
||||
if (task == null)
|
||||
task = this.getServer().getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
|
||||
public void run() {
|
||||
final int[] a = ((DataBufferInt) smap.image.getRaster().getDataBuffer()).getData();
|
||||
final int[] data = computer.GetScreenPixelColors();
|
||||
System.arraycopy(data, 0, a, 0, data.length);
|
||||
}
|
||||
}, 1, 10);
|
||||
if (getServer().getPluginManager().isPluginEnabled("Movecraft")) {
|
||||
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
|
||||
public void run() {
|
||||
Craft[] crafts = CraftManager.getInstance().getCraftsInWorld(Bukkit.getWorlds().get(0));
|
||||
if (crafts == null)
|
||||
return;
|
||||
for (Craft c : crafts) {
|
||||
if (c.getType().getCraftName().equalsIgnoreCase("mouse")) {
|
||||
int dx = c.getLastDX();
|
||||
// int dy = c.getLastDY();
|
||||
int dz = c.getLastDZ();
|
||||
if (Bukkit.getWorlds().get(0).getBlockAt(c.getMinX(), c.getMinY() - 1, c.getMinZ())
|
||||
.getType() != Material.AIR && (dx != 0 || dz != 0))
|
||||
UpdateMouse(null, dx * MouseSpeed, dz * MouseSpeed, 0, 0, "");
|
||||
c.setLastDX(0);
|
||||
c.setLastDZ(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop(CommandSender sender) {
|
||||
sender.sendMessage("§eStopping computer...");
|
||||
computer.PowerOff();
|
||||
sender.sendMessage("§eComputer stopped.");
|
||||
}
|
||||
|
||||
public void PowerButton(CommandSender sender) {
|
||||
sender.sendMessage("§eStarting/stoppping computer...");
|
||||
final CommandSender s = sender;
|
||||
getServer().getScheduler().runTaskAsynchronously(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (computer.PowerButton()) {
|
||||
DoStart();
|
||||
s.sendMessage("§eComputer started.");
|
||||
} else
|
||||
s.sendMessage("§ePowerbutton pressed.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Reset(CommandSender sender) {
|
||||
sender.sendMessage("§eResetting computer...");
|
||||
computer.Reset();
|
||||
sender.sendMessage("§eComputer reset.");
|
||||
}
|
||||
|
||||
public void FixScreen(CommandSender sender) {
|
||||
sender.sendMessage("§eFixing screen...");
|
||||
computer.FixScreen();
|
||||
sender.sendMessage("§eScreen fixed.");
|
||||
}
|
||||
|
||||
public void PressKey(CommandSender sender, String key, String stateorduration) {
|
||||
if (stateorduration.length() == 0)
|
||||
computer.PressKey(key, (short) 0);
|
||||
else if (stateorduration.equalsIgnoreCase("down"))
|
||||
computer.PressKey(key, (short) -1);
|
||||
else if (stateorduration.equalsIgnoreCase("up"))
|
||||
computer.PressKey(key, (short) -2);
|
||||
else
|
||||
computer.PressKey(key, Short.parseShort(stateorduration));
|
||||
}
|
||||
|
||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs, boolean down) {
|
||||
if (down)
|
||||
computer.UpdateMouse(x, y, z, w, mbs);
|
||||
else
|
||||
computer.UpdateMouse(x, y, z, w, "");
|
||||
}
|
||||
|
||||
public void UpdateMouse(CommandSender sender, int x, int y, int z, int w, String mbs) {
|
||||
UpdateMouse(sender, x, y, z, w, mbs, true);
|
||||
UpdateMouse(sender, x, y, z, w, mbs, false);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualComputerSender", "VirtualComputerSender\VirtualComputerSender.csproj", "{5EF12535-ACDF-4D60-8E32-087F5A277946}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Debug|x64.Build.0 = Debug|x64
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Release|x64.ActiveCfg = Release|x64
|
||||
{5EF12535-ACDF-4D60-8E32-087F5A277946}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,145 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerSender //Copyright © NorbiPeti 2015-2016
|
||||
{
|
||||
public class Computer
|
||||
{ //Self-note: Don't add/edit public members
|
||||
private VirtualBoxClass vbox;
|
||||
private Session session;
|
||||
public Computer()
|
||||
{
|
||||
vbox = new VirtualBoxClass();
|
||||
session = new Session();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
var machine = (IMachine)vbox.Machines.GetValue(0);
|
||||
var progress = machine.LaunchVMProcess(session, "headless", "");
|
||||
progress.WaitForCompletion(100000);
|
||||
var fb = new MCFrameBuffer(session.Console.Display);
|
||||
Screen = fb.Screen; //fb.Screen is assigned on object creation
|
||||
session.Console.Display.AttachFramebuffer(0, fb);
|
||||
session.Console.Display.SetSeamlessMode(0);
|
||||
}
|
||||
|
||||
public bool PowerButton()
|
||||
{
|
||||
if (session.State != SessionState.SessionState_Locked || session.Machine == null)
|
||||
{
|
||||
Start();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
session.Console.PowerButton();
|
||||
if (session.State != SessionState.SessionState_Locked)
|
||||
Screen = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void PowerOff()
|
||||
{
|
||||
if (session.State == SessionState.SessionState_Locked)
|
||||
{
|
||||
session.Console.PowerDown().WaitForCompletion(10000);
|
||||
Screen = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (session.State == SessionState.SessionState_Locked)
|
||||
session.Console.Reset();
|
||||
}
|
||||
|
||||
private volatile int[] Screen;
|
||||
|
||||
public int[] GetScreenPixelColors()
|
||||
{
|
||||
if (Screen == null)
|
||||
{
|
||||
Screen = new int[640 * 480];
|
||||
for (int i = 0; i < Screen.Length; i++)
|
||||
Screen[i] = Color.Black.ToArgb();
|
||||
}
|
||||
return Screen;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern uint MapVirtualKey(uint uCode, uint uMapType);
|
||||
|
||||
const uint MAPVK_VK_TO_VSC = 0x00;
|
||||
const uint MAPVK_VSC_TO_VK = 0x01;
|
||||
const uint MAPVK_VK_TO_CHAR = 0x02;
|
||||
const uint MAPVK_VSC_TO_VK_EX = 0x03;
|
||||
const uint MAPVK_VK_TO_VSC_EX = 0x04;
|
||||
|
||||
public void PressKey(string key, short durationorstate)
|
||||
{
|
||||
if (session.State == SessionState.SessionState_Locked)
|
||||
{
|
||||
int code = 0;
|
||||
if (key == "testall")
|
||||
{
|
||||
int x = 0;
|
||||
session.Console.Keyboard.PutScancodes(new int[128].Select(i => x++).ToArray());
|
||||
return;
|
||||
}
|
||||
//Virtual key code taken from Kennedy.ManagedHooks project
|
||||
//Release key scan code concept taken from VirtualBox source code (KeyboardImpl.cpp:putCAD())
|
||||
//+128
|
||||
code = (int)MapVirtualKey((uint)(VirtualKeys)Enum.Parse(typeof(VirtualKeys), key, true), MAPVK_VK_TO_VSC);
|
||||
int codeShift = (int)MapVirtualKey((uint)VirtualKeys.ShiftLeft, MAPVK_VK_TO_VSC);
|
||||
int codeCtrl = (int)MapVirtualKey((uint)VirtualKeys.ControlLeft, MAPVK_VK_TO_VSC);
|
||||
int codeAlt = (int)MapVirtualKey((uint)VirtualKeys.AltLeft, MAPVK_VK_TO_VSC);
|
||||
if (durationorstate != -2) //<-- 2016.02.22.
|
||||
session.Console.Keyboard.PutScancode(code);
|
||||
if (durationorstate == 0 || durationorstate == -2)
|
||||
session.Console.Keyboard.PutScancodes(new int[] { code + 128, codeCtrl + 128, codeShift + 128, codeAlt + 128 });
|
||||
if (durationorstate > 0)
|
||||
{
|
||||
Timer t = new Timer();
|
||||
t.Tick += delegate
|
||||
{
|
||||
session.Console.Keyboard.PutScancode(code + 128);
|
||||
t.Stop();
|
||||
};
|
||||
t.Interval = durationorstate;
|
||||
t.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMouse(int x, int y, int z, int w, string mbs)
|
||||
{
|
||||
if (session.State != SessionState.SessionState_Locked)
|
||||
return;
|
||||
int state = 0;
|
||||
if (mbs.Length > 0)
|
||||
state = (int)(MouseBS)Enum.Parse(typeof(MouseBS), mbs, true);
|
||||
session.Console.Mouse.PutMouseEvent(x, y, z, w, state);
|
||||
}
|
||||
|
||||
public void FixScreen()
|
||||
{
|
||||
session.Console.Display.SetSeamlessMode(0);
|
||||
session.Console.Display.SetVideoModeHint(0, 1, 0, 0, 0, 640, 480, 32);
|
||||
}
|
||||
|
||||
~Computer()
|
||||
{
|
||||
if (session.State == SessionState.SessionState_Locked)
|
||||
session.Machine.SaveState();
|
||||
}
|
||||
}
|
||||
}
|
59
VirtualComputerSender/Form1.Designer.cs
generated
59
VirtualComputerSender/Form1.Designer.cs
generated
|
@ -1,59 +0,0 @@
|
|||
namespace VirtualComputerSender
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.BackColor = System.Drawing.Color.Black;
|
||||
this.panel1.Location = new System.Drawing.Point(12, 12);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(800, 600);
|
||||
this.panel1.TabIndex = 0;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(861, 662);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Name = "Form1";
|
||||
this.Text = "Form1";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerSender //Copyright © NorbiPeti 2015-2016
|
||||
{
|
||||
public partial class Form1: Form
|
||||
{
|
||||
private static Form1 Instance;
|
||||
public Form1()
|
||||
{
|
||||
Instance = this;
|
||||
InitializeComponent();
|
||||
Screen = panel1.CreateGraphics();
|
||||
var vbox = new VirtualBoxClass();
|
||||
var session = new Session();
|
||||
var machine = (IMachine)vbox.Machines.GetValue(0);
|
||||
var progress = machine.LaunchVMProcess(session, "headless", "");
|
||||
progress.WaitForCompletion(100000);
|
||||
session.Console.Display.AttachFramebuffer(0, new NetFrameBuffer(session.Console.Display));
|
||||
}
|
||||
|
||||
public static Graphics Screen;
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -1,179 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerSender //Copyright © NorbiPeti 2015-2016
|
||||
{
|
||||
public class MCFrameBuffer : IFramebuffer
|
||||
{
|
||||
private IDisplay Display;
|
||||
private Timer LastFullUpdateTimer;
|
||||
private UdpClient Client;
|
||||
|
||||
public MCFrameBuffer(IDisplay display)
|
||||
{
|
||||
Display = display;
|
||||
LastFullUpdateTimer = new Timer();
|
||||
LastFullUpdateTimer.Interval = 5000;
|
||||
LastFullUpdateTimer.Elapsed += UpdateScreen;
|
||||
Client = new UdpClient();
|
||||
Client.Connect(new IPEndPoint(IPAddress.Loopback, 5896));
|
||||
LastFullUpdateTimer.Start();
|
||||
}
|
||||
|
||||
private void UpdateScreen(object sender, EventArgs args)
|
||||
{
|
||||
Display.InvalidateAndUpdateScreen(0);
|
||||
}
|
||||
|
||||
public IntPtr Address
|
||||
{
|
||||
get
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public const uint CBitsPerPixel = 32;
|
||||
public uint BitsPerPixel
|
||||
{
|
||||
get
|
||||
{
|
||||
return CBitsPerPixel;
|
||||
}
|
||||
}
|
||||
|
||||
public uint BytesPerLine
|
||||
{
|
||||
get
|
||||
{
|
||||
return ScreenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Height
|
||||
{
|
||||
get
|
||||
{
|
||||
Console.WriteLine("Screen height queried.");
|
||||
return ScreenHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public uint HeightReduction
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public IFramebufferOverlay Overlay
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapFormat PixelFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitmapFormat.BitmapFormat_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Width
|
||||
{
|
||||
get
|
||||
{
|
||||
Console.WriteLine("Screen width queried.");
|
||||
return ScreenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public long WinId
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Array Capabilities
|
||||
{
|
||||
get
|
||||
{
|
||||
return new FramebufferCapabilities[] { FramebufferCapabilities.FramebufferCapabilities_UpdateImage };
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
throw new InvalidOperationException("This should not be used.");
|
||||
}
|
||||
|
||||
public void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ProcessVHWACommand(ref byte aCommand)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
}
|
||||
|
||||
public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public const int ScreenWidth = 640;
|
||||
public const int ScreenHeight = 480;
|
||||
|
||||
public volatile int[] Screen = new int[640 * 480];
|
||||
public void NotifyUpdateImage(uint aX, uint aY, uint aWidth, uint aHeight, Array aImage)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var img = (byte[])aImage;
|
||||
int x = 0;
|
||||
for (int j = (int)aY; j < aHeight && j < ScreenHeight; j++)
|
||||
{
|
||||
for (int i = (int)aX; i < aWidth && i < ScreenWidth; i++)
|
||||
{
|
||||
if (x + 4 > aImage.Length)
|
||||
return;
|
||||
Screen[640 * j + i] = Color.FromArgb(img[x + 2], img[x + 1], img[x]).ToArgb(); //TODO: Touchscreen and/or left click right click forwarding
|
||||
x += 4;
|
||||
}
|
||||
x += (int)aX * 4;
|
||||
int add = ((int)(aX + aWidth) - ScreenWidth);
|
||||
if (add > 0)
|
||||
x += add * 4;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void NotifyChange(uint aScreenId, uint aXOrigin, uint aYOrigin, uint aWidth, uint aHeight)
|
||||
{
|
||||
}
|
||||
|
||||
public void Notify3DEvent(uint aType, Array aData)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VirtualComputerSender
|
||||
{
|
||||
public enum MouseBS
|
||||
{
|
||||
LeftButton = 1,
|
||||
MiddleButton = 4,
|
||||
RightButton = 2,
|
||||
WheelDown = 16,
|
||||
WheelUp = 8,
|
||||
XButton1 = 32,
|
||||
XButton2 = 64
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerSender //Copyright © NorbiPeti 2015-2016
|
||||
{
|
||||
public class NetFrameBuffer : IFramebuffer
|
||||
{
|
||||
private IDisplay Display;
|
||||
private Timer LastFullUpdateTimer;
|
||||
private UdpClient Client;
|
||||
|
||||
public NetFrameBuffer(IDisplay display)
|
||||
{
|
||||
//address = Marshal.AllocHGlobal(1440 * 900 * 4);
|
||||
Display = display;
|
||||
LastFullUpdateTimer = new Timer();
|
||||
LastFullUpdateTimer.Interval = 60000;
|
||||
LastFullUpdateTimer.Elapsed += UpdateScreen;
|
||||
Client = new UdpClient();
|
||||
Client.Connect(new IPEndPoint(IPAddress.Loopback, 5896));
|
||||
LastFullUpdateTimer.Start();
|
||||
}
|
||||
|
||||
private void UpdateScreen(object sender, EventArgs args)
|
||||
{
|
||||
Display.InvalidateAndUpdateScreen(0);
|
||||
}
|
||||
|
||||
public IntPtr Address
|
||||
{
|
||||
get
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public const uint CBitsPerPixel = 32;
|
||||
public uint BitsPerPixel
|
||||
{
|
||||
get
|
||||
{
|
||||
return CBitsPerPixel;
|
||||
}
|
||||
}
|
||||
|
||||
public uint BytesPerLine
|
||||
{
|
||||
get
|
||||
{
|
||||
return ScreenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return ScreenHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public uint HeightReduction
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public IFramebufferOverlay Overlay
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapFormat PixelFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return BitmapFormat.BitmapFormat_RGBA;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return ScreenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public long WinId
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Array Capabilities
|
||||
{
|
||||
get
|
||||
{
|
||||
return new FramebufferCapabilities[] { FramebufferCapabilities.FramebufferCapabilities_UpdateImage };
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
throw new InvalidOperationException("This should not be used.");
|
||||
}
|
||||
|
||||
public void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight)
|
||||
{
|
||||
//throw new InvalidOperationException("This should not be used. (Only UpdateImage.)");
|
||||
}
|
||||
|
||||
public void ProcessVHWACommand(ref byte aCommand)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
}
|
||||
|
||||
public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public const int ScreenWidth = 640;
|
||||
public const int ScreenHeight = 480;
|
||||
|
||||
private Color[,] Screen = new Color[640, 480];
|
||||
public void NotifyUpdateImage(uint aX, uint aY, uint aWidth, uint aHeight, Array aImage)
|
||||
{
|
||||
var img = aImage.Cast<byte>().ToArray();
|
||||
int x = 0;
|
||||
for (int j = (int)aY; j < aHeight && j < ScreenHeight; j++)
|
||||
{
|
||||
//for (int i = (int)aX; (j % 20 == 0 ? (i < aWidth - 1 && i < ScreenWidth - 1) : (i < aWidth && i < ScreenWidth)); i++)
|
||||
for (int i = (int)aX; i < aWidth && i < ScreenWidth; i++)
|
||||
{
|
||||
if (x + 4 > aImage.Length)
|
||||
return;
|
||||
//Form1.Screen.FillRectangle(new SolidBrush(Color.FromArgb(255, img[x + 2], img[x + 1], img[x])), i, j, 1, 1);
|
||||
Screen[i, j] = Color.FromArgb(img[x + 2], img[x + 1], img[x]);
|
||||
//Form1.Screen.FillRectangle(new SolidBrush(Color.FromArgb(255, img[x], img[x + 1], img[x + 2])), i, j, 1, 1);
|
||||
x += 4;
|
||||
}
|
||||
x += (int)aX * 4;
|
||||
int add = ((int)(aX + aWidth) - ScreenWidth);
|
||||
if (add > 0)
|
||||
x += add * 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void NotifyChange(uint aScreenId, uint aXOrigin, uint aYOrigin, uint aWidth, uint aHeight)
|
||||
{
|
||||
}
|
||||
|
||||
public void Notify3DEvent(uint aType, Array aData)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace VirtualComputerSender
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace VirtualComputerSender.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VirtualComputerSender.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -1,26 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace VirtualComputerSender.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -1,159 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{5EF12535-ACDF-4D60-8E32-087F5A277946}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>VirtualComputerSender</RootNamespace>
|
||||
<AssemblyName>VirtualComputerSender</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\TheButtonMCAutoFlairProto\Spigot server\plugins\VirtualComputer\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Computer.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MCFrameBuffer.cs" />
|
||||
<Compile Include="MouseBS.cs" />
|
||||
<Compile Include="NetFrameBuffer.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="VirtualKeys.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="VirtualBox">
|
||||
<Guid>{D7569351-1750-46F0-936E-BD127D5BC264}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>3</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>False</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,129 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace VirtualComputerSender
|
||||
{
|
||||
internal enum VirtualKeys
|
||||
{
|
||||
Back = 0x08,
|
||||
Tab = 0x09,
|
||||
Clear = 0x0C,
|
||||
Return = 0x0D,
|
||||
|
||||
ShiftLeft = 0xA0,
|
||||
ControlLeft = 0xA2,
|
||||
ShiftRight = 0xA1,
|
||||
ControlRight = 0xA3,
|
||||
AltLeft = 0xA4,
|
||||
AltRight = 0xA5,
|
||||
|
||||
Menu = 0x12,
|
||||
Pause = 0x13,
|
||||
Capital = 0x14,
|
||||
Escape = 0x1B,
|
||||
Space = 0x20,
|
||||
Prior = 0x21,
|
||||
Next = 0x22,
|
||||
End = 0x23,
|
||||
Home = 0x24,
|
||||
Left = 0x25,
|
||||
Up = 0x26,
|
||||
Right = 0x27,
|
||||
Down = 0x28,
|
||||
Select = 0x29,
|
||||
Print = 0x2A,
|
||||
Execute = 0x2B,
|
||||
Snapshot = 0x2C,
|
||||
Insert = 0x2D,
|
||||
Delete = 0x2E,
|
||||
Help = 0x2F,
|
||||
|
||||
D0 = 0x30,
|
||||
D1 = 0x31,
|
||||
D2 = 0x32,
|
||||
D3 = 0x33,
|
||||
D4 = 0x34,
|
||||
D5 = 0x35,
|
||||
D6 = 0x36,
|
||||
D7 = 0x37,
|
||||
D8 = 0x38,
|
||||
D9 = 0x39,
|
||||
|
||||
A = 0x41,
|
||||
B = 0x42,
|
||||
C = 0x43,
|
||||
D = 0x44,
|
||||
E = 0x45,
|
||||
F = 0x46,
|
||||
G = 0x47,
|
||||
H = 0x48,
|
||||
I = 0x49,
|
||||
J = 0x4A,
|
||||
K = 0x4B,
|
||||
L = 0x4C,
|
||||
M = 0x4D,
|
||||
N = 0x4E,
|
||||
O = 0x4F,
|
||||
P = 0x50,
|
||||
Q = 0x51,
|
||||
R = 0x52,
|
||||
S = 0x53,
|
||||
T = 0x54,
|
||||
U = 0x55,
|
||||
V = 0x56,
|
||||
W = 0x57,
|
||||
X = 0x58,
|
||||
Y = 0x59,
|
||||
Z = 0x5A,
|
||||
|
||||
LWindows = 0x5B,
|
||||
RWindows = 0x5C,
|
||||
Apps = 0x5D,
|
||||
NumPad0 = 0x60,
|
||||
NumPad1 = 0x61,
|
||||
NumPad2 = 0x62,
|
||||
NumPad3 = 0x63,
|
||||
NumPad4 = 0x64,
|
||||
NumPad5 = 0x65,
|
||||
NumPad6 = 0x66,
|
||||
NumPad7 = 0x67,
|
||||
NumPad8 = 0x68,
|
||||
NumPad9 = 0x69,
|
||||
|
||||
Multiply = 0x6A,
|
||||
Add = 0x6B,
|
||||
Separator = 0x6C,
|
||||
Subtract = 0x6D,
|
||||
Decimal = 0x6E,
|
||||
Divide = 0x6F,
|
||||
F1 = 0x70,
|
||||
F2 = 0x71,
|
||||
F3 = 0x72,
|
||||
F4 = 0x73,
|
||||
F5 = 0x74,
|
||||
F6 = 0x75,
|
||||
F7 = 0x76,
|
||||
F8 = 0x77,
|
||||
F9 = 0x78,
|
||||
F10 = 0x79,
|
||||
F11 = 0x7A,
|
||||
F12 = 0x7B,
|
||||
F13 = 0x7C,
|
||||
F14 = 0x7D,
|
||||
F15 = 0x7E,
|
||||
F16 = 0x7F,
|
||||
F17 = 0x80,
|
||||
F18 = 0x81,
|
||||
F19 = 0x82,
|
||||
F20 = 0x83,
|
||||
F21 = 0x84,
|
||||
F22 = 0x85,
|
||||
F23 = 0x86,
|
||||
F24 = 0x87,
|
||||
|
||||
NumLock = 0x90,
|
||||
Scroll = 0x91,
|
||||
}
|
||||
}
|
34
VirtualComputerWindows/VirtualComputerWindows.sln
Normal file
34
VirtualComputerWindows/VirtualComputerWindows.sln
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26403.7
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualComputerWindows", "VirtualComputerWindows\VirtualComputerWindows.csproj", "{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x64.Build.0 = Debug|x64
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Debug|x86.Build.0 = Debug|x86
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x64.ActiveCfg = Release|x64
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x64.Build.0 = Release|x64
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x86.ActiveCfg = Release|x86
|
||||
{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
59
VirtualComputerWindows/VirtualComputerWindows/Exports.cs
Normal file
59
VirtualComputerWindows/VirtualComputerWindows/Exports.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerWindows
|
||||
{
|
||||
public static class Exports
|
||||
{
|
||||
[DllImport(@"C:\Program Files\Oracle\VirtualBox\VBoxRT.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern void RTR3InitExe(int argc, string argv, int zeroflags);
|
||||
/*[DllImport(@"C:\Program Files\Oracle\VirtualBox\VBoxVMM.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern int VMMDoHmTest(IntPtr vmstruct);*/
|
||||
|
||||
private static VirtualBoxClient vbc;
|
||||
|
||||
public static async Task<IVirtualBox> Init() => await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
//Environment.SetEnvironmentVariable("VBOX_HOME", @"C:\Program Files\Oracle\VirtualBox\");
|
||||
//TODO: Only finds the VBoxVMM.dll when placed in the VirtualBox dir (regardless of working dir)
|
||||
//Even then there are hardening issues: VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_1
|
||||
//https://www.virtualbox.org/svn/vbox/trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
|
||||
vbc = new VirtualBoxClientClass();
|
||||
var vbox = vbc.VirtualBox;
|
||||
RTR3InitExe(0, "", 0);
|
||||
var ses = vbc.Session;
|
||||
var machine = vbox.Machines.GetValue(0) as IMachine;
|
||||
ses.Name = "minecraft";
|
||||
machine.LockMachine(ses, LockType.LockType_VM);
|
||||
Console.WriteLine("Locking...");
|
||||
while (ses.State != SessionState.SessionState_Locked) ;
|
||||
Console.WriteLine("Locked");
|
||||
machine = ses.Machine;
|
||||
Console.WriteLine("Powering up...");
|
||||
ses.Console.PowerUp().WaitForCompletion(10000);
|
||||
Console.WriteLine("Framebuffer attach");
|
||||
ses.Console.Display.AttachFramebuffer(0, new VBFB(ses.Console.Display));
|
||||
return vbox;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
Console.ReadLine();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
Init();
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,12 +5,12 @@ using System.Runtime.InteropServices;
|
|||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("VirtualComputerSender")]
|
||||
[assembly: AssemblyTitle("VirtualComputerWindows")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("VirtualComputerSender")]
|
||||
[assembly: AssemblyCopyright("Copyright © NorbiPeti 2015-2016")]
|
||||
[assembly: AssemblyProduct("VirtualComputerWindows")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
@ -20,7 +20,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("5ef12535-acdf-4d60-8e32-087f5a277946")]
|
||||
[assembly: Guid("5e734f17-ff74-4187-a6e4-b7e1dab272f8")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
75
VirtualComputerWindows/VirtualComputerWindows/VBFB.cs
Normal file
75
VirtualComputerWindows/VirtualComputerWindows/VBFB.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using VirtualBox;
|
||||
|
||||
namespace VirtualComputerWindows
|
||||
{
|
||||
internal class VBFB : IFramebuffer
|
||||
{
|
||||
private IDisplay display;
|
||||
|
||||
public VBFB(IDisplay display)
|
||||
{
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public void NotifyUpdate(uint aX, uint aY, uint aWidth, uint aHeight)
|
||||
{
|
||||
Console.WriteLine("Update: " + aX + " " + aY + " " + aWidth + " " + aHeight);
|
||||
}
|
||||
|
||||
public void NotifyUpdateImage(uint aX, uint aY, uint aWidth, uint aHeight, Array aImage)
|
||||
{
|
||||
Console.WriteLine("UpdateImage: " + aX + " " + aY + " " + aWidth + " " + aHeight);
|
||||
}
|
||||
|
||||
public void NotifyChange(uint aScreenId, uint aXOrigin, uint aYOrigin, uint aWidth, uint aHeight)
|
||||
{
|
||||
Console.WriteLine("Change: " + aXOrigin + " " + aYOrigin + " " + aWidth + " " + aHeight);
|
||||
display.QuerySourceBitmap(0, out var isd);
|
||||
var addr = new IntPtr();
|
||||
isd.QueryBitmapInfo(addr, out var w, out var h, out var bpp, out var bpl, out var bf);
|
||||
Console.WriteLine("Bitmap info: " + addr + " " + w + " " + h + " " + bpp + " " + bpl + " " + bf);
|
||||
}
|
||||
|
||||
public int VideoModeSupported(uint aWidth, uint aHeight, uint aBpp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public uint GetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
return aCount;
|
||||
}
|
||||
|
||||
public void SetVisibleRegion(ref byte aRectangles, uint aCount)
|
||||
{
|
||||
}
|
||||
|
||||
public void ProcessVHWACommand(ref byte aCommand, int aEnmCmd, int aFromGuest)
|
||||
{
|
||||
}
|
||||
|
||||
public void Notify3DEvent(uint aType, Array aData)
|
||||
{
|
||||
}
|
||||
|
||||
public uint Width => 640;
|
||||
|
||||
public uint Height => 480;
|
||||
|
||||
public uint BitsPerPixel => 32;
|
||||
|
||||
public uint BytesPerLine => 640 * 4;
|
||||
|
||||
public BitmapFormat PixelFormat => BitmapFormat.BitmapFormat_BGRA;
|
||||
|
||||
public uint HeightReduction => 0;
|
||||
|
||||
public IFramebufferOverlay Overlay => null;
|
||||
|
||||
public long WinId => 0;
|
||||
|
||||
//public Array Capabilities => new[] { FramebufferCapabilities.FramebufferCapabilities_UpdateImage };
|
||||
public Array Capabilities => new FramebufferCapabilities[] { };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{5E734F17-FF74-4187-A6E4-B7E1DAB272F8}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>VirtualComputerWindows</RootNamespace>
|
||||
<AssemblyName>VirtualComputerWindows</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
<DllExportNamespace>VirtualComputerWindows</DllExportNamespace>
|
||||
<DllExportDDNSCecil>true</DllExportDDNSCecil>
|
||||
<DllExportSkipOnAnyCpu>false</DllExportSkipOnAnyCpu>
|
||||
<DllExportOrdinalsBase>1</DllExportOrdinalsBase>
|
||||
<DllExportGenExpLib>false</DllExportGenExpLib>
|
||||
<DllExportOurILAsm>false</DllExportOurILAsm>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Exports.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="VBFB.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="VirtualBox">
|
||||
<Guid>{D7569351-1750-46F0-936E-BD127D5BC264}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>3</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>False</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="../packages/DllExport.1.5.2/tools/net.r_eg.DllExport.targets" Condition="Exists('../packages/DllExport.1.5.2/tools/net.r_eg.DllExport.targets')" />
|
||||
</Project>
|
15
VirtualComputerWindows/VirtualComputerWindows/app.config
Normal file
15
VirtualComputerWindows/VirtualComputerWindows/app.config
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net462" />
|
||||
</packages>
|
3
libpxc/.gitignore
vendored
Normal file
3
libpxc/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
obj/
|
||||
out/
|
||||
|
11
libpxc/makefile
Normal file
11
libpxc/makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
CC=gcc
|
||||
# CFLAGS=-I.
|
||||
|
||||
pxct: pxct.c pxc
|
||||
$(CC) -Wall pxct.c -Lout -lpxc -Wl,-rpath=out -o out/pxct
|
||||
|
||||
pxc: pxc.c
|
||||
$(CC) -Wall -O4 -c -fpic pxc.c -o obj/pxc.o
|
||||
$(CC) -Wall -shared obj/pxc.o -o out/libpxc.so
|
||||
cp out/libpxc.so ../
|
||||
|
183
libpxc/pxc.c
Normal file
183
libpxc/pxc.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAPSIZE 128
|
||||
|
||||
#if MAPSIZE>255
|
||||
#error MAPSIZE must be a short value
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// http://www.pixelbeat.org/programming/gcc/static_assert.html
|
||||
#define ct_assert(e) {enum { ct_assert_value = 1/(!!(e)) };}
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
typedef long long int addr;
|
||||
typedef struct { //RGB
|
||||
unsigned int red : 8;
|
||||
unsigned int green : 8;
|
||||
unsigned int blue : 8;
|
||||
} Color; //Used for Bukkit's initializers (for simplicity)
|
||||
typedef struct { //BGRA
|
||||
unsigned int blue : 8;
|
||||
unsigned int green : 8;
|
||||
unsigned int red : 8;
|
||||
unsigned int alpha : 8;
|
||||
} NativeColor; //Used for the screen data
|
||||
|
||||
char matchColor(NativeColor nc);
|
||||
|
||||
void* image=NULL;
|
||||
void* maps=NULL; //Per map data (1st map, second map etc.)
|
||||
|
||||
short width, height, mapcx, mapcy;
|
||||
|
||||
void setSource(addr address, short w, short h, short mcx, short mcy) {
|
||||
ct_assert(sizeof(char)==1); //Compile-time assert
|
||||
ct_assert(sizeof(Color)==4); //Compile-time assert
|
||||
image=(void*)address;
|
||||
maps=malloc(MAPSIZE*MAPSIZE*mcx*mcy); //1 byte per pixel
|
||||
width=w, height=h, mapcx=mcx, mapcy=mcy;
|
||||
printf("PXC: w=%d h=%d mcx=%d mcy=%d\n", w, h, mcx, mcy);
|
||||
}
|
||||
|
||||
NativeColor* getNativeColor(int x, int y) {
|
||||
if(x<0||x>width||y<0||y>height) return NULL;
|
||||
return ((NativeColor*)image)+x+y*width;
|
||||
}
|
||||
|
||||
char* getMapColor(int x, int y) {
|
||||
if(x<0||x>width||y<0||y>height) return NULL;
|
||||
int mc=x/MAPSIZE+y/MAPSIZE*mapcx;
|
||||
return maps+mc*MAPSIZE*MAPSIZE; //TODO: Use
|
||||
}
|
||||
|
||||
//May return 0
|
||||
void* updateAndGetMap(int x, int y, int w, int h, int** out_changed) { //TODO: Support the parameters
|
||||
if(image==NULL || maps==NULL) return 0;
|
||||
for(int l=y; l<y+h; l++) {
|
||||
//printf("PXC: l=%d\n", l);
|
||||
for(int k=x; k<x+w; k++) {
|
||||
//printf("PXC: k=%d\n", k);
|
||||
char *mapp=getMapColor(k, l);
|
||||
char color=matchColor(*getNativeColor(k, l));
|
||||
//NativeColor x={.red=0, .green=0, .blue=255, .alpha=255};
|
||||
//*mapp=matchColor(x);
|
||||
*mapp=color;
|
||||
//printf("PXC: mapp: %d %d - %x\n", k, l, *mapp); //TODO: The bottom of the image
|
||||
//printf("PXC: mapcx: %d mapcy: %d\n", k, l); //TODO: Has nothing
|
||||
}
|
||||
}
|
||||
printf("PXC: ret maps=%p\n", maps);
|
||||
return maps; //TODO: Return changed only
|
||||
}
|
||||
|
||||
const Color colors[] = {
|
||||
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
|
||||
{89, 125, 39}, {109, 153, 48}, {127, 178, 56}, {67, 94, 29},
|
||||
{174, 164, 115}, {213, 201, 140}, {247, 233, 163}, {130, 123, 86},
|
||||
{140, 140, 140}, {171, 171, 171}, {199, 199, 199}, {105, 105, 105},
|
||||
{180, 0, 0}, {220, 0, 0}, {255, 0, 0}, {135, 0, 0},
|
||||
{112, 112, 180}, {138, 138, 220}, {160, 160, 255}, {84, 84, 135},
|
||||
{117, 117, 117}, {144, 144, 144}, {167, 167, 167}, {88, 88, 88},
|
||||
{0, 87, 0}, {0, 106, 0}, {0, 124, 0}, {0, 65, 0},
|
||||
{180, 180, 180}, {220, 220, 220}, {255, 255, 255}, {135, 135, 135},
|
||||
{115, 118, 129}, {141, 144, 158}, {164, 168, 184}, {86, 88, 97},
|
||||
{106, 76, 54}, {130, 94, 66}, {151, 109, 77}, {79, 57, 40},
|
||||
{79, 79, 79}, {96, 96, 96}, {112, 112, 112}, {59, 59, 59},
|
||||
{45, 45, 180}, {55, 55, 220}, {64, 64, 255}, {33, 33, 135},
|
||||
{100, 84, 50}, {123, 102, 62}, {143, 119, 72}, {75, 63, 38},
|
||||
{180, 177, 172}, {220, 217, 211}, {255, 252, 245}, {135, 133, 129},
|
||||
{152, 89, 36}, {186, 109, 44}, {216, 127, 51}, {114, 67, 27},
|
||||
{125, 53, 152}, {153, 65, 186}, {178, 76, 216}, {94, 40, 114},
|
||||
{72, 108, 152}, {88, 132, 186}, {102, 153, 216}, {54, 81, 114},
|
||||
{161, 161, 36}, {197, 197, 44}, {229, 229, 51}, {121, 121, 27},
|
||||
{89, 144, 17}, {109, 176, 21}, {127, 204, 25}, {67, 108, 13},
|
||||
{170, 89, 116}, {208, 109, 142}, {242, 127, 165}, {128, 67, 87},
|
||||
{53, 53, 53}, {65, 65, 65}, {76, 76, 76}, {40, 40, 40},
|
||||
{108, 108, 108}, {132, 132, 132}, {153, 153, 153}, {81, 81, 81},
|
||||
{53, 89, 108}, {65, 109, 132}, {76, 127, 153}, {40, 67, 81},
|
||||
{89, 44, 125}, {109, 54, 153}, {127, 63, 178}, {67, 33, 94},
|
||||
{36, 53, 125}, {44, 65, 153}, {51, 76, 178}, {27, 40, 94},
|
||||
{72, 53, 36}, {88, 65, 44}, {102, 76, 51}, {54, 40, 27},
|
||||
{72, 89, 36}, {88, 109, 44}, {102, 127, 51}, {54, 67, 27},
|
||||
{108, 36, 36}, {132, 44, 44}, {153, 51, 51}, {81, 27, 27},
|
||||
{17, 17, 17}, {21, 21, 21}, {25, 25, 25}, {13, 13, 13},
|
||||
{176, 168, 54}, {215, 205, 66}, {250, 238, 77}, {132, 126, 40},
|
||||
{64, 154, 150}, {79, 188, 183}, {92, 219, 213}, {48, 115, 112},
|
||||
{52, 90, 180}, {63, 110, 220}, {74, 128, 255}, {39, 67, 135},
|
||||
{0, 153, 40}, {0, 187, 50}, {0, 217, 58}, {0, 114, 30},
|
||||
{91, 60, 34}, {111, 74, 42}, {129, 86, 49}, {68, 45, 25},
|
||||
{79, 1, 0}, {96, 1, 0}, {112, 2, 0}, {59, 1, 0},
|
||||
{147, 124, 113}, {180, 152, 138}, {209, 177, 161}, {110, 93, 85},
|
||||
{112, 57, 25}, {137, 70, 31}, {159, 82, 36}, {84, 43, 19},
|
||||
{105, 61, 76}, {128, 75, 93}, {149, 87, 108}, {78, 46, 57},
|
||||
{79, 76, 97}, {96, 93, 119}, {112, 108, 138}, {59, 57, 73},
|
||||
{131, 93, 25}, {160, 114, 31}, {186, 133, 36}, {98, 70, 19},
|
||||
{72, 82, 37}, {88, 100, 45}, {103, 117, 53}, {54, 61, 28},
|
||||
{112, 54, 55}, {138, 66, 67}, {160, 77, 78}, {84, 40, 41},
|
||||
{40, 28, 24}, {49, 35, 30}, {57, 41, 35}, {30, 21, 18},
|
||||
{95, 75, 69}, {116, 92, 84}, {135, 107, 98}, {71, 56, 51},
|
||||
{61, 64, 64}, {75, 79, 79}, {87, 92, 92}, {46, 48, 48},
|
||||
{86, 51, 62}, {105, 62, 75}, {122, 73, 88}, {64, 38, 46},
|
||||
{53, 43, 64}, {65, 53, 79}, {76, 62, 92}, {40, 32, 48},
|
||||
{53, 35, 24}, {65, 43, 30}, {76, 50, 35}, {40, 26, 18},
|
||||
{53, 57, 29}, {65, 70, 36}, {76, 82, 42}, {40, 43, 22},
|
||||
{100, 42, 32}, {122, 51, 39}, {142, 60, 46}, {75, 31, 24},
|
||||
{26, 15, 11}, {31, 18, 13}, {37, 22, 16}, {19, 11, 8}
|
||||
};
|
||||
|
||||
|
||||
//Code from Bukkit's MapPalette class
|
||||
double getDistance(Color c1, Color c2) {
|
||||
double rmean = (c1.red + c2.red) / 2.0;
|
||||
double r = c1.red - c2.red;
|
||||
double g = c1.green - c2.green;
|
||||
int b = c1.blue - c2.blue;
|
||||
double weightR = 2 + rmean / 256.0;
|
||||
double weightG = 4.0;
|
||||
double weightB = 2 + (255 - rmean) / 256.0;
|
||||
return weightR * r * r + weightG * g * g + weightB * b * b;
|
||||
}
|
||||
|
||||
//Code from Bukkit's MapPalette class
|
||||
char matchColor(NativeColor nc) {
|
||||
//if (nc.alpha < 128) return 0;
|
||||
Color color={.red=nc.red, .green=nc.green, .blue=nc.blue};
|
||||
|
||||
char index = 0;
|
||||
double best = -1;
|
||||
|
||||
for (short i = 4; i < sizeof(colors)/sizeof(Color); i++) {
|
||||
double distance = getDistance(color, colors[i]);
|
||||
if (distance < best || best == -1) {
|
||||
best = distance;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Minecraft has 143 colors, some of which have negative byte representations
|
||||
//return (byte) (index < 128 ? index : -129 + (index - 127));
|
||||
return index;
|
||||
}
|
||||
|
||||
//Testing only
|
||||
int convert(int px[], int *out[]) {
|
||||
printf("convert...\n");
|
||||
printf("px0: %d\n", px[0]);
|
||||
*out[0]=19;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__ ((constructor)) initLibrary(void) {
|
||||
//
|
||||
// Function that is called when the library is loaded
|
||||
//
|
||||
printf("Library is initialized\n");
|
||||
}
|
||||
void __attribute__ ((destructor)) cleanUpLibrary(void) {
|
||||
//
|
||||
// Function that is called when the library is »closed«.
|
||||
//
|
||||
printf("Library is exited\n");
|
||||
}
|
31
libpxc/pxct.c
Normal file
31
libpxc/pxct.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/* https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
|
||||
gcc -Wall -c -fpic pxc.c
|
||||
gcc -Wall -shared pxc.o -o pxc.so
|
||||
gcc -Wall pxct.c -L. -lpxc -Wl,-rpath=.
|
||||
*/
|
||||
|
||||
int convert(int px[], int *out[]);
|
||||
|
||||
typedef long long int addr;
|
||||
void setSource(addr address, short w, short h, short mcx, short mcy);
|
||||
void* updateAndGetMap(int x, int y, int w, int h, int** out_changed);
|
||||
|
||||
int main() {
|
||||
printf("Setting source...");
|
||||
void* p = malloc(640*480*4);
|
||||
setSource((addr)p, 640, 480, 5, 4);
|
||||
printf("Adding random values...\n");
|
||||
srand(time(NULL));
|
||||
unsigned int* xp=p;
|
||||
for(int i=0; i<640*480; i++)
|
||||
*(xp++)=rand();
|
||||
printf("Updating map...");
|
||||
void* x=updateAndGetMap(0, 0, 320, 240, NULL);
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in a new issue