Initial commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
# 📌 Pull Request
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Provide a clear and concise summary of what this PR does.
|
||||||
|
Explain *why* the change is needed and what problem it solves.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Related Issues / Discussions
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Link any related issues, PRs, or discussions.
|
||||||
|
Use "Fixes #123" to automatically close issues when merged.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- Fixes #
|
||||||
|
- Related to #
|
||||||
|
|
||||||
|
## Motivation & Context
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Why is this change important for Project Poseidon?
|
||||||
|
Does it fix a bug, improve stability, add a feature, or improve compatibility?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Type of Change
|
||||||
|
|
||||||
|
Please tick all that apply:
|
||||||
|
|
||||||
|
- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)
|
||||||
|
- [ ] ⚡ Performance improvement
|
||||||
|
- [ ] 🧩 New feature (non-breaking)
|
||||||
|
- [ ] 🔧 Refactor / cleanup (no functional changes)
|
||||||
|
- [ ] 🔥 Crash / exploit fix
|
||||||
|
- [ ] 📚 Documentation update
|
||||||
|
- [ ] ❗ Breaking change (may affect plugins or server behavior)
|
||||||
|
|
||||||
|
## Testing Performed
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Describe how this change was tested.
|
||||||
|
Include environments, steps, and results.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- [ ] Compiled successfully with `mvn clean package`
|
||||||
|
- [ ] Tested on a Beta 1.7.3 server
|
||||||
|
- [ ] Existing functionality verified
|
||||||
|
- [ ] Edge cases considered
|
||||||
|
|
||||||
|
**Test details:**
|
||||||
|
```text
|
||||||
|
Example:
|
||||||
|
- Local server with multiple players
|
||||||
|
- Testing on production environment on RetroMC
|
||||||
|
- Tested login, chunk loading, plugins, and shutdown
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logs / Screenshots (if applicable)
|
||||||
|
|
||||||
|
<!-- Paste relevant log output, stack traces, or attach screenshots to help reviewers understand the change. -->
|
||||||
|
|
||||||
|
```(Optional)```
|
||||||
|
|
||||||
|
## Compatibility Considerations
|
||||||
|
|
||||||
|
<!-- Does this change affect: Plugins? Network behavior? UUID / inventory handling? Other? -->
|
||||||
|
|
||||||
|
- [ ] No known compatibility impact
|
||||||
|
- [ ] Potential plugin impact (described below)
|
||||||
|
- [ ] Network / protocol (Netcode) behavior changed
|
||||||
|
- [ ] Configuration change required
|
||||||
|
|
||||||
|
|
||||||
|
## Compatibility Notes
|
||||||
|
|
||||||
|
<!-- Describe any known compatibility risks or required changes if applicable. -->
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
Please confirm the following:
|
||||||
|
- [ ] No unnecessary formatting or whitespace-only changes
|
||||||
|
- [ ] Changes are compatible with Minecraft Beta 1.7.3
|
||||||
|
- [ ] No dependencies have been added without discussion with the RetroMC team
|
||||||
|
|
||||||
|
## Additional Notes
|
||||||
|
<!-- Anything else reviewers should know? Design decisions, limitations, future follow-ups, etc. -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Thanks for contributing to Project Poseidon!
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
name: build-and-test
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Step 1: Checkout the repository
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Step 2: Set up JDK 1.8
|
||||||
|
- name: Set up JDK 1.8
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 8
|
||||||
|
|
||||||
|
# Step 3: Get the version from pom.xml
|
||||||
|
- name: Get the version from pom.xml
|
||||||
|
id: get_version
|
||||||
|
run: echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Step 4: Generate custom release version
|
||||||
|
- name: Generate Release Version
|
||||||
|
id: release_version
|
||||||
|
run: |
|
||||||
|
DATE=$(date +'%y%m%d-%H%M')
|
||||||
|
SHA=$(echo $GITHUB_SHA | cut -c1-7)
|
||||||
|
RELEASE_VERSION="${PROJECT_VERSION}-${DATE}-${SHA}"
|
||||||
|
echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# Step 5: Create version.properties file
|
||||||
|
- name: Create version.properties file
|
||||||
|
run: |
|
||||||
|
mkdir -p src/main/resources
|
||||||
|
|
||||||
|
# Application Information
|
||||||
|
APP_NAME=$(mvn help:evaluate -Dexpression=project.name -q -DforceStdout)
|
||||||
|
|
||||||
|
# Core Metadata
|
||||||
|
echo "version=${{ env.RELEASE_VERSION }}" >> src/main/resources/version.properties
|
||||||
|
echo "build_timestamp=$(date --utc +'%Y-%m-%dT%H:%M:%SZ')" >> src/main/resources/version.properties
|
||||||
|
echo "git_branch=${{ github.ref_name }}" >> src/main/resources/version.properties
|
||||||
|
echo "git_commit=${GITHUB_SHA}" >> src/main/resources/version.properties
|
||||||
|
|
||||||
|
echo "app_name=${APP_NAME}" >> src/main/resources/version.properties
|
||||||
|
echo "release_version=${{ env.RELEASE_VERSION }}" >> src/main/resources/version.properties
|
||||||
|
echo "maven_version=${{ env.PROJECT_VERSION }}" >> src/main/resources/version.properties
|
||||||
|
|
||||||
|
# Build Type
|
||||||
|
if [[ "${{ github.ref }}" == "refs/heads/master" || "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||||
|
BUILD_TYPE="production"
|
||||||
|
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||||
|
BUILD_TYPE="pull_request"
|
||||||
|
else
|
||||||
|
BUILD_TYPE="development"
|
||||||
|
fi
|
||||||
|
echo "build_type=${BUILD_TYPE}" >> src/main/resources/version.properties
|
||||||
|
|
||||||
|
# CI/CD Metadata
|
||||||
|
echo "workflow_name=${{ github.workflow }}" >> src/main/resources/version.properties
|
||||||
|
echo "workflow_run_id=${{ github.run_id }}" >> src/main/resources/version.properties
|
||||||
|
echo "workflow_run_number=${{ github.run_number }}" >> src/main/resources/version.properties
|
||||||
|
|
||||||
|
# Team or Author Information
|
||||||
|
echo "build_author=${{ github.actor }}" >> src/main/resources/version.properties
|
||||||
|
|
||||||
|
- name: Set up Maven
|
||||||
|
uses: stCarolas/setup-maven@v4.5
|
||||||
|
with:
|
||||||
|
maven-version: 3.9.1
|
||||||
|
|
||||||
|
# Step 6: Build application
|
||||||
|
- name: Build Application
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mvn clean install
|
||||||
|
|
||||||
|
# Step 7: Run Tests
|
||||||
|
- name: Run Tests
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mvn test
|
||||||
|
|
||||||
|
# Step 8: Upload artifact
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ github.event.repository.name }}-artifact
|
||||||
|
path: target/*.jar
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Java-Compatibility
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
- reopened
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# Java 8 is tested as a part of the build-and-test workflow
|
||||||
|
java-version: ['17', '21' ]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Java ${{ matrix.java-version }}
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java-version }}
|
||||||
|
distribution: temurin
|
||||||
|
java-package: jdk
|
||||||
|
|
||||||
|
- name: Set up Maven
|
||||||
|
uses: stCarolas/setup-maven@v4.5
|
||||||
|
with:
|
||||||
|
maven-version: 3.9.1
|
||||||
|
|
||||||
|
- name: Build application
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mvn clean install
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
name: Release Workflow
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up JDK 8
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "8"
|
||||||
|
cache: maven
|
||||||
|
|
||||||
|
- name: Get Maven project version
|
||||||
|
id: get_version
|
||||||
|
run: echo "PROJECT_VERSION=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version)" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Fail if snapshot version
|
||||||
|
run: |
|
||||||
|
if [[ "$PROJECT_VERSION" == *"-SNAPSHOT"* ]]; then
|
||||||
|
echo "Snapshot versions are not releasable: $PROJECT_VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Generate Release Version
|
||||||
|
run: |
|
||||||
|
DATE=$(date +'%y%m%d-%H%M')
|
||||||
|
SHA=$(echo "$GITHUB_SHA" | cut -c1-7)
|
||||||
|
RELEASE_VERSION="${PROJECT_VERSION}-${DATE}-${SHA}"
|
||||||
|
echo "RELEASE_VERSION=$RELEASE_VERSION" >> "$GITHUB_ENV"
|
||||||
|
echo "Release version: $RELEASE_VERSION"
|
||||||
|
|
||||||
|
- name: Set Maven version to Release Version (no commit)
|
||||||
|
run: |
|
||||||
|
mvn -B versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false
|
||||||
|
|
||||||
|
- name: Create version.properties
|
||||||
|
run: |
|
||||||
|
mkdir -p src/main/resources
|
||||||
|
|
||||||
|
APP_NAME=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.name)
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "version=${RELEASE_VERSION}"
|
||||||
|
echo "build_timestamp=$(date --utc +'%Y-%m-%dT%H:%M:%SZ')"
|
||||||
|
echo "git_branch=${GITHUB_REF_NAME}"
|
||||||
|
echo "git_commit=${GITHUB_SHA}"
|
||||||
|
echo "app_name=${APP_NAME}"
|
||||||
|
echo "release_version=${RELEASE_VERSION}"
|
||||||
|
echo "maven_version=${RELEASE_VERSION}"
|
||||||
|
|
||||||
|
if [[ "$GITHUB_REF" == "refs/heads/master" || "$GITHUB_REF" == "refs/heads/main" ]]; then
|
||||||
|
BUILD_TYPE="production"
|
||||||
|
else
|
||||||
|
BUILD_TYPE="development"
|
||||||
|
fi
|
||||||
|
echo "build_type=${BUILD_TYPE}"
|
||||||
|
|
||||||
|
echo "workflow_name=${GITHUB_WORKFLOW}"
|
||||||
|
echo "workflow_run_id=${GITHUB_RUN_ID}"
|
||||||
|
echo "workflow_run_number=${GITHUB_RUN_NUMBER}"
|
||||||
|
echo "build_author=${GITHUB_ACTOR}"
|
||||||
|
} > src/main/resources/version.properties
|
||||||
|
|
||||||
|
- name: Write Maven settings.xml for Nexus auth
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.m2
|
||||||
|
cat > ~/.m2/settings.xml << 'EOF'
|
||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||||
|
<servers>
|
||||||
|
<server>
|
||||||
|
<id>johnymuffin-nexus</id>
|
||||||
|
<username>${env.NEXUS_USERNAME}</username>
|
||||||
|
<password>${env.NEXUS_PASSWORD}</password>
|
||||||
|
</server>
|
||||||
|
</servers>
|
||||||
|
</settings>
|
||||||
|
EOF
|
||||||
|
env:
|
||||||
|
NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
|
||||||
|
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build & Deploy to Nexus
|
||||||
|
run: mvn -B -DskipTests clean deploy
|
||||||
|
env:
|
||||||
|
NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
|
||||||
|
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.RELEASE_VERSION }}
|
||||||
|
name: ${{ env.RELEASE_VERSION }}
|
||||||
|
files: |
|
||||||
|
target/*.jar
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
+237
@@ -0,0 +1,237 @@
|
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/java,intellij,intellij+all,intellij+iml
|
||||||
|
# Edit at https://www.gitignore.io/?templates=java,intellij,intellij+all,intellij+iml
|
||||||
|
|
||||||
|
### Intellij ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Intellij Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/**/sonarlint/
|
||||||
|
|
||||||
|
# SonarQube Plugin
|
||||||
|
.idea/**/sonarIssues.xml
|
||||||
|
|
||||||
|
# Markdown Navigator plugin
|
||||||
|
.idea/**/markdown-navigator.xml
|
||||||
|
.idea/**/markdown-navigator/
|
||||||
|
|
||||||
|
### Intellij+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### Intellij+all Patch ###
|
||||||
|
# Ignores the whole .idea folder and all .iml files
|
||||||
|
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
modules.xml
|
||||||
|
.idea/misc.xml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/sonarlint
|
||||||
|
|
||||||
|
### Intellij+iml ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### Intellij+iml Patch ###
|
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||||
|
|
||||||
|
|
||||||
|
### Java ###
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/java,intellij,intellij+all,intellij+iml
|
||||||
|
/bin/
|
||||||
|
|
||||||
|
# Eclipse project files (Hopefully I don't mess everything up now -Saghetti)
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# Remvoe server stuff from path
|
||||||
|
/server/
|
||||||
|
|
||||||
|
# Maven target files
|
||||||
|
/target
|
||||||
|
|
||||||
|
# Don't need dependecy reduced pom
|
||||||
|
dependency-reduced-pom.xml
|
||||||
+674
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Project-Poseidon
|
||||||
|

|
||||||
|
## What's Project Poseidon?
|
||||||
|
**A CraftBukkit CB1060 fork for Beta 1.7.3 fixing bugs and adding basic features.<br>**
|
||||||
|
|
||||||
|
If your looking for Project Poseidon support on pre-1.7.3 versions, please check out [Project Poseidon Uberbukkit](https://github.com/Moresteck/Project-Poseidon-Uberbukkit) developed by Moresteck which supports earlier versions.<br>
|
||||||
|
|
||||||
|
Discord: https://discord.gg/FwKg676
|
||||||
|
|
||||||
|
## Features
|
||||||
|
This is a non-exhaustive list of features that Project Poseidon includes:
|
||||||
|
|
||||||
|
- **UUID Support:** Settings to enable UUID-based inventories alongside methods for plugins to transition to UUID-based systems similar to modern Minecraft server implementations.
|
||||||
|
- **Poseidon Watchdog Implementation:** An automatic utility for detecting server hangs, ending the server process, and providing diagnostics to fix the underlying issues.
|
||||||
|
- **Packet Events:** Adds packet send and receive events for advanced plugin development without needing Spout or to use Reflections that are incompatible with modern Java versions.
|
||||||
|
- **Inventory Block Duplication Fixes:** Includes fixes for chest, furnace, inventory block duplication, and Minecart duplication issues.
|
||||||
|
- **Cross-World Duplication Fix:** Fixes a cross-world duplication glitch.
|
||||||
|
- **Duplication Glitch Fix:** Fix a bug with the Bukkit chunk cache which allowed users to duplicate and get unobtainable items.
|
||||||
|
- **Server Crash Fix:** Addresses multiple server crash issues.
|
||||||
|
- **Connection Pauses:** A powerful feature allowing developers to retrieve information asynchronously before a player connects.
|
||||||
|
- **Event Handlers:** Modern event handlers backported to facilitating easier coding, plugin backporting, and early release plugin support.
|
||||||
|
- **Vanish API Backport:** Backports the modern vanish API for easy vanish plugin creation and fixes issues with hacking players seeing vanished players.
|
||||||
|
- **Logging Enhancements:** Adds an option for daily log file creation and logs player commands to the console, with exceptions for Authme, XAuth, and similar plugins.
|
||||||
|
- **TPS API and Command:** Adds a TPS command and API for plugins to access historical TPS data.
|
||||||
|
- **Server Shutdown Improvements:** Enhances server shutdown procedures to ensure world/player data and plugin data are properly saved.
|
||||||
|
- **Release2Beta Support:** Added support for Release2Beta, including IP Forwarding.
|
||||||
|
- **Tree Growth Blockage Settings:** Allows server owners to block tree growth from replacing certain blocks to prevent griefing.
|
||||||
|
- **TCP NoDelay Option:** Improves netcode performance for compatible clients.
|
||||||
|
- **Ragequit/Ragejoin Fixes:** Prevents ragequit and ragejoin connection/chat spam.
|
||||||
|
- **Plugin Hiding:** Allows plugins to be hidden from the server list via an attribute in `plugin.yml`.
|
||||||
|
- **Improve Console Debug:** Make multiple common errors less verbose in the console.
|
||||||
|
- **Event Handling Improvements:** Ensures primed TNT fires the correct event and backports the explosion event from modern Bukkit.
|
||||||
|
- **Spawn Location Options:** Provides options to disable spawn location randomization and teleportation to the highest safe block on join.
|
||||||
|
- **Configurable Mob Spawner Area Limit:** Allows server owners to set a mob-cap for mob spawners to prevent mob farms from causing extreme lag.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Want to use Project Poseidon on your server?
|
||||||
|
Please read the following article before changing over to Project Poseidon: https://github.com/RhysB/Project-Poseidon/wiki/Implementing-Project-Poseidon-In-Production
|
||||||
|
|
||||||
|
# Download
|
||||||
|
You can download the latest builds at the [GitHub Releases](https://github.com/retromcorg/Project-Poseidon/releases/).
|
||||||
|
|
||||||
|
Historical builds can be found on the [Glass Launcher Jenkins](https://jenkins.glass-launcher.net/job/Project-Poseidon/).
|
||||||
|
|
||||||
|
Please note, download the artifact (JAR) without original in the name, eg. `project-poseidon-1.1.8.jar`.
|
||||||
|
|
||||||
|
## Maven Repository & Plugin Development
|
||||||
|
|
||||||
|
### Maven Repository
|
||||||
|
Project Poseidon releases are published to the Legacy Minecraft Maven repository:
|
||||||
|
|
||||||
|
- **Repository:** https://repository.johnymuffin.com/
|
||||||
|
- **Browse Poseidon artifacts:**
|
||||||
|
https://repository.johnymuffin.com/#browse/browse:maven-releases:com%2Flegacyminecraft%2Fposeidon%2Fposeidon-craftbukkit
|
||||||
|
|
||||||
|
This repository can be used to depend on Poseidon artifacts directly in your build tooling (e.g. Maven or Gradle) when developing plugins.
|
||||||
|
|
||||||
|
### Plugin Development Examples
|
||||||
|
Examples demonstrating how to develop plugins for Poseidon using **Maven** and **GitHub Actions** can be found here:
|
||||||
|
|
||||||
|
- **Poseidon Plugin Template:**
|
||||||
|
https://github.com/retromcorg/Poseidon-Plugin-Template
|
||||||
|
|
||||||
|
The template includes:
|
||||||
|
- A preconfigured Maven project
|
||||||
|
- GitHub Actions CI configuration
|
||||||
|
- Correct repository and dependency setup for Poseidon plugin development
|
||||||
|
- Example code including player listeners and a config system
|
||||||
|
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
CraftBukkit and Bukkit are licensed under GNU General Public License v3.0<br>
|
||||||
|
Any future commits to this repository will remain under the same GNU General Public License v3.0<br>
|
||||||
|
Libraries in the compiled .jar files distrusted may contain their own licenses.<br>
|
||||||
|
This project contains decompiled code that is copyrighted by Mojang AB typically under the `net.minecraft.server` package.<br>
|
||||||
|
|
||||||
|
## How To Setup - IntelliJ IDEA
|
||||||
|
|
||||||
|
1. Clone this project using Git or a desktop client.
|
||||||
|
2. Open IntelliJ and create a new project in the same directory as the Project Poseidon folder.
|
||||||
|
|
||||||
|
## Compiling
|
||||||
|
|
||||||
|
Compiling is done via maven. To compile a JAR, cd into the Project Poseidon directory and run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
mvn clean package
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now have a runnable JAR inside the /target folder!
|
||||||
|
|
||||||
|
## Regarding the DMCA of CraftBukkit in 2014
|
||||||
|
The contributor Wolverness who first contributed on CraftBukkit in February 2012 issued a DMCA against CraftBukkit and other major forks of CraftBukkit.
|
||||||
|
This project is based on the following commits:
|
||||||
|
|
||||||
|
* CraftBukkit: [54bcd1c1f36691a714234e5ca2f30a20b3ad2816](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/54bcd1c1f36691a714234e5ca2f30a20b3ad2816) (SpigotMC)
|
||||||
|
* Bukkit: [3524fde5ffc387ef9e39f6ee7dae83ff4dbf8229](https://github.com/Bukkit/Bukkit/commit/3524fde5ffc387ef9e39f6ee7dae83ff4dbf8229) (GitHub)
|
||||||
|
|
||||||
|
The Bukkit and CraftBukkit commits that Project Poseidon is based on are before Wolverness started contributing.
|
||||||
|
|
||||||
|
If you were a contributor before these commits please feel free to contact me or open an issue asking for this repository to be taken down.
|
||||||
|
|
||||||
|
## MC-DEV
|
||||||
|
We include files from the mc-dev GitHub repository. This code is automatically generated using minecraft_server.jar and sourced from the Bukkit repositories.
|
||||||
|
* MC-DEV: [1a792ed860ebe2c6d4c40c52f3bc7b9e0789ca23](https://github.com/Bukkit/mc-dev/commit/1a792ed860ebe2c6d4c40c52f3bc7b9e0789ca23)
|
||||||
|
|
||||||
|
If Mojang Studios or someone on their behalf wants to have this repository removed due to including copyrighted Minecraft sources like bukkit/mc-dev, please contact me or make an issue.
|
||||||
|
|
||||||
|
## How to setup ModLoaderMP support (NOT WORKING)
|
||||||
|
Please read the following: https://github.com/RhysB/Project-Poseidon/wiki/Adding-ModLoaderMP
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 345 KiB |
@@ -0,0 +1,253 @@
|
|||||||
|
<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/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.legacyminecraft.poseidon</groupId>
|
||||||
|
<artifactId>poseidon-craftbukkit</artifactId>
|
||||||
|
<version>1.1.12</version>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Project Poseidon</name>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<api.version>unknown</api.version>
|
||||||
|
</properties>
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git://github.com/Bukkit/CraftBukkit.git</connection>
|
||||||
|
<developerConnection>scm:git:ssh://git@github.com/Bukkit/CraftBukkit.git</developerConnection>
|
||||||
|
<url>https://github.com/Bukkit/CraftBukkit</url>
|
||||||
|
</scm>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>bukkit-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
<!-- <repository>-->
|
||||||
|
<!-- <id>chew-jenkins</id>-->
|
||||||
|
<!-- <url>https://jenkins.chew.pw/plugin/repository/everything</url>-->
|
||||||
|
<!-- </repository>-->
|
||||||
|
<repository>
|
||||||
|
<id>jline</id>
|
||||||
|
<name>JLine Project Repository</name>
|
||||||
|
<url>http://jline.sourceforge.net/m2repo</url>
|
||||||
|
</repository>
|
||||||
|
<!-- Repository for resolving release dependencies -->
|
||||||
|
<repository>
|
||||||
|
<id>johnymuffin-nexus-releases</id>
|
||||||
|
<url>https://repository.johnymuffin.com/repository/maven-public/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<!-- Repository for resolving snapshot dependencies -->
|
||||||
|
<repository>
|
||||||
|
<id>johnymuffin-nexus-snapshots</id>
|
||||||
|
<url>https://repository.johnymuffin.com/repository/maven-snapshots/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>johnymuffin-nexus</id>
|
||||||
|
<url>https://repository.johnymuffin.com/repository/maven-releases/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>johnymuffin-nexus</id>
|
||||||
|
<url>https://repository.johnymuffin.com/repository/maven-snapshots/</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.bukkit</groupId>-->
|
||||||
|
<!-- <artifactId>bukkit</artifactId>-->
|
||||||
|
<!-- <version>0.0.1-SNAPSHOT</version>-->
|
||||||
|
<!-- <type>jar</type>-->
|
||||||
|
<!-- <scope>compile</scope>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bukkit</groupId>
|
||||||
|
<artifactId>bukkit</artifactId>
|
||||||
|
<version>0.0.1-POSEIDON</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.jopt-simple</groupId>
|
||||||
|
<artifactId>jopt-simple</artifactId>
|
||||||
|
<version>6.0-alpha-3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jline</groupId>
|
||||||
|
<artifactId>jline</artifactId>
|
||||||
|
<version>0.9.93</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
<version>3.7.2</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>5.1.14</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>modloader</groupId>
|
||||||
|
<artifactId>ModLoaderMP-B1.7.3</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/ModLoaderMP.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.avaje</groupId>
|
||||||
|
<artifactId>ebean</artifactId>
|
||||||
|
<version>2.7.3</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava-collections</artifactId>
|
||||||
|
<version>r03</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>20.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Bukkit Mods -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>32.0.0-jre</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.9.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<!-- This builds a completely 'ready to start' jar with all dependencies inside -->
|
||||||
|
<build>
|
||||||
|
<defaultGoal>clean install</defaultGoal>
|
||||||
|
<!-- <sourceDirectory>src</sourceDirectory>-->
|
||||||
|
<!-- <resources>-->
|
||||||
|
<!-- <resource>-->
|
||||||
|
<!-- <directory>src</directory>-->
|
||||||
|
<!-- <excludes>-->
|
||||||
|
<!-- <exclude>**/*.java</exclude>-->
|
||||||
|
<!-- </excludes>-->
|
||||||
|
<!-- </resource>-->
|
||||||
|
<!-- </resources>-->
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>org.bukkit.craftbukkit.Main</Main-Class>
|
||||||
|
<Implementation-Title>Project-Posiden</Implementation-Title>
|
||||||
|
<Implementation-Vendor>RhysB</Implementation-Vendor>
|
||||||
|
<Specification-Title>Bukkit</Specification-Title>
|
||||||
|
<Specification-Version>${api.version}</Specification-Version>
|
||||||
|
<Specification-Vendor>Bukkit Team</Specification-Vendor>
|
||||||
|
<Sealed>true</Sealed>
|
||||||
|
</manifestEntries>
|
||||||
|
<manifestSections>
|
||||||
|
<manifestSection>
|
||||||
|
<name>net/bukkit/</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Sealed>true</Sealed>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>com/bukkit/</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Sealed>true</Sealed>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
<manifestSection>
|
||||||
|
<name>org/bukkit/</name>
|
||||||
|
<manifestEntries>
|
||||||
|
<Sealed>true</Sealed>
|
||||||
|
</manifestEntries>
|
||||||
|
</manifestSection>
|
||||||
|
</manifestSections>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactSet>
|
||||||
|
<excludes>
|
||||||
|
<exclude>junit:junit</exclude>
|
||||||
|
</excludes>
|
||||||
|
</artifactSet>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Created-By: 1.6.0
|
||||||
|
Specification-Title: Bukkit
|
||||||
|
Main-Class: org.bukkit.craftbukkit.Main
|
||||||
|
Specification-Version: unknown
|
||||||
|
Specification-Vendor: Bukkit Team
|
||||||
|
Implementation-Version: git-Bukkit-0.0.0-980-g4ed23b1-b1060jnks
|
||||||
|
Implementation-Vendor: Bukkit Team
|
||||||
|
Sealed: true
|
||||||
|
Implementation-Title: CraftBukkit
|
||||||
|
|
||||||
|
Name: net/bukkit/
|
||||||
|
Sealed: true
|
||||||
|
|
||||||
|
Name: com/bukkit/
|
||||||
|
Sealed: true
|
||||||
|
|
||||||
|
Name: org/bukkit/
|
||||||
|
Sealed: true
|
||||||
@@ -0,0 +1,446 @@
|
|||||||
|
1000,43ddd8b48469d9a8c011718aa846facb
|
||||||
|
1001,aaed8c669f583cf35300f7c5d5396fce
|
||||||
|
1002,d517ae73160fd8576d7687ead1c1a973
|
||||||
|
1003,ac37df168bae3c69a24d7fd5bae913c7
|
||||||
|
1004,6d2591e94464b8327afadbdba44978d
|
||||||
|
1100,8b1df73e012e2ae34cd2d84a72a7898b
|
||||||
|
2000,c9ee0d494e0524c86a577cf684f5816d
|
||||||
|
2001,cd7a2836ea0b77b23a6131222f5be354
|
||||||
|
2002,381aeedb2c5c5a7a9a01333e0eebc839
|
||||||
|
2003,229048d1bb9e928831734cb2e5000286
|
||||||
|
2004,b2c088c3c6928bfe29684a75ae1b127c
|
||||||
|
2005,1ce3491a1021a5aed07c687e3f6133e6
|
||||||
|
2006,6c3d114caffd8160f7d56fc8757419a
|
||||||
|
2007,bcb501cfac8f7e73b455563bddbcb417
|
||||||
|
2008,e1aa93d7bba48898a32810c43c6ff5c3
|
||||||
|
2010,d0818779df1b967cc2f8ffc3ada631ec
|
||||||
|
2011,ecf0dbe93240e84edf6bd263645e634f
|
||||||
|
2020,b4a67353e11c3039ad755a3e96b4a046
|
||||||
|
2021,1bb21f7731a5b3ffc6a1e2b586dae3f5
|
||||||
|
2022,e58162e284df8fe339f05626eb46d835
|
||||||
|
2023,739948643f5f6f685aea81c42883a480
|
||||||
|
2024,799b0d35362a9574d3226c2d762b53c6
|
||||||
|
2025,5ec18fbb462516a1e1a3427e0595a7d6
|
||||||
|
16908544,12512904b67d2091dd516dc8eeb0cfa0
|
||||||
|
16908545,a5c35cc01a263f91419d3e8e981708f1
|
||||||
|
16908546,f6bdebf227e42c204066cede8cb5928c
|
||||||
|
16908547,9c44e6d3ab80afa2bb52fe3499559d5e
|
||||||
|
16908548,2e1799ddfdab14417c2a8e24d8c0c731
|
||||||
|
16908549,3f4169a181feb5d2532efc6aa91f2ee5
|
||||||
|
16908550,895725d3432cbf374b1cce4f7db28e9
|
||||||
|
16908551,12892864f18d30521b6f4a6c45b65ece
|
||||||
|
16908552,146f6c3458adde8e0bca04d976275f85
|
||||||
|
16908553,7c40dbd9451129b4762f3ab04ce7ffb9
|
||||||
|
16908554,56d763eeb6a0107c2146d7dccd686d2a
|
||||||
|
16908555,9a4fff004ae419711c2a876b57cba69f
|
||||||
|
16908556,170ff67dd90d8d3d8dae393037da5e9b
|
||||||
|
16908557,3e65d657af8611cb3578cd8713419d4c
|
||||||
|
16908558,f3cb95383f698c4e9721b5aaa5fac3a7
|
||||||
|
16908559,65bd006dc163a186f2dbb127f8ec0b27
|
||||||
|
16908560,8c6479d786f9117e04910153a4f47d86
|
||||||
|
16908561,75a25bd69f36250789d914ac01da34c1
|
||||||
|
16908562,87a28b2bf2fad838af72ce00e2fb1937
|
||||||
|
16908563,249ff32d605c5ba0a07694ff4fbbf15a
|
||||||
|
16908564,ba3b355eb9134bcd7522a1fc203c4c58
|
||||||
|
16908565,321e1cb3657d2aca73fb9a8083d9c3bf
|
||||||
|
16908566,adb182051fab2c2269df89b4f75e505e
|
||||||
|
16908567,3d9ae8982f01fb6a6c56cffbe2fa074e
|
||||||
|
16908568,1efffb054b2c864f5ebe180ae46891c3
|
||||||
|
16908569,25c73629d0b6b46690d222cecf331ba2
|
||||||
|
16908570,6a46694c996e5721b14c9da1f00fe62c
|
||||||
|
16908571,5efc1c291eef23fe33f5209388b8cc33
|
||||||
|
16908572,f71fc7deef6835c8efc305a00f1e8b8f
|
||||||
|
16908573,15484a373254c6024d90edf3b7a82947
|
||||||
|
16908574,8253f1aaa2205dcaf828903cfce46e4
|
||||||
|
16908575,ab778410d1fb2c0e55fec0c7d764b17c
|
||||||
|
16908576,19ad61c04ff3ae082955f72fc8771866
|
||||||
|
16908577,b5d3eeff40086643a03f034b5345504d
|
||||||
|
16908578,3d647bf5562e743263cbd90be36b6a1c
|
||||||
|
16908579,5a9d2fb7050009785421257d5ef24416
|
||||||
|
16908580,909b03e2d2eeee2e868b5aaf446e81ea
|
||||||
|
16908581,e603a4cbfdfcbf4d0bfe25efb753b424
|
||||||
|
16908582,e355f481f99220e50e4b2b2eb45dcc56
|
||||||
|
16908583,73a25e59c2d18ae77db02928b0a70e3
|
||||||
|
16908584,8f81a2fb647f817422a299829994de7b
|
||||||
|
16908585,128e9978380ee9ef981d2e12d008255e
|
||||||
|
16908586,fd1453f3e2a3125e7d16cfe6fd2d4722
|
||||||
|
16908587,8e27b6f750bec22333a5d4108ce1e094
|
||||||
|
16908588,b2169f6190bdf95236037bed2301712b
|
||||||
|
16908589,536e6340e5328075ede672428d94d921
|
||||||
|
16908590,cb9eede8b783b4a5d7ff7529e3fb1f44
|
||||||
|
16908591,267d51d891c3c32b3a02577d38f4e242
|
||||||
|
16908592,3f31e8ab260f02acca218c720fafc7b8
|
||||||
|
16908593,552869a63aa3151e79e875596f31e505
|
||||||
|
16908594,c5b0399e7fc64f0561a82063773e1282
|
||||||
|
16908595,cfd61cdbf22133caeca528da9b53474e
|
||||||
|
16908596,8d3802169313f270d5adcda790170ca2
|
||||||
|
16908597,a82c4f31d6d3f5bef9aa3062945c02d6
|
||||||
|
16908598,85eca649072752e9ffafdefa1287470f
|
||||||
|
16908599,98ffd259abbe2e4794c00716a9d2da7
|
||||||
|
16908600,263f8fab89ae0f9d695a74512443070b
|
||||||
|
16908601,b4ae28e8babe7bd09b2a392780565dbe
|
||||||
|
16908602,dfd84b5b35231267a47891cc8c8f48ba
|
||||||
|
16908603,f6990bbd57862a238aaf68b0c2f4c998
|
||||||
|
16908604,9dca837e109ae977a89ed64dd17fab10
|
||||||
|
16908605,ebdb407fd6e4d5c450f73173487c3162
|
||||||
|
16908606,fdf869946d814f4f2aeebe269db06e31
|
||||||
|
16908607,f9ea1fa393862a86e79ffade6a2662e7
|
||||||
|
16908608,60491b4f5956534afd5959e7c2411cda
|
||||||
|
16908609,b78fc6d8b8b8ecb1266eb9c04c5129b
|
||||||
|
16908610,add241f6dcfe6af3f096a45b96fb04e1
|
||||||
|
16908611,38760b28c0d26204b1e0383ca318947a
|
||||||
|
16908612,d3d8076b8b7a911b7cbbf5099f8ffd48
|
||||||
|
16908613,fc78be6fb5735b715325ac499990550e
|
||||||
|
16908614,a7504fcd85d6696a8880f32b97b34a60
|
||||||
|
16908615,f0821b6fdc8ebbf8a6fcb37c75086b1d
|
||||||
|
16908616,88b0e1b842fc88f0cbc5f38e95d68417
|
||||||
|
16908617,d977f8453c349a44baa7e05c3dd81cb8
|
||||||
|
16908618,26184c3c1edfa7623d5620433c0ff36
|
||||||
|
16908619,8edbf7f3996852add4fcb18008cb722f
|
||||||
|
16908620,39e5881696ed1141fb934593dd6bab70
|
||||||
|
16908621,1e0d787240ea16af6edbbdb1ab372fe7
|
||||||
|
16908622,af6ec83a0b072b4abd4194d8d43f7f02
|
||||||
|
16908623,658b5f77ff892a455a7fce5dc93268ac
|
||||||
|
16908624,6474336f089d541c9cec4a1df0c3b6cf
|
||||||
|
16908625,72cfc6fe503df207d53119aa7d5b84b4
|
||||||
|
16908626,3070c2283ca5fd0fe00f7880a4bcdf18
|
||||||
|
16908627,340cef5b043dceb7073ede0be69d700d
|
||||||
|
16908628,24dda1839a72d6707ed1932f6f32bd8e
|
||||||
|
16908629,1c50c7d94cec18710417d513708094d1
|
||||||
|
16908630,2b1f11fed636bf7892650b9adc9b8e94
|
||||||
|
16908631,afd9ba61c39fa742a840fe6ab2cfb490
|
||||||
|
16908632,b709157ffabe225e820218b020508173
|
||||||
|
16908633,3e9f7b867952f7b2df48e156402d558
|
||||||
|
16908634,ab9f22a1fbc265d19a4dd7f84f3a4585
|
||||||
|
16908635,c89cf9510108d63d7d181b3f7c546094
|
||||||
|
16908636,c7af3251ce44f2dafb2c192d817e9c52
|
||||||
|
16908637,796f607d214012447b7c552673f95b4a
|
||||||
|
16908638,ea796bd83dd7689d322085c74d0957a7
|
||||||
|
16908639,ce2f6f842d68418baad5fc2ecefcb879
|
||||||
|
16908640,6b3016429a5f814f3cccaff484a46831
|
||||||
|
16908641,7dea9bdb69c9c5965609eab99af9f9d9
|
||||||
|
16908642,3add5c50b3427182fcb7dd04fe953945
|
||||||
|
16908643,4175965cd5cee134d43038ac54858b0f
|
||||||
|
16908644,feae27a32b6cc95860ec46da6d37c4b0
|
||||||
|
16908645,5898813ee0b2785afc9dad2524f56162
|
||||||
|
16910544,adb04e128238341b88a18532f3448d13
|
||||||
|
16910545,8e274d3a14b5cb87cbce019d0a3b9a23
|
||||||
|
16974080,cfed396d9f54d3c04bc390a004916c52
|
||||||
|
16974081,64f1b3409c0937114f77f9933a4e2b82
|
||||||
|
16974082,5a6e9dc254405a6cb066472172fa09b1
|
||||||
|
16974083,b23adf8b24d9a42637977c3322f02b75
|
||||||
|
16974091,df1b76bca1e6a035d3e22e7c01f67bc6
|
||||||
|
16974092,4bb3d702d36739ba62041c0c936cbfb6
|
||||||
|
16974093,d02062bdb07f81100381ef87e6fc2922
|
||||||
|
16974094,1a0d208f9f489b37b800c6eeaaa752c9
|
||||||
|
16974095,34ee6807c2040168606740d0e3f46e30
|
||||||
|
16974096,9b8bb8517841df03f1a894b238251068
|
||||||
|
16974097,bb0b43349ffa6aa13b5d84ca70d25eb3
|
||||||
|
16974098,b3b647da85fe51c6da997e28b66cb4c3
|
||||||
|
16974099,d33c3d7d3fbc6880e0e03ce573644b1e
|
||||||
|
16974100,17d45fba9866349c133608e9d42e4ac9
|
||||||
|
16974101,74205e9529729bd0ef51c3d544c1e372
|
||||||
|
16974102,edf620106dc10c10a3357436a306400d
|
||||||
|
16974103,74b3a17953dca5a0cb9bb8c47b241eca
|
||||||
|
16974107,1938aff98985ef5e79c7003868c1e91
|
||||||
|
16974108,14b782f5d9afda571ce6c8bad868e2bd
|
||||||
|
16974109,cb124718b4ecfb29a900e1e617c79544
|
||||||
|
16974110,ae3c73a1546a058da74d4b8a588b59f2
|
||||||
|
16974114,cbdefe9bd14088ad45141843474d2bb0
|
||||||
|
16974115,641938697f84f6e7b59ebc08edc4648b
|
||||||
|
16974116,74ccb1de521aa54c65ffcb906ffd1d3b
|
||||||
|
16974117,fffed44e7bb844ad6c69f7eb4540cff3
|
||||||
|
16974118,536b2d3a4009eed61300bf5f0af7419e
|
||||||
|
16974122,8a8ea889723fc0f8de50c53339819871
|
||||||
|
16974123,768b65f8e24b1e042b75cf6f576cfcd1
|
||||||
|
16974124,a4b5522486920acfc2ed97e105c7831
|
||||||
|
16974125,6e9b513f3c219f4276556070b36a0339
|
||||||
|
16974126,942450301cd8068c9a14352c1cecc2d0
|
||||||
|
16974127,c98e2b8eb252d75a2a1f90144596ada4
|
||||||
|
16974128,7b13a95332dac62ad73cddf33d3bba0f
|
||||||
|
16974129,1951adc5a346867490626a854788b9ad
|
||||||
|
16974130,b75636944eeba77a4ce3f254460e0d49
|
||||||
|
16974131,bb5bc2285c0a2e24548533f59af76788
|
||||||
|
16974132,929561410b14786db52aa89b675a9759
|
||||||
|
16974133,6b07bd2605f311d8134a8170ba49fd73
|
||||||
|
16974134,2f97923d891e3e8c1967d53f7734ff55
|
||||||
|
16974135,dea0b11c8760d28eafbe76e25df7d301
|
||||||
|
16974136,586e309c00ba6f3c2ada595b742bef23
|
||||||
|
16974137,29e48d74dc5062eb900d376196fd4f23
|
||||||
|
16974138,fa79e8b641b225166b17ea86a9ecb174
|
||||||
|
16974139,7a66328b6b976337ff5bde5c7edccaa5
|
||||||
|
16974140,95559b402657cf222a87248d1e6ce0f5
|
||||||
|
16974141,52843420526ced65d57513afad342515
|
||||||
|
16974170,56690bacbebf8107b83e80528f40740
|
||||||
|
16908289,83cfae9a11032a88e08c95b7fcef84cc
|
||||||
|
16908291,39a4ea3b5ddf7f89b41faf675f7bfc0f
|
||||||
|
16908292,64ec21dc8495fb180cc94f59f873efb8
|
||||||
|
16908293,fda16e9858404b9545649ba21a828a6a
|
||||||
|
16908294,a57157213ffc25d269ea46e45984eae0
|
||||||
|
16908295,90f2ac6ac3005ad4cabcd248831f2205
|
||||||
|
16908296,4adafcbbef5ace168ca03e173af10452
|
||||||
|
16908298,bb2e0425d8b489fc856cab2c0828f2ff
|
||||||
|
16908300,76b80613789c553593097956002a392b
|
||||||
|
16908301,23bd5cc4fb97d25e432604be0958320d
|
||||||
|
16908302,7b129f5775b2d4997681338012130cad
|
||||||
|
16908303,4935425ac3ef59e71bca7c4c8bf7e2ea
|
||||||
|
16908304,564d5c2df622b99692929bedbcd7f4b1
|
||||||
|
16908305,e06bb538b6b224ce1376b47804ee2bbb
|
||||||
|
16908306,f13b4a0fa66e65ed33dcbd7ead08ac46
|
||||||
|
16908307,29710a54739e35ae0d34919fca091640
|
||||||
|
16908308,8693b46ac89dd595f8e3efd4437e6e90
|
||||||
|
16908309,3ebf10825c7d8f2e17deae70b37d1fbd
|
||||||
|
16908310,354d414b2a1f29494a80b3acedb72ae2
|
||||||
|
16908311,de662954670ec00899809b916abe6c60
|
||||||
|
16908312,831dd7a79cd7e5f3cad86690c6724902
|
||||||
|
16908313,265f19645487a858e4f53b9706cdff03
|
||||||
|
16908314,2ad06f9f7e24f920fb067e2f2cc7869c
|
||||||
|
16908315,99f3286cc36b9a4393b3e967878b01d4
|
||||||
|
16908316,4fbc91a39f7f4814f8f79ba425e4f30a
|
||||||
|
16908318,ccb82be2278587dd637ac763a1087c7
|
||||||
|
16908323,8e8a2f6a87c3701e76650680e7b2f6e6
|
||||||
|
16908325,fcd992a9a44518d5de6bd09c409ea7de
|
||||||
|
16908326,e41e706456c10963824e032484992946
|
||||||
|
16908327,662301d3344073cc69887a27a8c42f24
|
||||||
|
16908329,313738e052612f868d55f47940080288
|
||||||
|
16908330,79474b10f860f09be4e9183ad5f1c7b4
|
||||||
|
16908332,60a3062d151151a2ff229a02d3221337
|
||||||
|
16908333,833c8c420ce04aa18b9912ff05e5ced2
|
||||||
|
16908334,6e0f4183ad7abbb63c5b6a1ead24214a
|
||||||
|
16908335,477292deea02d72acc1087b2425c570a
|
||||||
|
16908336,82cf44076f1a94ed31f3172433a80ef6
|
||||||
|
16908337,84f64a9f8523d35a1cf8319f580dd578
|
||||||
|
16908338,b6365376050089a025a1ed1d85a85dba
|
||||||
|
16908339,4e989db8b445f22b61bd4d30daee1a05
|
||||||
|
16908340,50ec890e85029d44ea96bfa31d8ed16a
|
||||||
|
16908341,b4f23438454d39a742546dafd5d3cfc6
|
||||||
|
16908342,5414035b686e0fb0a1ce0d535d0a0f82
|
||||||
|
16908343,72d6218e86d3787422fa6b03f30ccaf3
|
||||||
|
16908344,ddfe42c53aae03dd94c2d3163869ddc0
|
||||||
|
16908345,b8b09ac7af1bb81e28715a3e0f0eeb17
|
||||||
|
16908346,c53d28ac584d8053ec438f692a58cd1a
|
||||||
|
16908347,243cf7fb2bf36e60e3a25cde83b33a5e
|
||||||
|
16908349,2837ae3dabc00c4c5515bafa34a302dc
|
||||||
|
16908351,4973e12438ce4c870f6ba1c158873c43
|
||||||
|
16908352,37678301896aa95cc358bcd73308232c
|
||||||
|
16908353,31c5e38768bda9a8a7cd1bbca7c9226d
|
||||||
|
16908354,5ff1e27f9ef25fcf0a3c51b0551f7fd2
|
||||||
|
16908355,60a060ee3e51167f4d87cf6d923f9ca7
|
||||||
|
16908356,b24aa4a609b3483b795c4f3bf89116b7
|
||||||
|
16908357,7a17a96ff758cd4ff8c0ffd070230cc7
|
||||||
|
16908358,c14586711c04239a174c192d24b8ce20
|
||||||
|
16908359,1f0abe2925128be5191932a1cc4a3019
|
||||||
|
16908360,a9c8343cf444aa7686d9dd2b40e90a47
|
||||||
|
16908361,94a02b3ef18bb35970105bf276001fe0
|
||||||
|
16908363,bfa45b4169d1944debabc84b04880837
|
||||||
|
16908365,a3d0bb31ba7c30209129e4366e072b05
|
||||||
|
16908366,de6d35451526c85c7c5907a0adcbeff7
|
||||||
|
16908367,4a0d45a9aedaa06eb574f88f580c265b
|
||||||
|
16908368,56ab2510d3cb4787bdcfa9680aa7e757
|
||||||
|
16908369,feef935305ae32e1972d3b017a4eb
|
||||||
|
16908370,41b270e7ecb39d0b81d1b60f32c3943
|
||||||
|
16908371,b159339fc55e60000efee4c55d0e1d1c
|
||||||
|
16908372,74ca5387c7d373fc88e65e0623d5991f
|
||||||
|
16908373,8b8ae20ea681d47cd899f74f75bde08d
|
||||||
|
16908374,5cb926f4743f6ccdb4988c8b35dc97dd
|
||||||
|
16908375,947a02e037fe9d31c8eb4c4a22dba58c
|
||||||
|
16908376,2c2a7e8a269a770cc4afbe695e662601
|
||||||
|
16908377,9a992e19651652de8b4f5ce07d1d2af0
|
||||||
|
16908378,3e37efadc720d972ddc30ccae606ab00
|
||||||
|
16908380,77b1802a2504a685bf8ff34a1f9de6c3
|
||||||
|
16908381,45c0dbda39dca97dc634a6e89f037716
|
||||||
|
16908383,ca404ded18b83fd872a5810c8a44517d
|
||||||
|
16843027,ecc0eb0ba51e2c14aaa006e168eacc8c
|
||||||
|
16842753,f6282e18f6f87e4cf68970579aac7219
|
||||||
|
16843026,6f3d105b3e6d1624af4ce68b2a55362d
|
||||||
|
16843025,aa1c8e137823bf5245f0d27c980796e7
|
||||||
|
16843024,ed65803a11251872c6cf659381d0aaaa
|
||||||
|
16843031,fa2f9de197813d8e32d78bd184603161
|
||||||
|
16842757,1a13db89ae6fdbb152856edbe3688d95
|
||||||
|
16843030,46bd8fadf2f12988d808e69dcfc138cb
|
||||||
|
16843029,bf398d8ec9fef1d04c67fbf474fda790
|
||||||
|
16843028,69ee29bc3bd715b3203d888ca2a88cc0
|
||||||
|
16843035,2f79ed9030fe0339dec2eb43f56fa369
|
||||||
|
16843034,e2f097a36cdf87a1b211d27eb31dea32
|
||||||
|
16843033,c02e9379a6624b40fef669494a7e7183
|
||||||
|
16843032,af44f7fe9a4366c67479a44b24ae80b
|
||||||
|
16843038,501ead1cb03222808aa09b376c9d5cac
|
||||||
|
16843037,a2d01853631a9b52006ad32497ddc865
|
||||||
|
16843036,6e381ac09bfc75ef7f71e02f3b99f279
|
||||||
|
16843010,bcfe734d49949142a5073766188213dc
|
||||||
|
16843011,88ea7e11c57b09139afe92169c443e20
|
||||||
|
16843008,91f14375672f1b2003202ec7682771cb
|
||||||
|
16843009,f5007e4886946d1eb603979a35726d69
|
||||||
|
16843014,b0bde3daab8a1cc6354cd86c65db90e2
|
||||||
|
16842772,b59c880de07e668eaba0888fc4de229a
|
||||||
|
16843015,7184233667abf34d2ee3eea20fb9f82b
|
||||||
|
16842775,bcc06ff4c56de9b4a1557d3c47ec1783
|
||||||
|
16842774,6f2eab110a33c15cb17238708244db4d
|
||||||
|
16843013,3fe45d065187550d481cc745780c29c2
|
||||||
|
16843018,7bddb0161d99059f0a6c1c09d0b35b34
|
||||||
|
16842777,fdc779803765398f0c782a1fd55a9d86
|
||||||
|
16842776,6b6c09ee89a933288c37f55d2187eddd
|
||||||
|
16843019,87545673867c5cf2f97ea6cc3e0d3595
|
||||||
|
16843016,e2288c9f60d09d5f2882175abf161bd
|
||||||
|
16842779,9667a31366f5dcf740d64b775402c64
|
||||||
|
16843017,e3108d8ee8530e50d7b425de217a4585
|
||||||
|
16843022,847f1b6f38ebf442a1d34cac0fd6080e
|
||||||
|
16843023,5d01d19f8441e4d5dd5c41266f480ffc
|
||||||
|
16842780,b02509b360e6f14eac4fb03f55c11fed
|
||||||
|
16843020,90e2ab194dab9f482eca64c651ea41e9
|
||||||
|
16843021,58d3e73bd29c14b6ec97d4187cee5500
|
||||||
|
16843057,bf533b7d78ccc350cfd2f41a8e1f0822
|
||||||
|
16842787,e49146643faf3308ca7246d82fc5b2bb
|
||||||
|
16843056,d8e023c15aa80df2445c782c6b2179da
|
||||||
|
16843059,c649596d99d96be696332cb08b4a33f2
|
||||||
|
16843058,d129fce211dfb56e80195a11f39ab1e9
|
||||||
|
16843061,441d86175b74884ef3f672066ae52c90
|
||||||
|
16843060,cf6d7dfef99b200a4551cd65467fb9fc
|
||||||
|
16843063,f50f8b7fafde6d640ced3ec4d797f807
|
||||||
|
16843062,d22de0ebc290280b2699b5cb77568fcb
|
||||||
|
16842794,d347d92a886b9d445d7d60b090a5bcda
|
||||||
|
16843065,a393477443f20a1a8a511c390024f963
|
||||||
|
16843064,e6f28eea0ebbad0d18d23ea3c15f2102
|
||||||
|
16843067,d6efe6a63f529d675417c2092546e144
|
||||||
|
16842793,d5ac3bcc56cbc370ae3b172dd6ed5df4
|
||||||
|
16843066,935aa84de286e8bced6a127b69347997
|
||||||
|
16842798,377a21bcb39dcfcb4a0902a7555a984f
|
||||||
|
16843069,63cc6da6165cc068740827890b4460ed
|
||||||
|
16843068,6dda3129884399b67b935bb4e51ad34f
|
||||||
|
16842799,d4831a785c1c65ad2054bb1232babf0c
|
||||||
|
16842796,48be99a37d3a885d38657a50d6f77365
|
||||||
|
16842797,8da03c2f611c7f0654aa71096832b5c
|
||||||
|
16842802,9b2a96570a99f6677e299d8215b1eecd
|
||||||
|
16843042,322d7c02f205806126f1529564ab3cd0
|
||||||
|
16843043,660acf0ca76261ec49deb7a7bd072f8c
|
||||||
|
16843044,d8dd28acc9e4431ff8eb481c1d8d9832
|
||||||
|
16842806,919bc6715eddf74c0517372ead95cdcb
|
||||||
|
16843045,72ae59db2ef5c472f671b31f1c6f07ce
|
||||||
|
16842805,9e359ce06b5603c820bd749592beb4a7
|
||||||
|
16843046,cee09c2303e44dfbbaadbf167cdc503c
|
||||||
|
16842810,8ecd9ec7607c958cdf2e252f516fe3d8
|
||||||
|
16843049,47171b2af8bb14c3816f52f79579b46d
|
||||||
|
16842809,fef5bbbc588422579bf3de8a49c73e18
|
||||||
|
16843050,6b29998dbe690122afdf6da71e905009
|
||||||
|
16843051,5f9f017aa89719c7a282aa222c65baf
|
||||||
|
16843052,216a61701714cb3f04e23a74a1336864
|
||||||
|
16843053,e146704e3fe30e6821352ceb3b090184
|
||||||
|
16842813,899942760d5a83d94cf58a536be6171e
|
||||||
|
16843054,5aa0a467c7451f88f9c6056e8c7427cc
|
||||||
|
16843055,6881fc74a0574433e9e0f05f7cae53f7
|
||||||
|
16843095,50f6c2ffdc69bea12cd7b58c69824be1
|
||||||
|
16842821,42b4814e4e61191b61a8d3f7c6041938
|
||||||
|
16843094,356c3f0d5b88d0e2077d85168eac6306
|
||||||
|
16842822,d69011621d777519c5ab6a68da8959
|
||||||
|
16843092,d84a39f3d30a72b13640e3afb7ea2018
|
||||||
|
16843091,37603e187bd7ad9dceccb8ef2b6b5335
|
||||||
|
16842817,bad6f1072232c28353aabf42142cbd26
|
||||||
|
16842818,bd0c4079c99e529e55abef5ac44dcdf8
|
||||||
|
16843088,5e5d08b1780bfd69747216c24b7aee92
|
||||||
|
16842819,ae608e1ca5ca083163d92974d7c66b06
|
||||||
|
16843103,d4d1b946336039e515c3e4a392694223
|
||||||
|
16842828,6a15bcf38bcf78021f9416ac395cac85
|
||||||
|
16843102,603020acbbdc6e8765c2e2cd589f7933
|
||||||
|
16842829,41cce73f9ce59993afa3517becd4bd3c
|
||||||
|
16842824,2368ffe803beb1d06772e96eeffd9cc9
|
||||||
|
16843099,c373e78822d440c926edf7f1b700d4c5
|
||||||
|
16843098,503a4fb49cbfebe1fb71ef185c8ced56
|
||||||
|
16843097,4e72dc4d35b34147ce69d691aa2937e3
|
||||||
|
16842837,4c903ddf3b9cd49a952a3889fc2c5573
|
||||||
|
16842836,a304f875b846d65498366479fbf34568
|
||||||
|
16843076,1b11a34d5c6cee280c727938ee96054b
|
||||||
|
16843077,ff170af78a0a674445f16e24394546c0
|
||||||
|
16843074,ba8bd10757ab9a4446f024952bf3f1e3
|
||||||
|
16843075,b34ec8f0f5f92acf230925c89eacec65
|
||||||
|
16842832,3b10180dc99ab99568b51010d89c655c
|
||||||
|
16843072,d752bd5dd907feec915d036d76707ee5
|
||||||
|
16843073,168e43895b105169862fa2e3c205529b
|
||||||
|
16842834,58efc828918aa006d5af09e32fe7799b
|
||||||
|
16843085,b30c099494e63d26f755d58ba109136a
|
||||||
|
16842841,2c471142bddf9a982a48e0ecb52cbb8
|
||||||
|
16843082,5574b9699d71e02f3efb48f3712da8bf
|
||||||
|
16843080,4945e39d1260ff273c49d39dfc58c2a8
|
||||||
|
16842843,bfc9dce4c1ccef959c57360fb9f70205
|
||||||
|
16843108,4e225dd49c0231b617a15ded1ba6cb0a
|
||||||
|
16843109,35715377a038019c56925b2e661cfdab
|
||||||
|
16843105,3b91182484dc677a0bf27263e612d818
|
||||||
|
16843106,affab7221afa03df4b7306b9ce50be7f
|
||||||
|
16843107,e3710bc197d17e0dc78ae3f607c46048
|
||||||
|
16777217,9012132a1d0f770eca67e62a68247137
|
||||||
|
16777219,58fc65723143afeb33f742c17e028c94
|
||||||
|
16777220,1d5e2088f7137e304366873dd829ca98
|
||||||
|
16777221,66a18fa3f554756edc12bf1a08586bc8
|
||||||
|
16777222,4007295f7bdae0b78a6e47a9d64521
|
||||||
|
16777228,c154160ce7b52d4bdc220fc954edf796
|
||||||
|
16777229,2400808c6f442f2663b6869e4930c879
|
||||||
|
16777230,7ae3b31e8e0f2f22f50fbf224e1fe4f7
|
||||||
|
16777231,fe5698e183b10037e38f979a411489b8
|
||||||
|
16777232,aeae00c7b4a95ff05423c1629bf3ad7e
|
||||||
|
16777233,72153ea3d60930cebf4c0d37fac89102
|
||||||
|
16777235,f517ab768fbb35e275440b74b6631bfc
|
||||||
|
16777236,623df9298630687873579ea16bb97e7b
|
||||||
|
16777237,6984cb9e6a322728be736860b97b971a
|
||||||
|
16777238,6947378f4e2abb24b47e2b943945b16f
|
||||||
|
16777239,55a585682bf0569a60a71a66f031ca2
|
||||||
|
16777240,f653295b0c48244dc2aa68fc5b94fa29
|
||||||
|
16777241,c213fb7ee968403b24ff6ede98686add
|
||||||
|
16777243,afd641da6f3834b319b761ba6d72ff74
|
||||||
|
16777244,8d822c710a221b8a407b2def97885470
|
||||||
|
16777246,9c99187cc6fd9c958417b4736772e4d3
|
||||||
|
16777251,6418210d69669c4a602148ed42ab2ecd
|
||||||
|
16777253,afe51ea56dc8c831f9b0b5ae02bac702
|
||||||
|
16777254,95812c1d4021558b6a7f62521228c52a
|
||||||
|
16777255,3a1252acb6fe968751d2b61d57557e09
|
||||||
|
16777257,fd7caeeb5d16756028f19ba016ed1970
|
||||||
|
16777258,6339b8043c05d19c6b15135eade95f94
|
||||||
|
16777260,aa1ed939a8b275df9dc5474bc0477a33
|
||||||
|
16777261,b631dcf219d3add3560f243ff6cceb75
|
||||||
|
16777262,91eca0c33ac53fb155feb15db48c43de
|
||||||
|
16777263,b681c19d7812c281b4b2feabb88697f4
|
||||||
|
16777264,a2b07ae4f37a65fe1f5992826b578b02
|
||||||
|
16777265,af5255a4dcb486e2ab11669fd3de8441
|
||||||
|
16777266,8a4b2b706f219e52a261e342b47a3964
|
||||||
|
16777269,921cb54cfb47ca9eca0edcf8e660e3cd
|
||||||
|
16777270,b79b3a522d1e2f865eb1e9aeb63dc66a
|
||||||
|
16777272,36e1c1dd8cbb267488e1669811319e7e
|
||||||
|
16777273,c84a7d710228024c2e100a79a2c30e55
|
||||||
|
16777274,a1674e3020689bae5680f29f937e5424
|
||||||
|
16777277,46b34dd723f7efeb38f670925ee3824f
|
||||||
|
16777281,da71e3e4f9a25c6621d2f0b40ffd1c72
|
||||||
|
16777282,388109bb9b9b49c1f5bb604abee91671
|
||||||
|
16777283,eb6912fd84b2d57ed3433acb3f85d3e6
|
||||||
|
16777285,619967351702f1d570d4d0195bbbcc1e
|
||||||
|
16777286,ebff74d54387fb154d5b467e01d92b64
|
||||||
|
16777288,f8154dd7c9c1d397dd64eeb6569d7d34
|
||||||
|
16777289,971cc6f827398c6c4755b310c6795672
|
||||||
|
16777291,bb952ff9523f248ddaae56317e91a509
|
||||||
|
16777293,e5c24577cf35a31bd217d206b88a7499
|
||||||
|
16777294,f4c170867c75982e604358da611b26e3
|
||||||
|
16777295,922200512d058ecc0ef19a0efcdb51bf
|
||||||
|
16777296,39283c3dbafb10b2a732f9d6ef3e08b6
|
||||||
|
16777297,3603ae881c41c957a89aaa30990c0040
|
||||||
|
16777298,fbf9e47600457d091060b0f877458a83
|
||||||
|
16777300,2b0d53bafa91c68bf59b5863354bd7ae
|
||||||
|
16777301,50b99fabae858e971eb02ed5146fd63a
|
||||||
|
16777302,7a32eac396b4cf3930ba9ca7b5d8dbae
|
||||||
|
16777303,115f1e956219026bb9cca0bcafb2b11b
|
||||||
|
16777304,afb2f032a96d859ca5f24d8ff129bd64
|
||||||
|
16777305,372b3a0fd7c09f64f3cfcab89f03a9a0
|
||||||
|
16777306,e4b6233ac91337dcc3940e309d21c3c
|
||||||
|
16777311,d290638555ce76ce3053c70fdacf7d55
|
||||||
|
5242880,8099ff561e194072c9086dea38757a89
|
||||||
|
5242881,90b3d9a90a8cf3e21527fc8fe3b43c49
|
||||||
|
5242882,c9806dd45be8ebed3e4ab94f66e65212
|
||||||
|
5242883,f382ded5f9a4299e3879dea4f7fe1c50
|
||||||
|
5242884,27af08a994f76a2a08ec8671d14fdcc2
|
||||||
|
5242885,9969ce4355ae7338470461f48f4e5ef5
|
||||||
|
5242886,39208e0b0f070629cad494da5fb95f0d
|
||||||
|
5242887,678e63329d3d813f22e0f15006a93768
|
||||||
|
5242888,694ffe9efa49193780d4b757115c9064
|
||||||
|
5242889,9080a51ccefd23f9924bae9a854e7b49
|
||||||
|
5242890,5f1d51ccd1b4adf141707907233f8379
|
||||||
|
5242891,73df45f45e0b7484ef51441ad0e50604
|
||||||
|
5242892,c9e52234c475354483dc3e9e6386af61
|
||||||
|
5242893,3c3ee1df989ecf5de70a5673acfa33b8
|
||||||
|
5242894,468cc8b546e1586406b78ad733976f5f
|
||||||
|
5242895,e546a7afaaa6c6729e3b062fc4ace4ae
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# This file NEEDS to be in UTF-8 format!
|
||||||
|
!"#$%&'()*+,-./
|
||||||
|
0123456789:;<=>?
|
||||||
|
@ABCDEFGHIJKLMNO
|
||||||
|
PQRSTUVWXYZ[\]^_
|
||||||
|
'abcdefghijklmno
|
||||||
|
pqrstuvwxyz{|}~⌂
|
||||||
|
ÇüéâäàåçêëèïîìÄÅ
|
||||||
|
ÉæÆôöòûùÿÖÜø£Ø×ƒ
|
||||||
|
áíóúñѪº¿®¬½¼¡«»
|
||||||
@@ -0,0 +1,579 @@
|
|||||||
|
|
||||||
|
gui.done=Done
|
||||||
|
gui.cancel=Cancel
|
||||||
|
gui.toMenu=Back to title screen
|
||||||
|
gui.up=Up
|
||||||
|
gui.down=Down
|
||||||
|
gui.yes=Yes
|
||||||
|
gui.no=No
|
||||||
|
|
||||||
|
menu.singleplayer=Singleplayer
|
||||||
|
menu.multiplayer=Multiplayer
|
||||||
|
menu.mods=Mods and Texture Packs
|
||||||
|
menu.options=Options...
|
||||||
|
menu.quit=Quit Game
|
||||||
|
|
||||||
|
selectWorld.title=Select World
|
||||||
|
selectWorld.empty=empty
|
||||||
|
selectWorld.world=World
|
||||||
|
selectWorld.select=Play Selected World
|
||||||
|
selectWorld.create=Create New World
|
||||||
|
selectWorld.createDemo=Play New Demo World
|
||||||
|
selectWorld.delete=Delete
|
||||||
|
selectWorld.rename=Rename
|
||||||
|
selectWorld.deleteQuestion=Are you sure you want to delete this world?
|
||||||
|
selectWorld.deleteWarning=will be lost forever! (A long time!)
|
||||||
|
selectWorld.deleteButton=Delete
|
||||||
|
selectWorld.renameButton=Rename
|
||||||
|
selectWorld.renameTitle=Rename World
|
||||||
|
selectWorld.conversion=Must be converted!
|
||||||
|
selectWorld.newWorld=New World
|
||||||
|
selectWorld.enterName=World Name
|
||||||
|
selectWorld.resultFolder=Will be saved in:
|
||||||
|
selectWorld.enterSeed=Seed for the World Generator
|
||||||
|
selectWorld.seedInfo=Leave blank for a random seed
|
||||||
|
|
||||||
|
multiplayer.title=Play Multiplayer
|
||||||
|
multiplayer.connect=Connect
|
||||||
|
multiplayer.info1=Minecraft Multiplayer is currently not finished, but there
|
||||||
|
multiplayer.info2=is some buggy early testing going on.
|
||||||
|
multiplayer.ipinfo=Enter the IP of a server to connect to it:
|
||||||
|
|
||||||
|
multiplayer.downloadingTerrain=Downloading terrain
|
||||||
|
|
||||||
|
multiplayer.stopSleeping=Leave Bed
|
||||||
|
|
||||||
|
demo.day.1=This demo will last five game days, do your best!
|
||||||
|
demo.day.2=Day Two
|
||||||
|
demo.day.3=Day Three
|
||||||
|
demo.day.4=Day Four
|
||||||
|
demo.day.5=This is your last day!
|
||||||
|
demo.day.warning=Your time is almost up!
|
||||||
|
demo.day.6=You have passed your fifth day, use F2 to save a screenshot of your creation
|
||||||
|
demo.reminder=The demo time has expired, buy the game to continue or start a new world!
|
||||||
|
demo.help.movement=Use %1$s, %2$s, %3$s, %4$s and the mouse to move around
|
||||||
|
demo.help.jump=Jump by pressing %1$s
|
||||||
|
demo.help.inventory=Use %1$s to open your inventory
|
||||||
|
|
||||||
|
connect.connecting=Connecting to the server...
|
||||||
|
connect.authorizing=Logging in...
|
||||||
|
connect.failed=Failed to connect to the server
|
||||||
|
|
||||||
|
disconnect.genericReason=%s
|
||||||
|
disconnect.disconnected=Disconnected by Server
|
||||||
|
disconnect.lost=Connection Lost
|
||||||
|
disconnect.kicked=Was kicked from the game
|
||||||
|
disconnect.timeout=Timed out
|
||||||
|
disconnect.closed=Connection closed
|
||||||
|
disconnect.loginFailed=Failed to login
|
||||||
|
disconnect.loginFailedInfo=Failed to login: %s
|
||||||
|
disconnect.quitting=Quitting
|
||||||
|
disconnect.endOfStream=End of stream
|
||||||
|
disconnect.overflow=Buffer overflow
|
||||||
|
|
||||||
|
options.off=OFF
|
||||||
|
options.on=ON
|
||||||
|
options.title=Options
|
||||||
|
options.controls=Controls...
|
||||||
|
options.video=Video Settings...
|
||||||
|
options.videoTitle=Video Settings
|
||||||
|
options.music=Music
|
||||||
|
options.sound=Sound
|
||||||
|
options.invertMouse=Invert Mouse
|
||||||
|
options.sensitivity=Sensitivity
|
||||||
|
options.sensitivity.min=*yawn*
|
||||||
|
options.sensitivity.max=HYPERSPEED!!!
|
||||||
|
options.renderDistance=Render Distance
|
||||||
|
options.renderDistance.tiny=Tiny
|
||||||
|
options.renderDistance.short=Short
|
||||||
|
options.renderDistance.normal=Normal
|
||||||
|
options.renderDistance.far=Far
|
||||||
|
options.viewBobbing=View Bobbing
|
||||||
|
options.ao=Smooth Lighting
|
||||||
|
options.anaglyph=3D Anaglyph
|
||||||
|
options.framerateLimit=Performance
|
||||||
|
options.difficulty=Difficulty
|
||||||
|
options.difficulty.peaceful=Peaceful
|
||||||
|
options.difficulty.easy=Easy
|
||||||
|
options.difficulty.normal=Normal
|
||||||
|
options.difficulty.hard=Hard
|
||||||
|
options.graphics=Graphics
|
||||||
|
options.graphics.fancy=Fancy
|
||||||
|
options.graphics.fast=Fast
|
||||||
|
options.guiScale=GUI Scale
|
||||||
|
options.guiScale.auto=Auto
|
||||||
|
options.guiScale.small=Small
|
||||||
|
options.guiScale.normal=Normal
|
||||||
|
options.guiScale.large=Large
|
||||||
|
options.advancedOpengl=Advanced OpenGL
|
||||||
|
|
||||||
|
performance.max=Max FPS
|
||||||
|
performance.balanced=Balanced
|
||||||
|
performance.powersaver=Power saver
|
||||||
|
|
||||||
|
controls.title=Controls
|
||||||
|
|
||||||
|
key.forward=Forward
|
||||||
|
key.left=Left
|
||||||
|
key.back=Back
|
||||||
|
key.right=Right
|
||||||
|
key.jump=Jump
|
||||||
|
key.inventory=Inventory
|
||||||
|
key.drop=Drop
|
||||||
|
key.chat=Chat
|
||||||
|
key.fog=Toggle Fog
|
||||||
|
key.sneak=Sneak
|
||||||
|
key.playerlist=List players
|
||||||
|
|
||||||
|
texturePack.openFolder=Open texture pack folder
|
||||||
|
texturePack.title=Select Texture Pack
|
||||||
|
texturePack.folderInfo=(Place texture pack files here)
|
||||||
|
|
||||||
|
tile.stone.name=Stone
|
||||||
|
tile.stone.desc=
|
||||||
|
tile.grass.name=Grass
|
||||||
|
tile.grass.desc=
|
||||||
|
tile.dirt.name=Dirt
|
||||||
|
tile.dirt.desc=
|
||||||
|
tile.stonebrick.name=Cobblestone
|
||||||
|
tile.stonebrick.desc=
|
||||||
|
tile.wood.name=Wooden Planks
|
||||||
|
tile.wood.desc=
|
||||||
|
tile.sapling.name=Sapling
|
||||||
|
tile.sapling.desc=
|
||||||
|
tile.bedrock.name=Bedrock
|
||||||
|
tile.bedrock.desc=
|
||||||
|
tile.water.name=Water
|
||||||
|
tile.water.desc=
|
||||||
|
tile.lava.name=Lava
|
||||||
|
tile.lava.desc=
|
||||||
|
tile.sand.name=Sand
|
||||||
|
tile.sand.desc=
|
||||||
|
tile.sandStone.name=Sandstone
|
||||||
|
tile.sand.desc=
|
||||||
|
tile.gravel.name=Gravel
|
||||||
|
tile.gravel.desc=
|
||||||
|
tile.oreGold.name=Gold Ore
|
||||||
|
tile.oreGold.desc=
|
||||||
|
tile.oreIron.name=Iron Ore
|
||||||
|
tile.oreIron.desc=
|
||||||
|
tile.oreCoal.name=Coal Ore
|
||||||
|
tile.oreCoal.desc=
|
||||||
|
tile.log.name=Wood
|
||||||
|
tile.log.desc=
|
||||||
|
tile.leaves.name=Leaves
|
||||||
|
tile.leaves.desc=
|
||||||
|
tile.sponge.name=Sponge
|
||||||
|
tile.sponge.desc=
|
||||||
|
tile.glass.name=Glass
|
||||||
|
tile.glass.desc=
|
||||||
|
tile.cloth.name=Wool
|
||||||
|
tile.cloth.desc=
|
||||||
|
tile.flower.name=Flower
|
||||||
|
tile.flower.desc=
|
||||||
|
tile.rose.name=Rose
|
||||||
|
tile.rose.desc=
|
||||||
|
tile.mushroom.name=Mushroom
|
||||||
|
tile.mushroom.desc=
|
||||||
|
tile.blockGold.name=Block of Gold
|
||||||
|
tile.blockGold.desc=
|
||||||
|
tile.blockIron.name=Block of Iron
|
||||||
|
tile.blockIron.desc=
|
||||||
|
tile.stoneSlab.stone.name=Stone Slab
|
||||||
|
tile.stoneSlab.stone.desc=
|
||||||
|
tile.stoneSlab.sand.name=Sandstone Slab
|
||||||
|
tile.stoneSlab.sand.desc=
|
||||||
|
tile.stoneSlab.wood.name=Wooden Slab
|
||||||
|
tile.stoneSlab.wood.desc=
|
||||||
|
tile.stoneSlab.cobble.name=Stone Slab
|
||||||
|
tile.stoneSlab.cobble.desc=
|
||||||
|
tile.brick.name=Bricks
|
||||||
|
tile.brick.desc=
|
||||||
|
tile.tnt.name=TNT
|
||||||
|
tile.tnt.desc=
|
||||||
|
tile.bookshelf.name=Bookshelf
|
||||||
|
tile.bookshelf.desc=
|
||||||
|
tile.stoneMoss.name=Moss Stone
|
||||||
|
tile.stoneMoss.desc=
|
||||||
|
tile.obsidian.name=Obsidian
|
||||||
|
tile.obsidian.desc=
|
||||||
|
tile.torch.name=Torch
|
||||||
|
tile.torch.desc=
|
||||||
|
tile.fire.name=Fire
|
||||||
|
tile.fire.desc=
|
||||||
|
tile.mobSpawner.name=Monster Spawner
|
||||||
|
tile.mobSpawner.desc=
|
||||||
|
tile.stairsWood.name=Wooden Stairs
|
||||||
|
tile.stairsWood.desc=
|
||||||
|
tile.chest.name=Chest
|
||||||
|
tile.chest.desc=
|
||||||
|
tile.redstoneDust.name=Redstone Dust
|
||||||
|
tile.redstoneDust.desc=
|
||||||
|
tile.oreDiamond.name=Diamond Ore
|
||||||
|
tile.oreDiamond.desc=
|
||||||
|
tile.blockDiamond.name=Block of Diamond
|
||||||
|
tile.blockDiamond.desc=
|
||||||
|
tile.workbench.name=Crafting Table
|
||||||
|
tile.workbench.desc=
|
||||||
|
tile.crops.name=Crops
|
||||||
|
tile.crops.desc=
|
||||||
|
tile.farmland.name=Farmland
|
||||||
|
tile.farmland.desc=
|
||||||
|
tile.furnace.name=Furnace
|
||||||
|
tile.furnace.desc=
|
||||||
|
tile.sign.name=Sign
|
||||||
|
tile.sign.desc=
|
||||||
|
tile.doorWood.name=Wooden Door
|
||||||
|
tile.doorWood.desc=
|
||||||
|
tile.ladder.name=Ladder
|
||||||
|
tile.ladder.desc=
|
||||||
|
tile.rail.name=Rail
|
||||||
|
tile.rail.desc=
|
||||||
|
tile.goldenRail.name=Powered Rail
|
||||||
|
tile.goldenRail.desc=
|
||||||
|
tile.detectorRail.name=Detector Rail
|
||||||
|
tile.detectorRail.desc=
|
||||||
|
tile.stairsStone.name=Stone Stairs
|
||||||
|
tile.stairsStone.desc=
|
||||||
|
tile.lever.name=Lever
|
||||||
|
tile.lever.desc=
|
||||||
|
tile.pressurePlate.name=Pressure Plate
|
||||||
|
tile.pressurePlate.desc=
|
||||||
|
tile.doorIron.name=Iron Door
|
||||||
|
tile.doorIron.desc=
|
||||||
|
tile.oreRedstone.name=Redstone Ore
|
||||||
|
tile.oreRedstone.desc=
|
||||||
|
tile.notGate.name=Redstone Torch
|
||||||
|
tile.notGate.desc=
|
||||||
|
tile.button.name=Button
|
||||||
|
tile.button.desc=
|
||||||
|
tile.snow.name=Snow
|
||||||
|
tile.snow.desc=
|
||||||
|
tile.ice.name=Ice
|
||||||
|
tile.ice.desc=
|
||||||
|
tile.cactus.name=Cactus
|
||||||
|
tile.cactus.desc=
|
||||||
|
tile.clay.name=Clay
|
||||||
|
tile.clay.desc=
|
||||||
|
tile.reeds.name=Sugar cane
|
||||||
|
tile.reeds.desc=
|
||||||
|
tile.jukebox.name=Jukebox
|
||||||
|
tile.jukebox.desc=
|
||||||
|
tile.fence.name=Fence
|
||||||
|
tile.fence.desc=
|
||||||
|
tile.pumpkin.name=Pumpkin
|
||||||
|
tile.pumpkin.desc=
|
||||||
|
tile.litpumpkin.name=Jack 'o' Lantern
|
||||||
|
tile.litpumpkin.desc=
|
||||||
|
tile.hellrock.name=Netherrack
|
||||||
|
tile.hellrock.desc=
|
||||||
|
tile.hellsand.name=Soul Sand
|
||||||
|
tile.hellsand.desc=
|
||||||
|
tile.lightgem.name=Glowstone
|
||||||
|
tile.lightgem.desc=
|
||||||
|
tile.portal.name=Portal
|
||||||
|
tile.portal.desc=
|
||||||
|
tile.cloth.black.name=Black Wool
|
||||||
|
tile.cloth.black.desc=
|
||||||
|
tile.cloth.red.name=Red Wool
|
||||||
|
tile.cloth.red.desc=
|
||||||
|
tile.cloth.green.name=Green Wool
|
||||||
|
tile.cloth.green.desc=
|
||||||
|
tile.cloth.brown.name=Brown Wool
|
||||||
|
tile.cloth.brown.desc=
|
||||||
|
tile.cloth.blue.name=Blue Wool
|
||||||
|
tile.cloth.blue.desc=
|
||||||
|
tile.cloth.purple.name=Purple Wool
|
||||||
|
tile.cloth.purple.desc=
|
||||||
|
tile.cloth.cyan.name=Cyan Wool
|
||||||
|
tile.cloth.cyan.desc=
|
||||||
|
tile.cloth.silver.name=Light Gray Wool
|
||||||
|
tile.cloth.silver.desc=
|
||||||
|
tile.cloth.gray.name=Gray Wool
|
||||||
|
tile.cloth.gray.desc=
|
||||||
|
tile.cloth.pink.name=Pink Wool
|
||||||
|
tile.cloth.pink.desc=
|
||||||
|
tile.cloth.lime.name=Lime Wool
|
||||||
|
tile.cloth.lime.desc=
|
||||||
|
tile.cloth.yellow.name=Yellow Wool
|
||||||
|
tile.cloth.yellow.desc=
|
||||||
|
tile.cloth.lightBlue.name=Light Blue Wool
|
||||||
|
tile.cloth.lightBlue.desc=
|
||||||
|
tile.cloth.magenta.name=Magenta Wool
|
||||||
|
tile.cloth.magenta.desc=
|
||||||
|
tile.cloth.orange.name=Orange Wool
|
||||||
|
tile.cloth.orange.desc=
|
||||||
|
tile.cloth.white.name=Wool
|
||||||
|
tile.cloth.white.desc=
|
||||||
|
tile.oreLapis.name=Lapis Lazuli Ore
|
||||||
|
tile.oreLapis.desc=
|
||||||
|
tile.blockLapis.name=Lapis Lazuli Block
|
||||||
|
tile.blockLapis.desc=
|
||||||
|
tile.dispenser.name=Dispenser
|
||||||
|
tile.dispenser.desc=
|
||||||
|
tile.musicBlock.name=Note Block
|
||||||
|
tile.musicBlock.desc=
|
||||||
|
tile.cake.name=Cake
|
||||||
|
tile.cake.desc=
|
||||||
|
tile.bed.name=Bed
|
||||||
|
tile.bed.desc=
|
||||||
|
tile.bed.occupied=This bed is occupied
|
||||||
|
tile.bed.noSleep=You can only sleep at night
|
||||||
|
tile.bed.notValid=Your home bed was missing or obstructed
|
||||||
|
tile.lockedchest.name=Locked chest
|
||||||
|
tile.lockedchest.desc=
|
||||||
|
tile.trapdoor.name=Trapdoor
|
||||||
|
tile.trapdoor.desc=
|
||||||
|
tile.web.name=Cobweb
|
||||||
|
tile.web.desc=
|
||||||
|
tile.stonebricksmooth.name=Stone Bricks
|
||||||
|
tile.stonebricksmooth.desc=
|
||||||
|
tile.pistonBase.name=Piston
|
||||||
|
tile.pistonBase.desc=
|
||||||
|
tile.pistonStickyBase.name=Sticky Piston
|
||||||
|
tile.pistonStickyBase.desc=
|
||||||
|
|
||||||
|
item.shovelIron.name=Iron Shovel
|
||||||
|
item.shovelIron.desc=
|
||||||
|
item.pickaxeIron.name=Iron Pickaxe
|
||||||
|
item.pickaxeIron.desc=
|
||||||
|
item.hatchetIron.name=Iron Axe
|
||||||
|
item.hatchetIron.desc=
|
||||||
|
item.flintAndSteel.name=Flint and Steel
|
||||||
|
item.flintAndSteel.desc=
|
||||||
|
item.apple.name=Apple
|
||||||
|
item.apple.desc=
|
||||||
|
item.cookie.name=Cookie
|
||||||
|
item.cookie.desc=
|
||||||
|
item.bow.name=Bow
|
||||||
|
item.bow.desc=
|
||||||
|
item.arrow.name=Arrow
|
||||||
|
item.arrow.desc=
|
||||||
|
item.coal.name=Coal
|
||||||
|
item.coal.desc=
|
||||||
|
item.charcoal.name=Charcoal
|
||||||
|
item.charcoal.desc=
|
||||||
|
item.emerald.name=Diamond
|
||||||
|
item.emerald.desc=
|
||||||
|
item.ingotIron.name=Iron Ingot
|
||||||
|
item.ingotIron.desc=
|
||||||
|
item.ingotGold.name=Gold Ingot
|
||||||
|
item.ingotGold.desc=
|
||||||
|
item.swordIron.name=Iron Sword
|
||||||
|
item.swordIron.desc=
|
||||||
|
item.swordWood.name=Wooden Sword
|
||||||
|
item.swordWood.desc=
|
||||||
|
item.shovelWood.name=Wooden Shovel
|
||||||
|
item.shovelWood.desc=
|
||||||
|
item.pickaxeWood.name=Wooden Pickaxe
|
||||||
|
item.pickaxeWood.desc=
|
||||||
|
item.hatchetWood.name=Wooden Axe
|
||||||
|
item.hatchetWood.desc=
|
||||||
|
item.swordStone.name=Stone Sword
|
||||||
|
item.swordStone.desc=
|
||||||
|
item.shovelStone.name=Stone Shovel
|
||||||
|
item.shovelStone.desc=
|
||||||
|
item.pickaxeStone.name=Stone Pickaxe
|
||||||
|
item.pickaxeStone.desc=
|
||||||
|
item.hatchetStone.name=Stone Axe
|
||||||
|
item.hatchetStone.desc=
|
||||||
|
item.swordDiamond.name=Diamond Sword
|
||||||
|
item.swordDiamond.desc=
|
||||||
|
item.shovelDiamond.name=Diamond Shovel
|
||||||
|
item.shovelDiamond.desc=
|
||||||
|
item.pickaxeDiamond.name=Diamond Pickaxe
|
||||||
|
item.pickaxeDiamond.desc=
|
||||||
|
item.hatchetDiamond.name=Diamond Axe
|
||||||
|
item.hatchetDiamond.desc=
|
||||||
|
item.stick.name=Stick
|
||||||
|
item.stick.desc=
|
||||||
|
item.bowl.name=Bowl
|
||||||
|
item.bowl.desc=
|
||||||
|
item.mushroomStew.name=Mushroom Stew
|
||||||
|
item.mushroomStew.desc=
|
||||||
|
item.swordGold.name=Golden Sword
|
||||||
|
item.swordGold.desc=
|
||||||
|
item.shovelGold.name=Golden Shovel
|
||||||
|
item.shovelGold.desc=
|
||||||
|
item.pickaxeGold.name=Golden Pickaxe
|
||||||
|
item.pickaxeGold.desc=
|
||||||
|
item.hatchetGold.name=Golden Axe
|
||||||
|
item.hatchetGold.desc=
|
||||||
|
item.string.name=String
|
||||||
|
item.string.desc=
|
||||||
|
item.feather.name=Feather
|
||||||
|
item.feather.desc=
|
||||||
|
item.sulphur.name=Gunpowder
|
||||||
|
item.sulphur.desc=
|
||||||
|
item.hoeWood.name=Wooden Hoe
|
||||||
|
item.hoeWood.desc=
|
||||||
|
item.hoeStone.name=Stone Hoe
|
||||||
|
item.hoeStone.desc=
|
||||||
|
item.hoeIron.name=Iron Hoe
|
||||||
|
item.hoeIron.desc=
|
||||||
|
item.hoeDiamond.name=Diamond Hoe
|
||||||
|
item.hoeDiamond.desc=
|
||||||
|
item.hoeGold.name=Golden Hoe
|
||||||
|
item.hoeGold.desc=
|
||||||
|
item.seeds.name=Seeds
|
||||||
|
item.seeds.desc=
|
||||||
|
item.wheat.name=Wheat
|
||||||
|
item.wheat.desc=
|
||||||
|
item.bread.name=Bread
|
||||||
|
item.bread.desc=
|
||||||
|
item.helmetCloth.name=Leather Cap
|
||||||
|
item.helmetCloth.desc=
|
||||||
|
item.chestplateCloth.name=Leather Tunic
|
||||||
|
item.chestplateCloth.desc=
|
||||||
|
item.leggingsCloth.name=Leather Pants
|
||||||
|
item.leggingsCloth.desc=
|
||||||
|
item.bootsCloth.name=Leather Boots
|
||||||
|
item.bootsCloth.desc=
|
||||||
|
item.helmetChain.name=Chain Helmet
|
||||||
|
item.helmetChain.desc=
|
||||||
|
item.chestplateChain.name=Chain Chestplate
|
||||||
|
item.chestplateChain.desc=
|
||||||
|
item.leggingsChain.name=Chain Leggings
|
||||||
|
item.leggingsChain.desc=
|
||||||
|
item.bootsChain.name=Chain Boots
|
||||||
|
item.bootsChain.desc=
|
||||||
|
item.helmetIron.name=Iron Helmet
|
||||||
|
item.helmetIron.desc=
|
||||||
|
item.chestplateIron.name=Iron Chestplate
|
||||||
|
item.chestplateIron.desc=
|
||||||
|
item.leggingsIron.name=Iron Leggings
|
||||||
|
item.leggingsIron.desc=
|
||||||
|
item.bootsIron.name=Iron Boots
|
||||||
|
item.bootsIron.desc=
|
||||||
|
item.helmetDiamond.name=Diamond Helmet
|
||||||
|
item.helmetDiamond.desc=
|
||||||
|
item.chestplateDiamond.name=Diamond Chestplate
|
||||||
|
item.chestplateDiamond.desc=
|
||||||
|
item.leggingsDiamond.name=Diamond Leggings
|
||||||
|
item.leggingsDiamond.desc=
|
||||||
|
item.bootsDiamond.name=Diamond Boots
|
||||||
|
item.bootsDiamond.desc=
|
||||||
|
item.helmetGold.name=Golden Helmet
|
||||||
|
item.helmetGold.desc=
|
||||||
|
item.chestplateGold.name=Golden Chestplate
|
||||||
|
item.chestplateGold.desc=
|
||||||
|
item.leggingsGold.name=Golden Leggings
|
||||||
|
item.leggingsGold.desc=
|
||||||
|
item.bootsGold.name=Golden boots
|
||||||
|
item.bootsGold.desc=
|
||||||
|
item.flint.name=Flint
|
||||||
|
item.flint.desc=
|
||||||
|
item.porkchopRaw.name=Raw Porkchop
|
||||||
|
item.porkchopRaw.desc=
|
||||||
|
item.porkchopCooked.name=Cooked Porkchop
|
||||||
|
item.porkchopCooked.desc=
|
||||||
|
item.painting.name=Painting
|
||||||
|
item.painting.desc=
|
||||||
|
item.appleGold.name=Golden Apple
|
||||||
|
item.appleGold.desc=
|
||||||
|
item.sign.name=Sign
|
||||||
|
item.sign.desc=
|
||||||
|
item.doorWood.name=Wooden Door
|
||||||
|
item.doorWood.desc=
|
||||||
|
item.bucket.name=Bucket
|
||||||
|
item.bucket.desc=
|
||||||
|
item.bucketWater.name=Water Bucket
|
||||||
|
item.bucketWater.desc=
|
||||||
|
item.bucketLava.name=Lava bucket
|
||||||
|
item.bucketLava.desc=
|
||||||
|
item.minecart.name=Minecart
|
||||||
|
item.minecart.desc=
|
||||||
|
item.saddle.name=Saddle
|
||||||
|
item.saddle.desc=
|
||||||
|
item.doorIron.name=Iron Door
|
||||||
|
item.doorIron.desc=
|
||||||
|
item.redstone.name=Redstone
|
||||||
|
item.redstone.desc=
|
||||||
|
item.snowball.name=Snowball
|
||||||
|
item.snowball.desc=
|
||||||
|
item.boat.name=Boat
|
||||||
|
item.boat.desc=
|
||||||
|
item.leather.name=Leather
|
||||||
|
item.leather.desc=
|
||||||
|
item.milk.name=Milk
|
||||||
|
item.milk.desc=
|
||||||
|
item.brick.name=Brick
|
||||||
|
item.brick.desc=
|
||||||
|
item.clay.name=Clay
|
||||||
|
item.clay.desc=
|
||||||
|
item.reeds.name=Sugar Canes
|
||||||
|
item.reeds.desc=
|
||||||
|
item.paper.name=Paper
|
||||||
|
item.paper.desc=
|
||||||
|
item.book.name=Book
|
||||||
|
item.book.desc=
|
||||||
|
item.slimeball.name=Slimeball
|
||||||
|
item.slimeball.desc=
|
||||||
|
item.minecartChest.name=Minecart with Chest
|
||||||
|
item.minecartChest.desc=
|
||||||
|
item.minecartFurnace.name=Minecart with Furnace
|
||||||
|
item.minecartFurnace.desc=
|
||||||
|
item.egg.name=Egg
|
||||||
|
item.egg.desc=
|
||||||
|
item.compass.name=Compass
|
||||||
|
item.compass.desc=
|
||||||
|
item.fishingRod.name=Fishing Rod
|
||||||
|
item.fishingRod.desc=
|
||||||
|
item.clock.name=Clock
|
||||||
|
item.clock.desc=
|
||||||
|
item.yellowDust.name=Glowstone Dust
|
||||||
|
item.yellowDust.desc=
|
||||||
|
item.fishRaw.name=Raw Fish
|
||||||
|
item.fishRaw.desc=
|
||||||
|
item.fishCooked.name=Cooked Fish
|
||||||
|
item.fishCooked.desc=
|
||||||
|
item.record.name=Music Disc
|
||||||
|
item.record.desc=
|
||||||
|
item.bone.name=Bone
|
||||||
|
item.bone.desc=
|
||||||
|
item.dyePowder.black.name=Ink Sac
|
||||||
|
item.dyePowder.black.desc=
|
||||||
|
item.dyePowder.red.name=Rose Red
|
||||||
|
item.dyePowder.red.desc=
|
||||||
|
item.dyePowder.green.name=Cactus Green
|
||||||
|
item.dyePowder.green.desc=
|
||||||
|
item.dyePowder.brown.name=Cocoa Beans
|
||||||
|
item.dyePowder.brown.desc=
|
||||||
|
item.dyePowder.blue.name=Lapis Lazuli
|
||||||
|
item.dyePowder.blue.desc=
|
||||||
|
item.dyePowder.purple.name=Purple Dye
|
||||||
|
item.dyePowder.purple.desc=
|
||||||
|
item.dyePowder.cyan.name=Cyan Dye
|
||||||
|
item.dyePowder.cyan.desc=
|
||||||
|
item.dyePowder.silver.name=Light Gray Dye
|
||||||
|
item.dyePowder.silver.desc=
|
||||||
|
item.dyePowder.gray.name=Gray Dye
|
||||||
|
item.dyePowder.gray.desc=
|
||||||
|
item.dyePowder.pink.name=Pink Dye
|
||||||
|
item.dyePowder.pink.desc=
|
||||||
|
item.dyePowder.lime.name=Lime Dye
|
||||||
|
item.dyePowder.lime.desc=
|
||||||
|
item.dyePowder.yellow.name=Dandelion Yellow
|
||||||
|
item.dyePowder.yellow.desc=
|
||||||
|
item.dyePowder.lightBlue.name=Light Blue Dye
|
||||||
|
item.dyePowder.lightBlue.desc=
|
||||||
|
item.dyePowder.magenta.name=Magenta Dye
|
||||||
|
item.dyePowder.magenta.desc=
|
||||||
|
item.dyePowder.orange.name=Orange Dye
|
||||||
|
item.dyePowder.orange.desc=
|
||||||
|
item.dyePowder.white.name=Bone Meal
|
||||||
|
item.dyePowder.white.desc=
|
||||||
|
item.sugar.name=Sugar
|
||||||
|
item.sugar.desc=
|
||||||
|
item.cake.name=Cake
|
||||||
|
item.cake.desc=
|
||||||
|
item.bed.name=Bed
|
||||||
|
item.bed.desc=
|
||||||
|
item.diode.name=Redstone Repeater
|
||||||
|
item.diode.desc=
|
||||||
|
item.map.name=Map
|
||||||
|
item.map.desc=
|
||||||
|
item.leaves.name=Leaves
|
||||||
|
item.leaves.desc=
|
||||||
|
item.shears.name=Shears
|
||||||
|
item.shears.desc=
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
gui.achievements=Achievements
|
||||||
|
gui.stats=Statistics
|
||||||
|
|
||||||
|
stat.generalButton=General
|
||||||
|
stat.blocksButton=Blocks
|
||||||
|
stat.itemsButton=Items
|
||||||
|
|
||||||
|
stat.used=Times Used
|
||||||
|
stat.mined=Times Mined
|
||||||
|
stat.depleted=Times Depleted
|
||||||
|
stat.crafted=Times Crafted
|
||||||
|
|
||||||
|
stat.startGame=Times played
|
||||||
|
stat.createWorld=Worlds played
|
||||||
|
stat.loadWorld=Saves loaded
|
||||||
|
stat.joinMultiplayer=Multiplayer joins
|
||||||
|
stat.leaveGame=Games quit
|
||||||
|
|
||||||
|
stat.playOneMinute=Minutes Played
|
||||||
|
|
||||||
|
stat.walkOneCm=Distance Walked
|
||||||
|
stat.fallOneCm=Distance Fallen
|
||||||
|
stat.swimOneCm=Distance Swum
|
||||||
|
stat.flyOneCm=Distance Flown
|
||||||
|
stat.climbOneCm=Distance Climbed
|
||||||
|
stat.diveOneCm=Distance Dove
|
||||||
|
stat.minecartOneCm=Distance by Minecart
|
||||||
|
stat.boatOneCm=Distance by Boat
|
||||||
|
stat.pigOneCm=Distance by Pig
|
||||||
|
stat.jump=Jumps
|
||||||
|
stat.drop=Items Dropped
|
||||||
|
|
||||||
|
stat.damageDealt=Damage Dealt
|
||||||
|
stat.damageTaken=Damage Taken
|
||||||
|
stat.deaths=Number of Deaths
|
||||||
|
stat.mobKills=Mob Kills
|
||||||
|
stat.playerKills=Player Kills
|
||||||
|
stat.fishCaught=Fish Caught
|
||||||
|
|
||||||
|
stat.mineBlock=%1$s Mined
|
||||||
|
stat.craftItem=%1$s Crafted
|
||||||
|
stat.useItem=%1$s Used
|
||||||
|
stat.breakItem=%1$s Depleted
|
||||||
|
|
||||||
|
achievement.get=Achievement get!
|
||||||
|
|
||||||
|
achievement.taken=Taken!
|
||||||
|
|
||||||
|
achievement.requires=Requires '%1$s'
|
||||||
|
achievement.openInventory=Taking Inventory
|
||||||
|
achievement.openInventory.desc=Press '%1$s' to open your inventory.
|
||||||
|
achievement.mineWood=Getting Wood
|
||||||
|
achievement.mineWood.desc=Attack a tree until a block of wood pops out
|
||||||
|
achievement.buildWorkBench=Benchmarking
|
||||||
|
achievement.buildWorkBench.desc=Craft a workbench with four blocks of planks
|
||||||
|
achievement.buildPickaxe=Time to Mine!
|
||||||
|
achievement.buildPickaxe.desc=Use planks and sticks to make a pickaxe
|
||||||
|
achievement.buildFurnace=Hot Topic
|
||||||
|
achievement.buildFurnace.desc=Construct a furnace out of eight stone blocks
|
||||||
|
achievement.acquireIron=Acquire Hardware
|
||||||
|
achievement.acquireIron.desc=Smelt an iron ingot
|
||||||
|
achievement.buildHoe=Time to Farm!
|
||||||
|
achievement.buildHoe.desc=Use planks and sticks to make a hoe
|
||||||
|
achievement.makeBread=Bake Bread
|
||||||
|
achievement.makeBread.desc=Turn wheat into bread
|
||||||
|
achievement.bakeCake=The Lie
|
||||||
|
achievement.bakeCake.desc=Wheat, sugar, milk and eggs!
|
||||||
|
achievement.buildBetterPickaxe=Getting an Upgrade
|
||||||
|
achievement.buildBetterPickaxe.desc=Construct a better pickaxe
|
||||||
|
achievement.cookFish=Delicious Fish
|
||||||
|
achievement.cookFish.desc=Catch and cook fish!
|
||||||
|
achievement.onARail=On A Rail
|
||||||
|
achievement.onARail.desc=Travel by minecart at least 1 km from where you started
|
||||||
|
achievement.buildSword=Time to Strike!
|
||||||
|
achievement.buildSword.desc=Use planks and sticks to make a sword
|
||||||
|
achievement.killEnemy=Monster Hunter
|
||||||
|
achievement.killEnemy.desc=Attack and destroy a monster
|
||||||
|
achievement.killCow=Cow Tipper
|
||||||
|
achievement.killCow.desc=Harvest some leather
|
||||||
|
achievement.flyPig=When Pigs Fly
|
||||||
|
achievement.flyPig.desc=Fly a pig off a cliff
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.plugin.InvalidDescriptionException;
|
||||||
|
import org.bukkit.plugin.InvalidPluginException;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
import org.yaml.snakeyaml.error.YAMLException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public final class PluginLoadPlanner {
|
||||||
|
private final Server server;
|
||||||
|
private final Set<Pattern> fileFilters;
|
||||||
|
private final File updateDirectory;
|
||||||
|
|
||||||
|
public PluginLoadPlanner(Server server, Set<Pattern> fileFilters, File updateDirectory) {
|
||||||
|
this.server = server;
|
||||||
|
this.fileFilters = fileFilters;
|
||||||
|
this.updateDirectory = updateDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a load order for plugins in a given directory based on dependencies.
|
||||||
|
public List<PlannedPlugin> plan(File directory, File[] files) {
|
||||||
|
if (files == null || files.length == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize filesystem enumeration so plugin order is not platform-dependent.
|
||||||
|
// Issue identified by RobertWesner
|
||||||
|
Arrays.sort(files, (left, right) -> left.getName().compareToIgnoreCase(right.getName()));
|
||||||
|
|
||||||
|
// Index plugin metadata up front so dependency decisions can be made before any plugin code runs.
|
||||||
|
LinkedHashMap<String, PluginCandidate> candidates = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// Loop through files in the directory and parse plugin descriptions, skipping duplicates and invalid plugins.
|
||||||
|
//TODO: We should figure out how we want to handle dupe plugins in Poseidon in the future. No reason exists for them and they just cause hard to trobleshoot issues
|
||||||
|
for (File file : files) {
|
||||||
|
PluginCandidate candidate = createCandidate(file);
|
||||||
|
if (candidate == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginCandidate existing = candidates.get(candidate.name);
|
||||||
|
if (existing != null) {
|
||||||
|
server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': duplicate plugin name '" + candidate.name + "' also found in '" + existing.file.getPath() + "'");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates.put(candidate.name, candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PlannedPlugin> plan = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
// Create a deterministic load order
|
||||||
|
Set<String> loadedNames = new LinkedHashSet<>();
|
||||||
|
LinkedHashSet<PluginCandidate> remaining = new LinkedHashSet<>(candidates.values());
|
||||||
|
|
||||||
|
// Iterate until no plugins remain or no progress can be made due to missing or circular dependencies.
|
||||||
|
while (!remaining.isEmpty()) {
|
||||||
|
List<PluginCandidate> ready = new ArrayList<>();
|
||||||
|
|
||||||
|
// First try to satisfy both hard dependencies
|
||||||
|
for (PluginCandidate candidate : remaining) {
|
||||||
|
if (hasMissingHardDependencies(candidate, candidates)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefer loading after both hard and present soft dependencies when the graph allows it.
|
||||||
|
if (dependenciesLoaded(candidate.getHardDependencies(), loadedNames)
|
||||||
|
&& dependenciesLoaded(candidate.getPresentSoftDependencies(candidates), loadedNames)) {
|
||||||
|
ready.add(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no plugin can satisfy every soft dependency, fall back to hard-dependency order.
|
||||||
|
boolean relaxedSoftDependencies = false;
|
||||||
|
if (ready.isEmpty()) {
|
||||||
|
for (PluginCandidate candidate : remaining) {
|
||||||
|
if (hasMissingHardDependencies(candidate, candidates)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This preserves startup progress when soft dependencies form cycles or long chains.
|
||||||
|
if (dependenciesLoaded(candidate.getHardDependencies(), loadedNames)) {
|
||||||
|
ready.add(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relaxedSoftDependencies = !ready.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ready.isEmpty()) {
|
||||||
|
// Anything left here either references a missing hard dependency or is part of a cycle.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort deterministically to ensure a stable load order
|
||||||
|
Collections.sort(ready, (left, right) -> {
|
||||||
|
int loadOrder = left.description.getLoad().compareTo(right.description.getLoad());
|
||||||
|
if (loadOrder != 0) {
|
||||||
|
return loadOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nameOrder = left.name.compareToIgnoreCase(right.name);
|
||||||
|
if (nameOrder != 0) {
|
||||||
|
return nameOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left.file.getName().compareToIgnoreCase(right.file.getName());
|
||||||
|
});
|
||||||
|
|
||||||
|
for (PluginCandidate candidate : ready) {
|
||||||
|
// Tell the legacy loader to ignore soft dependencies only when the planner already relaxed them.
|
||||||
|
boolean ignoreSoftDependencies = relaxedSoftDependencies || candidate.hasMissingSoftDependencies(candidates);
|
||||||
|
plan.add(new PlannedPlugin(candidate.file, candidate.name, ignoreSoftDependencies));
|
||||||
|
loadedNames.add(candidate.name);
|
||||||
|
remaining.remove(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print errors
|
||||||
|
for (PluginCandidate candidate : remaining) {
|
||||||
|
// If the candidate has missing hard dependencies, report them. Otherwise, report a circular or unresolved dependency chain.
|
||||||
|
if (hasMissingHardDependencies(candidate, candidates)) {
|
||||||
|
for (String dependency : candidate.getMissingHardDependencies(candidates)) {
|
||||||
|
server.getLogger().log(Level.SEVERE, "Could not load '" + candidate.file.getPath() + "' in folder '" + directory.getPath() + "': Unknown dependency " + dependency);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server.getLogger().log(Level.SEVERE, "Could not load '" + candidate.file.getPath() + "' in folder '" + directory.getPath() + "': circular or unresolved dependency chain");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PluginCandidate createCandidate(File file) {
|
||||||
|
PluginDescriptionFile description;
|
||||||
|
|
||||||
|
try {
|
||||||
|
description = getPluginDescription(file);
|
||||||
|
} catch (InvalidPluginException | InvalidDescriptionException ex) {
|
||||||
|
server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "'.", ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (description == null) {
|
||||||
|
// Non-plugin files in the directory are ignored by the registered file filters.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PluginCandidate(file, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PluginDescriptionFile getPluginDescription(File file) throws InvalidPluginException, InvalidDescriptionException {
|
||||||
|
// Read plugin.yml first so ordering can be computed without instantiating plugin classes.
|
||||||
|
File descriptionSource = getEffectivePluginFile(file); // If plugin has an update, read description from the update file instead as it might have new dependencies.
|
||||||
|
|
||||||
|
for (Pattern filter : fileFilters) {
|
||||||
|
Matcher match = filter.matcher(descriptionSource.getName());
|
||||||
|
if (!match.find()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (JarFile jar = new JarFile(descriptionSource)) {
|
||||||
|
JarEntry entry = jar.getJarEntry("plugin.yml");
|
||||||
|
|
||||||
|
if (entry == null) {
|
||||||
|
throw new InvalidPluginException(new IOException("Jar does not contain plugin.yml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream stream = jar.getInputStream(entry)) {
|
||||||
|
return new PluginDescriptionFile(stream);
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new InvalidPluginException(ex);
|
||||||
|
} catch (YAMLException ex) {
|
||||||
|
throw new InvalidPluginException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getEffectivePluginFile(File file) {
|
||||||
|
if (updateDirectory == null || !updateDirectory.isDirectory()) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
File updateFile = new File(updateDirectory, file.getName());
|
||||||
|
if (updateFile.isFile()) {
|
||||||
|
// Return the update file instead for processing
|
||||||
|
return updateFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasMissingHardDependencies(PluginCandidate candidate, Map<String, PluginCandidate> candidates) {
|
||||||
|
return !candidate.getMissingHardDependencies(candidates).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean dependenciesLoaded(Collection<String> dependencies, Set<String> loadedNames) {
|
||||||
|
for (String dependency : dependencies) {
|
||||||
|
if (!loadedNames.contains(dependency)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PlannedPlugin {
|
||||||
|
public final File file;
|
||||||
|
public final String name;
|
||||||
|
public final boolean ignoreSoftDependencies;
|
||||||
|
|
||||||
|
PlannedPlugin(File file, String name, boolean ignoreSoftDependencies) {
|
||||||
|
this.file = file;
|
||||||
|
this.name = name;
|
||||||
|
this.ignoreSoftDependencies = ignoreSoftDependencies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PluginCandidate {
|
||||||
|
private final File file;
|
||||||
|
private final PluginDescriptionFile description;
|
||||||
|
private final String name;
|
||||||
|
private final List<String> hardDependencies;
|
||||||
|
private final List<String> softDependencies;
|
||||||
|
|
||||||
|
private PluginCandidate(File file, PluginDescriptionFile description) {
|
||||||
|
this.file = file;
|
||||||
|
this.description = description;
|
||||||
|
this.name = description.getName();
|
||||||
|
this.hardDependencies = copyDependencies(description.getDepend());
|
||||||
|
this.softDependencies = copyDependencies(description.getSoftDepend());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getHardDependencies() {
|
||||||
|
return hardDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getMissingHardDependencies(Map<String, PluginCandidate> candidates) {
|
||||||
|
List<String> missing = new ArrayList<>();
|
||||||
|
for (String dependency : hardDependencies) {
|
||||||
|
if (!candidates.containsKey(dependency)) {
|
||||||
|
missing.add(dependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getPresentSoftDependencies(Map<String, PluginCandidate> candidates) {
|
||||||
|
List<String> present = new ArrayList<>();
|
||||||
|
for (String dependency : softDependencies) {
|
||||||
|
if (candidates.containsKey(dependency)) {
|
||||||
|
present.add(dependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return present;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasMissingSoftDependencies(Map<String, PluginCandidate> candidates) {
|
||||||
|
// Missing soft dependencies should not block load, but present ones still influence ordering.
|
||||||
|
return getPresentSoftDependencies(candidates).size() != softDependencies.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static List<String> copyDependencies(Object dependencies) {
|
||||||
|
if (dependencies == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>((Collection<String>) dependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public final class Poseidon {
|
||||||
|
private static PoseidonServer server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the server's TPS (Ticks Per Second) records for performance monitoring.
|
||||||
|
* The list contains Double values indicating the TPS at each second, ordered from most recent to oldest.
|
||||||
|
*
|
||||||
|
* @return LinkedList<Double> of TPS records.
|
||||||
|
*/
|
||||||
|
public static LinkedList<Double> getTpsRecords() {
|
||||||
|
return ((CraftServer) Bukkit.getServer()).getServer().getTpsRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PoseidonServer getServer() {
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setServer(PoseidonServer server) {
|
||||||
|
if (Poseidon.server != null) {
|
||||||
|
throw new UnsupportedOperationException("Cannot redefine singleton Server");
|
||||||
|
}
|
||||||
|
|
||||||
|
Poseidon.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,395 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import org.bukkit.util.config.Configuration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class PoseidonConfig extends Configuration {
|
||||||
|
private static PoseidonConfig singleton;
|
||||||
|
private final int configVersion = 5;
|
||||||
|
private Integer[] treeBlacklistIDs;
|
||||||
|
|
||||||
|
public Integer[] getTreeBlacklistIDs() {
|
||||||
|
return treeBlacklistIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PoseidonConfig() {
|
||||||
|
super(new File("poseidon.yml"));
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
this.load();
|
||||||
|
this.write();
|
||||||
|
this.validation();
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetConfig() {
|
||||||
|
// Delete all the config options
|
||||||
|
for (String key : this.getKeys()) {
|
||||||
|
this.removeProperty(key);
|
||||||
|
}
|
||||||
|
// Reload the config
|
||||||
|
this.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validation() {
|
||||||
|
//Confirm settings.uuid-fetcher.method.value is either POST or GET
|
||||||
|
if (!this.getConfigString("settings.uuid-fetcher.method.value").equalsIgnoreCase("POST") && !this.getConfigString("settings.uuid-fetcher.method.value").equalsIgnoreCase("GET")) {
|
||||||
|
System.out.println("[Poseidon] Config: settings.uuid-fetcher.method.value is not POST or GET. Changing to POST.");
|
||||||
|
this.setProperty("settings.uuid-fetcher.method.value", "POST");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write() {
|
||||||
|
if (this.getString("config-version") == null || Integer.valueOf(this.getString("config-version")) < configVersion) {
|
||||||
|
System.out.println("[Poseidon] Converting from config version " + (this.getString("config-version") == null ? "0" : this.getString("config-version")) + " to " + configVersion);
|
||||||
|
convertToNewConfig();
|
||||||
|
this.setProperty("config-version", configVersion);
|
||||||
|
}
|
||||||
|
//Main
|
||||||
|
generateConfigOption("config-version", configVersion);
|
||||||
|
//Setting
|
||||||
|
// generateConfigOption("settings.allow-graceful-uuids", true);
|
||||||
|
generateConfigOption("settings.delete-duplicate-uuids", false);
|
||||||
|
generateConfigOption("settings.save-playerdata-by-uuid", true);
|
||||||
|
// Log management and rotation
|
||||||
|
generateConfigOption("settings.per-day-log-file.info", "This setting causes the server to create a new log file each day. This is useful for log rotation and log file management.");
|
||||||
|
generateConfigOption("settings.per-day-log-file.enabled", false);
|
||||||
|
generateConfigOption("settings.per-day-log-file.latest-log.info", "This setting causes the server to create a latest.log similar to modern Minecraft servers. This can be useful for certain control panels and log file management.");
|
||||||
|
generateConfigOption("settings.per-day-log-file.latest-log.enabled", true);
|
||||||
|
|
||||||
|
//generateConfigOption("settings.fetch-uuids-from", "https://api.mojang.com/profiles/minecraft");
|
||||||
|
|
||||||
|
// UUID Fetcher Settings
|
||||||
|
generateConfigOption("settings.uuid-fetcher.post.info", "This setting allows you to change the URL that the server fetches UUIDs from. This is useful if you have a custom UUID server or a proxy server that fetches UUIDs.");
|
||||||
|
generateConfigOption("settings.uuid-fetcher.post.value", "https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname");
|
||||||
|
|
||||||
|
generateConfigOption("settings.uuid-fetcher.get.info", "This setting allows you to change the URL that the server fetches UUIDs from. This is useful if you have a custom UUID server or a proxy server that fetches UUIDs.");
|
||||||
|
generateConfigOption("settings.uuid-fetcher.get.value", "https://api.minecraftservices.com/minecraft/profile/lookup/name/{username}");
|
||||||
|
generateConfigOption("settings.uuid-fetcher.get.enforce-case-sensitivity.enabled", true);
|
||||||
|
generateConfigOption("settings.uuid-fetcher.get.enforce-case-sensitivity.info", "The Mojang API is case-insensitive by default meaning usernames with different casing will return the same UUID. This setting checks the case of the username to prevent this issue. If the name is invalid, the player will be kicked.");
|
||||||
|
|
||||||
|
|
||||||
|
generateConfigOption("settings.uuid-fetcher.method.value", "POST");
|
||||||
|
generateConfigOption("settings.uuid-fetcher.method.info", "This setting allows for POST or GET method for fetching UUIDs. This is useful if you have a custom UUID server, Mojang API is down, or a proxy server that fetches UUIDs.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.uuid-fetcher.allow-graceful-uuids.value", true);
|
||||||
|
generateConfigOption("settings.uuid-fetcher.allow-graceful-uuids.info", "This setting means offline UUIDs are generated for players who don't have a Mojang UUID. This is useful for cracked or semi-cracked servers.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.uuid-fetcher.always-use-graceful-uuids.enabled", false);
|
||||||
|
generateConfigOption("settings.uuid-fetcher.always-use-graceful-uuids.info", "Will always use offline UUIDs. Useful if you need the server to run completely offline.");
|
||||||
|
|
||||||
|
// Setting to automatically add a . prefix to cracked account usernames
|
||||||
|
generateConfigOption("settings.cracked-username-prefix.enabled", false);
|
||||||
|
generateConfigOption("settings.cracked-username-prefix.info", "This setting automatically adds a . prefix to cracked account usernames to prevent username conflicts with premium accounts.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.remove-join-leave-debug", true);
|
||||||
|
generateConfigOption("settings.enable-tpc-nodelay", false);
|
||||||
|
|
||||||
|
//generateConfigOption("settings.use-get-for-uuids.enabled", true);
|
||||||
|
//generateConfigOption("settings.use-get-for-uuids.info", "This setting causes the server to use the GET method for Username to UUID conversion. This is useful incase the POST method goes offline.");
|
||||||
|
|
||||||
|
//generateConfigOption("settings.use-get-for-uuids.case-sensitive.enabled", true);
|
||||||
|
//generateConfigOption("settings.use-get-for-uuids.case-sensitive.info", "This setting will verify sensitivity of the username as the GET method is case-insensitive.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.faster-packets.enabled", true);
|
||||||
|
generateConfigOption("settings.faster-packets.info", "This setting increases the speed of packets, a fix from newer Minecraft versions.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.fix-drowning-push-down.enabled", true);
|
||||||
|
generateConfigOption("settings.fix-drowning-push-down.info", "This setting fixes taking drowning damage pushing you down.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.player-knockback-fix.enabled", true);
|
||||||
|
generateConfigOption("settings.player-knockback-fix.info", "This setting fixes reduced knockback for certain players on the server.");
|
||||||
|
|
||||||
|
//Watchdog
|
||||||
|
//generateConfigOption("settings.enable-watchdog", true);
|
||||||
|
generateConfigOption("settings.watchdog.info", "Watchdog is a automatic hang detection system which can print stacktraces and kill the server automatically after a predefined interval.");
|
||||||
|
generateConfigOption("settings.watchdog.enable", true);
|
||||||
|
generateConfigOption("settings.watchdog.timeout.value", 120);
|
||||||
|
generateConfigOption("settings.watchdog.timeout.info", "The number of seconds to kill the server process after no ticks occurring.");
|
||||||
|
generateConfigOption("settings.watchdog.debug-timeout.enabled", false);
|
||||||
|
generateConfigOption("settings.watchdog.debug-timeout.value", 30);
|
||||||
|
generateConfigOption("settings.watchdog.debug-timeout.info", "debug-timeout can be used to print a stack trace at a lower interval then the main timeout allowing admins to locate blocking tasks that cause hangs over a certain duration. Only enable this if you have experienced temporary hangs/server freezes.");
|
||||||
|
|
||||||
|
// Performance Monitoring
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.info", "This setting will cause the server to record listener execution times.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.enabled", true);
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.print-statistics-on-shutdown.info", "Prints the listener statistics to the console on server shutdown.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.print-statistics-on-shutdown.enabled", false);
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.print-on-slow-listeners.info", "Print to console when a listener takes longer than the specified time in milliseconds. It isn't recommended to set this any lower then 10ms to prevent console spam.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.print-on-slow-listeners.enabled", true);
|
||||||
|
generateConfigOption("settings.performance-monitoring.listener-reporting.print-on-slow-listeners.value", 100); // Default to two Minecraft tick
|
||||||
|
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.info", "This setting will cause the server to record synchronous task execution times.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.enabled", true);
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.print-statistics-on-shutdown.info", "Prints the task statistics to the console on server shutdown.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.print-statistics-on-shutdown.enabled", false);
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.print-on-slow-tasks.info", "Print to console when a task takes longer than the specified time in milliseconds. It isn't recommended to set this any lower then 10ms to prevent console spam.");
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.print-on-slow-tasks.enabled", true);
|
||||||
|
generateConfigOption("settings.performance-monitoring.task-reporting.print-on-slow-tasks.value", 100); // Default to two Minecraft tick
|
||||||
|
|
||||||
|
//Packet Events
|
||||||
|
generateConfigOption("settings.packet-events.enabled", false);
|
||||||
|
generateConfigOption("settings.packet-events.info", "This setting causes the server to fire a Bukkit event for each packet received and sent to a player once they have finished the initial login process. This only needs to be enabled if you have a plugin that uses this specific feature.");
|
||||||
|
// generateConfigOption("settings.bukkit-event.disabled-plugin-unregister.value", true);
|
||||||
|
// generateConfigOption("settings.bukkit-event.disabled-plugin-unregister.info", "This setting will automatically unregister listeners from disabled plugins. This is useful if you have a plugin that can get disabled at runtime and you want to prevent errors to the disabled plugin.");
|
||||||
|
generateConfigOption("settings.packet-spam-detection.enabled", true);
|
||||||
|
generateConfigOption("settings.packet-spam-detection.info", "This setting causes the server to detect and kick malicious players who send too many packets in a short period of time. This is useful to prevent players from sending too many packets to the server to cause lag.");
|
||||||
|
generateConfigOption("settings.packet-spam-detection.threshold", 10000);
|
||||||
|
|
||||||
|
//Statistics
|
||||||
|
generateConfigOption("settings.statistics.key", UUID.randomUUID().toString());
|
||||||
|
generateConfigOption("settings.statistics.enabled", true);
|
||||||
|
|
||||||
|
//World Settings
|
||||||
|
generateConfigOption("world-settings.optimized-explosions", false);
|
||||||
|
generateConfigOption("world-settings.send-explosion-velocity", true);
|
||||||
|
generateConfigOption("world-settings.randomize-spawn", true);
|
||||||
|
generateConfigOption("world-settings.teleport-to-highest-safe-block", true);
|
||||||
|
generateConfigOption("world-settings.use-modern-fence-bounding-boxes", false);
|
||||||
|
//TODO: Actually implement the tree growth functionality stuff
|
||||||
|
generateConfigOption("world.settings.block-tree-growth.enabled", true);
|
||||||
|
generateConfigOption("world.settings.block-tree-growth.list", "54,63,68");
|
||||||
|
generateConfigOption("world.settings.block-tree-growth.info", "This setting allows for server owners to easily block trees growing from automatically destroying certain blocks. The list must be a string with numerical item ids separated by commas.");
|
||||||
|
generateConfigOption("world.settings.block-pistons-pushing-furnaces.info", "This workaround prevents pistons from pushing furnaces which prevents a malicious server crash.");
|
||||||
|
generateConfigOption("world.settings.block-pistons-pushing-furnaces.enabled", true);
|
||||||
|
generateConfigOption("world.settings.pistons.transmutation-fix.enabled", true);
|
||||||
|
generateConfigOption("world.settings.pistons.transmutation-fix.info", "This setting fixes block transmutation exploits.");
|
||||||
|
generateConfigOption("world.settings.pistons.sand-gravel-duping-fix.enabled", true);
|
||||||
|
generateConfigOption("world.settings.pistons.sand-gravel-duping-fix.info", "This setting fixes sand/gravel duplication exploits.");
|
||||||
|
generateConfigOption("world.settings.pistons.other-fixes.enabled", true);
|
||||||
|
generateConfigOption("world.settings.pistons.other-fixes.info", "This setting fixes various other piston exploits like creating illegal pistons, breaking bedrock and duplicating redstone torches.");
|
||||||
|
generateConfigOption("world.settings.skeleton-shooting-sound-fix.info", "This setting fixes the sound of skeletons and players shooting not playing on clients.");
|
||||||
|
generateConfigOption("world.settings.skeleton-shooting-sound-fix.enabled", true);
|
||||||
|
generateConfigOption("world.settings.speed-hack-check.enable", true);
|
||||||
|
generateConfigOption("world.settings.speed-hack-check.teleport", true);
|
||||||
|
generateConfigOption("world.settings.speed-hack-check.distance", 100.0D);
|
||||||
|
generateConfigOption("world.settings.speed-hack-check.info", "This setting allows you to configure the automatic speedhack detection.");
|
||||||
|
generateConfigOption("world.settings.flowing-lava-fix.enabled", true);
|
||||||
|
generateConfigOption("world.settings.flowing-lava-fix.info", "This setting fixes flowing lava not disappearing when the source block is removed.");
|
||||||
|
//Mob Spawner Area Limit (8 chunks)
|
||||||
|
generateConfigOption("world.settings.mob-spawner-area-limit.enable", true);
|
||||||
|
generateConfigOption("world.settings.mob-spawner-area-limit.limit", 150);
|
||||||
|
generateConfigOption("world.settings.mob-spawner-area-limit.chunk-radius", 8);
|
||||||
|
generateConfigOption("world.settings.mob-spawner-area-limit.info",
|
||||||
|
"This setting controls the maximum number of entities of a mob spawner type that can exist within the defined chunk radius around a mob spawner. If the number of entities exceeds this limit, the spawner will stop spawning additional entities of that type. This is useful to stop the extreme lag that can be caused by mob spawners.");
|
||||||
|
|
||||||
|
|
||||||
|
//generateConfigOption("world-settings.eject-from-vehicle-on-teleport.enabled", true);
|
||||||
|
//generateConfigOption("world-settings.eject-from-vehicle-on-teleport.info", "Eject the player from a boat or minecart before teleporting them preventing cross world coordinate exploits.");
|
||||||
|
|
||||||
|
//Release2Beta Settings
|
||||||
|
generateConfigOption("settings.release2beta.enable-ip-pass-through", false);
|
||||||
|
generateConfigOption("settings.release2beta.proxy-ip", "127.0.0.1");
|
||||||
|
|
||||||
|
//BungeeCord
|
||||||
|
generateConfigOption("settings.bungeecord.bungee-mode.enable", false);
|
||||||
|
generateConfigOption("settings.bungeecord.bungee-mode.kick-message", "You must connect through BungeeCord to join this server!");
|
||||||
|
generateConfigOption("settings.bungeecord.bungee-mode.info", "Only allows connections via BungeeCord to join. Includes optional custom kick message for players not using BungeeCord.");
|
||||||
|
|
||||||
|
//Modded Jar Support
|
||||||
|
generateConfigOption("settings.support.modloader.enable", false);
|
||||||
|
generateConfigOption("settings.support.modloader.info", "EXPERIMENTAL support for ModloaderMP.");
|
||||||
|
|
||||||
|
//Offline Username Check
|
||||||
|
generateConfigOption("settings.check-username-validity.enabled", true);
|
||||||
|
generateConfigOption("settings.check-username-validity.info", "If enabled, verifies the validity of a usernames of cracked players.");
|
||||||
|
generateConfigOption("settings.check-username-validity.regex", "[a-zA-Z0-9_.]*");
|
||||||
|
generateConfigOption("settings.check-username-validity.max-length", 16);
|
||||||
|
generateConfigOption("settings.check-username-validity.min-length", 3);
|
||||||
|
generateConfigOption("emergency.debug.regenerate-corrupt-chunks.enable", false);
|
||||||
|
generateConfigOption("emergency.debug.regenerate-corrupt-chunks.info", "This setting allows you to automatically regenerate corrupt chunks. This is useful after a ungraceful shutdown while a file is being written to or out of memory exception.");
|
||||||
|
|
||||||
|
generateConfigOption("settings.update-checker.enabled", true);
|
||||||
|
generateConfigOption("settings.update-checker.info", "This setting allows you to disable the update checker. This is useful if you have a custom build of Poseidon or don't want to be notified of updates.");
|
||||||
|
generateConfigOption("settings.update-checker.notify-staff.enabled", true);
|
||||||
|
generateConfigOption("settings.update-checker.notify-staff.info", "This setting notifies operators and players with the permission poseidon.update when a new version of Poseidon is available on join.");
|
||||||
|
generateConfigOption("settings.update-checker.notify-if-up-to-date.enabled", false);
|
||||||
|
generateConfigOption("settings.update-checker.notify-if-up-to-date.info", "This setting controls if the update checker will print a message in console if the server is up to date.");
|
||||||
|
generateConfigOption("settings.update-checker.interval.ticks", 20 * 60 * 60);
|
||||||
|
generateConfigOption("settings.update-checker.interval.info", "Controls how often the update checker will query the latest Poseidon version");
|
||||||
|
|
||||||
|
//Messages
|
||||||
|
generateConfigOption("message.kick.banned", "You are banned from this server!");
|
||||||
|
generateConfigOption("message.kick.ip-banned", "Your IP address is banned from this server!");
|
||||||
|
generateConfigOption("message.kick.not-whitelisted", "You are not white-listed on this server!");
|
||||||
|
generateConfigOption("message.kick.full", "The server is full!");
|
||||||
|
generateConfigOption("message.kick.shutdown", "\u00A7cServer is shutting down, please rejoin later.");
|
||||||
|
generateConfigOption("message.kick.already-online", "\u00A7cA player with your username or uuid is already online, try reconnecting in a minute.");
|
||||||
|
generateConfigOption("message.player.join", "\u00A7e%player% joined the game.");
|
||||||
|
generateConfigOption("message.player.leave", "\u00A7e%player% left the game.");
|
||||||
|
generateConfigOption("message.update.available", "\u00A7dA newer version of Poseidon is available: %newversion%");
|
||||||
|
|
||||||
|
//Optional Poseidon Commands
|
||||||
|
generateConfigOption("command.info", "This section allows you to enable or disable optional Poseidon commands. This is useful if you have a plugin that conflicts with a Poseidon command.");
|
||||||
|
generateConfigOption("command.tps.info", "Enables the /tps command to show the server's TPS for various intervals.");
|
||||||
|
generateConfigOption("command.tps.enabled", true);
|
||||||
|
|
||||||
|
//UberBukkit
|
||||||
|
generateConfigOption("fix.optimize-sponges.enabled", true);
|
||||||
|
generateConfigOption("fix.optimize-sponges.info", "Optimizes sponges by removing unnecessary block updates. This can also prevent some block duplication methods.");
|
||||||
|
|
||||||
|
//Tree Leave Destroy Blacklist
|
||||||
|
if (Boolean.valueOf(String.valueOf(getConfigOption("world.settings.block-tree-growth.enabled", true)))) {
|
||||||
|
if (String.valueOf(this.getConfigOption("world.settings.block-tree-growth.list", "")).trim().isEmpty()) {
|
||||||
|
//Empty Blacklist
|
||||||
|
} else {
|
||||||
|
String[] rawBlacklist = String.valueOf(this.getConfigOption("world.settings.block-tree-growth.list", "")).trim().split(",");
|
||||||
|
int blackListCount = 0;
|
||||||
|
for (String stringID : rawBlacklist) {
|
||||||
|
if (Pattern.compile("-?[0-9]+").matcher(stringID).matches()) {
|
||||||
|
blackListCount = blackListCount + 1;
|
||||||
|
} else {
|
||||||
|
System.out.println("The ID " + stringID + " for leaf decay blocker has been detected as invalid, and won't be used.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Loop a second time to get correct array length. I know this is horrible code, but it works and only runs on server startup.
|
||||||
|
treeBlacklistIDs = new Integer[blackListCount];
|
||||||
|
int i = 0;
|
||||||
|
for (String stringID : rawBlacklist) {
|
||||||
|
if (Pattern.compile("-?[0-9]+").matcher(stringID).matches()) {
|
||||||
|
treeBlacklistIDs[i] = Integer.valueOf(stringID);
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Leaf blocks can't replace the following block IDs: " + Arrays.toString(treeBlacklistIDs));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
treeBlacklistIDs = new Integer[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void generateConfigOption(String key, Object defaultValue) {
|
||||||
|
if (this.getProperty(key) == null) {
|
||||||
|
this.setProperty(key, defaultValue);
|
||||||
|
}
|
||||||
|
final Object value = this.getProperty(key);
|
||||||
|
this.removeProperty(key);
|
||||||
|
this.setProperty(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Getters Start
|
||||||
|
public Object getConfigOption(String key) {
|
||||||
|
return this.getProperty(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getConfigOption(String key, Object defaultValue) {
|
||||||
|
Object value = getConfigOption(key);
|
||||||
|
if (value == null) {
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigString(String key) {
|
||||||
|
return String.valueOf(getConfigOption(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getConfigInteger(String key) {
|
||||||
|
return Integer.valueOf(getConfigString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getConfigLong(String key) {
|
||||||
|
return Long.valueOf(getConfigString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getConfigDouble(String key) {
|
||||||
|
return Double.valueOf(getConfigString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getConfigBoolean(String key) {
|
||||||
|
return Boolean.valueOf(getConfigString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getConfigBoolean(String key, Boolean defaultValue) {
|
||||||
|
Boolean value = getConfigBoolean(key);
|
||||||
|
if (value == null) {
|
||||||
|
System.out.println("[Poseidon] Config: " + key + " does not exist. Using default value: " + defaultValue);
|
||||||
|
System.out.println("[Poseidon] Config: This is likely the result of an error. Please report this to the developer.");
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Getters End
|
||||||
|
|
||||||
|
private void convertToNewConfig() {
|
||||||
|
// 1- 2/3 Conversion
|
||||||
|
convertToNewAddress("settings.statistics.enabled", "settings.enable-statistics");
|
||||||
|
convertToNewAddress("settings.allow-graceful-uuids", "allowGracefulUUID");
|
||||||
|
convertToNewAddress("settings.save-playerdata-by-uuid", "savePlayerdataByUUID");
|
||||||
|
convertToNewAddress("settings.watchdog.enable", "settings.enable-watchdog");
|
||||||
|
// 3-4 Conversion
|
||||||
|
|
||||||
|
// Don't automatically enable the latest log file for servers that have the per-day-logfile setting enabled as this is a change in behavior
|
||||||
|
if (this.getString("settings.per-day-logfile") != null && this.getConfigBoolean("settings.per-day-logfile")) {
|
||||||
|
this.setProperty("settings.per-day-log-file.latest-log.enabled", false);
|
||||||
|
}
|
||||||
|
convertToNewAddress("settings.per-day-log-file.enabled", "settings.per-day-logfile");
|
||||||
|
|
||||||
|
// 4-5 Conversion
|
||||||
|
convertToNewAddress("settings.uuid-fetcher.post.value", "settings.fetch-uuids-from");
|
||||||
|
if (this.getString("settings.uuid-fetcher.post.value", "https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname").equals("https://api.mojang.com/profiles/minecraft")) {
|
||||||
|
System.out.println("[Poseidon] Config: settings.fetch-uuids-from is set to the default value (" + this.getString("settings.uuid-fetcher.post.value") + "). Changing to the new default value (https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname)");
|
||||||
|
this.setProperty("settings.uuid-fetcher.post.value", "https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean usePost = !this.getConfigBoolean("settings.use-get-for-uuids.enabled", false); // Is the server currently using POST?
|
||||||
|
if (usePost) {
|
||||||
|
this.setProperty("settings.uuid-fetcher.method.value", "POST");
|
||||||
|
} else {
|
||||||
|
this.setProperty("settings.uuid-fetcher.method.value", "GET");
|
||||||
|
}
|
||||||
|
|
||||||
|
removeDeprecatedConfig("settings.use-get-for-uuids.enabled", "settings.use-get-for-uuids.info");
|
||||||
|
|
||||||
|
convertToNewAddress("settings.uuid-fetcher.allow-graceful-uuids.value", "settings.allow-graceful-uuids");
|
||||||
|
convertToNewAddress("settings.uuid-fetcher.get.enforce-case-sensitivity.enabled", "settings.use-get-for-uuids.case-sensitive.enabled");
|
||||||
|
removeDeprecatedConfig("settings.use-get-for-uuids.case-sensitive.info");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Allow any number of string arguments to be passed to this method
|
||||||
|
private boolean removeDeprecatedConfig(String... keys) {
|
||||||
|
boolean removed = false;
|
||||||
|
for (String key : keys) {
|
||||||
|
if (this.getString(key) != null) {
|
||||||
|
System.out.println("[Poseidon] Config: " + key + " is deprecated. Removing.");
|
||||||
|
this.removeProperty(key);
|
||||||
|
removed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean convertToNewAddress(String newKey, String oldKey) {
|
||||||
|
if (this.getString(newKey) != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.getString(oldKey) == null) {
|
||||||
|
System.out.println("[Poseidon] Config: " + oldKey + " does not exist. Skipping conversion.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
System.out.println("[Poseidon] Converting Config: " + oldKey + " to " + newKey);
|
||||||
|
Object value = this.getProperty(oldKey);
|
||||||
|
this.setProperty(newKey, value);
|
||||||
|
this.removeProperty(oldKey);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized static PoseidonConfig getInstance() {
|
||||||
|
if (PoseidonConfig.singleton == null) {
|
||||||
|
PoseidonConfig.singleton = new PoseidonConfig();
|
||||||
|
}
|
||||||
|
return PoseidonConfig.singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import com.avaje.ebean.EbeanServer;
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
import org.bukkit.plugin.PluginLoader;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.util.config.Configuration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class PoseidonPlugin implements Plugin {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getDataFolder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginDescriptionFile getDescription() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Configuration getConfiguration() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginLoader getPluginLoader() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Server getServer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNaggable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNaggable(boolean canNag) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EbeanServer getDatabase() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.utility.PerformanceStatistic;
|
||||||
|
import com.legacyminecraft.poseidon.utility.PoseidonVersionChecker;
|
||||||
|
import com.legacyminecraft.poseidon.watchdog.WatchDogThread;
|
||||||
|
import com.projectposeidon.johnymuffin.UUIDManager;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.NetServerHandler;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public final class PoseidonServer {
|
||||||
|
private final MinecraftServer server;
|
||||||
|
private final CraftServer craftServer;
|
||||||
|
|
||||||
|
private final List<String> hiddenCommands = new ArrayList<>();
|
||||||
|
private final Properties versionProperties = new Properties();
|
||||||
|
|
||||||
|
private boolean serverInitialized = false;
|
||||||
|
|
||||||
|
private PoseidonVersionChecker poseidonVersionChecker;
|
||||||
|
private WatchDogThread watchDogThread;
|
||||||
|
|
||||||
|
private Map<String, PerformanceStatistic> listenerPerformance = new HashMap<String, PerformanceStatistic>();
|
||||||
|
|
||||||
|
private Map<String, PerformanceStatistic> taskPerformance = new HashMap<String, PerformanceStatistic>();
|
||||||
|
|
||||||
|
private PoseidonConfig config;
|
||||||
|
|
||||||
|
public PoseidonServer(MinecraftServer server, CraftServer craftServer) {
|
||||||
|
this.server = server;
|
||||||
|
this.craftServer = craftServer;
|
||||||
|
this.config = PoseidonConfig.getInstance();
|
||||||
|
|
||||||
|
loadVersionProperties();
|
||||||
|
|
||||||
|
addHiddenCommands(Arrays.asList("login", "l", "register", "reg", "unregister", "changepassword", "changepw"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadVersionProperties() {
|
||||||
|
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("version.properties")) {
|
||||||
|
if (inputStream != null) {
|
||||||
|
versionProperties.load(inputStream);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
getLogger().warning("Failed to load version.properties: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeServer() {
|
||||||
|
if (serverInitialized) {
|
||||||
|
throw new UnsupportedOperationException("Server already initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogger().info("[Poseidon] Starting Project Poseidon Modules!");
|
||||||
|
|
||||||
|
PoseidonConfig.getInstance();
|
||||||
|
UUIDManager.getInstance();
|
||||||
|
|
||||||
|
initializeUpdateChecker();
|
||||||
|
|
||||||
|
//Start Watchdog
|
||||||
|
watchDogThread = new WatchDogThread(Thread.currentThread());
|
||||||
|
if (PoseidonConfig.getInstance().getBoolean("settings.watchdog.enable", true)) {
|
||||||
|
getLogger().info("[Poseidon] Starting Watchdog to detect any server hangs!");
|
||||||
|
watchDogThread.start();
|
||||||
|
watchDogThread.tickUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
serverInitialized = true;
|
||||||
|
getLogger().info("[Poseidon] Finished loading Project Poseidon Modules!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeUpdateChecker() {
|
||||||
|
if (!PoseidonConfig.getInstance().getConfigBoolean("settings.update-checker.enabled", true)) {
|
||||||
|
getLogger().info("[Poseidon] Version checker disabled. The server will not check for updates.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String releaseVersion = getReleaseVersion();
|
||||||
|
|
||||||
|
if (releaseVersion == null) {
|
||||||
|
getLogger().warning("[Poseidon] Version checker is disabled as no version.properties file was found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!getBuildType().equalsIgnoreCase("production")) {
|
||||||
|
getLogger().warning("[Poseidon] Version checker is disabled as this is a " + getBuildType() + " build. The updater will only check for updates on production builds.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
poseidonVersionChecker = new PoseidonVersionChecker(craftServer, releaseVersion);
|
||||||
|
|
||||||
|
getLogger().info("[Poseidon] Version checker enabled. The server will check for updates every hour.");
|
||||||
|
// Run the version checker in a separate thread every hour
|
||||||
|
Bukkit.getScheduler().scheduleAsyncRepeatingTask(new PoseidonPlugin(), new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
poseidonVersionChecker.fetchLatestVersion();
|
||||||
|
}
|
||||||
|
}, 0, PoseidonConfig.getInstance().getConfigLong("settings.update-checker.interval.ticks"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdownServer() {
|
||||||
|
if (!serverInitialized) {
|
||||||
|
// throw new UnsupportedOperationException("Server not initialized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogger().info("[Poseidon] Stopping Project Poseidon Modules!");
|
||||||
|
|
||||||
|
UUIDManager.getInstance().saveJsonArray();
|
||||||
|
|
||||||
|
if (watchDogThread != null) {
|
||||||
|
getLogger().info("[Poseidon] Stopping Watchdog!");
|
||||||
|
watchDogThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
serverInitialized = false;
|
||||||
|
getLogger().info("[Poseidon] Finished unloading Project Poseidon Modules!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return MinecraftServer.log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppName() {
|
||||||
|
return versionProperties.getProperty("app_name", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReleaseVersion() {
|
||||||
|
return versionProperties.getProperty("release_version", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMavenVersion() {
|
||||||
|
return versionProperties.getProperty("maven_version", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBuildTimestamp() {
|
||||||
|
return versionProperties.getProperty("build_timestamp", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGitCommit() {
|
||||||
|
return versionProperties.getProperty("git_commit", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBuildType() {
|
||||||
|
return versionProperties.getProperty("build_type", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUpdateAvailable() {
|
||||||
|
return poseidonVersionChecker != null && poseidonVersionChecker.isUpdateAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewestVersion() {
|
||||||
|
return poseidonVersionChecker == null ? "Unknown" : poseidonVersionChecker.getLatestVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatchDogThread getWatchDogThread() {
|
||||||
|
return watchDogThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current hide state of the command from param (Hide from console)
|
||||||
|
*
|
||||||
|
* @param cmdName Command name
|
||||||
|
* @return True if the command from param is hidden and false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isCommandHidden(String cmdName) {
|
||||||
|
return hiddenCommands.contains(cmdName.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the command from param from being logged to server console
|
||||||
|
*
|
||||||
|
* @param cmd Command name
|
||||||
|
*/
|
||||||
|
public void addHiddenCommand(String cmd) {
|
||||||
|
cmd = cmd.toLowerCase();
|
||||||
|
|
||||||
|
if (hiddenCommands.contains(cmd)) {
|
||||||
|
Logger.getLogger(NetServerHandler.class.getName()).warning("List of Hidden commands already contains " + cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hiddenCommands.add(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the commands from param from being logged to server console
|
||||||
|
*
|
||||||
|
* @param commands List of command names
|
||||||
|
*/
|
||||||
|
public void addHiddenCommands(List<String> commands) {
|
||||||
|
for (String cmd : commands) {
|
||||||
|
addHiddenCommand(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, PerformanceStatistic> getListenerPerformance() {
|
||||||
|
return listenerPerformance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, PerformanceStatistic> getTaskPerformance() {
|
||||||
|
return taskPerformance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic method to sort any performance map
|
||||||
|
public Map<String, PerformanceStatistic> getSortedPerformance(Map<String, PerformanceStatistic> unsortedMap) {
|
||||||
|
return unsortedMap.entrySet()
|
||||||
|
.stream()
|
||||||
|
.sorted(Map.Entry.<String, PerformanceStatistic>comparingByValue(
|
||||||
|
Comparator.comparingLong(PerformanceStatistic::getAverageExecutionTime).reversed()
|
||||||
|
))
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
Map.Entry::getValue,
|
||||||
|
(e1, e2) -> e1, // if same key, keep the first
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specific method to get sorted listener performance
|
||||||
|
public Map<String, PerformanceStatistic> getSortedListenerPerformance() {
|
||||||
|
return getSortedPerformance(getListenerPerformance());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specific method to get sorted task performance
|
||||||
|
public Map<String, PerformanceStatistic> getSortedTaskPerformance() {
|
||||||
|
return getSortedPerformance(getTaskPerformance());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseidonConfig getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package com.legacyminecraft.poseidon;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class PoseidonStatisticsAgent {
|
||||||
|
//Default details
|
||||||
|
private int protocolID = 1;
|
||||||
|
public final String postTo = "https://poseidon.johnymuffin.com/statistics.php";
|
||||||
|
//Unique Details
|
||||||
|
private String uniqueID;
|
||||||
|
private final String sessionID;
|
||||||
|
private final String version;
|
||||||
|
private final String branch;
|
||||||
|
private final Long startTime;
|
||||||
|
private Object syncLock = new Object();
|
||||||
|
|
||||||
|
public PoseidonStatisticsAgent(MinecraftServer server, CraftServer craftServer) {
|
||||||
|
//This really shouldn't be needed, but it runs once, whats the harm?
|
||||||
|
synchronized (syncLock) {
|
||||||
|
this.startTime = (System.currentTimeMillis() / 1000L);
|
||||||
|
this.uniqueID = PoseidonConfig.getInstance().getString("settings.statistics.key");
|
||||||
|
//Create temp value
|
||||||
|
Random rnd = new Random();
|
||||||
|
this.sessionID = String.valueOf(100000 + rnd.nextInt(900000));
|
||||||
|
this.version = craftServer.getPoseidonVersion();
|
||||||
|
this.branch = craftServer.getPoseidonReleaseType();
|
||||||
|
}
|
||||||
|
|
||||||
|
PoseidonStatisticsSender poseidonStatisticsSender = new PoseidonStatisticsSender();
|
||||||
|
poseidonStatisticsSender.start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getPing() {
|
||||||
|
synchronized (syncLock) {
|
||||||
|
JSONObject ping = new JSONObject();
|
||||||
|
ping.put("protocol", protocolID);
|
||||||
|
ping.put("uniqueID", uniqueID);
|
||||||
|
ping.put("sessionID", sessionID);
|
||||||
|
ping.put("version", version);
|
||||||
|
ping.put("branch", branch);
|
||||||
|
int uptime = (int) ((System.currentTimeMillis() / 1000L) - startTime);
|
||||||
|
ping.put("uptime", uptime);
|
||||||
|
return ping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PoseidonStatisticsSender extends Thread {
|
||||||
|
public volatile boolean errored = false;
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while (true && !this.isInterrupted()) {
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
try {
|
||||||
|
System.out.println("Submitting Project Poseidon Statistics.");
|
||||||
|
final JSONObject ping = getPing();
|
||||||
|
URL url = new URL(postTo);
|
||||||
|
//Create Connection
|
||||||
|
connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
//Write Body
|
||||||
|
OutputStream stream = connection.getOutputStream();
|
||||||
|
stream.write(ping.toJSONString().getBytes());
|
||||||
|
stream.flush();
|
||||||
|
stream.close();
|
||||||
|
//Get Response
|
||||||
|
String response = String.valueOf(new InputStreamReader(connection.getInputStream()));
|
||||||
|
connection.disconnect();
|
||||||
|
errored = false;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
if (!errored) {
|
||||||
|
System.out.println("Failed to submit statistics for Project Poseidon. " + exception + " : " + exception.getMessage() + ".");
|
||||||
|
}
|
||||||
|
errored = true;
|
||||||
|
} finally {
|
||||||
|
if (connection != null) {
|
||||||
|
connection.disconnect();
|
||||||
|
connection = null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(300000L);
|
||||||
|
} catch (InterruptedException exception) {
|
||||||
|
System.out.println("Project Poseidon statistics thread has been closed.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package com.legacyminecraft.poseidon.commands;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.Poseidon;
|
||||||
|
import com.projectposeidon.api.PoseidonUUID;
|
||||||
|
import com.projectposeidon.api.UUIDType;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PoseidonCommand extends Command {
|
||||||
|
|
||||||
|
private final Properties versionProperties = new Properties();
|
||||||
|
|
||||||
|
public PoseidonCommand(String name) {
|
||||||
|
super(name);
|
||||||
|
this.description = "Show data regarding the server's version of Project Poseidon";
|
||||||
|
this.usageMessage = "/poseidon";
|
||||||
|
this.setAliases(Arrays.asList("projectposeidon"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||||
|
|
||||||
|
if (args.length >= 1 && args[0].equalsIgnoreCase("resolve")) {
|
||||||
|
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
ResolveCommand resolver = new ResolveCommand("resolve");
|
||||||
|
return resolver.execute(sender, "resolve", subArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
String appName = Poseidon.getServer().getAppName();
|
||||||
|
String releaseVersion = Poseidon.getServer().getReleaseVersion();
|
||||||
|
String mavenVersion = Poseidon.getServer().getMavenVersion();
|
||||||
|
String buildTimestamp = Poseidon.getServer().getBuildTimestamp();
|
||||||
|
String gitCommit = Poseidon.getServer().getGitCommit();
|
||||||
|
String buildType = Poseidon.getServer().getBuildType();
|
||||||
|
|
||||||
|
// Shorten the git commit hash to 7 characters
|
||||||
|
if (gitCommit.length() > 7) {
|
||||||
|
gitCommit = gitCommit.substring(0, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("Unknown".equals(releaseVersion)) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Warning: version.properties not found. This is a local or unconfigured build.");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "This server is running " + ChatColor.AQUA + appName + ChatColor.GRAY + ":");
|
||||||
|
sender.sendMessage(ChatColor.GRAY + " - Version: " + ChatColor.YELLOW + releaseVersion);
|
||||||
|
sender.sendMessage(ChatColor.GRAY + " - Built at: " + ChatColor.YELLOW + buildTimestamp);
|
||||||
|
sender.sendMessage(ChatColor.GRAY + " - Git SHA: " + ChatColor.YELLOW + gitCommit);
|
||||||
|
|
||||||
|
if ("production".equalsIgnoreCase(buildType)) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "This is a release build.");
|
||||||
|
} else if ("pull_request".equalsIgnoreCase(buildType)) {
|
||||||
|
sender.sendMessage(ChatColor.BLUE + "This is a pull request build.");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "This is a development build.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (args.length == 1) {
|
||||||
|
if (args[0].equalsIgnoreCase("uuid")) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "Please specify a user /poseidon uuid (username)");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "Unknown sub command.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!args[0].equalsIgnoreCase("uuid")) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "Unknown sub command.");
|
||||||
|
} else {
|
||||||
|
UUID uuid = PoseidonUUID.getPlayerUUIDFromCache(args[1], true);
|
||||||
|
if (uuid == null) {
|
||||||
|
uuid = PoseidonUUID.getPlayerUUIDFromCache(args[1], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uuid == null) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "Unable to locate the UUID of the player called: " + ChatColor.WHITE + args[1] + ChatColor.GRAY + ". Please remember usernames are cap sensitive");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String latestUsername = PoseidonUUID.getPlayerUsernameFromUUID(uuid);
|
||||||
|
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "Username: " + latestUsername);
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "UUID: " + uuid.toString());
|
||||||
|
UUIDType uuidType = PoseidonUUID.getPlayerUUIDCacheStatus(args[1]);
|
||||||
|
if (uuidType.equals(UUIDType.ONLINE)) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "UUID Type: " + ChatColor.GREEN + "Online");
|
||||||
|
} else if (uuidType.equals(UUIDType.OFFLINE)) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "UUID Type: " + ChatColor.RED + "Offline");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + "UUID Type: " + ChatColor.DARK_RED + "UNKNOWN");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package com.legacyminecraft.poseidon.commands;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.PluginCommand;
|
||||||
|
import org.bukkit.command.SimpleCommandMap;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ResolveCommand extends Command {
|
||||||
|
|
||||||
|
public ResolveCommand(String name) {
|
||||||
|
super(name);
|
||||||
|
this.description = "Find out what plugin a command belongs to";
|
||||||
|
this.usageMessage = "/poseidon resolve <command>";
|
||||||
|
this.setPermission("poseidon.command.resolve");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||||
|
if (!testPermission(sender)) return true;
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Usage: /poseidon resolve <command>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetCommand = args[0].toLowerCase();
|
||||||
|
if (targetCommand.startsWith("/")) {
|
||||||
|
targetCommand = targetCommand.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find the command in the server's command map
|
||||||
|
Command cmd = Bukkit.getServer().getPluginCommand(targetCommand);
|
||||||
|
|
||||||
|
if (cmd != null && cmd instanceof PluginCommand) {
|
||||||
|
displayPluginCommand(sender, (PluginCommand) cmd, targetCommand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not found as PluginCommand, search through all known commands
|
||||||
|
try {
|
||||||
|
SimpleCommandMap commandMap = getCommandMap();
|
||||||
|
|
||||||
|
if (commandMap == null) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Unable to access command map.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands");
|
||||||
|
knownCommandsField.setAccessible(true);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Command> knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
|
||||||
|
|
||||||
|
for (Map.Entry<String, Command> entry : knownCommands.entrySet()) {
|
||||||
|
if (entry.getKey().equalsIgnoreCase(targetCommand) ||
|
||||||
|
entry.getValue().getName().equalsIgnoreCase(targetCommand)) {
|
||||||
|
|
||||||
|
Command foundCmd = entry.getValue();
|
||||||
|
|
||||||
|
if (foundCmd instanceof PluginCommand) {
|
||||||
|
displayPluginCommand(sender, (PluginCommand) foundCmd, targetCommand);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
displayServerCommand(sender, foundCmd, targetCommand);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Error while searching for command: " + e.getMessage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sender.sendMessage(ChatColor.RED + "Command '" + targetCommand + "' not found.");
|
||||||
|
sender.sendMessage(ChatColor.YELLOW + "Note: The command might not be registered or might be case-sensitive.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayPluginCommand(CommandSender sender, PluginCommand pluginCmd, String targetCommand) {
|
||||||
|
Plugin plugin = pluginCmd.getPlugin();
|
||||||
|
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Command: " + ChatColor.WHITE + "/" + targetCommand);
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Plugin: " + ChatColor.WHITE + plugin.getDescription().getName());
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Author: " + ChatColor.WHITE + plugin.getDescription().getAuthors());
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Version: " + ChatColor.WHITE + plugin.getDescription().getVersion());
|
||||||
|
|
||||||
|
if (pluginCmd.getAliases() != null && !pluginCmd.getAliases().isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Aliases: " + ChatColor.WHITE +
|
||||||
|
String.join(", ", pluginCmd.getAliases()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pluginCmd.getDescription() != null && !pluginCmd.getDescription().isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Description: " + ChatColor.WHITE +
|
||||||
|
pluginCmd.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayServerCommand(CommandSender sender, Command cmd, String targetCommand) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Command: " + ChatColor.WHITE + "/" + targetCommand);
|
||||||
|
sender.sendMessage(ChatColor.AQUA + "Source: " + ChatColor.WHITE + "Server (Poseidon/Bukkit)");
|
||||||
|
|
||||||
|
if (!cmd.getAliases().isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Aliases: " + ChatColor.WHITE +
|
||||||
|
String.join(", ", cmd.getAliases()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.getDescription() != null && !cmd.getDescription().isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Description: " + ChatColor.WHITE +
|
||||||
|
cmd.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.getPermission() != null && !cmd.getPermission().isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Permission: " + ChatColor.WHITE +
|
||||||
|
cmd.getPermission());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("CatchMayIgnoreException")
|
||||||
|
private SimpleCommandMap getCommandMap() {
|
||||||
|
try {
|
||||||
|
if (Bukkit.getServer() instanceof CraftServer) {
|
||||||
|
CraftServer craftServer = (CraftServer) Bukkit.getServer();
|
||||||
|
Field commandMapField = CraftServer.class.getDeclaredField("commandMap");
|
||||||
|
commandMapField.setAccessible(true);
|
||||||
|
return (SimpleCommandMap) commandMapField.get(craftServer);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.legacyminecraft.poseidon.commands;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.Poseidon;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.defaults.VanillaCommand;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TPSCommand extends Command {
|
||||||
|
|
||||||
|
private final LinkedHashMap<String, Integer> intervals = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
public TPSCommand(String name) {
|
||||||
|
super(name);
|
||||||
|
this.description = "Shows the server's TPS for various intervals";
|
||||||
|
this.usageMessage = "/tps";
|
||||||
|
this.setPermission("poseidon.command.tps");
|
||||||
|
|
||||||
|
// Define the intervals for TPS calculation
|
||||||
|
intervals.put("5s", 5);
|
||||||
|
intervals.put("30s", 30);
|
||||||
|
intervals.put("1m", 60);
|
||||||
|
intervals.put("5m", 300);
|
||||||
|
intervals.put("10m", 600);
|
||||||
|
intervals.put("15m", 900);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||||
|
if (!testPermission(sender)) return true;
|
||||||
|
|
||||||
|
LinkedList<Double> tpsRecords = Poseidon.getTpsRecords();
|
||||||
|
StringBuilder message = new StringBuilder("§bServer TPS: ");
|
||||||
|
|
||||||
|
// Calculate and format TPS for each interval dynamically
|
||||||
|
for (Map.Entry<String, Integer> entry : intervals.entrySet()) {
|
||||||
|
double averageTps = calculateAverage(tpsRecords, entry.getValue());
|
||||||
|
message.append(formatTps(averageTps)).append(" (").append(entry.getKey()).append("), ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the trailing comma and space
|
||||||
|
if (message.length() > 0) {
|
||||||
|
message.setLength(message.length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(message.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateAverage(LinkedList<Double> records, int seconds) {
|
||||||
|
int size = Math.min(records.size(), seconds);
|
||||||
|
if (size == 0) return 20.0;
|
||||||
|
|
||||||
|
double total = 0;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
total += records.get(i);
|
||||||
|
}
|
||||||
|
return total / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTps(double tps) {
|
||||||
|
String colorCode;
|
||||||
|
if (tps >= 19) {
|
||||||
|
colorCode = "§a";
|
||||||
|
} else if (tps >= 15) {
|
||||||
|
colorCode = "§e";
|
||||||
|
} else {
|
||||||
|
colorCode = "§c";
|
||||||
|
}
|
||||||
|
return colorCode + String.format("%.2f", tps);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.legacyminecraft.poseidon.event;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PlayerDeathEvent extends EntityDeathEvent {
|
||||||
|
private String deathMessage = "";
|
||||||
|
private boolean keepInventory = false;
|
||||||
|
|
||||||
|
public PlayerDeathEvent(Entity what, List<ItemStack> drops) {
|
||||||
|
super(what, drops);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the death message that will appear to everyone on the server.
|
||||||
|
*
|
||||||
|
* @param deathMessage Message to appear to other players on the server.
|
||||||
|
*/
|
||||||
|
public void setDeathMessage(String deathMessage) {
|
||||||
|
this.deathMessage = deathMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the death message that will appear to everyone on the server.
|
||||||
|
*
|
||||||
|
* @return Message to appear to other players on the server.
|
||||||
|
*/
|
||||||
|
public String getDeathMessage() {
|
||||||
|
return deathMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if the Player keeps inventory on death.
|
||||||
|
*
|
||||||
|
* @param keepInventory True to keep the inventory
|
||||||
|
*/
|
||||||
|
public void setKeepInventory(boolean keepInventory) {
|
||||||
|
this.keepInventory = keepInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the Player keeps inventory on death.
|
||||||
|
*
|
||||||
|
* @return True if the player keeps inventory on death
|
||||||
|
*/
|
||||||
|
public boolean getKeepInventory() {
|
||||||
|
return keepInventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.legacyminecraft.poseidon.event;
|
||||||
|
|
||||||
|
import net.minecraft.server.Packet;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
|
|
||||||
|
public class PlayerPacketEvent extends Event implements Cancellable {
|
||||||
|
private boolean cancel;
|
||||||
|
private Packet packet;
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
public PlayerPacketEvent(Type type, String username, Packet packet) {
|
||||||
|
super(type);
|
||||||
|
this.cancel = false;
|
||||||
|
this.packet = packet;
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPacketID() {
|
||||||
|
return packet.b();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet getPacket() {
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPacket(Packet packet) {
|
||||||
|
this.packet = packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancel) {
|
||||||
|
this.cancel = cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.legacyminecraft.poseidon.event;
|
||||||
|
|
||||||
|
import net.minecraft.server.Packet;
|
||||||
|
|
||||||
|
public class PlayerReceivePacketEvent extends PlayerPacketEvent {
|
||||||
|
public PlayerReceivePacketEvent(String username, Packet packet) {
|
||||||
|
super(Type.PLAYER_RECEIVE_PACKET, username, packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.legacyminecraft.poseidon.event;
|
||||||
|
|
||||||
|
import net.minecraft.server.Packet;
|
||||||
|
|
||||||
|
public class PlayerSendPacketEvent extends PlayerPacketEvent {
|
||||||
|
|
||||||
|
public PlayerSendPacketEvent(String username, Packet packet) {
|
||||||
|
super(Type.PLAYER_SEND_PACKET, username, packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.legacyminecraft.poseidon.event;
|
||||||
|
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
public interface PoseidonCustomListener extends Listener {
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.legacyminecraft.poseidon.packets;
|
||||||
|
|
||||||
|
import net.minecraft.server.NetHandler;
|
||||||
|
import net.minecraft.server.Packet;
|
||||||
|
import net.minecraft.server.World;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ArtificialPacket53BlockChange extends Packet {
|
||||||
|
|
||||||
|
public int a;
|
||||||
|
public int b;
|
||||||
|
public int c;
|
||||||
|
public int material;
|
||||||
|
public int data;
|
||||||
|
|
||||||
|
public ArtificialPacket53BlockChange() {
|
||||||
|
this.k = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtificialPacket53BlockChange(int i, int j, int k, World world) {
|
||||||
|
this.k = true;
|
||||||
|
this.a = i;
|
||||||
|
this.b = j;
|
||||||
|
this.c = k;
|
||||||
|
this.material = world.getTypeId(i, j, k);
|
||||||
|
this.data = world.getData(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtificialPacket53BlockChange(int i, int j, int k, int materialType, int data) {
|
||||||
|
this.k = true;
|
||||||
|
this.a = i;
|
||||||
|
this.b = j;
|
||||||
|
this.c = k;
|
||||||
|
this.material = materialType;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(DataInputStream datainputstream) throws IOException {
|
||||||
|
this.a = datainputstream.readInt();
|
||||||
|
this.b = datainputstream.read();
|
||||||
|
this.c = datainputstream.readInt();
|
||||||
|
this.material = datainputstream.read();
|
||||||
|
this.data = datainputstream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(DataOutputStream dataoutputstream) throws IOException {
|
||||||
|
dataoutputstream.writeInt(this.a);
|
||||||
|
dataoutputstream.write(this.b);
|
||||||
|
dataoutputstream.writeInt(this.c);
|
||||||
|
dataoutputstream.write(this.material);
|
||||||
|
dataoutputstream.write(this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(NetHandler nethandler) {
|
||||||
|
nethandler.a(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a() {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static com.projectposeidon.johnymuffin.UUIDManager.generateOfflineUUID;
|
||||||
|
|
||||||
|
public class GetUUIDFetcher {
|
||||||
|
|
||||||
|
public static class UUIDAndUsernameResult {
|
||||||
|
private UUIDResult uuidResult;
|
||||||
|
private String returnedUsername;
|
||||||
|
|
||||||
|
public UUIDAndUsernameResult(UUIDResult uuidResult, String returnedUsername) {
|
||||||
|
this.uuidResult = uuidResult;
|
||||||
|
this.returnedUsername = returnedUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUIDResult getUuidResult() {
|
||||||
|
return uuidResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturnedUsername() {
|
||||||
|
return returnedUsername;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static UUIDAndUsernameResult getUUID(String username) {
|
||||||
|
try {
|
||||||
|
String url = PoseidonConfig.getInstance().getString("settings.uuid-fetcher.get.value", "https://api.minecraftservices.com/minecraft/profile/lookup/name/{username}");
|
||||||
|
url = url.replace("{username}", encode(username));
|
||||||
|
|
||||||
|
JSONObject jsonObject = readJsonFromUrl(url);
|
||||||
|
UUIDResult uuidResult;
|
||||||
|
String returnedUsername = null;
|
||||||
|
|
||||||
|
if (!jsonObject.containsKey("id")) {
|
||||||
|
uuidResult = new UUIDResult(generateOfflineUUID(username), UUIDResult.ReturnType.OFFLINE);
|
||||||
|
} else {
|
||||||
|
UUID uuid = toUUIDWithDashes(String.valueOf(jsonObject.get("id")));
|
||||||
|
if (uuid == null) {
|
||||||
|
uuidResult = new UUIDResult(null, UUIDResult.ReturnType.API_OFFLINE);
|
||||||
|
} else {
|
||||||
|
returnedUsername = String.valueOf(jsonObject.get("name"));
|
||||||
|
uuidResult = new UUIDResult(uuid, UUIDResult.ReturnType.ONLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UUIDAndUsernameResult(uuidResult, returnedUsername);
|
||||||
|
|
||||||
|
} catch (Exception exception) {
|
||||||
|
UUIDResult uuidResult = null;
|
||||||
|
if (exception == null || exception instanceof FileNotFoundException || exception.getMessage() == null) {
|
||||||
|
// This is a hacky solution to tell if the API is offline, or the user is cracked.
|
||||||
|
uuidResult = new UUIDResult(generateOfflineUUID(username), UUIDResult.ReturnType.OFFLINE);
|
||||||
|
} else {
|
||||||
|
uuidResult = new UUIDResult(null, UUIDResult.ReturnType.API_OFFLINE);
|
||||||
|
uuidResult.setException(exception);
|
||||||
|
}
|
||||||
|
return new UUIDAndUsernameResult(uuidResult, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String encode(String string) {
|
||||||
|
try {
|
||||||
|
return URLEncoder.encode(string, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID toUUIDWithDashes(String uuid) {
|
||||||
|
return UUID.fromString(uuid.replaceFirst("(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean verifyJSONArguments(JSONObject jsonObject, String... arguments) {
|
||||||
|
for (String s : arguments) {
|
||||||
|
if (!jsonObject.containsKey(s)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isURL(String url) {
|
||||||
|
try {
|
||||||
|
new URL(url);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validUUID(String uuid) {
|
||||||
|
return Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$").matcher(uuid).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String readAll(Reader rd) throws IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int cp;
|
||||||
|
while ((cp = rd.read()) != -1) {
|
||||||
|
sb.append((char) cp);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject readJsonFromUrl(String url) throws IOException, ParseException {
|
||||||
|
InputStream is = new URL(url).openStream();
|
||||||
|
try {
|
||||||
|
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
|
||||||
|
String jsonText = readAll(rd);
|
||||||
|
JSONParser jsp = new JSONParser();
|
||||||
|
JSONObject json = (JSONObject) jsp.parse(jsonText);
|
||||||
|
return json;
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
public class HTTPResponse
|
||||||
|
{
|
||||||
|
private String response;
|
||||||
|
private int responseCode;
|
||||||
|
|
||||||
|
public HTTPResponse(String response, int responseCode)
|
||||||
|
{
|
||||||
|
this.response = response;
|
||||||
|
this.responseCode = responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponse()
|
||||||
|
{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getResponseCode()
|
||||||
|
{
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
|
public class Release2Beta {
|
||||||
|
|
||||||
|
public static long serializeAddress(SocketAddress address) {
|
||||||
|
String str = address.toString();
|
||||||
|
String[] parts = str.split(":");
|
||||||
|
|
||||||
|
String realAddress = parts[0].substring(1); // remove '/'
|
||||||
|
return ipToLong(realAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InetSocketAddress deserializeAddress(long spoofedAddress) {
|
||||||
|
String realAddress = longToIp(spoofedAddress);
|
||||||
|
return new InetSocketAddress(realAddress, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Credit: https://mkyong.com/java/java-convert-ip-address-to-decimal-number/
|
||||||
|
public static long ipToLong(String ipAddress) {
|
||||||
|
// ipAddressInArray[0] = 192
|
||||||
|
String[] ipAddressInArray = ipAddress.split("\\.");
|
||||||
|
|
||||||
|
long result = 0;
|
||||||
|
for (int i = 0; i < ipAddressInArray.length; i++) {
|
||||||
|
|
||||||
|
int power = 3 - i;
|
||||||
|
int ip = Integer.parseInt(ipAddressInArray[i]);
|
||||||
|
|
||||||
|
// 1. 192 * 256^3
|
||||||
|
// 2. 168 * 256^2
|
||||||
|
// 3. 1 * 256^1
|
||||||
|
// 4. 2 * 256^0
|
||||||
|
result += ip * Math.pow(256, power);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Credit: https://mkyong.com/java/java-convert-ip-address-to-decimal-number/
|
||||||
|
private static String longToIp(long i) {
|
||||||
|
|
||||||
|
return ((i >> 24) & 0xFF) +
|
||||||
|
"." + ((i >> 16) & 0xFF) +
|
||||||
|
"." + ((i >> 8) & 0xFF) +
|
||||||
|
"." + (i & 0xFF);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.logging.*;
|
||||||
|
|
||||||
|
public class ServerLogRotator {
|
||||||
|
private final String latestLogFileName;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public ServerLogRotator(String latestLogFileName) {
|
||||||
|
this.latestLogFileName = latestLogFileName;
|
||||||
|
this.logger = Logger.getLogger("Minecraft");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the date in the log line is today's date
|
||||||
|
* @param date The date in the log line. Format: "yyyy-MM-dd"
|
||||||
|
* @return True if the date in the log line is today's date, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isToday(String date) {
|
||||||
|
String[] dateParts = date.split("-");
|
||||||
|
LocalDateTime logLineDateTime = LocalDateTime.of(Integer.parseInt(dateParts[0]), Integer.parseInt(dateParts[1]), Integer.parseInt(dateParts[2]), 0, 0, 0);
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
return logLineDateTime.getYear() == now.getYear() && logLineDateTime.getMonthValue() == now.getMonthValue() && logLineDateTime.getDayOfMonth() == now.getDayOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archives a log line to a log file with the same date as the date in the log line
|
||||||
|
* @param parts The log line to archive to a log file haven been split already e.g. ["2024-03-20", "13:02:27", "[INFO]", "This is a log message..."]
|
||||||
|
*/
|
||||||
|
private void archiveLine(String[] parts) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
String date = parts[0];
|
||||||
|
String time = parts[1];
|
||||||
|
String logLevel = parts[2];
|
||||||
|
String message = String.join(" ", Arrays.copyOfRange(parts, 3, parts.length));
|
||||||
|
// check if a log file with this information already exists
|
||||||
|
File logFile = new File("." + File.separator + "logs" + File.separator + date + ".log");
|
||||||
|
if (!logFile.exists()) {
|
||||||
|
logFile.createNewFile();
|
||||||
|
}
|
||||||
|
// append the log line to the log file with the same date as the date in the log line
|
||||||
|
FileWriter fileWriter = new FileWriter(logFile, true);
|
||||||
|
PrintWriter writer = new PrintWriter(fileWriter);
|
||||||
|
writer.println(date + " " + time + " " + logLevel + " " + message);
|
||||||
|
writer.close();
|
||||||
|
|
||||||
|
// catch any exceptions that occur during the process, and log them. IOExceptions are possible when calling createNewFile()
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.log(Level.SEVERE, "[Poseidon] Failed to create new log file!");
|
||||||
|
logger.log(Level.SEVERE, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds historical logs from the latest.log file. Logs from today's date are kept in the latest.log file, while logs from previous dates are archived to log files with the same date as the date in the log line.
|
||||||
|
* Note that if latest.log contains logs from multiple days, the logs will be split by date and archived to the appropriate log files.
|
||||||
|
*/
|
||||||
|
private void buildHistoricalLogsFromLatestLogFile() {
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "[Poseidon] Building logs from latest.log...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// open latest log file
|
||||||
|
File latestLog = new File("." + File.separator + "logs" + File.separator + this.latestLogFileName + ".log");
|
||||||
|
if (!latestLog.exists()) {
|
||||||
|
logger.log(Level.INFO, "[Poseidon] No logs to build from latest.log!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split the contents of the latest log file by line (and strip the newline character)
|
||||||
|
String content = new String(Files.readAllBytes(latestLog.toPath()));
|
||||||
|
String[] lines = content.split("\n");
|
||||||
|
// create a StringBuilder to store today's logs (to write back to latest.log after archiving the rest of the logs)
|
||||||
|
StringBuilder todayLogs = new StringBuilder();
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
|
||||||
|
String[] splitLine = line.split(" ");
|
||||||
|
if (splitLine.length < 3) { // all lines will start with a date, time, and log level e.g. "2024-03-20 13:02:27 [INFO]"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the first index is a date
|
||||||
|
if (!splitLine[0].matches("\\d{4}-\\d{2}-\\d{2}")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the log line is of today's date, do not archive it (ignore times)
|
||||||
|
if (isToday(splitLine[0])) {
|
||||||
|
todayLogs.append(line).append("\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// archive the log line to a log file with the same date as the date in the log line
|
||||||
|
archiveLine(splitLine);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear latest.log and write back today's logs from the StringBuilder
|
||||||
|
FileWriter fileWriter = new FileWriter(latestLog);
|
||||||
|
PrintWriter writer = new PrintWriter(fileWriter);
|
||||||
|
writer.print(todayLogs);
|
||||||
|
writer.close();
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "[Poseidon] Logs built from latest.log!");
|
||||||
|
|
||||||
|
// catch any exceptions that occur during the process, and log them
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, "[Poseidon] Failed to build logs from latest.log!");
|
||||||
|
logger.log(Level.SEVERE, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
// Calculate the initial delay and period for the log rotation task
|
||||||
|
ZonedDateTime now = ZonedDateTime.now();
|
||||||
|
ZonedDateTime nextRun = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||||
|
if(now.compareTo(nextRun) > 0)
|
||||||
|
nextRun = nextRun.plusDays(1);
|
||||||
|
Duration duration = Duration.between(now, nextRun);
|
||||||
|
long initialDelay = duration.getSeconds();
|
||||||
|
long period = TimeUnit.DAYS.toSeconds(1);
|
||||||
|
|
||||||
|
// do log rotation immediately upon startup to ensure that logs are archived correctly.
|
||||||
|
buildHistoricalLogsFromLatestLogFile();
|
||||||
|
|
||||||
|
// Schedule the log rotation task to run every day at midnight offset by one second to avoid missing logs
|
||||||
|
logger.log(Level.INFO, "[Poseidon] Log rotation task scheduled for run in " + initialDelay + " seconds, and then every " + period + " seconds.");
|
||||||
|
logger.log(Level.INFO, "[Poseidon] If latest.log contains logs from earlier, not previously archived dates, they will be archived to the appropriate log files " +
|
||||||
|
"upon first run of the log rotation task. If log files already exist for these dates, the logs will be appended to the existing log files!");
|
||||||
|
Bukkit.getScheduler().scheduleAsyncRepeatingTask(new PoseidonPlugin(), this::buildHistoricalLogsFromLatestLogFile, (initialDelay + 1) * 20, period * 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class for the Minecraft session API
|
||||||
|
*
|
||||||
|
* TODO maybe make the HTTP requests asynchronous? idk if it really matters
|
||||||
|
*
|
||||||
|
* @author moderator_man
|
||||||
|
*/
|
||||||
|
public class SessionAPI
|
||||||
|
{
|
||||||
|
public static final String SESSION_BASE = "http://session.minecraft.net/game/";
|
||||||
|
|
||||||
|
public static boolean hasJoined(String username, String serverId)
|
||||||
|
{
|
||||||
|
HTTPResponse response = httpGetRequest(SESSION_BASE + String.format("checkserver.jsp?user=%s&serverId=%s", username, serverId));
|
||||||
|
if (response.getResponse() != "YES")
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hasJoined(String username, String serverId, String ip, SessionRequestRunnable callback)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boolean checkIP = ip == "127.0.0.1" || ip == "localhost";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(System.getProperty("minecraft.api.session.host", "https://sessionserver.mojang.com") + "/session/minecraft/hasJoined");
|
||||||
|
sb.append("?username=" + username);
|
||||||
|
sb.append("&serverId=" + serverId);
|
||||||
|
if (checkIP)
|
||||||
|
sb.append("&ip=" + ip);
|
||||||
|
String requestUrl = sb.toString();
|
||||||
|
|
||||||
|
HTTPResponse response = httpGetRequest(requestUrl);
|
||||||
|
JSONObject obj = (JSONObject) new JSONParser().parse(response.getResponse());
|
||||||
|
String res_username = (obj.containsKey("name") ? (String) obj.get("name") : "nousername");
|
||||||
|
String res_uuid = (obj.containsKey("id") ? (String) obj.get("id") : "nouuid");
|
||||||
|
String res_ip = (obj.containsKey("ip") ? (String) obj.get("ip") : "noip");
|
||||||
|
callback.callback(response.getResponseCode(), res_username, res_uuid, res_ip);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(String.format("Failed to authenticate session for '%s': %s", username, ex.getMessage()));
|
||||||
|
// TODO: if debug, print the stack trace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HTTPResponse httpGetRequest(String url)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
URL obj = new URL(url);
|
||||||
|
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||||
|
con.setRequestMethod("GET");
|
||||||
|
con.setRequestProperty("User-Agent", "Project-Poseidon/0");
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuffer response = new StringBuffer();
|
||||||
|
while ((inputLine = in.readLine()) != null)
|
||||||
|
response.append(inputLine);
|
||||||
|
in.close();
|
||||||
|
return new HTTPResponse(response.toString(), con.getResponseCode());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return new HTTPResponse("", -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
public interface SessionRequestRunnable
|
||||||
|
{
|
||||||
|
public void callback(int responseCode, String username, String uuid, String ip);
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class UUIDFetcher implements Callable<Map<String, UUID>> {
|
||||||
|
private static final double PROFILES_PER_REQUEST = 100;
|
||||||
|
private static final String PROFILE_URL = PoseidonConfig.getInstance().getString("settings.uuid-fetcher.post.value", "https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname");
|
||||||
|
private final JSONParser jsonParser = new JSONParser();
|
||||||
|
private final List<String> names;
|
||||||
|
private final boolean rateLimiting;
|
||||||
|
|
||||||
|
public UUIDFetcher(List<String> names, boolean rateLimiting) {
|
||||||
|
this.names = ImmutableList.copyOf(names);
|
||||||
|
this.rateLimiting = rateLimiting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUIDFetcher(List<String> names) {
|
||||||
|
this(names, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, UUID> call() throws Exception {
|
||||||
|
Map<String, UUID> uuidMap = new HashMap<String, UUID>();
|
||||||
|
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
|
||||||
|
for (int i = 0; i < requests; i++) {
|
||||||
|
HttpURLConnection connection = createConnection();
|
||||||
|
String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
|
||||||
|
writeBody(connection, body);
|
||||||
|
JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
|
||||||
|
for (Object profile : array) {
|
||||||
|
JSONObject jsonProfile = (JSONObject) profile;
|
||||||
|
String id = (String) jsonProfile.get("id");
|
||||||
|
String name = (String) jsonProfile.get("name");
|
||||||
|
UUID uuid = UUIDFetcher.getUUID(id);
|
||||||
|
uuidMap.put(name, uuid);
|
||||||
|
}
|
||||||
|
if (rateLimiting && i != requests - 1) {
|
||||||
|
Thread.sleep(100L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uuidMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeBody(HttpURLConnection connection, String body) throws Exception {
|
||||||
|
OutputStream stream = connection.getOutputStream();
|
||||||
|
stream.write(body.getBytes());
|
||||||
|
stream.flush();
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpURLConnection createConnection() throws Exception {
|
||||||
|
URL url = new URL(PROFILE_URL);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
connection.setUseCaches(false);
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UUID getUUID(String id) {
|
||||||
|
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +id.substring(20, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] toBytes(UUID uuid) {
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
|
||||||
|
byteBuffer.putLong(uuid.getMostSignificantBits());
|
||||||
|
byteBuffer.putLong(uuid.getLeastSignificantBits());
|
||||||
|
return byteBuffer.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID fromBytes(byte[] array) {
|
||||||
|
if (array.length != 16) {
|
||||||
|
throw new IllegalArgumentException("Illegal byte array length: " + array.length);
|
||||||
|
}
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.wrap(array);
|
||||||
|
long mostSignificant = byteBuffer.getLong();
|
||||||
|
long leastSignificant = byteBuffer.getLong();
|
||||||
|
return new UUID(mostSignificant, leastSignificant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID getUUIDOf(String name) throws Exception {
|
||||||
|
return new UUIDFetcher(Arrays.asList(name)).call().get(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.legacyminecraft.poseidon.util;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UUIDResult {
|
||||||
|
private final UUID uuid;
|
||||||
|
private final ReturnType returnType;
|
||||||
|
private Exception exception;
|
||||||
|
|
||||||
|
public UUIDResult(UUID uuid, ReturnType returnType) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.returnType = returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReturnType getReturnType() {
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setException(Exception exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum ReturnType {
|
||||||
|
ONLINE,
|
||||||
|
OFFLINE,
|
||||||
|
API_OFFLINE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.legacyminecraft.poseidon.utility;
|
||||||
|
|
||||||
|
public class PerformanceStatistic {
|
||||||
|
private long minTime = Long.MAX_VALUE;
|
||||||
|
private long maxTime = 0;
|
||||||
|
private long totalTime = 0;
|
||||||
|
private long count = 0;
|
||||||
|
|
||||||
|
// Update the stats with a new execution time
|
||||||
|
public void update(long duration) {
|
||||||
|
if (duration < minTime) {
|
||||||
|
minTime = duration;
|
||||||
|
}
|
||||||
|
if (duration > maxTime) {
|
||||||
|
maxTime = duration;
|
||||||
|
}
|
||||||
|
totalTime += duration;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the average execution time
|
||||||
|
long getAverageTime() {
|
||||||
|
return count > 0 ? totalTime / count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the statistics for this listener
|
||||||
|
public String printStats() {
|
||||||
|
return String.format("Called: %d times, Min: %dms, Avg: %dms, Max: %dms", count, minTime, getAverageTime(), maxTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getEventCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotalExecutionTime() {
|
||||||
|
return totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAverageExecutionTime() {
|
||||||
|
return getAverageTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMinExecutionTime() {
|
||||||
|
return minTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMaxExecutionTime() {
|
||||||
|
return maxTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.legacyminecraft.poseidon.utility;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class PoseidonVersionChecker {
|
||||||
|
|
||||||
|
private static final String GITHUB_API_URL = "https://api.github.com/repos/retromcorg/Project-Poseidon/releases/latest";
|
||||||
|
private static final String releaseUrl = "https://github.com/retromcorg/Project-Poseidon/releases";
|
||||||
|
private final String currentVersion;
|
||||||
|
private volatile String latestVersion;
|
||||||
|
private CraftServer server;
|
||||||
|
|
||||||
|
public PoseidonVersionChecker(CraftServer server, String currentVersion) {
|
||||||
|
this.currentVersion = currentVersion;
|
||||||
|
this.latestVersion = currentVersion; // Assume the latest version is the current version until checked
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a new version is available.
|
||||||
|
*
|
||||||
|
* @return true if a newer version is available, false otherwise.
|
||||||
|
*/
|
||||||
|
public synchronized boolean isUpdateAvailable() {
|
||||||
|
return latestVersion != null && !currentVersion.equalsIgnoreCase(latestVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the latest release version from GitHub API.
|
||||||
|
*
|
||||||
|
* @return the latest version as a String or null if fetching fails.
|
||||||
|
*/
|
||||||
|
public void fetchLatestVersion() {
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(GITHUB_API_URL);
|
||||||
|
connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
connection.setRequestProperty("Accept", "application/json");
|
||||||
|
connection.setConnectTimeout(5000);
|
||||||
|
connection.setReadTimeout(5000);
|
||||||
|
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
if (responseCode != HttpURLConnection.HTTP_OK) {
|
||||||
|
server.getLogger().log(Level.WARNING, "[Poseidon] Failed to check GitHub for latest version. HTTP Response Code: " + responseCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
JSONParser parser = new JSONParser();
|
||||||
|
JSONObject json = (JSONObject) parser.parse(response.toString());
|
||||||
|
|
||||||
|
this.latestVersion = (String) json.get("tag_name");
|
||||||
|
|
||||||
|
if (isUpdateAvailable()) {
|
||||||
|
server.getLogger().log(Level.INFO, "[Poseidon] A new version is available: " + latestVersion);
|
||||||
|
server.getLogger().log(Level.INFO, "[Poseidon] You are currently running version: " + currentVersion);
|
||||||
|
server.getLogger().log(Level.INFO, "[Poseidon] Download the latest version here: " + releaseUrl);
|
||||||
|
} else {
|
||||||
|
if (PoseidonConfig.getInstance().getConfigBoolean("settings.update-checker.notify-if-up-to-date.enabled"))
|
||||||
|
server.getLogger().log(Level.INFO, "[Poseidon] You are running the latest version (" + currentVersion + ") of Project Poseidon.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
server.getLogger().log(Level.WARNING, "[Poseidon] Failed to check GitHub for latest version.", e);
|
||||||
|
} finally {
|
||||||
|
if (connection != null) {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrentVersion() {
|
||||||
|
return currentVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLatestVersion() {
|
||||||
|
return latestVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.legacyminecraft.poseidon.uuid;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import com.legacyminecraft.poseidon.util.GetUUIDFetcher;
|
||||||
|
import com.legacyminecraft.poseidon.util.UUIDResult;
|
||||||
|
import com.projectposeidon.johnymuffin.LoginProcessHandler;
|
||||||
|
import net.minecraft.server.Packet1Login;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.legacyminecraft.poseidon.util.UUIDFetcher.getUUIDOf;
|
||||||
|
import static com.projectposeidon.johnymuffin.UUIDManager.generateOfflineUUID;
|
||||||
|
|
||||||
|
public class ThreadUUIDFetcher extends Thread {
|
||||||
|
|
||||||
|
final Packet1Login loginPacket;
|
||||||
|
// final NetLoginHandler netLoginHandler;
|
||||||
|
final LoginProcessHandler loginProcessHandler;
|
||||||
|
final boolean useGetMethod;
|
||||||
|
|
||||||
|
public ThreadUUIDFetcher(Packet1Login packet1Login, LoginProcessHandler loginProcessHandler, boolean useGetMethod) {
|
||||||
|
// this.netLoginHandler = netloginhandler; // The login handler
|
||||||
|
this.loginProcessHandler = loginProcessHandler;
|
||||||
|
this.loginPacket = packet1Login; // The login packet
|
||||||
|
this.useGetMethod = useGetMethod;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if (PoseidonConfig.getInstance().getBoolean("settings.uuid-fetcher.always-use-graceful-uuids.enabled", false)) {
|
||||||
|
System.out.println("[Poseidon] Skipping UUID fetching since always-use-graceful-uuids is enabled, " + loginPacket.name + " will use offline UUID.");
|
||||||
|
UUID offlineUUID = generateOfflineUUID(loginPacket.name);
|
||||||
|
loginProcessHandler.userUUIDReceived(offlineUUID, false);
|
||||||
|
return;
|
||||||
|
} else if (useGetMethod) {
|
||||||
|
getMethod();
|
||||||
|
} else {
|
||||||
|
postMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getMethod() {
|
||||||
|
UUIDResult uuidResult;
|
||||||
|
GetUUIDFetcher.UUIDAndUsernameResult uuidAndUsernameResult = GetUUIDFetcher.getUUID(loginPacket.name);
|
||||||
|
uuidResult = uuidAndUsernameResult.getUuidResult();
|
||||||
|
|
||||||
|
if (uuidResult.getReturnType().equals(UUIDResult.ReturnType.ONLINE) && uuidAndUsernameResult.getReturnedUsername().equals(loginPacket.name)) {
|
||||||
|
System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " using GET - " + uuidResult.getUuid().toString());
|
||||||
|
loginProcessHandler.userUUIDReceived(uuidResult.getUuid(), true);
|
||||||
|
return;
|
||||||
|
} else if (uuidResult.getReturnType().equals(UUIDResult.ReturnType.ONLINE)) {
|
||||||
|
if(PoseidonConfig.getInstance().getConfigBoolean("settings.uuid-fetcher.get.enforce-case-sensitivity.enabled")) {
|
||||||
|
System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " using GET - " + uuidResult.getUuid().toString() + " however, the username returned was " + uuidAndUsernameResult.getReturnedUsername() + ". The user has been kicked as the server is configured to use case sensitive usernames");
|
||||||
|
loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, that username has invalid casing");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " - " + uuidResult.getUuid().toString());
|
||||||
|
loginProcessHandler.userUUIDReceived(uuidResult.getUuid(), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (uuidResult.getReturnType().equals(UUIDResult.ReturnType.OFFLINE)) {
|
||||||
|
if ((boolean) PoseidonConfig.getInstance().getProperty("settings.uuid-fetcher.allow-graceful-uuids.value")) {
|
||||||
|
System.out.println("[Poseidon] " + loginPacket.name + " does not have a Mojang UUID associated with their name");
|
||||||
|
UUID offlineUUID = uuidResult.getUuid();
|
||||||
|
loginProcessHandler.userUUIDReceived(offlineUUID, false);
|
||||||
|
System.out.println("[Poseidon] Using Offline Based UUID for " + loginPacket.name + " - " + offlineUUID);
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon] " + loginPacket.name + " does not have a UUID with Mojang. Player has been kicked as graceful UUID is disabled");
|
||||||
|
loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, we only support premium accounts");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("[Poseidon] Failed to fetch UUID for " + loginPacket.name + " using GET method from Mojang.");
|
||||||
|
System.out.println("[Poseidon] Mojang's API may be offline, your internet connection may be down, or something else may be wrong.");
|
||||||
|
|
||||||
|
uuidResult.getException().printStackTrace();
|
||||||
|
loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, we can't connect to Mojang currently, please try again later");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void postMethod() {
|
||||||
|
UUID uuid;
|
||||||
|
try {
|
||||||
|
uuid = getUUIDOf(loginPacket.name);
|
||||||
|
if (uuid == null) {
|
||||||
|
if (PoseidonConfig.getInstance().getConfigBoolean("settings.uuid-fetcher.allow-graceful-uuids.value", true)) {
|
||||||
|
System.out.println("[Poseidon] " + loginPacket.name + " does not have a Mojang UUID associated with their name");
|
||||||
|
UUID offlineUUID = generateOfflineUUID(loginPacket.name);
|
||||||
|
loginProcessHandler.userUUIDReceived(offlineUUID, false);
|
||||||
|
System.out.println("[Poseidon] Using Offline Based UUID for " + loginPacket.name + " - " + offlineUUID);
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon] " + loginPacket.name + " does not have a UUID with Mojang. Player has been kicked as graceful UUID is disabled");
|
||||||
|
loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, we only support premium accounts");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " using POST - " + uuid.toString());
|
||||||
|
loginProcessHandler.userUUIDReceived(uuid, true);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("[Poseidon] Mojang failed contact for user " + loginPacket.name + ":");
|
||||||
|
|
||||||
|
System.out.println("[Poseidon] If this issue persists, please utilize the GET method. Mojang's API frequently has issues with POST requests.");
|
||||||
|
System.out.println("[Poseidon] You can do this by changing settings.uuid-fetcher.method.value to GET in the config");
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, we can't connect to Mojang currently, please try again later");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.legacyminecraft.poseidon.watchdog;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class WatchDogThread extends Thread {
|
||||||
|
private int count = 0;
|
||||||
|
private Long lastTick = System.currentTimeMillis() / 1000L;
|
||||||
|
private volatile AtomicBoolean tickOccurred = new AtomicBoolean(true);
|
||||||
|
private Thread serverThread;
|
||||||
|
private final int killTimeout;
|
||||||
|
//Debug Timeout
|
||||||
|
private final boolean debugTimeoutEnabled;
|
||||||
|
private final int debugTimeout;
|
||||||
|
private boolean printedDebug;
|
||||||
|
|
||||||
|
public WatchDogThread(Thread thread) {
|
||||||
|
this.serverThread = thread;
|
||||||
|
this.killTimeout = PoseidonConfig.getInstance().getConfigInteger("settings.watchdog.timeout.value");
|
||||||
|
|
||||||
|
this.debugTimeoutEnabled = PoseidonConfig.getInstance().getConfigBoolean("settings.watchdog.debug-timeout.enabled");
|
||||||
|
this.debugTimeout = PoseidonConfig.getInstance().getConfigInteger("settings.watchdog.debug-timeout.value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
boolean running = true;
|
||||||
|
while (true && !this.isInterrupted() && running) {
|
||||||
|
try {
|
||||||
|
if (tickOccurred.get()) {
|
||||||
|
lastTick = System.currentTimeMillis() / 1000L;
|
||||||
|
tickOccurred.set(false);
|
||||||
|
printedDebug = false; //Set back tp false so if server hangs again debug is printed.
|
||||||
|
} else {
|
||||||
|
//Server timout check
|
||||||
|
if ((lastTick + killTimeout) < (System.currentTimeMillis() / 1000L)) {
|
||||||
|
System.out.println("[Poseidon-Watchdog] Server has hanged. Killing the process as a result of the watchdog timeout being exceeded.");
|
||||||
|
System.out.println("--------------------[Stacktrace For Developers]--------------------");
|
||||||
|
Arrays.asList(serverThread.getStackTrace()).forEach(System.out::println);
|
||||||
|
System.out.println("-------------------------------------------------------------------");
|
||||||
|
Runtime.getRuntime().halt(0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon-Watchdog] A server tick hasn't occurred in " + ((int) ((System.currentTimeMillis() / 1000L) - lastTick)) + " seconds.");
|
||||||
|
//Server debug timeout
|
||||||
|
if((lastTick + debugTimeout) < (System.currentTimeMillis() / 1000L) && debugTimeoutEnabled && !printedDebug) {
|
||||||
|
System.out.println("[Poseidon-Watchdog] Server hang detected. Printing debug as debug timeout has been exceeded.");
|
||||||
|
System.out.println("--------------------[Stacktrace For Developers]--------------------");
|
||||||
|
Arrays.asList(serverThread.getStackTrace()).forEach(System.out::println);
|
||||||
|
System.out.println("-------------------------------------------------------------------");
|
||||||
|
printedDebug = true; //This variable prevents debug from printing multiple times during a single tick.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.sleep(3000L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("[Poseidon-Watchdog] The watchdog has been interrupted.");
|
||||||
|
// e.printStackTrace();
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickUpdate() {
|
||||||
|
tickOccurred.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHangDetected() {
|
||||||
|
return tickOccurred.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.projectposeidon;
|
||||||
|
|
||||||
|
public enum ConnectionType {
|
||||||
|
NORMAL,
|
||||||
|
RELEASE2BETA,
|
||||||
|
RELEASE2BETA_ONLINE_MODE_IP_FORWARDING,
|
||||||
|
RELEASE2BETA_OFFLINE_MODE_IP_FORWARDING,
|
||||||
|
BUNGEECORD,
|
||||||
|
BUNGEECORD_OFFLINE_MODE_IP_FORWARDING,
|
||||||
|
BUNGEECORD_ONLINE_MODE_IP_FORWARDING,
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
We will no longer store classes under the name of the developer who created it. Current legacy stuff may stay in its current position tho.
|
||||||
|
All new classes must be created under com.legacyminecraft.poseidon
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.projectposeidon.api;
|
||||||
|
|
||||||
|
import com.projectposeidon.johnymuffin.UUIDManager;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class PoseidonUUID {
|
||||||
|
|
||||||
|
private PoseidonUUID() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username Username of a player who has connected
|
||||||
|
* @return A Mojang UUID if known, otherwise null
|
||||||
|
*/
|
||||||
|
public static UUID getPlayerMojangUUID(String username) {
|
||||||
|
return UUIDManager.getInstance().getUUIDFromUsername(username, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username Username of a player who has connected
|
||||||
|
* @return A Mojang UUID if known, otherwise a offline uuid
|
||||||
|
*/
|
||||||
|
public static UUID getPlayerGracefulUUID(String username) {
|
||||||
|
return UUIDManager.getInstance().getUUIDGraceful(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a UUID of a player IF they have joined before.
|
||||||
|
*
|
||||||
|
* @param username Username of a player who has connected
|
||||||
|
* @param onlineUUID Search for online or offline UUIDs?
|
||||||
|
* @return Returns a UUID if known in cache, otherwise null
|
||||||
|
*/
|
||||||
|
public static UUID getPlayerUUIDFromCache(String username, boolean onlineUUID) {
|
||||||
|
return UUIDManager.getInstance().getUUIDFromUsername(username, onlineUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username Username of a player
|
||||||
|
* @return A offline UUID for a player
|
||||||
|
*/
|
||||||
|
public static UUID getPlayerOfflineUUID(String username) {
|
||||||
|
return UUIDManager.generateOfflineUUID(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username Username of a player
|
||||||
|
* @return A UUIDType enum.
|
||||||
|
*/
|
||||||
|
public static UUIDType getPlayerUUIDCacheStatus(String username) {
|
||||||
|
if (getPlayerUUIDFromCache(username, true) != null) {
|
||||||
|
return UUIDType.ONLINE;
|
||||||
|
}
|
||||||
|
if (getPlayerUUIDFromCache(username, false) != null) {
|
||||||
|
return UUIDType.OFFLINE;
|
||||||
|
}
|
||||||
|
return UUIDType.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uuid UUID for a player
|
||||||
|
* @return A corresponding username if known, otherwise null
|
||||||
|
*/
|
||||||
|
public static String getPlayerUsernameFromUUID(UUID uuid) {
|
||||||
|
return UUIDManager.getInstance().getUsernameFromUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.projectposeidon.api;
|
||||||
|
|
||||||
|
public enum UUIDType {
|
||||||
|
//I was not sure about the coding conventions regarding capitalization. I have followed the ALL caps example in the Java Docs: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
|
||||||
|
ONLINE,
|
||||||
|
OFFLINE,
|
||||||
|
UNKNOWN
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.projectposeidon.johnymuffin;
|
||||||
|
|
||||||
|
public class ConnectionPause {
|
||||||
|
private String pluginName;
|
||||||
|
private String connectionPauseName;
|
||||||
|
private LoginProcessHandler loginProcessHandler;
|
||||||
|
private long creationTime;
|
||||||
|
|
||||||
|
private long completionTime;
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
public ConnectionPause(String PluginName, String connectionPauseName, LoginProcessHandler loginProcessHandler) {
|
||||||
|
this.pluginName = PluginName;
|
||||||
|
this.connectionPauseName = connectionPauseName;
|
||||||
|
this.loginProcessHandler = loginProcessHandler;
|
||||||
|
this.creationTime = System.currentTimeMillis();
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is still undecided, please don't use it in production.
|
||||||
|
*/
|
||||||
|
public void removeConnectionPause() {
|
||||||
|
loginProcessHandler.removeConnectionPause(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPluginName() {
|
||||||
|
return this.pluginName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConnectionPauseName() {
|
||||||
|
return this.connectionPauseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getCreationTime() {
|
||||||
|
return creationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is for Poseidon, not plugin use. DON'T TOUCH THIS IF YOU DON'T KNOW WHAT YOU ARE DOING.
|
||||||
|
*/
|
||||||
|
public void setActive(boolean active) {
|
||||||
|
if(!active)
|
||||||
|
this.completionTime = System.currentTimeMillis();
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRunningTime() {
|
||||||
|
int running;
|
||||||
|
if (active) {
|
||||||
|
running = (int) (System.currentTimeMillis() - creationTime);
|
||||||
|
} else {
|
||||||
|
running = (int) (completionTime - creationTime);
|
||||||
|
}
|
||||||
|
running = running / 1000;
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LoginProcessHandler getLoginProcessHandler() {
|
||||||
|
return loginProcessHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCompletionTime() {
|
||||||
|
return completionTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,381 @@
|
|||||||
|
package com.projectposeidon.johnymuffin;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonPlugin;
|
||||||
|
import com.legacyminecraft.poseidon.uuid.ThreadUUIDFetcher;
|
||||||
|
import net.minecraft.server.NetLoginHandler;
|
||||||
|
import net.minecraft.server.Packet1Login;
|
||||||
|
import net.minecraft.server.ThreadLoginVerifier;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.craftbukkit.CraftServer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.player.PlayerConnectionInitializationEvent;
|
||||||
|
import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class LoginProcessHandler {
|
||||||
|
|
||||||
|
private NetLoginHandler netLoginHandler;
|
||||||
|
private final Packet1Login packet1Login;
|
||||||
|
private CraftServer server;
|
||||||
|
private boolean onlineMode;
|
||||||
|
private boolean loginCancelled = false;
|
||||||
|
private LoginProcessHandler loginProcessHandler;
|
||||||
|
private boolean loginSuccessful = false;
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
private HashSet<ConnectionPause> connectionPauses = new HashSet<ConnectionPause>();
|
||||||
|
|
||||||
|
private final String msgKickAlreadyOnline;
|
||||||
|
|
||||||
|
public LoginProcessHandler(NetLoginHandler netloginhandler, Packet1Login packet1login, CraftServer server, boolean onlineMode) {
|
||||||
|
this.loginProcessHandler = this;
|
||||||
|
this.netLoginHandler = netloginhandler;
|
||||||
|
this.packet1Login = packet1login;
|
||||||
|
this.server = server;
|
||||||
|
this.onlineMode = onlineMode;
|
||||||
|
|
||||||
|
this.msgKickAlreadyOnline = PoseidonConfig.getInstance().getConfigString("message.kick.already-online");
|
||||||
|
|
||||||
|
processAuthentication();
|
||||||
|
|
||||||
|
long connectionStartTime = System.currentTimeMillis() / 1000L;
|
||||||
|
runLoginTimer(connectionStartTime);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runLoginTimer(long connectionStartTime) {
|
||||||
|
Bukkit.getScheduler().scheduleAsyncDelayedTask(new PoseidonPlugin(), () -> {
|
||||||
|
int currentRunningTime = (int) (System.currentTimeMillis() / 1000L - connectionStartTime);
|
||||||
|
if (!loginSuccessful && !loginCancelled) {
|
||||||
|
//This if statement shouldn't be needed, but this is here just in case a players login fails but the appropriate variables aren't changed
|
||||||
|
System.out.println("[Poseidon] The login process for " + packet1Login.name + " is still running. It has been running for " + currentRunningTime + " seconds. The following plugins are still currently pausing the login process: " + getConnectionPauseNames(true));
|
||||||
|
|
||||||
|
//Cancel the login process if it has been running for more than 20 seconds.
|
||||||
|
if (currentRunningTime >= 20) {
|
||||||
|
cancelLoginProcess("Login Process Handler Timeout");
|
||||||
|
System.out.println("[Poseidon] LoginProcessHandler for user " + packet1Login.name + " has failed to respond after 20 seconds. And future calls to this class will result in error");
|
||||||
|
System.out.println("[Poseidon] Plugin Pauses: " + getConnectionPauseNames(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRunningTime < 60) {
|
||||||
|
runLoginTimer(connectionStartTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 20 * 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processAuthentication() {
|
||||||
|
PlayerConnectionInitializationEvent event = new PlayerConnectionInitializationEvent(this.packet1Login.name, this.netLoginHandler.getSocket().getInetAddress(), loginProcessHandler);
|
||||||
|
this.server.getPluginManager().callEvent(event);
|
||||||
|
if (loginCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlineMode) {
|
||||||
|
//Server is running online mode
|
||||||
|
verifyMojangSession();
|
||||||
|
} else {
|
||||||
|
//Server is not running online mode
|
||||||
|
getUserUUID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getUserUUID() {
|
||||||
|
//UUID uuid = UUIDManager.getInstance().getUUIDFromUsername(packet1Login.name, true);
|
||||||
|
long unixTime = (System.currentTimeMillis() / 1000L);
|
||||||
|
UUID uuid = UUIDManager.getInstance().getUUIDFromUsername(packet1Login.name, true, unixTime);
|
||||||
|
if (uuid == null) {
|
||||||
|
boolean useGetMethod = PoseidonConfig.getInstance().getString("settings.uuid-fetcher.method.value", "POST").equalsIgnoreCase("GET");
|
||||||
|
(new ThreadUUIDFetcher(packet1Login, this, useGetMethod)).start();
|
||||||
|
} else {
|
||||||
|
System.out.println("[Poseidon] Fetched UUID from Cache for " + packet1Login.name + " - " + uuid.toString());
|
||||||
|
connectPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void userUUIDReceived(UUID uuid, boolean onlineMode) {
|
||||||
|
if (!onlineMode) {
|
||||||
|
if (Boolean.valueOf(String.valueOf(PoseidonConfig.getInstance().getConfigOption("settings.check-username-validity.enabled", true))) && !isUsernameValid()) {
|
||||||
|
//Username is invalid, and is a cracked user
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the player based on their mode
|
||||||
|
if(onlineMode) {
|
||||||
|
// Handle saving the UUID for online mode user here
|
||||||
|
long unixTime = (System.currentTimeMillis() / 1000L) + 1382400;
|
||||||
|
UUIDManager.getInstance().receivedUUID(packet1Login.name, uuid, unixTime, onlineMode);
|
||||||
|
|
||||||
|
connectPlayerPremium(uuid);
|
||||||
|
} else {
|
||||||
|
// Handle saving the UUID for cracked user inside connectPlayerCracked method as it may need to be modified
|
||||||
|
|
||||||
|
connectPlayerCracked(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connectPlayerPremium(UUID uuid) {
|
||||||
|
connectPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connectPlayerCracked(UUID uuid) {
|
||||||
|
// Append . to the start of the username if not already present and generate offline UUID based on that
|
||||||
|
|
||||||
|
String username = this.packet1Login.name;
|
||||||
|
|
||||||
|
if (Boolean.valueOf(String.valueOf(PoseidonConfig.getInstance().getConfigOption("settings.check-username-validity.enabled", true))) && !isUsernameValid()) {
|
||||||
|
//Username is invalid, and is a cracked user
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean prefixDot = PoseidonConfig.getInstance().getConfigBoolean("settings.cracked-username-prefix.enabled", false);
|
||||||
|
|
||||||
|
if(prefixDot) {
|
||||||
|
if (!username.startsWith(".")) {
|
||||||
|
System.out.println("[Poseidon] Adding . prefix to cracked user " + username + "'s username");
|
||||||
|
username = "." + username;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename the player to have the . prefix
|
||||||
|
this.packet1Login.name = username;
|
||||||
|
netLoginHandler.updateUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID offlineUUID = UUIDManager.generateOfflineUUID(username);
|
||||||
|
// Add new UUID entry for cracked user
|
||||||
|
long expiresOn = (System.currentTimeMillis() / 1000L) + 1382400;
|
||||||
|
UUIDManager.getInstance().receivedUUID(username, offlineUUID, expiresOn, false);
|
||||||
|
|
||||||
|
connectPlayer(offlineUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//This function is only run if the user is cracked
|
||||||
|
public boolean isUsernameValid() {
|
||||||
|
String username = this.packet1Login.name;
|
||||||
|
|
||||||
|
// Ensure the username length is valid
|
||||||
|
int minimumLength = Integer.valueOf(String.valueOf(PoseidonConfig.getInstance().getConfigOption("settings.check-username-validity.min-length", 3)));
|
||||||
|
int maximumLength = Integer.valueOf(String.valueOf(PoseidonConfig.getInstance().getConfigOption("settings.check-username-validity.max-length", 16)));
|
||||||
|
|
||||||
|
if (username.length() < minimumLength) {
|
||||||
|
cancelLoginProcess("Sorry, your username is too short. The minimum length is: " + minimumLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the . prefix for validation if it exists and the server is configured to use it.
|
||||||
|
boolean prefixDot = PoseidonConfig.getInstance().getConfigBoolean("settings.cracked-username-prefix.enabled", false);
|
||||||
|
boolean dotAdded = false;
|
||||||
|
if(prefixDot) {
|
||||||
|
if (username.startsWith(".")) {
|
||||||
|
username = username.substring(1);
|
||||||
|
dotAdded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username.length() > maximumLength) {
|
||||||
|
cancelLoginProcess("Sorry, your username is too long. The maximum length is: " + (dotAdded ? (maximumLength - 1) : maximumLength)); // Adjust max length if dot was automatically added
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username.isEmpty()) {
|
||||||
|
cancelLoginProcess("Sorry, you don't have a username, messing with MC?????");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String regex = String.valueOf(PoseidonConfig.getInstance().getConfigOption("settings.check-username-validity.regex", "[a-zA-Z0-9_?]*"));
|
||||||
|
|
||||||
|
if (!username.matches(regex)) {
|
||||||
|
cancelLoginProcess("Sorry, your username is invalid, allowed characters: " + regex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void verifyMojangSession() {
|
||||||
|
if (!loginSuccessful & !loginCancelled) {
|
||||||
|
(new ThreadLoginVerifier(this, netLoginHandler, this.packet1Login, this.server)).start(); // CraftBukkit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void userMojangSessionVerified() {
|
||||||
|
if (!loginSuccessful & !loginCancelled) {
|
||||||
|
getUserUUID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectPlayer(UUID uuid) {
|
||||||
|
String username = packet1Login.name;
|
||||||
|
//Check if a player with the same UUID or Username is already online which is mainly an issue in Offline Mode servers.
|
||||||
|
for (Player p : server.getOnlinePlayers()) {
|
||||||
|
if (p.getName().equalsIgnoreCase(username) || p.getUniqueId().equals(uuid)) {
|
||||||
|
cancelLoginProcess(this.msgKickAlreadyOnline);
|
||||||
|
System.out.println("[Poseidon] User " + username + " has been blocked from connecting as they share a username or UUID with a user who is already online called " + p.getName() +
|
||||||
|
"\nMost likely the user has changed their UUID or the server is running in offline mode and someone has attempted to connect with their name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!loginSuccessful && !loginCancelled) {
|
||||||
|
|
||||||
|
//Bukkit Login Event Start
|
||||||
|
if (this.netLoginHandler.getSocket() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlayerPreLoginEvent event = new PlayerPreLoginEvent(this.packet1Login.name, ((InetSocketAddress) netLoginHandler.networkManager.getSocketAddress()).getAddress(), loginProcessHandler);
|
||||||
|
this.server.getPluginManager().callEvent(event);
|
||||||
|
if (event.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
|
||||||
|
cancelLoginProcess(event.getKickMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Bukkit Login Event End
|
||||||
|
if (isPlayerConnectionPaused()) {
|
||||||
|
startTime = System.currentTimeMillis() / 1000L;
|
||||||
|
} else {
|
||||||
|
loginSuccessful = true;
|
||||||
|
NetLoginHandler.a(netLoginHandler, packet1Login);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a players login before join or login events
|
||||||
|
*/
|
||||||
|
public void cancelLoginProcess(String s) {
|
||||||
|
if (!loginCancelled && !loginSuccessful) {
|
||||||
|
loginCancelled = true;
|
||||||
|
netLoginHandler.disconnect(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pause for your plugin
|
||||||
|
* Connection pauses are for fetching data for a player before they MIGHT be allowed to join
|
||||||
|
*
|
||||||
|
* @param plugin Instance of plugin
|
||||||
|
* @param connectionPauseName Name of connection pause (Ensure no duplicates)
|
||||||
|
* @return ConnectionPause Object, used to remove a connection pause
|
||||||
|
*/
|
||||||
|
public ConnectionPause addConnectionInterrupt(Plugin plugin, String connectionPauseName) {
|
||||||
|
final ConnectionPause connectionPause = new ConnectionPause(plugin.getDescription().getName(), connectionPauseName, loginProcessHandler);
|
||||||
|
connectionPauses.add(connectionPause);
|
||||||
|
return connectionPause;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void removeConnectionPause(ConnectionPause connectionPause) {
|
||||||
|
removeConnectionInterrupt(connectionPause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a connection pause
|
||||||
|
*
|
||||||
|
* @param connectionPause ConnectionPause object
|
||||||
|
*/
|
||||||
|
public void removeConnectionInterrupt(ConnectionPause connectionPause) {
|
||||||
|
//Check if the connection pause is registered and active
|
||||||
|
if (!connectionPauses.contains(connectionPause)) {
|
||||||
|
System.out.println("[Poseidon] A plugin has tried to remove a connection pause from the player " + packet1Login.name + " called " + connectionPause.getConnectionPauseName() +
|
||||||
|
" from the plugin " + connectionPause.getPluginName() + ". Please contact the plugin author and get them to check their logic as this is a duplicate remove, or a pause for another player.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Handle the completion of the pause
|
||||||
|
connectionPause.setActive(false);
|
||||||
|
//If there are no more pauses, connect the player
|
||||||
|
if (!isPlayerConnectionPaused()) {
|
||||||
|
long endTime = System.currentTimeMillis() / 1000L;
|
||||||
|
int timeTaken = (int) (endTime - startTime);
|
||||||
|
|
||||||
|
//If a pause has cancelled the login, don't connect the player
|
||||||
|
if (loginCancelled) {
|
||||||
|
System.out.println("[Poseidon] Player " + loginProcessHandler.packet1Login.name + " was not allowed to join after being on hold for " + timeTaken + " seconds by the following plugins: " + getConnectionPauseNames(false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setLoginSuccessful(true);
|
||||||
|
System.out.println("[Poseidon] Player " + loginProcessHandler.packet1Login.name + " has been allowed to join after being on hold for " + timeTaken + " seconds by the following plugins: " + getConnectionPauseNames(false));
|
||||||
|
NetLoginHandler.a(netLoginHandler, packet1Login);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionPause[] getActiveConnectionPauses() {
|
||||||
|
HashSet<ConnectionPause> activePauses = new HashSet<>();
|
||||||
|
for (ConnectionPause connectionPause : connectionPauses) {
|
||||||
|
if (connectionPause.isActive()) {
|
||||||
|
activePauses.add(connectionPause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activePauses.toArray(new ConnectionPause[activePauses.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConnectionPauseNames(boolean activeOnly) {
|
||||||
|
|
||||||
|
StringBuilder pauseNames = new StringBuilder();
|
||||||
|
for (ConnectionPause connectionPause : connectionPauses) {
|
||||||
|
String pluginName = connectionPause.getPluginName();
|
||||||
|
String pauseName = connectionPause.getConnectionPauseName();
|
||||||
|
boolean isActive = connectionPause.isActive();
|
||||||
|
int time = connectionPause.getRunningTime();
|
||||||
|
if (activeOnly) {
|
||||||
|
if (connectionPause.isActive()) {
|
||||||
|
pauseNames.append(pluginName).append(":").append(pauseName).append(":").append(isActive ? "Running" : "Complete").append(":").append(time).append("-Seconds, ");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pauseNames.append(pluginName).append(":").append(pauseName).append(":").append(isActive ? "Running" : "Complete").append(":").append(time).append("-Seconds, ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pauseNames.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ConnectionPause legacyConnectionPause;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pause for your plugin
|
||||||
|
* Connection pauses are for fetching data for a player before they MIGHT be allowed to join
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void addConnectionPause(Plugin plugin) throws Exception {
|
||||||
|
System.out.println("[Poseidon] " + plugin.getDescription().getName() + " is using the deprecated connection pause system which will be removed in the future. Contact the plugin author to get an updated version.");
|
||||||
|
legacyConnectionPause = addConnectionInterrupt(plugin, "Legacy-Connection-Pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a pause for your plugin
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void removeConnectionPause(Plugin plugin) {
|
||||||
|
if (legacyConnectionPause != null) {
|
||||||
|
removeConnectionInterrupt(legacyConnectionPause);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("[Poseidon] " + plugin.getDescription().getName() + " Attempted to remove a legacy (deprecated) connection pause that was never added. Please contact the plugin author and get them to check their logic and update to the new connection pause system.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See if the players connection currently paused
|
||||||
|
*/
|
||||||
|
public boolean isPlayerConnectionPaused() {
|
||||||
|
return getActiveConnectionPauses().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setLoginSuccessful(boolean loginSuccessful) {
|
||||||
|
this.loginSuccessful = loginSuccessful;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
package com.projectposeidon.johnymuffin;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class UUIDManager {
|
||||||
|
private static UUIDManager singleton;
|
||||||
|
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
private final File cacheFile = new File("uuidcache.json");
|
||||||
|
|
||||||
|
private final Map<String, List<UUIDEntry>> usernameCache = new ConcurrentHashMap<>();
|
||||||
|
private final Map<UUID, List<UUIDEntry>> uuidCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private List<UUIDEntry> uuidCacheList;
|
||||||
|
|
||||||
|
private UUIDManager() {
|
||||||
|
if (!cacheFile.exists()) {
|
||||||
|
try (FileWriter writer = new FileWriter(cacheFile)) {
|
||||||
|
System.out.println("[Poseidon] Generating uuidcache.json for Project Poseidon");
|
||||||
|
uuidCacheList = new ArrayList<>();
|
||||||
|
gson.toJson(uuidCacheList, writer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (FileReader reader = new FileReader(cacheFile)) {
|
||||||
|
System.out.println("[Poseidon] Reading uuidcache.json for Project Poseidon");
|
||||||
|
Type listType = new TypeToken<List<UUIDEntry>>() {}.getType();
|
||||||
|
uuidCacheList = gson.fromJson(reader, listType);
|
||||||
|
if (uuidCacheList == null) uuidCacheList = new ArrayList<>();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("[Poseidon] UUID cache corrupt or unreadable, resetting: " + e);
|
||||||
|
uuidCacheList = new ArrayList<>();
|
||||||
|
saveJsonArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuildCaches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUIDManager getInstance() {
|
||||||
|
if (singleton == null) {
|
||||||
|
singleton = new UUIDManager();
|
||||||
|
}
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void rebuildCaches() {
|
||||||
|
usernameCache.clear();
|
||||||
|
uuidCache.clear();
|
||||||
|
|
||||||
|
for (UUIDEntry entry : uuidCacheList) {
|
||||||
|
usernameCache.computeIfAbsent(entry.name.toLowerCase(), k -> new ArrayList<>()).add(entry);
|
||||||
|
uuidCache.computeIfAbsent(entry.uuid, k -> new ArrayList<>()).add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToCaches(UUIDEntry entry) {
|
||||||
|
usernameCache.computeIfAbsent(entry.name.toLowerCase(), k -> new ArrayList<>()).add(entry);
|
||||||
|
uuidCache.computeIfAbsent(entry.uuid, k -> new ArrayList<>()).add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeFromCaches(UUIDEntry entry) {
|
||||||
|
List<UUIDEntry> userEntries = usernameCache.get(entry.name.toLowerCase());
|
||||||
|
if (userEntries != null) userEntries.remove(entry);
|
||||||
|
List<UUIDEntry> uuidEntries = uuidCache.get(entry.uuid);
|
||||||
|
if (uuidEntries != null) uuidEntries.remove(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID generateOfflineUUID(String username) {
|
||||||
|
// TODO: Update to modern system: UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
|
||||||
|
return UUID.nameUUIDFromBytes(username.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUIDGraceful(String username) {
|
||||||
|
UUID uuid = getUUIDFromUsername(username, true);
|
||||||
|
return uuid != null ? uuid : generateOfflineUUID(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveJsonArray() {
|
||||||
|
try (FileWriter writer = new FileWriter(cacheFile)) {
|
||||||
|
gson.toJson(uuidCacheList, writer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receivedUUID(String username, UUID uuid, Long expiry, boolean online) {
|
||||||
|
// Check existing entry
|
||||||
|
List<UUIDEntry> entries = usernameCache.getOrDefault(username.toLowerCase(), Collections.emptyList());
|
||||||
|
for (UUIDEntry entry : entries) {
|
||||||
|
if (entry.uuid.equals(uuid) && entry.onlineUUID == online) {
|
||||||
|
entry.expiresOn = expiry;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeInstancesOfUsername(username);
|
||||||
|
removeInstancesOfUUID(uuid);
|
||||||
|
|
||||||
|
UUIDEntry newEntry = new UUIDEntry(username, uuid, expiry, online);
|
||||||
|
uuidCacheList.add(newEntry);
|
||||||
|
addToCaches(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UUID getUUIDFromUsername(String username) {
|
||||||
|
List<UUIDEntry> entries = usernameCache.get(username.toLowerCase());
|
||||||
|
if (entries != null && !entries.isEmpty()) {
|
||||||
|
return entries.get(0).uuid;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUIDFromUsername(String username, boolean online) {
|
||||||
|
List<UUIDEntry> entries = usernameCache.get(username.toLowerCase());
|
||||||
|
if (entries != null) {
|
||||||
|
for (UUIDEntry entry : entries) {
|
||||||
|
if (entry.onlineUUID == online) {
|
||||||
|
return entry.uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUUIDFromUsername(String username, boolean online, long afterUnix) {
|
||||||
|
List<UUIDEntry> entries = usernameCache.get(username.toLowerCase());
|
||||||
|
if (entries != null) {
|
||||||
|
for (UUIDEntry entry : entries) {
|
||||||
|
if (entry.onlineUUID == online && entry.expiresOn > afterUnix) {
|
||||||
|
return entry.uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsernameFromUUID(UUID uuid) {
|
||||||
|
List<UUIDEntry> entries = uuidCache.get(uuid);
|
||||||
|
if (entries == null || entries.isEmpty()) return null;
|
||||||
|
|
||||||
|
UUIDEntry newest = entries.get(0);
|
||||||
|
for (UUIDEntry entry : entries) {
|
||||||
|
if (entry.expiresOn > newest.expiresOn) {
|
||||||
|
newest = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newest.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeInstancesOfUsername(String username) {
|
||||||
|
List<UUIDEntry> entries = usernameCache.get(username.toLowerCase());
|
||||||
|
if (entries != null) {
|
||||||
|
for (UUIDEntry entry : new ArrayList<>(entries)) {
|
||||||
|
uuidCacheList.remove(entry);
|
||||||
|
removeFromCaches(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeInstancesOfUUID(UUID uuid) {
|
||||||
|
List<UUIDEntry> entries = uuidCache.get(uuid);
|
||||||
|
if (entries == null) return;
|
||||||
|
|
||||||
|
for (UUIDEntry entry : new ArrayList<>(entries)) {
|
||||||
|
if ((boolean) PoseidonConfig.getInstance().getConfigOption("settings.delete-duplicate-uuids")) {
|
||||||
|
uuidCacheList.remove(entry);
|
||||||
|
removeFromCaches(entry);
|
||||||
|
} else {
|
||||||
|
entry.expiresOn = 1L; // mark as outdated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class UUIDEntry {
|
||||||
|
public String name;
|
||||||
|
public UUID uuid;
|
||||||
|
public long expiresOn;
|
||||||
|
public boolean onlineUUID;
|
||||||
|
|
||||||
|
public UUIDEntry(String name, UUID uuid, long expiresOn, boolean onlineUUID) {
|
||||||
|
this.name = name;
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.expiresOn = expiresOn;
|
||||||
|
this.onlineUUID = onlineUUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class Achievement extends Statistic {
|
||||||
|
|
||||||
|
public final int a;
|
||||||
|
public final int b;
|
||||||
|
public final Achievement c;
|
||||||
|
private final String l;
|
||||||
|
public final ItemStack d;
|
||||||
|
private boolean m;
|
||||||
|
|
||||||
|
public Achievement(int i, String s, int j, int k, Item item, Achievement achievement) {
|
||||||
|
this(i, s, j, k, new ItemStack(item), achievement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Achievement(int i, String s, int j, int k, Block block, Achievement achievement) {
|
||||||
|
this(i, s, j, k, new ItemStack(block), achievement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Achievement(int i, String s, int j, int k, ItemStack itemstack, Achievement achievement) {
|
||||||
|
super(5242880 + i, StatisticCollector.a("achievement." + s));
|
||||||
|
this.d = itemstack;
|
||||||
|
this.l = StatisticCollector.a("achievement." + s + ".desc");
|
||||||
|
this.a = j;
|
||||||
|
this.b = k;
|
||||||
|
if (j < AchievementList.a) {
|
||||||
|
AchievementList.a = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < AchievementList.b) {
|
||||||
|
AchievementList.b = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j > AchievementList.c) {
|
||||||
|
AchievementList.c = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k > AchievementList.d) {
|
||||||
|
AchievementList.d = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.c = achievement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Achievement a() {
|
||||||
|
this.g = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Achievement b() {
|
||||||
|
this.m = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Achievement c() {
|
||||||
|
super.d();
|
||||||
|
AchievementList.e.add(this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AchievementList {
|
||||||
|
|
||||||
|
public static int a;
|
||||||
|
public static int b;
|
||||||
|
public static int c;
|
||||||
|
public static int d;
|
||||||
|
public static List e = new ArrayList();
|
||||||
|
public static Achievement f = (new Achievement(0, "openInventory", 0, 0, Item.BOOK, (Achievement) null)).a().c();
|
||||||
|
public static Achievement g = (new Achievement(1, "mineWood", 2, 1, Block.LOG, f)).c();
|
||||||
|
public static Achievement h = (new Achievement(2, "buildWorkBench", 4, -1, Block.WORKBENCH, g)).c();
|
||||||
|
public static Achievement i = (new Achievement(3, "buildPickaxe", 4, 2, Item.WOOD_PICKAXE, h)).c();
|
||||||
|
public static Achievement j = (new Achievement(4, "buildFurnace", 3, 4, Block.BURNING_FURNACE, i)).c();
|
||||||
|
public static Achievement k = (new Achievement(5, "acquireIron", 1, 4, Item.IRON_INGOT, j)).c();
|
||||||
|
public static Achievement l = (new Achievement(6, "buildHoe", 2, -3, Item.WOOD_HOE, h)).c();
|
||||||
|
public static Achievement m = (new Achievement(7, "makeBread", -1, -3, Item.BREAD, l)).c();
|
||||||
|
public static Achievement n = (new Achievement(8, "bakeCake", 0, -5, Item.CAKE, l)).c();
|
||||||
|
public static Achievement o = (new Achievement(9, "buildBetterPickaxe", 6, 2, Item.STONE_PICKAXE, i)).c();
|
||||||
|
public static Achievement p = (new Achievement(10, "cookFish", 2, 6, Item.COOKED_FISH, j)).c();
|
||||||
|
public static Achievement q = (new Achievement(11, "onARail", 2, 3, Block.RAILS, k)).b().c();
|
||||||
|
public static Achievement r = (new Achievement(12, "buildSword", 6, -1, Item.WOOD_SWORD, h)).c();
|
||||||
|
public static Achievement s = (new Achievement(13, "killEnemy", 8, -1, Item.BONE, r)).c();
|
||||||
|
public static Achievement t = (new Achievement(14, "killCow", 7, -3, Item.LEATHER, r)).c();
|
||||||
|
public static Achievement u = (new Achievement(15, "flyPig", 8, -4, Item.SADDLE, t)).b().c();
|
||||||
|
|
||||||
|
public AchievementList() {}
|
||||||
|
|
||||||
|
public static void a() {}
|
||||||
|
|
||||||
|
static {
|
||||||
|
System.out.println(e.size() + " achievements");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AchievementMap {
|
||||||
|
|
||||||
|
public static AchievementMap a = new AchievementMap();
|
||||||
|
private Map b = new HashMap();
|
||||||
|
|
||||||
|
private AchievementMap() {
|
||||||
|
try {
|
||||||
|
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(AchievementMap.class.getResourceAsStream("/achievement/map.txt")));
|
||||||
|
|
||||||
|
String s;
|
||||||
|
|
||||||
|
while ((s = bufferedreader.readLine()) != null) {
|
||||||
|
String[] astring = s.split(",");
|
||||||
|
int i = Integer.parseInt(astring[0]);
|
||||||
|
|
||||||
|
this.b.put(Integer.valueOf(i), astring[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedreader.close();
|
||||||
|
} catch (Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String a(int i) {
|
||||||
|
return (String) a.b.get(Integer.valueOf(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AxisAlignedBB {
|
||||||
|
|
||||||
|
private static List g = new ArrayList();
|
||||||
|
private static int h = 0;
|
||||||
|
public double a;
|
||||||
|
public double b;
|
||||||
|
public double c;
|
||||||
|
public double d;
|
||||||
|
public double e;
|
||||||
|
public double f;
|
||||||
|
|
||||||
|
public static AxisAlignedBB a(double d0, double d1, double d2, double d3, double d4, double d5) {
|
||||||
|
return new AxisAlignedBB(d0, d1, d2, d3, d4, d5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void a() {
|
||||||
|
h = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AxisAlignedBB b(double d0, double d1, double d2, double d3, double d4, double d5) {
|
||||||
|
if (h >= g.size()) {
|
||||||
|
g.add(a(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((AxisAlignedBB) g.get(h++)).c(d0, d1, d2, d3, d4, d5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AxisAlignedBB(double d0, double d1, double d2, double d3, double d4, double d5) {
|
||||||
|
this.a = d0;
|
||||||
|
this.b = d1;
|
||||||
|
this.c = d2;
|
||||||
|
this.d = d3;
|
||||||
|
this.e = d4;
|
||||||
|
this.f = d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB c(double d0, double d1, double d2, double d3, double d4, double d5) {
|
||||||
|
this.a = d0;
|
||||||
|
this.b = d1;
|
||||||
|
this.c = d2;
|
||||||
|
this.d = d3;
|
||||||
|
this.e = d4;
|
||||||
|
this.f = d5;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB a(double d0, double d1, double d2) {
|
||||||
|
double d3 = this.a;
|
||||||
|
double d4 = this.b;
|
||||||
|
double d5 = this.c;
|
||||||
|
double d6 = this.d;
|
||||||
|
double d7 = this.e;
|
||||||
|
double d8 = this.f;
|
||||||
|
|
||||||
|
if (d0 < 0.0D) {
|
||||||
|
d3 += d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d0 > 0.0D) {
|
||||||
|
d6 += d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d1 < 0.0D) {
|
||||||
|
d4 += d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d1 > 0.0D) {
|
||||||
|
d7 += d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d2 < 0.0D) {
|
||||||
|
d5 += d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d2 > 0.0D) {
|
||||||
|
d8 += d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b(d3, d4, d5, d6, d7, d8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB b(double d0, double d1, double d2) {
|
||||||
|
double d3 = this.a - d0;
|
||||||
|
double d4 = this.b - d1;
|
||||||
|
double d5 = this.c - d2;
|
||||||
|
double d6 = this.d + d0;
|
||||||
|
double d7 = this.e + d1;
|
||||||
|
double d8 = this.f + d2;
|
||||||
|
|
||||||
|
return b(d3, d4, d5, d6, d7, d8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB c(double d0, double d1, double d2) {
|
||||||
|
return b(this.a + d0, this.b + d1, this.c + d2, this.d + d0, this.e + d1, this.f + d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double a(AxisAlignedBB axisalignedbb, double d0) {
|
||||||
|
if (axisalignedbb.e > this.b && axisalignedbb.b < this.e) {
|
||||||
|
if (axisalignedbb.f > this.c && axisalignedbb.c < this.f) {
|
||||||
|
double d1;
|
||||||
|
|
||||||
|
if (d0 > 0.0D && axisalignedbb.d <= this.a) {
|
||||||
|
d1 = this.a - axisalignedbb.d;
|
||||||
|
if (d1 < d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d0 < 0.0D && axisalignedbb.a >= this.d) {
|
||||||
|
d1 = this.d - axisalignedbb.a;
|
||||||
|
if (d1 > d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d0;
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double b(AxisAlignedBB axisalignedbb, double d0) {
|
||||||
|
if (axisalignedbb.d > this.a && axisalignedbb.a < this.d) {
|
||||||
|
if (axisalignedbb.f > this.c && axisalignedbb.c < this.f) {
|
||||||
|
double d1;
|
||||||
|
|
||||||
|
if (d0 > 0.0D && axisalignedbb.e <= this.b) {
|
||||||
|
d1 = this.b - axisalignedbb.e;
|
||||||
|
if (d1 < d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d0 < 0.0D && axisalignedbb.b >= this.e) {
|
||||||
|
d1 = this.e - axisalignedbb.b;
|
||||||
|
if (d1 > d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d0;
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double c(AxisAlignedBB axisalignedbb, double d0) {
|
||||||
|
if (axisalignedbb.d > this.a && axisalignedbb.a < this.d) {
|
||||||
|
if (axisalignedbb.e > this.b && axisalignedbb.b < this.e) {
|
||||||
|
double d1;
|
||||||
|
|
||||||
|
if (d0 > 0.0D && axisalignedbb.f <= this.c) {
|
||||||
|
d1 = this.c - axisalignedbb.f;
|
||||||
|
if (d1 < d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d0 < 0.0D && axisalignedbb.c >= this.f) {
|
||||||
|
d1 = this.f - axisalignedbb.c;
|
||||||
|
if (d1 > d0) {
|
||||||
|
d0 = d1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d0;
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(AxisAlignedBB axisalignedbb) {
|
||||||
|
return axisalignedbb.d > this.a && axisalignedbb.a < this.d ? (axisalignedbb.e > this.b && axisalignedbb.b < this.e ? axisalignedbb.f > this.c && axisalignedbb.c < this.f : false) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB d(double d0, double d1, double d2) {
|
||||||
|
this.a += d0;
|
||||||
|
this.b += d1;
|
||||||
|
this.c += d2;
|
||||||
|
this.d += d0;
|
||||||
|
this.e += d1;
|
||||||
|
this.f += d2;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(Vec3D vec3d) {
|
||||||
|
return vec3d.a > this.a && vec3d.a < this.d ? (vec3d.b > this.b && vec3d.b < this.e ? vec3d.c > this.c && vec3d.c < this.f : false) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB shrink(double d0, double d1, double d2) {
|
||||||
|
double d3 = this.a + d0;
|
||||||
|
double d4 = this.b + d1;
|
||||||
|
double d5 = this.c + d2;
|
||||||
|
double d6 = this.d - d0;
|
||||||
|
double d7 = this.e - d1;
|
||||||
|
double d8 = this.f - d2;
|
||||||
|
|
||||||
|
return b(d3, d4, d5, d6, d7, d8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB clone() {
|
||||||
|
return b(this.a, this.b, this.c, this.d, this.e, this.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPosition a(Vec3D vec3d, Vec3D vec3d1) {
|
||||||
|
Vec3D vec3d2 = vec3d.a(vec3d1, this.a);
|
||||||
|
Vec3D vec3d3 = vec3d.a(vec3d1, this.d);
|
||||||
|
Vec3D vec3d4 = vec3d.b(vec3d1, this.b);
|
||||||
|
Vec3D vec3d5 = vec3d.b(vec3d1, this.e);
|
||||||
|
Vec3D vec3d6 = vec3d.c(vec3d1, this.c);
|
||||||
|
Vec3D vec3d7 = vec3d.c(vec3d1, this.f);
|
||||||
|
|
||||||
|
if (!this.b(vec3d2)) {
|
||||||
|
vec3d2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.b(vec3d3)) {
|
||||||
|
vec3d3 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.c(vec3d4)) {
|
||||||
|
vec3d4 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.c(vec3d5)) {
|
||||||
|
vec3d5 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.d(vec3d6)) {
|
||||||
|
vec3d6 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.d(vec3d7)) {
|
||||||
|
vec3d7 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3D vec3d8 = null;
|
||||||
|
|
||||||
|
if (vec3d2 != null && (vec3d8 == null || vec3d.b(vec3d2) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d3 != null && (vec3d8 == null || vec3d.b(vec3d3) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d4 != null && (vec3d8 == null || vec3d.b(vec3d4) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d5 != null && (vec3d8 == null || vec3d.b(vec3d5) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d6 != null && (vec3d8 == null || vec3d.b(vec3d6) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d7 != null && (vec3d8 == null || vec3d.b(vec3d7) < vec3d.b(vec3d8))) {
|
||||||
|
vec3d8 = vec3d7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
byte b0 = -1;
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d2) {
|
||||||
|
b0 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d3) {
|
||||||
|
b0 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d4) {
|
||||||
|
b0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d5) {
|
||||||
|
b0 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d6) {
|
||||||
|
b0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d7) {
|
||||||
|
b0 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovingObjectPosition(0, 0, 0, b0, vec3d8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean b(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.b >= this.b && vec3d.b <= this.e && vec3d.c >= this.c && vec3d.c <= this.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean c(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.a >= this.a && vec3d.a <= this.d && vec3d.c >= this.c && vec3d.c <= this.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean d(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.a >= this.a && vec3d.a <= this.d && vec3d.b >= this.b && vec3d.b <= this.e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(AxisAlignedBB axisalignedbb) {
|
||||||
|
this.a = axisalignedbb.a;
|
||||||
|
this.b = axisalignedbb.b;
|
||||||
|
this.c = axisalignedbb.c;
|
||||||
|
this.d = axisalignedbb.d;
|
||||||
|
this.e = axisalignedbb.e;
|
||||||
|
this.f = axisalignedbb.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "box[" + this.a + ", " + this.b + ", " + this.c + " -> " + this.d + ", " + this.e + ", " + this.f + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BedBlockTextures {
|
||||||
|
|
||||||
|
public static final int[] a = new int[] { 3, 4, 2, 5};
|
||||||
|
public static final int[] b = new int[] { 2, 3, 0, 1};
|
||||||
|
public static final int[][] c = new int[][] { { 1, 0, 3, 2, 5, 4}, { 1, 0, 5, 4, 2, 3}, { 1, 0, 2, 3, 4, 5}, { 1, 0, 4, 5, 3, 2}};
|
||||||
|
|
||||||
|
public BedBlockTextures() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BiomeBase {
|
||||||
|
|
||||||
|
public static final BiomeBase RAINFOREST = (new BiomeRainforest()).b(588342).a("Rainforest").a(2094168);
|
||||||
|
public static final BiomeBase SWAMPLAND = (new BiomeSwamp()).b(522674).a("Swampland").a(9154376);
|
||||||
|
public static final BiomeBase SEASONAL_FOREST = (new BiomeBase()).b(10215459).a("Seasonal Forest");
|
||||||
|
public static final BiomeBase FOREST = (new BiomeForest()).b(353825).a("Forest").a(5159473);
|
||||||
|
public static final BiomeBase SAVANNA = (new BiomeDesert()).b(14278691).a("Savanna");
|
||||||
|
public static final BiomeBase SHRUBLAND = (new BiomeBase()).b(10595616).a("Shrubland");
|
||||||
|
public static final BiomeBase TAIGA = (new BiomeTaiga()).b(3060051).a("Taiga").b().a(8107825);
|
||||||
|
public static final BiomeBase DESERT = (new BiomeDesert()).b(16421912).a("Desert").e();
|
||||||
|
public static final BiomeBase PLAINS = (new BiomeDesert()).b(16767248).a("Plains");
|
||||||
|
public static final BiomeBase ICE_DESERT = (new BiomeDesert()).b(16772499).a("Ice Desert").b().e().a(12899129);
|
||||||
|
public static final BiomeBase TUNDRA = (new BiomeBase()).b(5762041).a("Tundra").b().a(12899129);
|
||||||
|
public static final BiomeBase HELL = (new BiomeHell()).b(16711680).a("Hell").e();
|
||||||
|
public static final BiomeBase SKY = (new BiomeSky()).b(8421631).a("Sky").e();
|
||||||
|
public String n;
|
||||||
|
public int o;
|
||||||
|
public byte p;
|
||||||
|
public byte q;
|
||||||
|
public int r;
|
||||||
|
protected List s;
|
||||||
|
protected List t;
|
||||||
|
protected List u;
|
||||||
|
private boolean v;
|
||||||
|
private boolean w;
|
||||||
|
private static BiomeBase[] x = new BiomeBase[4096];
|
||||||
|
|
||||||
|
protected BiomeBase() {
|
||||||
|
this.p = (byte) Block.GRASS.id;
|
||||||
|
this.q = (byte) Block.DIRT.id;
|
||||||
|
this.r = 5169201;
|
||||||
|
this.s = new ArrayList();
|
||||||
|
this.t = new ArrayList();
|
||||||
|
this.u = new ArrayList();
|
||||||
|
this.w = true;
|
||||||
|
this.s.add(new BiomeMeta(EntitySpider.class, 10));
|
||||||
|
this.s.add(new BiomeMeta(EntityZombie.class, 10));
|
||||||
|
this.s.add(new BiomeMeta(EntitySkeleton.class, 10));
|
||||||
|
this.s.add(new BiomeMeta(EntityCreeper.class, 10));
|
||||||
|
this.s.add(new BiomeMeta(EntitySlime.class, 10));
|
||||||
|
this.t.add(new BiomeMeta(EntitySheep.class, 12));
|
||||||
|
this.t.add(new BiomeMeta(EntityPig.class, 10));
|
||||||
|
this.t.add(new BiomeMeta(EntityChicken.class, 10));
|
||||||
|
this.t.add(new BiomeMeta(EntityCow.class, 8));
|
||||||
|
this.u.add(new BiomeMeta(EntitySquid.class, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiomeBase e() {
|
||||||
|
this.w = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void a() {
|
||||||
|
for (int i = 0; i < 64; ++i) {
|
||||||
|
for (int j = 0; j < 64; ++j) {
|
||||||
|
x[i + j * 64] = a((float) i / 63.0F, (float) j / 63.0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DESERT.p = DESERT.q = (byte) Block.SAND.id;
|
||||||
|
ICE_DESERT.p = ICE_DESERT.q = (byte) Block.SAND.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldGenerator a(Random random) {
|
||||||
|
return (WorldGenerator) (random.nextInt(10) == 0 ? new WorldGenBigTree() : new WorldGenTrees());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BiomeBase b() {
|
||||||
|
this.v = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BiomeBase a(String s) {
|
||||||
|
this.n = s;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BiomeBase a(int i) {
|
||||||
|
this.r = i;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BiomeBase b(int i) {
|
||||||
|
this.o = i;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiomeBase a(double d0, double d1) {
|
||||||
|
int i = (int) (d0 * 63.0D);
|
||||||
|
int j = (int) (d1 * 63.0D);
|
||||||
|
|
||||||
|
return x[i + j * 64];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiomeBase a(float f, float f1) {
|
||||||
|
f1 *= f;
|
||||||
|
return f < 0.1F ? TUNDRA : (f1 < 0.2F ? (f < 0.5F ? TUNDRA : (f < 0.95F ? SAVANNA : DESERT)) : (f1 > 0.5F && f < 0.7F ? SWAMPLAND : (f < 0.5F ? TAIGA : (f < 0.97F ? (f1 < 0.35F ? SHRUBLAND : FOREST) : (f1 < 0.45F ? PLAINS : (f1 < 0.9F ? SEASONAL_FOREST : RAINFOREST))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List a(EnumCreatureType enumcreaturetype) {
|
||||||
|
return enumcreaturetype == EnumCreatureType.MONSTER ? this.s : (enumcreaturetype == EnumCreatureType.CREATURE ? this.t : (enumcreaturetype == EnumCreatureType.WATER_CREATURE ? this.u : null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean c() {
|
||||||
|
return this.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean d() {
|
||||||
|
return this.v ? false : this.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BiomeDesert extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeDesert() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BiomeForest extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeForest() {
|
||||||
|
this.t.add(new BiomeMeta(EntityWolf.class, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldGenerator a(Random random) {
|
||||||
|
return (WorldGenerator) (random.nextInt(5) == 0 ? new WorldGenForest() : (random.nextInt(3) == 0 ? new WorldGenBigTree() : new WorldGenTrees()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BiomeHell extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeHell() {
|
||||||
|
this.s.clear();
|
||||||
|
this.t.clear();
|
||||||
|
this.u.clear();
|
||||||
|
this.s.add(new BiomeMeta(EntityGhast.class, 10));
|
||||||
|
this.s.add(new BiomeMeta(EntityPigZombie.class, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BiomeMeta {
|
||||||
|
|
||||||
|
public Class a;
|
||||||
|
public int b;
|
||||||
|
|
||||||
|
public BiomeMeta(Class oclass, int i) {
|
||||||
|
this.a = oclass;
|
||||||
|
this.b = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BiomeRainforest extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeRainforest() {}
|
||||||
|
|
||||||
|
public WorldGenerator a(Random random) {
|
||||||
|
return (WorldGenerator) (random.nextInt(3) == 0 ? new WorldGenBigTree() : new WorldGenTrees());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BiomeSky extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeSky() {
|
||||||
|
this.s.clear();
|
||||||
|
this.t.clear();
|
||||||
|
this.u.clear();
|
||||||
|
this.t.add(new BiomeMeta(EntityChicken.class, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BiomeSwamp extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeSwamp() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BiomeTaiga extends BiomeBase {
|
||||||
|
|
||||||
|
public BiomeTaiga() {
|
||||||
|
this.t.add(new BiomeMeta(EntityWolf.class, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldGenerator a(Random random) {
|
||||||
|
return (WorldGenerator) (random.nextInt(3) == 0 ? new WorldGenTaiga1() : new WorldGenTaiga2());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,555 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Block {
|
||||||
|
|
||||||
|
public static final StepSound d = new StepSound("stone", 1.0F, 1.0F);
|
||||||
|
public static final StepSound e = new StepSound("wood", 1.0F, 1.0F);
|
||||||
|
public static final StepSound f = new StepSound("gravel", 1.0F, 1.0F);
|
||||||
|
public static final StepSound g = new StepSound("grass", 1.0F, 1.0F);
|
||||||
|
public static final StepSound h = new StepSound("stone", 1.0F, 1.0F);
|
||||||
|
public static final StepSound i = new StepSound("stone", 1.0F, 1.5F);
|
||||||
|
public static final StepSound j = new StepSoundStone("stone", 1.0F, 1.0F);
|
||||||
|
public static final StepSound k = new StepSound("cloth", 1.0F, 1.0F);
|
||||||
|
public static final StepSound l = new StepSoundSand("sand", 1.0F, 1.0F);
|
||||||
|
public static final Block[] byId = new Block[256];
|
||||||
|
public static final boolean[] n = new boolean[256];
|
||||||
|
public static final boolean[] o = new boolean[256];
|
||||||
|
public static final boolean[] isTileEntity = new boolean[256];
|
||||||
|
public static final int[] q = new int[256];
|
||||||
|
public static final boolean[] r = new boolean[256];
|
||||||
|
public static final int[] s = new int[256];
|
||||||
|
public static final boolean[] t = new boolean[256];
|
||||||
|
public static final Block STONE = (new BlockStone(1, 1)).c(1.5F).b(10.0F).a(h).a("stone");
|
||||||
|
public static final BlockGrass GRASS = (BlockGrass) (new BlockGrass(2)).c(0.6F).a(g).a("grass");
|
||||||
|
public static final Block DIRT = (new BlockDirt(3, 2)).c(0.5F).a(f).a("dirt");
|
||||||
|
public static final Block COBBLESTONE = (new Block(4, 16, Material.STONE)).c(2.0F).b(10.0F).a(h).a("stonebrick");
|
||||||
|
public static final Block WOOD = (new Block(5, 4, Material.WOOD)).c(2.0F).b(5.0F).a(e).a("wood").g();
|
||||||
|
public static final Block SAPLING = (new BlockSapling(6, 15)).c(0.0F).a(g).a("sapling").g();
|
||||||
|
public static final Block BEDROCK = (new Block(7, 17, Material.STONE)).i().b(6000000.0F).a(h).a("bedrock").n();
|
||||||
|
public static final Block WATER = (new BlockFlowing(8, Material.WATER)).c(100.0F).f(3).a("water").n().g();
|
||||||
|
public static final Block STATIONARY_WATER = (new BlockStationary(9, Material.WATER)).c(100.0F).f(3).a("water").n().g();
|
||||||
|
public static final Block LAVA = (new BlockFlowing(10, Material.LAVA)).c(0.0F).a(1.0F).f(255).a("lava").n().g();
|
||||||
|
public static final Block STATIONARY_LAVA = (new BlockStationary(11, Material.LAVA)).c(100.0F).a(1.0F).f(255).a("lava").n().g();
|
||||||
|
public static final Block SAND = (new BlockSand(12, 18)).c(0.5F).a(l).a("sand");
|
||||||
|
public static final Block GRAVEL = (new BlockGravel(13, 19)).c(0.6F).a(f).a("gravel");
|
||||||
|
public static final Block GOLD_ORE = (new BlockOre(14, 32)).c(3.0F).b(5.0F).a(h).a("oreGold");
|
||||||
|
public static final Block IRON_ORE = (new BlockOre(15, 33)).c(3.0F).b(5.0F).a(h).a("oreIron");
|
||||||
|
public static final Block COAL_ORE = (new BlockOre(16, 34)).c(3.0F).b(5.0F).a(h).a("oreCoal");
|
||||||
|
public static final Block LOG = (new BlockLog(17)).c(2.0F).a(e).a("log").g();
|
||||||
|
public static final BlockLeaves LEAVES = (BlockLeaves) (new BlockLeaves(18, 52)).c(0.2F).f(1).a(g).a("leaves").n().g();
|
||||||
|
public static final Block SPONGE = (new BlockSponge(19)).c(0.6F).a(g).a("sponge");
|
||||||
|
public static final Block GLASS = (new BlockGlass(20, 49, Material.SHATTERABLE, false)).c(0.3F).a(j).a("glass");
|
||||||
|
public static final Block LAPIS_ORE = (new BlockOre(21, 160)).c(3.0F).b(5.0F).a(h).a("oreLapis");
|
||||||
|
public static final Block LAPIS_BLOCK = (new Block(22, 144, Material.STONE)).c(3.0F).b(5.0F).a(h).a("blockLapis");
|
||||||
|
public static final Block DISPENSER = (new BlockDispenser(23)).c(3.5F).a(h).a("dispenser").g();
|
||||||
|
public static final Block SANDSTONE = (new BlockSandStone(24)).a(h).c(0.8F).a("sandStone");
|
||||||
|
public static final Block NOTE_BLOCK = (new BlockNote(25)).c(0.8F).a("musicBlock").g();
|
||||||
|
public static final Block BED = (new BlockBed(26)).c(0.2F).a("bed").n().g();
|
||||||
|
public static final Block GOLDEN_RAIL = (new BlockMinecartTrack(27, 179, true)).c(0.7F).a(i).a("goldenRail").g();
|
||||||
|
public static final Block DETECTOR_RAIL = (new BlockMinecartDetector(28, 195)).c(0.7F).a(i).a("detectorRail").g();
|
||||||
|
public static final Block PISTON_STICKY = (new BlockPiston(29, 106, true)).a("pistonStickyBase").g();
|
||||||
|
public static final Block WEB = (new BlockWeb(30, 11)).f(1).c(4.0F).a("web");
|
||||||
|
public static final BlockLongGrass LONG_GRASS = (BlockLongGrass) (new BlockLongGrass(31, 39)).c(0.0F).a(g).a("tallgrass");
|
||||||
|
public static final BlockDeadBush DEAD_BUSH = (BlockDeadBush) (new BlockDeadBush(32, 55)).c(0.0F).a(g).a("deadbush");
|
||||||
|
public static final Block PISTON = (new BlockPiston(33, 107, false)).a("pistonBase").g();
|
||||||
|
public static final BlockPistonExtension PISTON_EXTENSION = (BlockPistonExtension) (new BlockPistonExtension(34, 107)).g();
|
||||||
|
public static final Block WOOL = (new BlockCloth()).c(0.8F).a(k).a("cloth").g();
|
||||||
|
public static final BlockPistonMoving PISTON_MOVING = new BlockPistonMoving(36);
|
||||||
|
public static final BlockFlower YELLOW_FLOWER = (BlockFlower) (new BlockFlower(37, 13)).c(0.0F).a(g).a("flower");
|
||||||
|
public static final BlockFlower RED_ROSE = (BlockFlower) (new BlockFlower(38, 12)).c(0.0F).a(g).a("rose");
|
||||||
|
public static final BlockFlower BROWN_MUSHROOM = (BlockFlower) (new BlockMushroom(39, 29)).c(0.0F).a(g).a(0.125F).a("mushroom");
|
||||||
|
public static final BlockFlower RED_MUSHROOM = (BlockFlower) (new BlockMushroom(40, 28)).c(0.0F).a(g).a("mushroom");
|
||||||
|
public static final Block GOLD_BLOCK = (new BlockOreBlock(41, 23)).c(3.0F).b(10.0F).a(i).a("blockGold");
|
||||||
|
public static final Block IRON_BLOCK = (new BlockOreBlock(42, 22)).c(5.0F).b(10.0F).a(i).a("blockIron");
|
||||||
|
public static final Block DOUBLE_STEP = (new BlockStep(43, true)).c(2.0F).b(10.0F).a(h).a("stoneSlab");
|
||||||
|
public static final Block STEP = (new BlockStep(44, false)).c(2.0F).b(10.0F).a(h).a("stoneSlab");
|
||||||
|
public static final Block BRICK = (new Block(45, 7, Material.STONE)).c(2.0F).b(10.0F).a(h).a("brick");
|
||||||
|
public static final Block TNT = (new BlockTNT(46, 8)).c(0.0F).a(g).a("tnt");
|
||||||
|
public static final Block BOOKSHELF = (new BlockBookshelf(47, 35)).c(1.5F).a(e).a("bookshelf");
|
||||||
|
public static final Block MOSSY_COBBLESTONE = (new Block(48, 36, Material.STONE)).c(2.0F).b(10.0F).a(h).a("stoneMoss");
|
||||||
|
public static final Block OBSIDIAN = (new BlockObsidian(49, 37)).c(10.0F).b(2000.0F).a(h).a("obsidian");
|
||||||
|
public static final Block TORCH = (new BlockTorch(50, 80)).c(0.0F).a(0.9375F).a(e).a("torch").g();
|
||||||
|
public static final BlockFire FIRE = (BlockFire) (new BlockFire(51, 31)).c(0.0F).a(1.0F).a(e).a("fire").n().g();
|
||||||
|
public static final Block MOB_SPAWNER = (new BlockMobSpawner(52, 65)).c(5.0F).a(i).a("mobSpawner").n();
|
||||||
|
public static final Block WOOD_STAIRS = (new BlockStairs(53, WOOD)).a("stairsWood").g();
|
||||||
|
public static final Block CHEST = (new BlockChest(54)).c(2.5F).a(e).a("chest").g();
|
||||||
|
public static final Block REDSTONE_WIRE = (new BlockRedstoneWire(55, 164)).c(0.0F).a(d).a("redstoneDust").n().g();
|
||||||
|
public static final Block DIAMOND_ORE = (new BlockOre(56, 50)).c(3.0F).b(5.0F).a(h).a("oreDiamond");
|
||||||
|
public static final Block DIAMOND_BLOCK = (new BlockOreBlock(57, 24)).c(5.0F).b(10.0F).a(i).a("blockDiamond");
|
||||||
|
public static final Block WORKBENCH = (new BlockWorkbench(58)).c(2.5F).a(e).a("workbench");
|
||||||
|
public static final Block CROPS = (new BlockCrops(59, 88)).c(0.0F).a(g).a("crops").n().g();
|
||||||
|
public static final Block SOIL = (new BlockSoil(60)).c(0.6F).a(f).a("farmland");
|
||||||
|
public static final Block FURNACE = (new BlockFurnace(61, false)).c(3.5F).a(h).a("furnace").g();
|
||||||
|
public static final Block BURNING_FURNACE = (new BlockFurnace(62, true)).c(3.5F).a(h).a(0.875F).a("furnace").g();
|
||||||
|
public static final Block SIGN_POST = (new BlockSign(63, TileEntitySign.class, true)).c(1.0F).a(e).a("sign").n().g();
|
||||||
|
public static final Block WOODEN_DOOR = (new BlockDoor(64, Material.WOOD)).c(3.0F).a(e).a("doorWood").n().g();
|
||||||
|
public static final Block LADDER = (new BlockLadder(65, 83)).c(0.4F).a(e).a("ladder").g();
|
||||||
|
public static final Block RAILS = (new BlockMinecartTrack(66, 128, false)).c(0.7F).a(i).a("rail").g();
|
||||||
|
public static final Block COBBLESTONE_STAIRS = (new BlockStairs(67, COBBLESTONE)).a("stairsStone").g();
|
||||||
|
public static final Block WALL_SIGN = (new BlockSign(68, TileEntitySign.class, false)).c(1.0F).a(e).a("sign").n().g();
|
||||||
|
public static final Block LEVER = (new BlockLever(69, 96)).c(0.5F).a(e).a("lever").g();
|
||||||
|
public static final Block STONE_PLATE = (new BlockPressurePlate(70, STONE.textureId, EnumMobType.MOBS, Material.STONE)).c(0.5F).a(h).a("pressurePlate").g();
|
||||||
|
public static final Block IRON_DOOR_BLOCK = (new BlockDoor(71, Material.ORE)).c(5.0F).a(i).a("doorIron").n().g();
|
||||||
|
public static final Block WOOD_PLATE = (new BlockPressurePlate(72, WOOD.textureId, EnumMobType.EVERYTHING, Material.WOOD)).c(0.5F).a(e).a("pressurePlate").g();
|
||||||
|
public static final Block REDSTONE_ORE = (new BlockRedstoneOre(73, 51, false)).c(3.0F).b(5.0F).a(h).a("oreRedstone").g();
|
||||||
|
public static final Block GLOWING_REDSTONE_ORE = (new BlockRedstoneOre(74, 51, true)).a(0.625F).c(3.0F).b(5.0F).a(h).a("oreRedstone").g();
|
||||||
|
public static final Block REDSTONE_TORCH_OFF = (new BlockRedstoneTorch(75, 115, false)).c(0.0F).a(e).a("notGate").g();
|
||||||
|
public static final Block REDSTONE_TORCH_ON = (new BlockRedstoneTorch(76, 99, true)).c(0.0F).a(0.5F).a(e).a("notGate").g();
|
||||||
|
public static final Block STONE_BUTTON = (new BlockButton(77, STONE.textureId)).c(0.5F).a(h).a("button").g();
|
||||||
|
public static final Block SNOW = (new BlockSnow(78, 66)).c(0.1F).a(k).a("snow");
|
||||||
|
public static final Block ICE = (new BlockIce(79, 67)).c(0.5F).f(3).a(j).a("ice");
|
||||||
|
public static final Block SNOW_BLOCK = (new BlockSnowBlock(80, 66)).c(0.2F).a(k).a("snow");
|
||||||
|
public static final Block CACTUS = (new BlockCactus(81, 70)).c(0.4F).a(k).a("cactus");
|
||||||
|
public static final Block CLAY = (new BlockClay(82, 72)).c(0.6F).a(f).a("clay");
|
||||||
|
public static final Block SUGAR_CANE_BLOCK = (new BlockReed(83, 73)).c(0.0F).a(g).a("reeds").n();
|
||||||
|
public static final Block JUKEBOX = (new BlockJukeBox(84, 74)).c(2.0F).b(10.0F).a(h).a("jukebox").g();
|
||||||
|
public static final Block FENCE = (new BlockFence(85, 4)).c(2.0F).b(5.0F).a(e).a("fence").g();
|
||||||
|
public static final Block PUMPKIN = (new BlockPumpkin(86, 102, false)).c(1.0F).a(e).a("pumpkin").g();
|
||||||
|
public static final Block NETHERRACK = (new BlockBloodStone(87, 103)).c(0.4F).a(h).a("hellrock");
|
||||||
|
public static final Block SOUL_SAND = (new BlockSlowSand(88, 104)).c(0.5F).a(l).a("hellsand");
|
||||||
|
public static final Block GLOWSTONE = (new BlockLightStone(89, 105, Material.STONE)).c(0.3F).a(j).a(1.0F).a("lightgem");
|
||||||
|
public static final BlockPortal PORTAL = (BlockPortal) (new BlockPortal(90, 14)).c(-1.0F).a(j).a(0.75F).a("portal");
|
||||||
|
public static final Block JACK_O_LANTERN = (new BlockPumpkin(91, 102, true)).c(1.0F).a(e).a(1.0F).a("litpumpkin").g();
|
||||||
|
public static final Block CAKE_BLOCK = (new BlockCake(92, 121)).c(0.5F).a(k).a("cake").n().g();
|
||||||
|
public static final Block DIODE_OFF = (new BlockDiode(93, false)).c(0.0F).a(e).a("diode").n().g();
|
||||||
|
public static final Block DIODE_ON = (new BlockDiode(94, true)).c(0.0F).a(0.625F).a(e).a("diode").n().g();
|
||||||
|
public static final Block LOCKED_CHEST = (new BlockLockedChest(95)).c(0.0F).a(1.0F).a(e).a("lockedchest").a(true).g();
|
||||||
|
public static final Block TRAP_DOOR = (new BlockTrapdoor(96, Material.WOOD)).c(3.0F).a(e).a("trapdoor").n().g();
|
||||||
|
public static final List<Integer> leafDecayBlacklist = Arrays.asList(PoseidonConfig.getInstance().getTreeBlacklistIDs());
|
||||||
|
public int textureId;
|
||||||
|
public final int id;
|
||||||
|
protected float strength;
|
||||||
|
protected float durability;
|
||||||
|
protected boolean bq;
|
||||||
|
protected boolean br;
|
||||||
|
public double minX;
|
||||||
|
public double minY;
|
||||||
|
public double minZ;
|
||||||
|
public double maxX;
|
||||||
|
public double maxY;
|
||||||
|
public double maxZ;
|
||||||
|
public StepSound stepSound;
|
||||||
|
public float bz;
|
||||||
|
public final Material material;
|
||||||
|
public float frictionFactor;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
protected Block(int i, Material material) {
|
||||||
|
this.bq = true;
|
||||||
|
this.br = true;
|
||||||
|
this.stepSound = d;
|
||||||
|
this.bz = 1.0F;
|
||||||
|
this.frictionFactor = 0.6F;
|
||||||
|
if (byId[i] != null) {
|
||||||
|
throw new IllegalArgumentException("Slot " + i + " is already occupied by " + byId[i] + " when adding " + this);
|
||||||
|
} else {
|
||||||
|
this.material = material;
|
||||||
|
byId[i] = this;
|
||||||
|
this.id = i;
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
o[i] = this.a();
|
||||||
|
q[i] = this.a() ? 255 : 0;
|
||||||
|
r[i] = !material.blocksLight();
|
||||||
|
isTileEntity[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block g() {
|
||||||
|
t[this.id] = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void h() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block(int i, int j, Material material) {
|
||||||
|
this(i, material);
|
||||||
|
this.textureId = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block a(StepSound stepsound) {
|
||||||
|
this.stepSound = stepsound;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block f(int i) {
|
||||||
|
q[this.id] = i;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block a(float f) {
|
||||||
|
s[this.id] = (int) (15.0F * f);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block b(float f) {
|
||||||
|
this.durability = f * 3.0F;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block c(float f) {
|
||||||
|
this.strength = f;
|
||||||
|
if (this.durability < f * 5.0F) {
|
||||||
|
this.durability = f * 5.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block i() {
|
||||||
|
this.c(-1.0F);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float j() {
|
||||||
|
return this.strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block a(boolean flag) {
|
||||||
|
n[this.id] = flag;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(float f, float f1, float f2, float f3, float f4, float f5) {
|
||||||
|
this.minX = (double) f;
|
||||||
|
this.minY = (double) f1;
|
||||||
|
this.minZ = (double) f2;
|
||||||
|
this.maxX = (double) f3;
|
||||||
|
this.maxY = (double) f4;
|
||||||
|
this.maxZ = (double) f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
return iblockaccess.getMaterial(i, j, k).isBuildable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return this.a(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, AxisAlignedBB axisalignedbb, ArrayList arraylist) {
|
||||||
|
AxisAlignedBB axisalignedbb1 = this.e(world, i, j, k);
|
||||||
|
|
||||||
|
if (axisalignedbb1 != null && axisalignedbb.a(axisalignedbb1)) {
|
||||||
|
arraylist.add(axisalignedbb1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return AxisAlignedBB.b((double) i + this.minX, (double) j + this.minY, (double) k + this.minZ, (double) i + this.maxX, (double) j + this.maxY, (double) k + this.maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(int i, boolean flag) {
|
||||||
|
return this.k_();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean k_() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postBreak(World world, int i, int j, int k, int l) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int c() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDamage(EntityHuman entityhuman) {
|
||||||
|
return this.strength < 0.0F ? 0.0F : (!entityhuman.b(this) ? 1.0F / this.strength / 100.0F : entityhuman.a(this) / this.strength / 30.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void g(World world, int i, int j, int k, int l) {
|
||||||
|
this.dropNaturally(world, i, j, k, l, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropNaturally(World world, int i, int j, int k, int l, float f) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
int i1 = this.a(world.random);
|
||||||
|
|
||||||
|
for (int j1 = 0; j1 < i1; ++j1) {
|
||||||
|
// CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions
|
||||||
|
if (world.random.nextFloat() < f) {
|
||||||
|
int k1 = this.a(l, world.random);
|
||||||
|
|
||||||
|
if (k1 > 0) {
|
||||||
|
this.a(world, i, j, k, new ItemStack(k1, 1, this.a_(l)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void a(World world, int i, int j, int k, ItemStack itemstack) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
float f = 0.7F;
|
||||||
|
double d0 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.5D;
|
||||||
|
double d1 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.5D;
|
||||||
|
double d2 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.5D;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) i + d0, (double) j + d1, (double) k + d2, itemstack);
|
||||||
|
|
||||||
|
entityitem.pickupDelay = 10;
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int a_(int i) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float a(Entity entity) {
|
||||||
|
return this.durability / 5.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPosition a(World world, int i, int j, int k, Vec3D vec3d, Vec3D vec3d1) {
|
||||||
|
this.a(world, i, j, k);
|
||||||
|
vec3d = vec3d.add((double) (-i), (double) (-j), (double) (-k));
|
||||||
|
vec3d1 = vec3d1.add((double) (-i), (double) (-j), (double) (-k));
|
||||||
|
Vec3D vec3d2 = vec3d.a(vec3d1, this.minX);
|
||||||
|
Vec3D vec3d3 = vec3d.a(vec3d1, this.maxX);
|
||||||
|
Vec3D vec3d4 = vec3d.b(vec3d1, this.minY);
|
||||||
|
Vec3D vec3d5 = vec3d.b(vec3d1, this.maxY);
|
||||||
|
Vec3D vec3d6 = vec3d.c(vec3d1, this.minZ);
|
||||||
|
Vec3D vec3d7 = vec3d.c(vec3d1, this.maxZ);
|
||||||
|
|
||||||
|
if (!this.a(vec3d2)) {
|
||||||
|
vec3d2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.a(vec3d3)) {
|
||||||
|
vec3d3 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.b(vec3d4)) {
|
||||||
|
vec3d4 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.b(vec3d5)) {
|
||||||
|
vec3d5 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.c(vec3d6)) {
|
||||||
|
vec3d6 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.c(vec3d7)) {
|
||||||
|
vec3d7 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3D vec3d8 = null;
|
||||||
|
|
||||||
|
if (vec3d2 != null && (vec3d8 == null || vec3d.a(vec3d2) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d3 != null && (vec3d8 == null || vec3d.a(vec3d3) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d4 != null && (vec3d8 == null || vec3d.a(vec3d4) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d5 != null && (vec3d8 == null || vec3d.a(vec3d5) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d6 != null && (vec3d8 == null || vec3d.a(vec3d6) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d7 != null && (vec3d8 == null || vec3d.a(vec3d7) < vec3d.a(vec3d8))) {
|
||||||
|
vec3d8 = vec3d7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
byte b0 = -1;
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d2) {
|
||||||
|
b0 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d3) {
|
||||||
|
b0 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d4) {
|
||||||
|
b0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d5) {
|
||||||
|
b0 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d6) {
|
||||||
|
b0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vec3d8 == vec3d7) {
|
||||||
|
b0 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovingObjectPosition(i, j, k, b0, vec3d8.add((double) i, (double) j, (double) k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean a(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.b >= this.minY && vec3d.b <= this.maxY && vec3d.c >= this.minZ && vec3d.c <= this.maxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean b(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.a >= this.minX && vec3d.a <= this.maxX && vec3d.c >= this.minZ && vec3d.c <= this.maxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean c(Vec3D vec3d) {
|
||||||
|
return vec3d == null ? false : vec3d.a >= this.minX && vec3d.a <= this.maxX && vec3d.b >= this.minY && vec3d.b <= this.maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void d(World world, int i, int j, int k) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k, int l) {
|
||||||
|
return this.canPlace(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
int l = world.getTypeId(i, j, k);
|
||||||
|
|
||||||
|
return l == 0 || byId[l].material.isReplacable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, Entity entity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, int l) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Entity entity, Vec3D vec3d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPowerSource() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Entity entity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean d(World world, int i, int j, int k, int l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, EntityHuman entityhuman, int i, int j, int k, int l) {
|
||||||
|
entityhuman.a(StatisticList.C[this.id], 1);
|
||||||
|
this.g(world, i, j, k, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean f(World world, int i, int j, int k) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, EntityLiving entityliving) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block a(String s) {
|
||||||
|
this.name = "tile." + s;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String k() {
|
||||||
|
return StatisticCollector.a(this.l() + ".name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String l() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, int l, int i1) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean m() {
|
||||||
|
return this.br;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Block n() {
|
||||||
|
this.br = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int e() {
|
||||||
|
return this.material.j();
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
Item.byId[WOOL.id] = (new ItemCloth(WOOL.id - 256)).a("cloth");
|
||||||
|
Item.byId[LOG.id] = (new ItemLog(LOG.id - 256)).a("log");
|
||||||
|
Item.byId[STEP.id] = (new ItemStep(STEP.id - 256)).a("stoneSlab");
|
||||||
|
Item.byId[SAPLING.id] = (new ItemSapling(SAPLING.id - 256)).a("sapling");
|
||||||
|
Item.byId[LEAVES.id] = (new ItemLeaves(LEAVES.id - 256)).a("leaves");
|
||||||
|
Item.byId[PISTON.id] = new ItemPiston(PISTON.id - 256);
|
||||||
|
Item.byId[PISTON_STICKY.id] = new ItemPiston(PISTON_STICKY.id - 256);
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; ++i) {
|
||||||
|
if (byId[i] != null && Item.byId[i] == null) {
|
||||||
|
Item.byId[i] = new ItemBlock(i - 256);
|
||||||
|
byId[i].h();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r[0] = true;
|
||||||
|
StatisticList.b();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockBed extends Block {
|
||||||
|
|
||||||
|
public static final int[][] a = new int[][] { { 0, 1}, { -1, 0}, { 0, -1}, { 1, 0}};
|
||||||
|
|
||||||
|
public BlockBed(int i) {
|
||||||
|
super(i, 134, Material.CLOTH);
|
||||||
|
this.o();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (world.isStatic) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (!d(l)) {
|
||||||
|
int i1 = c(l);
|
||||||
|
|
||||||
|
i += a[i1][0];
|
||||||
|
k += a[i1][1];
|
||||||
|
if (world.getTypeId(i, j, k) != this.id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = world.getData(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.worldProvider.d()) {
|
||||||
|
double d0 = (double) i + 0.5D;
|
||||||
|
double d1 = (double) j + 0.5D;
|
||||||
|
double d2 = (double) k + 0.5D;
|
||||||
|
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
int j1 = c(l);
|
||||||
|
|
||||||
|
i += a[j1][0];
|
||||||
|
k += a[j1][1];
|
||||||
|
if (world.getTypeId(i, j, k) == this.id) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
d0 = (d0 + (double) i + 0.5D) / 2.0D;
|
||||||
|
d1 = (d1 + (double) j + 0.5D) / 2.0D;
|
||||||
|
d2 = (d2 + (double) k + 0.5D) / 2.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.createExplosion((Entity) null, (double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), 5.0F, true, EntityDamageEvent.DamageCause.BED_EXPLOSION); //Project poseidon
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (e(l)) {
|
||||||
|
EntityHuman entityhuman1 = null;
|
||||||
|
Iterator iterator = world.players.iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
EntityHuman entityhuman2 = (EntityHuman) iterator.next();
|
||||||
|
|
||||||
|
if (entityhuman2.isSleeping()) {
|
||||||
|
ChunkCoordinates chunkcoordinates = entityhuman2.A;
|
||||||
|
|
||||||
|
if (chunkcoordinates.x == i && chunkcoordinates.y == j && chunkcoordinates.z == k) {
|
||||||
|
entityhuman1 = entityhuman2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityhuman1 != null) {
|
||||||
|
entityhuman.a("tile.bed.occupied");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
a(world, i, j, k, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumBedError enumbederror = entityhuman.a(i, j, k);
|
||||||
|
|
||||||
|
if (enumbederror == EnumBedError.OK) {
|
||||||
|
a(world, i, j, k, true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (enumbederror == EnumBedError.NOT_POSSIBLE_NOW) {
|
||||||
|
entityhuman.a("tile.bed.noSleep");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
if (i == 0) {
|
||||||
|
return Block.WOOD.textureId;
|
||||||
|
} else {
|
||||||
|
int k = c(j);
|
||||||
|
int l = BedBlockTextures.c[k][i];
|
||||||
|
|
||||||
|
return d(j) ? (l == 2 ? this.textureId + 2 + 16 : (l != 5 && l != 4 ? this.textureId + 1 : this.textureId + 1 + 16)) : (l == 3 ? this.textureId - 1 + 16 : (l != 5 && l != 4 ? this.textureId : this.textureId + 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
this.o();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
int j1 = c(i1);
|
||||||
|
|
||||||
|
if (d(i1)) {
|
||||||
|
if (world.getTypeId(i - a[j1][0], j, k - a[j1][1]) != this.id) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
} else if (world.getTypeId(i + a[j1][0], j, k + a[j1][1]) != this.id) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
if (!world.isStatic) {
|
||||||
|
this.g(world, i, j, k, i1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return d(i) ? 0 : Item.BED.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void o() {
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int c(int i) {
|
||||||
|
return i & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean d(int i) {
|
||||||
|
return (i & 8) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean e(int i) {
|
||||||
|
return (i & 4) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void a(World world, int i, int j, int k, boolean flag) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
l |= 4;
|
||||||
|
} else {
|
||||||
|
l &= -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChunkCoordinates f(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
int j1 = c(i1);
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 <= 1; ++k1) {
|
||||||
|
int l1 = i - a[j1][0] * k1 - 1;
|
||||||
|
int i2 = k - a[j1][1] * k1 - 1;
|
||||||
|
int j2 = l1 + 2;
|
||||||
|
int k2 = i2 + 2;
|
||||||
|
|
||||||
|
for (int l2 = l1; l2 <= j2; ++l2) {
|
||||||
|
for (int i3 = i2; i3 <= k2; ++i3) {
|
||||||
|
if (world.e(l2, j - 1, i3) && world.isEmpty(l2, j, i3) && world.isEmpty(l2, j + 1, i3)) {
|
||||||
|
if (l <= 0) {
|
||||||
|
return new ChunkCoordinates(l2, j, i3);
|
||||||
|
}
|
||||||
|
|
||||||
|
--l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropNaturally(World world, int i, int j, int k, int l, float f) {
|
||||||
|
if (!d(l)) {
|
||||||
|
super.dropNaturally(world, i, j, k, l, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int e() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||||
|
|
||||||
|
public class BlockBloodStone extends Block {
|
||||||
|
|
||||||
|
public BlockBloodStone(int i, int j) {
|
||||||
|
super(i, j, Material.STONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (net.minecraft.server.Block.byId[l] != null && net.minecraft.server.Block.byId[l].isPowerSource()) {
|
||||||
|
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
int power = block.getBlockPower();
|
||||||
|
|
||||||
|
BlockRedstoneEvent event = new BlockRedstoneEvent(block, power, power);
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockBookshelf extends Block {
|
||||||
|
|
||||||
|
public BlockBookshelf(int i, int j) {
|
||||||
|
super(i, j, Material.WOOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i <= 1 ? 4 : this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BlockBreakable extends Block {
|
||||||
|
|
||||||
|
private boolean a;
|
||||||
|
|
||||||
|
protected BlockBreakable(int i, int j, Material material, boolean flag) {
|
||||||
|
super(i, j, material);
|
||||||
|
this.a = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockButton extends Block {
|
||||||
|
|
||||||
|
protected BlockButton(int i, int j) {
|
||||||
|
super(i, j, Material.ORIENTABLE);
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int c() {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k, int l) {
|
||||||
|
return l == 2 && world.e(i, j, k + 1) ? true : (l == 3 && world.e(i, j, k - 1) ? true : (l == 4 && world.e(i + 1, j, k) ? true : l == 5 && world.e(i - 1, j, k)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return world.e(i - 1, j, k) ? true : (world.e(i + 1, j, k) ? true : (world.e(i, j, k - 1) ? true : world.e(i, j, k + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
int j1 = i1 & 8;
|
||||||
|
|
||||||
|
i1 &= 7;
|
||||||
|
if (l == 2 && world.e(i, j, k + 1)) {
|
||||||
|
i1 = 4;
|
||||||
|
} else if (l == 3 && world.e(i, j, k - 1)) {
|
||||||
|
i1 = 3;
|
||||||
|
} else if (l == 4 && world.e(i + 1, j, k)) {
|
||||||
|
i1 = 2;
|
||||||
|
} else if (l == 5 && world.e(i - 1, j, k)) {
|
||||||
|
i1 = 1;
|
||||||
|
} else {
|
||||||
|
i1 = this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, i1 + j1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int g(World world, int i, int j, int k) {
|
||||||
|
return world.e(i - 1, j, k) ? 1 : (world.e(i + 1, j, k) ? 2 : (world.e(i, j, k - 1) ? 3 : (world.e(i, j, k + 1) ? 4 : 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (this.h(world, i, j, k)) {
|
||||||
|
int i1 = world.getData(i, j, k) & 7;
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (!world.e(i - 1, j, k) && i1 == 1) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i + 1, j, k) && i1 == 2) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j, k - 1) && i1 == 3) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j, k + 1) && i1 == 4) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean h(World world, int i, int j, int k) {
|
||||||
|
if (!this.canPlace(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
int l = iblockaccess.getData(i, j, k);
|
||||||
|
int i1 = l & 7;
|
||||||
|
boolean flag = (l & 8) > 0;
|
||||||
|
float f = 0.375F;
|
||||||
|
float f1 = 0.625F;
|
||||||
|
float f2 = 0.1875F;
|
||||||
|
float f3 = 0.125F;
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
f3 = 0.0625F;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 1) {
|
||||||
|
this.a(0.0F, f, 0.5F - f2, f3, f1, 0.5F + f2);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
this.a(1.0F - f3, f, 0.5F - f2, 1.0F, f1, 0.5F + f2);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
this.a(0.5F - f2, f, 0.0F, 0.5F + f2, f1, f3);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
this.a(0.5F - f2, f, 1.0F - f3, 0.5F + f2, f1, 1.0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
this.interact(world, i, j, k, entityhuman);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
int i1 = l & 7;
|
||||||
|
int j1 = 8 - (l & 8);
|
||||||
|
|
||||||
|
if (j1 == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
int old = (j1 != 8) ? 1 : 0;
|
||||||
|
int current = (j1 == 8) ? 1 : 0;
|
||||||
|
|
||||||
|
BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
|
||||||
|
world.getServer().getPluginManager().callEvent(eventRedstone);
|
||||||
|
|
||||||
|
if ((eventRedstone.getNewCurrent() > 0) != (j1 == 8)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
world.setData(i, j, k, i1 + j1);
|
||||||
|
world.b(i, j, k, i, j, k);
|
||||||
|
world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.click", 0.3F, 0.6F);
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
if (i1 == 1) {
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
} else {
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) > 0) {
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
int i1 = l & 7;
|
||||||
|
|
||||||
|
if (i1 == 1) {
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
} else {
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
return (iblockaccess.getData(i, j, k) & 8) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean d(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((i1 & 8) == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int j1 = i1 & 7;
|
||||||
|
|
||||||
|
return j1 == 5 && l == 1 ? true : (j1 == 4 && l == 2 ? true : (j1 == 3 && l == 3 ? true : (j1 == 2 && l == 4 ? true : j1 == 1 && l == 5)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPowerSource() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) != 0) {
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
|
||||||
|
BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, 1, 0);
|
||||||
|
world.getServer().getPluginManager().callEvent(eventRedstone);
|
||||||
|
|
||||||
|
if (eventRedstone.getNewCurrent() > 0) return;
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
world.setData(i, j, k, l & 7);
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
int i1 = l & 7;
|
||||||
|
|
||||||
|
if (i1 == 1) {
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
} else {
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.click", 0.3F, 0.5F);
|
||||||
|
world.b(i, j, k, i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
|
||||||
|
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
public class BlockCactus extends Block {
|
||||||
|
|
||||||
|
protected BlockCactus(int i, int j) {
|
||||||
|
super(i, j, Material.CACTUS);
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (world.isEmpty(i, j + 1, k)) {
|
||||||
|
int l;
|
||||||
|
|
||||||
|
for (l = 1; world.getTypeId(i, j - l, k) == this.id; ++l) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l < 3) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (i1 == 15) {
|
||||||
|
world.setTypeId(i, j + 1, k, this.id);
|
||||||
|
world.setData(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
world.setData(i, j, k, i1 + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
float f = 0.0625F;
|
||||||
|
|
||||||
|
return AxisAlignedBB.b((double) ((float) i + f), (double) j, (double) ((float) k + f), (double) ((float) (i + 1) - f), (double) ((float) (j + 1) - f), (double) ((float) (k + 1) - f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId - 1 : (i == 0 ? this.textureId + 1 : this.textureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return !super.canPlace(world, i, j, k) ? false : this.f(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (!this.f(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean f(World world, int i, int j, int k) {
|
||||||
|
if (world.getMaterial(i - 1, j, k).isBuildable()) {
|
||||||
|
return false;
|
||||||
|
} else if (world.getMaterial(i + 1, j, k).isBuildable()) {
|
||||||
|
return false;
|
||||||
|
} else if (world.getMaterial(i, j, k - 1).isBuildable()) {
|
||||||
|
return false;
|
||||||
|
} else if (world.getMaterial(i, j, k + 1).isBuildable()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int l = world.getTypeId(i, j - 1, k);
|
||||||
|
|
||||||
|
return l == Block.CACTUS.id || l == Block.SAND.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Entity entity) {
|
||||||
|
// CraftBukkit start - ENTITY_DAMAGEBY_BLOCK event
|
||||||
|
if (entity instanceof EntityLiving) {
|
||||||
|
org.bukkit.block.Block damager = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
org.bukkit.entity.Entity damagee = (entity == null) ? null : entity.getBukkitEntity();
|
||||||
|
|
||||||
|
EntityDamageByBlockEvent event = new EntityDamageByBlockEvent(damager, damagee, EntityDamageEvent.DamageCause.CONTACT, 1);
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
entity.damageEntity((Entity) null, event.getDamage());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
entity.damageEntity((Entity) null, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockCake extends Block {
|
||||||
|
|
||||||
|
protected BlockCake(int i, int j) {
|
||||||
|
super(i, j, Material.CAKE);
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
int l = iblockaccess.getData(i, j, k);
|
||||||
|
float f = 0.0625F;
|
||||||
|
float f1 = (float) (1 + l * 2) / 16.0F;
|
||||||
|
float f2 = 0.5F;
|
||||||
|
|
||||||
|
this.a(f1, 0.0F, f, 1.0F - f, f2, 1.0F - f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
float f = 0.0625F;
|
||||||
|
float f1 = (float) (1 + l * 2) / 16.0F;
|
||||||
|
float f2 = 0.5F;
|
||||||
|
|
||||||
|
return AxisAlignedBB.b((double) ((float) i + f1), (double) j, (double) ((float) k + f), (double) ((float) (i + 1) - f), (double) ((float) j + f2 - f), (double) ((float) (k + 1) - f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return i == 1 ? this.textureId : (i == 0 ? this.textureId + 3 : (j > 0 && i == 4 ? this.textureId + 2 : this.textureId + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId : (i == 0 ? this.textureId + 3 : this.textureId + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
this.c(world, i, j, k, entityhuman);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
this.c(world, i, j, k, entityhuman);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void c(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (entityhuman.health < 20) {
|
||||||
|
entityhuman.b(3);
|
||||||
|
int l = world.getData(i, j, k) + 1;
|
||||||
|
|
||||||
|
if (l >= 6) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
world.setData(i, j, k, l);
|
||||||
|
world.i(i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return !super.canPlace(world, i, j, k) ? false : this.f(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (!this.f(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean f(World world, int i, int j, int k) {
|
||||||
|
return world.getMaterial(i, j - 1, k).isBuildable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockChest extends BlockContainer {
|
||||||
|
|
||||||
|
private Random a = new Random();
|
||||||
|
|
||||||
|
protected BlockChest(int i) {
|
||||||
|
super(i, Material.WOOD);
|
||||||
|
this.textureId = 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId - 1 : (i == 0 ? this.textureId - 1 : (i == 3 ? this.textureId + 1 : this.textureId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
int l = 0;
|
||||||
|
|
||||||
|
if (world.getTypeId(i - 1, j, k) == this.id) {
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i + 1, j, k) == this.id) {
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i, j, k - 1) == this.id) {
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i, j, k + 1) == this.id) {
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l > 1 ? false : (this.g(world, i - 1, j, k) ? false : (this.g(world, i + 1, j, k) ? false : (this.g(world, i, j, k - 1) ? false : !this.g(world, i, j, k + 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean g(World world, int i, int j, int k) {
|
||||||
|
return world.getTypeId(i, j, k) != this.id ? false : (world.getTypeId(i - 1, j, k) == this.id ? true : (world.getTypeId(i + 1, j, k) == this.id ? true : (world.getTypeId(i, j, k - 1) == this.id ? true : world.getTypeId(i, j, k + 1) == this.id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
TileEntityChest tileentitychest = (TileEntityChest) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
for (int l = 0; l < tileentitychest.getSize(); ++l) {
|
||||||
|
ItemStack itemstack = tileentitychest.getItem(l);
|
||||||
|
|
||||||
|
if (itemstack != null) {
|
||||||
|
float f = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f1 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f2 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
|
||||||
|
while (itemstack.count > 0) {
|
||||||
|
int i1 = this.a.nextInt(21) + 10;
|
||||||
|
|
||||||
|
if (i1 > itemstack.count) {
|
||||||
|
i1 = itemstack.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemstack.count -= i1;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) ((float) i + f), (double) ((float) j + f1), (double) ((float) k + f2), new ItemStack(itemstack.id, i1, itemstack.getData()));
|
||||||
|
float f3 = 0.05F;
|
||||||
|
|
||||||
|
entityitem.motX = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F);
|
||||||
|
entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
tileentitychest.setItem(l, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
Object object = (TileEntityChest) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
if (world.e(i, j + 1, k)) {
|
||||||
|
return true;
|
||||||
|
} else if (world.getTypeId(i - 1, j, k) == this.id && world.e(i - 1, j + 1, k)) {
|
||||||
|
return true;
|
||||||
|
} else if (world.getTypeId(i + 1, j, k) == this.id && world.e(i + 1, j + 1, k)) {
|
||||||
|
return true;
|
||||||
|
} else if (world.getTypeId(i, j, k - 1) == this.id && world.e(i, j + 1, k - 1)) {
|
||||||
|
return true;
|
||||||
|
} else if (world.getTypeId(i, j, k + 1) == this.id && world.e(i, j + 1, k + 1)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (world.getTypeId(i - 1, j, k) == this.id) {
|
||||||
|
object = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(i - 1, j, k), (IInventory) object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i + 1, j, k) == this.id) {
|
||||||
|
object = new InventoryLargeChest("Large chest", (IInventory) object, (TileEntityChest) world.getTileEntity(i + 1, j, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i, j, k - 1) == this.id) {
|
||||||
|
object = new InventoryLargeChest("Large chest", (TileEntityChest) world.getTileEntity(i, j, k - 1), (IInventory) object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.getTypeId(i, j, k + 1) == this.id) {
|
||||||
|
object = new InventoryLargeChest("Large chest", (IInventory) object, (TileEntityChest) world.getTileEntity(i, j, k + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.isStatic) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
entityhuman.a((IInventory) object);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TileEntity a_() {
|
||||||
|
return new TileEntityChest();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockClay extends Block {
|
||||||
|
|
||||||
|
public BlockClay(int i, int j) {
|
||||||
|
super(i, j, Material.CLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Item.CLAY_BALL.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BlockCloth extends Block {
|
||||||
|
|
||||||
|
public BlockCloth() {
|
||||||
|
super(35, 64, Material.CLOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
if (j == 0) {
|
||||||
|
return this.textureId;
|
||||||
|
} else {
|
||||||
|
j = ~(j & 15);
|
||||||
|
return 113 + ((j & 8) >> 3) + (j & 7) * 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int a_(int i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int c(int i) {
|
||||||
|
return ~i & 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int d(int i) {
|
||||||
|
return ~i & 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public abstract class BlockContainer extends Block {
|
||||||
|
|
||||||
|
protected BlockContainer(int i, Material material) {
|
||||||
|
super(i, material);
|
||||||
|
isTileEntity[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockContainer(int i, int j, Material material) {
|
||||||
|
super(i, j, material);
|
||||||
|
isTileEntity[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
super.c(world, i, j, k);
|
||||||
|
world.setTileEntity(i, j, k, this.a_());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
world.o(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TileEntity a_();
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockCrops extends BlockFlower {
|
||||||
|
|
||||||
|
protected BlockCrops(int i, int j) {
|
||||||
|
super(i, j);
|
||||||
|
this.textureId = j;
|
||||||
|
this.a(true);
|
||||||
|
float f = 0.5F;
|
||||||
|
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.25F, 0.5F + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean c(int i) {
|
||||||
|
return i == Block.SOIL.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
super.a(world, i, j, k, random);
|
||||||
|
if (world.getLightLevel(i, j + 1, k) >= 9) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (l < 7) {
|
||||||
|
float f = this.h(world, i, j, k);
|
||||||
|
|
||||||
|
if (random.nextInt((int) (100.0F / f)) == 0) {
|
||||||
|
++l;
|
||||||
|
world.setData(i, j, k, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void d_(World world, int i, int j, int k) {
|
||||||
|
world.setData(i, j, k, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float h(World world, int i, int j, int k) {
|
||||||
|
float f = 1.0F;
|
||||||
|
int l = world.getTypeId(i, j, k - 1);
|
||||||
|
int i1 = world.getTypeId(i, j, k + 1);
|
||||||
|
int j1 = world.getTypeId(i - 1, j, k);
|
||||||
|
int k1 = world.getTypeId(i + 1, j, k);
|
||||||
|
int l1 = world.getTypeId(i - 1, j, k - 1);
|
||||||
|
int i2 = world.getTypeId(i + 1, j, k - 1);
|
||||||
|
int j2 = world.getTypeId(i + 1, j, k + 1);
|
||||||
|
int k2 = world.getTypeId(i - 1, j, k + 1);
|
||||||
|
boolean flag = j1 == this.id || k1 == this.id;
|
||||||
|
boolean flag1 = l == this.id || i1 == this.id;
|
||||||
|
boolean flag2 = l1 == this.id || i2 == this.id || j2 == this.id || k2 == this.id;
|
||||||
|
|
||||||
|
for (int l2 = i - 1; l2 <= i + 1; ++l2) {
|
||||||
|
for (int i3 = k - 1; i3 <= k + 1; ++i3) {
|
||||||
|
int j3 = world.getTypeId(l2, j - 1, i3);
|
||||||
|
float f1 = 0.0F;
|
||||||
|
|
||||||
|
if (j3 == Block.SOIL.id) {
|
||||||
|
f1 = 1.0F;
|
||||||
|
if (world.getData(l2, j - 1, i3) > 0) {
|
||||||
|
f1 = 3.0F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l2 != i || i3 != k) {
|
||||||
|
f1 /= 4.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
f += f1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag2 || flag && flag1) {
|
||||||
|
f /= 2.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
if (j < 0) {
|
||||||
|
j = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.textureId + j;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropNaturally(World world, int i, int j, int k, int l, float f) {
|
||||||
|
super.dropNaturally(world, i, j, k, l, f);
|
||||||
|
if (!world.isStatic) {
|
||||||
|
for (int i1 = 0; i1 < 3; ++i1) {
|
||||||
|
if (world.random.nextInt(15) <= l) {
|
||||||
|
float f1 = 0.7F;
|
||||||
|
float f2 = world.random.nextFloat() * f1 + (1.0F - f1) * 0.5F;
|
||||||
|
float f3 = world.random.nextFloat() * f1 + (1.0F - f1) * 0.5F;
|
||||||
|
float f4 = world.random.nextFloat() * f1 + (1.0F - f1) * 0.5F;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) ((float) i + f2), (double) ((float) j + f3), (double) ((float) k + f4), new ItemStack(Item.SEEDS));
|
||||||
|
|
||||||
|
entityitem.pickupDelay = 10;
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return i == 7 ? Item.WHEAT.id : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockDeadBush extends BlockFlower {
|
||||||
|
|
||||||
|
protected BlockDeadBush(int i, int j) {
|
||||||
|
super(i, j);
|
||||||
|
float f = 0.4F;
|
||||||
|
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean c(int i) {
|
||||||
|
return i == Block.SAND.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockDiode extends Block {
|
||||||
|
|
||||||
|
public static final double[] a = new double[] { -0.0625D, 0.0625D, 0.1875D, 0.3125D};
|
||||||
|
private static final int[] b = new int[] { 1, 2, 3, 4};
|
||||||
|
private final boolean c;
|
||||||
|
|
||||||
|
protected BlockDiode(int i, boolean flag) {
|
||||||
|
super(i, 6, Material.ORIENTABLE);
|
||||||
|
this.c = flag;
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return !world.e(i, j - 1, k) ? false : super.canPlace(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean f(World world, int i, int j, int k) {
|
||||||
|
return !world.e(i, j - 1, k) ? false : super.f(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
boolean flag = this.f(world, i, j, k, l);
|
||||||
|
|
||||||
|
if (this.c && !flag) {
|
||||||
|
world.setTypeIdAndData(i, j, k, Block.DIODE_OFF.id, l);
|
||||||
|
} else if (!this.c) {
|
||||||
|
world.setTypeIdAndData(i, j, k, Block.DIODE_ON.id, l);
|
||||||
|
if (!flag) {
|
||||||
|
int i1 = (l & 12) >> 2;
|
||||||
|
|
||||||
|
world.c(i, j, k, Block.DIODE_ON.id, b[i1] * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return i == 0 ? (this.c ? 99 : 115) : (i == 1 ? (this.c ? 147 : 131) : 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return this.a(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean d(World world, int i, int j, int k, int l) {
|
||||||
|
return this.a(world, i, j, k, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
if (!this.c) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int i1 = iblockaccess.getData(i, j, k) & 3;
|
||||||
|
|
||||||
|
return i1 == 0 && l == 3 ? true : (i1 == 1 && l == 4 ? true : (i1 == 2 && l == 2 ? true : i1 == 3 && l == 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (!this.f(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
boolean flag = this.f(world, i, j, k, i1);
|
||||||
|
int j1 = (i1 & 12) >> 2;
|
||||||
|
|
||||||
|
if (this.c && !flag) {
|
||||||
|
world.c(i, j, k, this.id, b[j1] * 2);
|
||||||
|
} else if (!this.c && flag) {
|
||||||
|
world.c(i, j, k, this.id, b[j1] * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean f(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = l & 3;
|
||||||
|
|
||||||
|
switch (i1) {
|
||||||
|
case 0:
|
||||||
|
return world.isBlockFaceIndirectlyPowered(i, j, k + 1, 3) || world.getTypeId(i, j, k + 1) == Block.REDSTONE_WIRE.id && world.getData(i, j, k + 1) > 0;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return world.isBlockFaceIndirectlyPowered(i - 1, j, k, 4) || world.getTypeId(i - 1, j, k) == Block.REDSTONE_WIRE.id && world.getData(i - 1, j, k) > 0;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return world.isBlockFaceIndirectlyPowered(i, j, k - 1, 2) || world.getTypeId(i, j, k - 1) == Block.REDSTONE_WIRE.id && world.getData(i, j, k - 1) > 0;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return world.isBlockFaceIndirectlyPowered(i + 1, j, k, 5) || world.getTypeId(i + 1, j, k) == Block.REDSTONE_WIRE.id && world.getData(i + 1, j, k) > 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
int i1 = (l & 12) >> 2;
|
||||||
|
|
||||||
|
i1 = i1 + 1 << 2 & 12;
|
||||||
|
world.setData(i, j, k, i1 | l & 3);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPowerSource() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, EntityLiving entityliving) {
|
||||||
|
int l = ((MathHelper.floor((double) (entityliving.yaw * 4.0F / 360.0F) + 0.5D) & 3) + 2) % 4;
|
||||||
|
|
||||||
|
world.setData(i, j, k, l);
|
||||||
|
boolean flag = this.f(world, i, j, k, l);
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
world.c(i, j, k, this.id, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
world.applyPhysics(i, j + 1, k, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Item.DIODE.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BlockDirt extends Block {
|
||||||
|
|
||||||
|
protected BlockDirt(int i, int j) {
|
||||||
|
super(i, j, Material.EARTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
|
import org.bukkit.event.block.BlockDispenseEvent;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
public class BlockDispenser extends BlockContainer {
|
||||||
|
|
||||||
|
private Random a = new Random();
|
||||||
|
|
||||||
|
protected BlockDispenser(int i) {
|
||||||
|
super(i, Material.STONE);
|
||||||
|
this.textureId = 45;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int c() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Block.DISPENSER.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
super.c(world, i, j, k);
|
||||||
|
this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void g(World world, int i, int j, int k) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
int l = world.getTypeId(i, j, k - 1);
|
||||||
|
int i1 = world.getTypeId(i, j, k + 1);
|
||||||
|
int j1 = world.getTypeId(i - 1, j, k);
|
||||||
|
int k1 = world.getTypeId(i + 1, j, k);
|
||||||
|
byte b0 = 3;
|
||||||
|
|
||||||
|
if (Block.o[l] && !Block.o[i1]) {
|
||||||
|
b0 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[i1] && !Block.o[l]) {
|
||||||
|
b0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[j1] && !Block.o[k1]) {
|
||||||
|
b0 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[k1] && !Block.o[j1]) {
|
||||||
|
b0 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, b0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId + 17 : (i == 0 ? this.textureId + 17 : (i == 3 ? this.textureId + 1 : this.textureId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (world.isStatic) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
TileEntityDispenser tileentitydispenser = (TileEntityDispenser) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
entityhuman.a(tileentitydispenser);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CraftBukkit - private -> public
|
||||||
|
public void dispense(World world, int i, int j, int k, Random random) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
byte b0 = 0;
|
||||||
|
byte b1 = 0;
|
||||||
|
|
||||||
|
if (l == 3) {
|
||||||
|
b1 = 1;
|
||||||
|
} else if (l == 2) {
|
||||||
|
b1 = -1;
|
||||||
|
} else if (l == 5) {
|
||||||
|
b0 = 1;
|
||||||
|
} else {
|
||||||
|
b0 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntityDispenser tileentitydispenser = (TileEntityDispenser) world.getTileEntity(i, j, k);
|
||||||
|
// CraftBukkit start
|
||||||
|
int dispenseSlot = tileentitydispenser.findDispenseSlot();
|
||||||
|
ItemStack itemstack = null;
|
||||||
|
if (dispenseSlot > -1) {
|
||||||
|
itemstack = tileentitydispenser.getContents()[dispenseSlot];
|
||||||
|
|
||||||
|
// Copy item stack, because we want it to have 1 item
|
||||||
|
itemstack = new ItemStack(itemstack.id, 1, itemstack.damage);
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
double d0 = (double) i + (double) b0 * 0.6D + 0.5D;
|
||||||
|
double d1 = (double) j + 0.5D;
|
||||||
|
double d2 = (double) k + (double) b1 * 0.6D + 0.5D;
|
||||||
|
|
||||||
|
if (itemstack == null) {
|
||||||
|
world.e(1001, i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
// CraftBukkit start
|
||||||
|
double d3 = random.nextDouble() * 0.1D + 0.2D;
|
||||||
|
double motX = (double) b0 * d3;
|
||||||
|
double motY = 0.20000000298023224D;
|
||||||
|
double motZ = (double) b1 * d3;
|
||||||
|
motX += random.nextGaussian() * 0.007499999832361937D * 6.0D;
|
||||||
|
motY += random.nextGaussian() * 0.007499999832361937D * 6.0D;
|
||||||
|
motZ += random.nextGaussian() * 0.007499999832361937D * 6.0D;
|
||||||
|
|
||||||
|
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack).clone();
|
||||||
|
|
||||||
|
BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new Vector(motX, motY, motZ));
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually remove the item
|
||||||
|
tileentitydispenser.splitStack(dispenseSlot, 1);
|
||||||
|
|
||||||
|
motX = event.getVelocity().getX();
|
||||||
|
motY = event.getVelocity().getY();
|
||||||
|
motZ = event.getVelocity().getZ();
|
||||||
|
|
||||||
|
itemstack = new ItemStack(event.getItem().getTypeId(), event.getItem().getAmount(), event.getItem().getDurability());
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
if (itemstack.id == Item.ARROW.id) {
|
||||||
|
EntityArrow entityarrow = new EntityArrow(world, d0, d1, d2);
|
||||||
|
|
||||||
|
entityarrow.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
|
||||||
|
entityarrow.fromPlayer = true;
|
||||||
|
world.addEntity(entityarrow);
|
||||||
|
world.e(1002, i, j, k, 0);
|
||||||
|
} else if (itemstack.id == Item.EGG.id) {
|
||||||
|
EntityEgg entityegg = new EntityEgg(world, d0, d1, d2);
|
||||||
|
|
||||||
|
entityegg.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
|
||||||
|
world.addEntity(entityegg);
|
||||||
|
world.e(1002, i, j, k, 0);
|
||||||
|
} else if (itemstack.id == Item.SNOW_BALL.id) {
|
||||||
|
EntitySnowball entitysnowball = new EntitySnowball(world, d0, d1, d2);
|
||||||
|
|
||||||
|
entitysnowball.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
|
||||||
|
world.addEntity(entitysnowball);
|
||||||
|
world.e(1002, i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
EntityItem entityitem = new EntityItem(world, d0, d1 - 0.3D, d2, itemstack);
|
||||||
|
// CraftBukkit start
|
||||||
|
// double d3 = random.nextDouble() * 0.1D + 0.2D; // Moved up
|
||||||
|
entityitem.motX = motX;
|
||||||
|
entityitem.motY = motY;
|
||||||
|
entityitem.motZ = motZ;
|
||||||
|
// CraftBukkit end
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
world.e(1000, i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.e(2000, i, j, k, b0 + 1 + (b1 + 1) * 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (l > 0 && Block.byId[l].isPowerSource()) {
|
||||||
|
boolean flag = world.isBlockIndirectlyPowered(i, j, k) || world.isBlockIndirectlyPowered(i, j + 1, k);
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (world.isBlockIndirectlyPowered(i, j, k) || world.isBlockIndirectlyPowered(i, j + 1, k)) {
|
||||||
|
this.dispense(world, i, j, k, random);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TileEntity a_() {
|
||||||
|
return new TileEntityDispenser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, EntityLiving entityliving) {
|
||||||
|
int l = MathHelper.floor((double) (entityliving.yaw * 4.0F / 360.0F) + 0.5D) & 3;
|
||||||
|
|
||||||
|
if (l == 0) {
|
||||||
|
world.setData(i, j, k, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 1) {
|
||||||
|
world.setData(i, j, k, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 2) {
|
||||||
|
world.setData(i, j, k, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 3) {
|
||||||
|
world.setData(i, j, k, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
TileEntityDispenser tileentitydispenser = (TileEntityDispenser) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
for (int l = 0; l < tileentitydispenser.getSize(); ++l) {
|
||||||
|
ItemStack itemstack = tileentitydispenser.getItem(l);
|
||||||
|
|
||||||
|
if (itemstack != null) {
|
||||||
|
float f = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f1 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f2 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
|
||||||
|
while (itemstack.count > 0) {
|
||||||
|
int i1 = this.a.nextInt(21) + 10;
|
||||||
|
|
||||||
|
if (i1 > itemstack.count) {
|
||||||
|
i1 = itemstack.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemstack.count -= i1;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) ((float) i + f), (double) ((float) j + f1), (double) ((float) k + f2), new ItemStack(itemstack.id, i1, itemstack.getData()));
|
||||||
|
float f3 = 0.05F;
|
||||||
|
|
||||||
|
entityitem.motX = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F);
|
||||||
|
entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
tileentitydispenser.setItem(l, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockDoor extends Block {
|
||||||
|
|
||||||
|
protected BlockDoor(int i, Material material) {
|
||||||
|
super(i, material);
|
||||||
|
this.textureId = 97;
|
||||||
|
if (material == Material.ORE) {
|
||||||
|
++this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
float f = 0.5F;
|
||||||
|
float f1 = 1.0F;
|
||||||
|
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f1, 0.5F + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
if (i != 0 && i != 1) {
|
||||||
|
int k = this.d(j);
|
||||||
|
|
||||||
|
if ((k == 0 || k == 2) ^ i <= 3) {
|
||||||
|
return this.textureId;
|
||||||
|
} else {
|
||||||
|
int l = k / 2 + (i & 1 ^ k);
|
||||||
|
|
||||||
|
l += (j & 4) / 4;
|
||||||
|
int i1 = this.textureId - (j & 8) * 2;
|
||||||
|
|
||||||
|
if ((l & 1) != 0) {
|
||||||
|
i1 = -i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.textureId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
this.a(world, i, j, k);
|
||||||
|
return super.e(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
this.c(this.d(iblockaccess.getData(i, j, k)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(int i) {
|
||||||
|
float f = 0.1875F;
|
||||||
|
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F);
|
||||||
|
if (i == 0) {
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 1) {
|
||||||
|
this.a(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 2) {
|
||||||
|
this.a(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 3) {
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
this.interact(world, i, j, k, entityhuman);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (this.material == Material.ORE) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) != 0) {
|
||||||
|
if (world.getTypeId(i, j - 1, k) == this.id) {
|
||||||
|
this.interact(world, i, j - 1, k, entityhuman);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (world.getTypeId(i, j + 1, k) == this.id) {
|
||||||
|
world.setData(i, j + 1, k, (l ^ 4) + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, l ^ 4);
|
||||||
|
world.b(i, j - 1, k, i, j, k);
|
||||||
|
world.a(entityhuman, 1003, i, j, k, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoor(World world, int i, int j, int k, boolean flag) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) != 0) {
|
||||||
|
if (world.getTypeId(i, j - 1, k) == this.id) {
|
||||||
|
this.setDoor(world, i, j - 1, k, flag);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boolean flag1 = (world.getData(i, j, k) & 4) > 0;
|
||||||
|
|
||||||
|
if (flag1 != flag) {
|
||||||
|
if (world.getTypeId(i, j + 1, k) == this.id) {
|
||||||
|
world.setData(i, j + 1, k, (l ^ 4) + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, l ^ 4);
|
||||||
|
world.b(i, j - 1, k, i, j, k);
|
||||||
|
world.a((EntityHuman) null, 1003, i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((i1 & 8) != 0) {
|
||||||
|
if (world.getTypeId(i, j - 1, k) != this.id) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l > 0 && Block.byId[l].isPowerSource()) {
|
||||||
|
this.doPhysics(world, i, j - 1, k, l);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (world.getTypeId(i, j + 1, k) != this.id) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j - 1, k)) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
flag = true;
|
||||||
|
if (world.getTypeId(i, j + 1, k) == this.id) {
|
||||||
|
world.setTypeId(i, j + 1, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
this.g(world, i, j, k, i1);
|
||||||
|
}
|
||||||
|
} else if (l > 0 && Block.byId[l].isPowerSource()) {
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.World bworld = world.getWorld();
|
||||||
|
org.bukkit.block.Block block = bworld.getBlockAt(i, j, k);
|
||||||
|
org.bukkit.block.Block blockTop = bworld.getBlockAt(i, j + 1, k);
|
||||||
|
|
||||||
|
int power = block.getBlockPower();
|
||||||
|
int powerTop = blockTop.getBlockPower();
|
||||||
|
if (powerTop > power) power = powerTop;
|
||||||
|
int oldPower = (world.getData(i, j, k) & 4) > 0 ? 15 : 0;
|
||||||
|
|
||||||
|
if (oldPower == 0 ^ power == 0) {
|
||||||
|
BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, oldPower, power);
|
||||||
|
world.getServer().getPluginManager().callEvent(eventRedstone);
|
||||||
|
|
||||||
|
this.setDoor(world, i, j, k, eventRedstone.getNewCurrent() > 0);
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return (i & 8) != 0 ? 0 : (this.material == Material.ORE ? Item.IRON_DOOR.id : Item.WOOD_DOOR.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovingObjectPosition a(World world, int i, int j, int k, Vec3D vec3d, Vec3D vec3d1) {
|
||||||
|
this.a(world, i, j, k);
|
||||||
|
return super.a(world, i, j, k, vec3d, vec3d1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int d(int i) {
|
||||||
|
return (i & 4) == 0 ? i - 1 & 3 : i & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return j >= 127 ? false : world.e(i, j - 1, k) && super.canPlace(world, i, j, k) && super.canPlace(world, i, j + 1, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean e(int i) {
|
||||||
|
return (i & 4) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int e() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
|
||||||
|
public class BlockFence extends Block {
|
||||||
|
private boolean modernFencingBounding = false;
|
||||||
|
|
||||||
|
public BlockFence(int i, int j) {
|
||||||
|
super(i, j, Material.WOOD);
|
||||||
|
modernFencingBounding = (boolean) PoseidonConfig.getInstance().getConfigOption("world-settings.use-modern-fence-bounding-boxes", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return world.getTypeId(i, j - 1, k) == this.id ? true : (!world.getMaterial(i, j - 1, k).isBuildable() ? false : super.canPlace(world, i, j, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
if(!modernFencingBounding) {
|
||||||
|
return AxisAlignedBB.b((double) i, (double) j, (double) k, (double) (i + 1), (double) ((float) j + 1.5F), (double) (k + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag = this.b(world, i, j, k - 1);
|
||||||
|
boolean flag1 = this.b(world, i, j, k + 1);
|
||||||
|
boolean flag2 = this.b(world, i - 1, j, k);
|
||||||
|
boolean flag3 = this.b(world, i + 1, j, k);
|
||||||
|
float f = 0.375F;
|
||||||
|
float f1 = 0.625F;
|
||||||
|
float f2 = 0.375F;
|
||||||
|
float f3 = 0.625F;
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
f2 = 0.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag1) {
|
||||||
|
f3 = 1.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag2) {
|
||||||
|
f = 0.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag3) {
|
||||||
|
f1 = 1.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AxisAlignedBB.b((double) ((float) i + f), (double) j, (double) ((float) k + f2), (double) ((float) i + f1), (double) ((float) j + 1.5F), (double) ((float) k + f3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
int l = iblockaccess.getTypeId(i, j, k);
|
||||||
|
|
||||||
|
if (l != this.id) {
|
||||||
|
Block block = Block.byId[l];
|
||||||
|
|
||||||
|
return block != null && block.material.h() && block.b() ? block.material != Material.PUMPKIN : false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.BlockBurnEvent;
|
||||||
|
import org.bukkit.event.block.BlockIgniteEvent;
|
||||||
|
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
|
||||||
|
import org.bukkit.event.block.BlockSpreadEvent;
|
||||||
|
import org.bukkit.material.MaterialData;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
public class BlockFire extends Block {
|
||||||
|
|
||||||
|
private int[] a = new int[256];
|
||||||
|
private int[] b = new int[256];
|
||||||
|
|
||||||
|
protected BlockFire(int i, int j) {
|
||||||
|
super(i, j, Material.FIRE);
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void h() {
|
||||||
|
this.a(Block.WOOD.id, 5, 20);
|
||||||
|
this.a(Block.FENCE.id, 5, 20);
|
||||||
|
this.a(Block.WOOD_STAIRS.id, 5, 20);
|
||||||
|
this.a(Block.LOG.id, 5, 5);
|
||||||
|
this.a(Block.LEAVES.id, 30, 60);
|
||||||
|
this.a(Block.BOOKSHELF.id, 30, 20);
|
||||||
|
this.a(Block.TNT.id, 15, 100);
|
||||||
|
this.a(Block.LONG_GRASS.id, 60, 100);
|
||||||
|
this.a(Block.WOOL.id, 30, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void a(int i, int j, int k) {
|
||||||
|
this.a[i] = j;
|
||||||
|
this.b[i] = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int c() {
|
||||||
|
return 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
boolean flag = world.getTypeId(i, j - 1, k) == Block.NETHERRACK.id;
|
||||||
|
|
||||||
|
if (!this.canPlace(world, i, j, k)) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag && world.v() && (world.s(i, j, k) || world.s(i - 1, j, k) || world.s(i + 1, j, k) || world.s(i, j, k - 1) || world.s(i, j, k + 1))) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (l < 15) {
|
||||||
|
world.setRawData(i, j, k, l + random.nextInt(3) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
if (!flag && !this.g(world, i, j, k)) {
|
||||||
|
if (!world.e(i, j - 1, k) || l > 3) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
} else if (!flag && !this.b(world, i, j - 1, k) && l == 15 && random.nextInt(4) == 0) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
this.a(world, i + 1, j, k, 300, random, l);
|
||||||
|
this.a(world, i - 1, j, k, 300, random, l);
|
||||||
|
this.a(world, i, j - 1, k, 250, random, l);
|
||||||
|
this.a(world, i, j + 1, k, 250, random, l);
|
||||||
|
this.a(world, i, j, k - 1, 300, random, l);
|
||||||
|
this.a(world, i, j, k + 1, 300, random, l);
|
||||||
|
|
||||||
|
// CraftBukkit start - Call to stop spread of fire.
|
||||||
|
org.bukkit.Server server = world.getServer();
|
||||||
|
org.bukkit.World bworld = world.getWorld();
|
||||||
|
|
||||||
|
IgniteCause igniteCause = BlockIgniteEvent.IgniteCause.SPREAD;
|
||||||
|
org.bukkit.block.Block fromBlock = bworld.getBlockAt(i, j, k);
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
for (int i1 = i - 1; i1 <= i + 1; ++i1) {
|
||||||
|
for (int j1 = k - 1; j1 <= k + 1; ++j1) {
|
||||||
|
for (int k1 = j - 1; k1 <= j + 4; ++k1) {
|
||||||
|
if (i1 != i || k1 != j || j1 != k) {
|
||||||
|
int l1 = 100;
|
||||||
|
|
||||||
|
if (k1 > j + 1) {
|
||||||
|
l1 += (k1 - (j + 1)) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2 = this.h(world, i1, k1, j1);
|
||||||
|
|
||||||
|
if (i2 > 0) {
|
||||||
|
int j2 = (i2 + 40) / (l + 30);
|
||||||
|
|
||||||
|
if (j2 > 0 && random.nextInt(l1) <= j2 && (!world.v() || !world.s(i1, k1, j1)) && !world.s(i1 - 1, k1, k) && !world.s(i1 + 1, k1, j1) && !world.s(i1, k1, j1 - 1) && !world.s(i1, k1, j1 + 1)) {
|
||||||
|
int k2 = l + random.nextInt(5) / 4;
|
||||||
|
|
||||||
|
if (k2 > 15) {
|
||||||
|
k2 = 15;
|
||||||
|
}
|
||||||
|
// CraftBukkit start - Call to stop spread of fire.
|
||||||
|
org.bukkit.block.Block block = bworld.getBlockAt(i1, k1, j1);
|
||||||
|
|
||||||
|
if (block.getTypeId() != Block.FIRE.id) {
|
||||||
|
BlockIgniteEvent event = new BlockIgniteEvent(block, igniteCause, null);
|
||||||
|
server.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
org.bukkit.block.BlockState blockState = bworld.getBlockAt(i1, k1, j1).getState();
|
||||||
|
blockState.setTypeId(this.id);
|
||||||
|
blockState.setData(new MaterialData(this.id, (byte) k2));
|
||||||
|
|
||||||
|
BlockSpreadEvent spreadEvent = new BlockSpreadEvent(blockState.getBlock(), fromBlock, blockState);
|
||||||
|
server.getPluginManager().callEvent(spreadEvent);
|
||||||
|
|
||||||
|
if (!spreadEvent.isCancelled()) {
|
||||||
|
blockState.update(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void a(World world, int i, int j, int k, int l, Random random, int i1) {
|
||||||
|
int j1 = this.b[world.getTypeId(i, j, k)];
|
||||||
|
|
||||||
|
if (random.nextInt(l) < j1) {
|
||||||
|
boolean flag = world.getTypeId(i, j, k) == Block.TNT.id;
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
|
||||||
|
BlockBurnEvent event = new BlockBurnEvent(theBlock);
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
if (random.nextInt(i1 + 10) < 5 && !world.s(i, j, k)) {
|
||||||
|
int k1 = i1 + random.nextInt(5) / 4;
|
||||||
|
|
||||||
|
if (k1 > 15) {
|
||||||
|
k1 = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setTypeIdAndData(i, j, k, this.id, k1);
|
||||||
|
} else {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
Block.TNT.postBreak(world, i, j, k, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean g(World world, int i, int j, int k) {
|
||||||
|
return this.b(world, i + 1, j, k) ? true : (this.b(world, i - 1, j, k) ? true : (this.b(world, i, j - 1, k) ? true : (this.b(world, i, j + 1, k) ? true : (this.b(world, i, j, k - 1) ? true : this.b(world, i, j, k + 1)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int h(World world, int i, int j, int k) {
|
||||||
|
byte b0 = 0;
|
||||||
|
|
||||||
|
if (!world.isEmpty(i, j, k)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
int l = this.f(world, i + 1, j, k, b0);
|
||||||
|
|
||||||
|
l = this.f(world, i - 1, j, k, l);
|
||||||
|
l = this.f(world, i, j - 1, k, l);
|
||||||
|
l = this.f(world, i, j + 1, k, l);
|
||||||
|
l = this.f(world, i, j, k - 1, l);
|
||||||
|
l = this.f(world, i, j, k + 1, l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean k_() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
return this.a[iblockaccess.getTypeId(i, j, k)] > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int f(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = this.a[world.getTypeId(i, j, k)];
|
||||||
|
|
||||||
|
return i1 > l ? i1 : l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return world.e(i, j - 1, k) || this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (!world.e(i, j - 1, k) && !this.g(world, i, j, k)) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
if (world.getTypeId(i, j - 1, k) != Block.OBSIDIAN.id || !Block.PORTAL.a_(world, i, j, k)) {
|
||||||
|
if (!world.e(i, j - 1, k) && !this.g(world, i, j, k)) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockFlower extends Block {
|
||||||
|
|
||||||
|
protected BlockFlower(int i, int j) {
|
||||||
|
super(i, Material.PLANT);
|
||||||
|
this.textureId = j;
|
||||||
|
this.a(true);
|
||||||
|
float f = 0.2F;
|
||||||
|
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 3.0F, 0.5F + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return super.canPlace(world, i, j, k) && this.c(world.getTypeId(i, j - 1, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean c(int i) {
|
||||||
|
return i == Block.GRASS.id || i == Block.DIRT.id || i == Block.SOIL.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
super.doPhysics(world, i, j, k, l);
|
||||||
|
this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void g(World world, int i, int j, int k) {
|
||||||
|
if (!this.f(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean f(World world, int i, int j, int k) {
|
||||||
|
return (world.k(i, j, k) >= 8 || world.isChunkLoaded(i, j, k)) && this.c(world.getTypeId(i, j - 1, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import com.legacyminecraft.poseidon.PoseidonConfig;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.event.block.BlockFromToEvent;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
public class BlockFlowing extends BlockFluids {
|
||||||
|
|
||||||
|
int a = 0;
|
||||||
|
boolean[] b = new boolean[4];
|
||||||
|
int[] c = new int[4];
|
||||||
|
|
||||||
|
protected BlockFlowing(int i, Material material) {
|
||||||
|
super(i, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void i(World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
world.setRawTypeIdAndData(i, j, k, this.id + 1, l);
|
||||||
|
world.b(i, j, k, i, j, k);
|
||||||
|
world.notify(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.World bworld = world.getWorld();
|
||||||
|
org.bukkit.Server server = world.getServer();
|
||||||
|
org.bukkit.block.Block source = bworld == null ? null : bworld.getBlockAt(i, j, k);
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
int l = this.g(world, i, j, k);
|
||||||
|
byte b0 = 1;
|
||||||
|
|
||||||
|
if (this.material == Material.LAVA && !world.worldProvider.d) {
|
||||||
|
b0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag = true;
|
||||||
|
int i1;
|
||||||
|
|
||||||
|
if (l > 0) {
|
||||||
|
byte b1 = -100;
|
||||||
|
|
||||||
|
this.a = 0;
|
||||||
|
int j1 = this.f(world, i - 1, j, k, b1);
|
||||||
|
|
||||||
|
j1 = this.f(world, i + 1, j, k, j1);
|
||||||
|
j1 = this.f(world, i, j, k - 1, j1);
|
||||||
|
j1 = this.f(world, i, j, k + 1, j1);
|
||||||
|
i1 = j1 + b0;
|
||||||
|
if (i1 >= 8 || j1 < 0) {
|
||||||
|
i1 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.g(world, i, j + 1, k) >= 0) {
|
||||||
|
int k1 = this.g(world, i, j + 1, k);
|
||||||
|
|
||||||
|
if (k1 >= 8) {
|
||||||
|
i1 = k1;
|
||||||
|
} else {
|
||||||
|
i1 = k1 + 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a >= 2 && this.material == Material.WATER) {
|
||||||
|
if (world.getMaterial(i, j - 1, k).isBuildable()) {
|
||||||
|
i1 = 0;
|
||||||
|
} else if (world.getMaterial(i, j - 1, k) == this.material && world.getData(i, j, k) == 0) {
|
||||||
|
i1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.material == Material.LAVA && l < 8 && i1 < 8 && i1 > l && random.nextInt(4) != 0) {
|
||||||
|
// Poseidon start - Fix flowing lava not disappearing
|
||||||
|
boolean fixFlowingLava = PoseidonConfig.getInstance().getConfigBoolean("world.settings.flowing-lava-fix.enabled", true);
|
||||||
|
if (!fixFlowingLava) {
|
||||||
|
i1 = l;
|
||||||
|
}
|
||||||
|
// Poseidon end
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 != l) {
|
||||||
|
l = i1;
|
||||||
|
if (i1 < 0) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
world.setData(i, j, k, i1);
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
}
|
||||||
|
} else if (flag) {
|
||||||
|
this.i(world, i, j, k);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.i(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.l(world, i, j - 1, k)) {
|
||||||
|
// CraftBukkit start - send "down" to the server
|
||||||
|
BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN);
|
||||||
|
if (server != null) {
|
||||||
|
server.getPluginManager().callEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
if (l >= 8) {
|
||||||
|
world.setTypeIdAndData(i, j - 1, k, this.id, l);
|
||||||
|
} else {
|
||||||
|
world.setTypeIdAndData(i, j - 1, k, this.id, l + 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
} else if (l >= 0 && (l == 0 || this.k(world, i, j - 1, k))) {
|
||||||
|
boolean[] aboolean = this.j(world, i, j, k);
|
||||||
|
|
||||||
|
i1 = l + b0;
|
||||||
|
if (l >= 8) {
|
||||||
|
i1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 >= 8) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CraftBukkit start - all four cardinal directions. Do not change the order!
|
||||||
|
BlockFace[] faces = new BlockFace[] { BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST };
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (BlockFace currentFace: faces) {
|
||||||
|
if (aboolean[index]) {
|
||||||
|
BlockFromToEvent event = new BlockFromToEvent(source, currentFace);
|
||||||
|
|
||||||
|
if (server != null) {
|
||||||
|
server.getPluginManager().callEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
this.flow(world, i + currentFace.getModX(), j, k + currentFace.getModZ(), i1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flow(World world, int i, int j, int k, int l) {
|
||||||
|
if (this.l(world, i, j, k)) {
|
||||||
|
int i1 = world.getTypeId(i, j, k);
|
||||||
|
|
||||||
|
if (i1 > 0) {
|
||||||
|
if (this.material == Material.LAVA) {
|
||||||
|
this.h(world, i, j, k);
|
||||||
|
} else {
|
||||||
|
Block.byId[i1].g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setTypeIdAndData(i, j, k, this.id, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int b(World world, int i, int j, int k, int l, int i1) {
|
||||||
|
int j1 = 1000;
|
||||||
|
|
||||||
|
for (int k1 = 0; k1 < 4; ++k1) {
|
||||||
|
if ((k1 != 0 || i1 != 1) && (k1 != 1 || i1 != 0) && (k1 != 2 || i1 != 3) && (k1 != 3 || i1 != 2)) {
|
||||||
|
int l1 = i;
|
||||||
|
int i2 = k;
|
||||||
|
|
||||||
|
if (k1 == 0) {
|
||||||
|
l1 = i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k1 == 1) {
|
||||||
|
++l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k1 == 2) {
|
||||||
|
i2 = k - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k1 == 3) {
|
||||||
|
++i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.k(world, l1, j, i2) && (world.getMaterial(l1, j, i2) != this.material || world.getData(l1, j, i2) != 0)) {
|
||||||
|
if (!this.k(world, l1, j - 1, i2)) {
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l < 4) {
|
||||||
|
int j2 = this.b(world, l1, j, i2, l + 1, k1);
|
||||||
|
|
||||||
|
if (j2 < j1) {
|
||||||
|
j1 = j2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return j1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean[] j(World world, int i, int j, int k) {
|
||||||
|
int l;
|
||||||
|
int i1;
|
||||||
|
|
||||||
|
for (l = 0; l < 4; ++l) {
|
||||||
|
this.c[l] = 1000;
|
||||||
|
i1 = i;
|
||||||
|
int j1 = k;
|
||||||
|
|
||||||
|
if (l == 0) {
|
||||||
|
i1 = i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 1) {
|
||||||
|
++i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 2) {
|
||||||
|
j1 = k - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 3) {
|
||||||
|
++j1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.k(world, i1, j, j1) && (world.getMaterial(i1, j, j1) != this.material || world.getData(i1, j, j1) != 0)) {
|
||||||
|
if (!this.k(world, i1, j - 1, j1)) {
|
||||||
|
this.c[l] = 0;
|
||||||
|
} else {
|
||||||
|
this.c[l] = this.b(world, i1, j, j1, 1, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l = this.c[0];
|
||||||
|
|
||||||
|
for (i1 = 1; i1 < 4; ++i1) {
|
||||||
|
if (this.c[i1] < l) {
|
||||||
|
l = this.c[i1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i1 = 0; i1 < 4; ++i1) {
|
||||||
|
this.b[i1] = this.c[i1] == l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean k(World world, int i, int j, int k) {
|
||||||
|
int l = world.getTypeId(i, j, k);
|
||||||
|
|
||||||
|
if (l != Block.WOODEN_DOOR.id && l != Block.IRON_DOOR_BLOCK.id && l != Block.SIGN_POST.id && l != Block.LADDER.id && l != Block.SUGAR_CANE_BLOCK.id) {
|
||||||
|
if (l == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Material material = Block.byId[l].material;
|
||||||
|
|
||||||
|
return material.isSolid();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int f(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = this.g(world, i, j, k);
|
||||||
|
|
||||||
|
if (i1 < 0) {
|
||||||
|
return l;
|
||||||
|
} else {
|
||||||
|
if (i1 == 0) {
|
||||||
|
++this.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 >= 8) {
|
||||||
|
i1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l >= 0 && i1 >= l ? l : i1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean l(World world, int i, int j, int k) {
|
||||||
|
Material material = world.getMaterial(i, j, k);
|
||||||
|
|
||||||
|
return material == this.material ? false : (material == Material.LAVA ? false : !this.k(world, i, j, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
super.c(world, i, j, k);
|
||||||
|
if (world.getTypeId(i, j, k) == this.id) {
|
||||||
|
world.c(i, j, k, this.id, this.c());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,234 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public abstract class BlockFluids extends Block {
|
||||||
|
|
||||||
|
protected BlockFluids(int i, Material material) {
|
||||||
|
super(i, (material == Material.LAVA ? 14 : 12) * 16 + 13, material);
|
||||||
|
float f = 0.0F;
|
||||||
|
float f1 = 0.0F;
|
||||||
|
|
||||||
|
this.a(0.0F + f1, 0.0F + f, 0.0F + f1, 1.0F + f1, 1.0F + f, 1.0F + f1);
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float c(int i) {
|
||||||
|
if (i >= 8) {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float f = (float) (i + 1) / 9.0F;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i != 0 && i != 1 ? this.textureId + 1 : this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int g(World world, int i, int j, int k) {
|
||||||
|
return world.getMaterial(i, j, k) != this.material ? -1 : world.getData(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int b(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
if (iblockaccess.getMaterial(i, j, k) != this.material) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
int l = iblockaccess.getData(i, j, k);
|
||||||
|
|
||||||
|
if (l >= 8) {
|
||||||
|
l = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(int i, boolean flag) {
|
||||||
|
return flag && i == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
Material material = iblockaccess.getMaterial(i, j, k);
|
||||||
|
|
||||||
|
return material == this.material ? false : (material == Material.ICE ? false : (l == 1 ? true : super.b(iblockaccess, i, j, k, l)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec3D c(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
Vec3D vec3d = Vec3D.create(0.0D, 0.0D, 0.0D);
|
||||||
|
int l = this.b(iblockaccess, i, j, k);
|
||||||
|
|
||||||
|
for (int i1 = 0; i1 < 4; ++i1) {
|
||||||
|
int j1 = i;
|
||||||
|
int k1 = k;
|
||||||
|
|
||||||
|
if (i1 == 0) {
|
||||||
|
j1 = i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 1) {
|
||||||
|
k1 = k - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 2) {
|
||||||
|
++j1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 3) {
|
||||||
|
++k1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int l1 = this.b(iblockaccess, j1, j, k1);
|
||||||
|
int i2;
|
||||||
|
|
||||||
|
if (l1 < 0) {
|
||||||
|
if (!iblockaccess.getMaterial(j1, j, k1).isSolid()) {
|
||||||
|
l1 = this.b(iblockaccess, j1, j - 1, k1);
|
||||||
|
if (l1 >= 0) {
|
||||||
|
i2 = l1 - (l - 8);
|
||||||
|
vec3d = vec3d.add((double) ((j1 - i) * i2), (double) ((j - j) * i2), (double) ((k1 - k) * i2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (l1 >= 0) {
|
||||||
|
i2 = l1 - l;
|
||||||
|
vec3d = vec3d.add((double) ((j1 - i) * i2), (double) ((j - j) * i2), (double) ((k1 - k) * i2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iblockaccess.getData(i, j, k) >= 8) {
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i, j, k - 1, 2)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i, j, k + 1, 3)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i - 1, j, k, 4)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i + 1, j, k, 5)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i, j + 1, k - 1, 2)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i, j + 1, k + 1, 3)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i - 1, j + 1, k, 4)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || this.b(iblockaccess, i + 1, j + 1, k, 5)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
vec3d = vec3d.b().add(0.0D, -6.0D, 0.0D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3d = vec3d.b();
|
||||||
|
return vec3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Entity entity, Vec3D vec3d) {
|
||||||
|
Vec3D vec3d1 = this.c((IBlockAccess) world, i, j, k);
|
||||||
|
|
||||||
|
vec3d.a += vec3d1.a;
|
||||||
|
vec3d.b += vec3d1.b;
|
||||||
|
vec3d.c += vec3d1.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int c() {
|
||||||
|
return this.material == Material.WATER ? 5 : (this.material == Material.LAVA ? 30 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
super.a(world, i, j, k, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
this.i(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
this.i(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void i(World world, int i, int j, int k) {
|
||||||
|
if (world.getTypeId(i, j, k) == this.id) {
|
||||||
|
if (this.material == Material.LAVA) {
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (flag || world.getMaterial(i, j, k - 1) == Material.WATER) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || world.getMaterial(i, j, k + 1) == Material.WATER) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || world.getMaterial(i - 1, j, k) == Material.WATER) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || world.getMaterial(i + 1, j, k) == Material.WATER) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag || world.getMaterial(i, j + 1, k) == Material.WATER) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if (l == 0) {
|
||||||
|
world.setTypeId(i, j, k, Block.OBSIDIAN.id);
|
||||||
|
} else if (l <= 4) {
|
||||||
|
world.setTypeId(i, j, k, Block.COBBLESTONE.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.h(world, i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void h(World world, int i, int j, int k) {
|
||||||
|
world.makeSound((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), "random.fizz", 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
|
||||||
|
|
||||||
|
for (int l = 0; l < 8; ++l) {
|
||||||
|
world.a("largesmoke", (double) i + Math.random(), (double) j + 1.2D, (double) k + Math.random(), 0.0D, 0.0D, 0.0D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockFurnace extends BlockContainer {
|
||||||
|
|
||||||
|
private Random a = new Random();
|
||||||
|
private final boolean b;
|
||||||
|
private static boolean c = false;
|
||||||
|
|
||||||
|
protected BlockFurnace(int i, boolean flag) {
|
||||||
|
super(i, Material.STONE);
|
||||||
|
this.b = flag;
|
||||||
|
this.textureId = 45;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Block.FURNACE.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c(World world, int i, int j, int k) {
|
||||||
|
super.c(world, i, j, k);
|
||||||
|
this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void g(World world, int i, int j, int k) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
int l = world.getTypeId(i, j, k - 1);
|
||||||
|
int i1 = world.getTypeId(i, j, k + 1);
|
||||||
|
int j1 = world.getTypeId(i - 1, j, k);
|
||||||
|
int k1 = world.getTypeId(i + 1, j, k);
|
||||||
|
byte b0 = 3;
|
||||||
|
|
||||||
|
if (Block.o[l] && !Block.o[i1]) {
|
||||||
|
b0 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[i1] && !Block.o[l]) {
|
||||||
|
b0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[j1] && !Block.o[k1]) {
|
||||||
|
b0 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Block.o[k1] && !Block.o[j1]) {
|
||||||
|
b0 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, b0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId + 17 : (i == 0 ? this.textureId + 17 : (i == 3 ? this.textureId - 1 : this.textureId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (world.isStatic) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
TileEntityFurnace tileentityfurnace = (TileEntityFurnace) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
entityhuman.a(tileentityfurnace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void a(boolean flag, World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
TileEntity tileentity = world.getTileEntity(i, j, k);
|
||||||
|
if (tileentity == null) return; // CraftBukkit
|
||||||
|
|
||||||
|
c = true;
|
||||||
|
if (flag) {
|
||||||
|
world.setTypeId(i, j, k, Block.BURNING_FURNACE.id);
|
||||||
|
} else {
|
||||||
|
world.setTypeId(i, j, k, Block.FURNACE.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = false;
|
||||||
|
world.setData(i, j, k, l);
|
||||||
|
tileentity.j();
|
||||||
|
world.setTileEntity(i, j, k, tileentity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TileEntity a_() {
|
||||||
|
return new TileEntityFurnace();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, EntityLiving entityliving) {
|
||||||
|
int l = MathHelper.floor((double) (entityliving.yaw * 4.0F / 360.0F) + 0.5D) & 3;
|
||||||
|
|
||||||
|
if (l == 0) {
|
||||||
|
world.setData(i, j, k, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 1) {
|
||||||
|
world.setData(i, j, k, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 2) {
|
||||||
|
world.setData(i, j, k, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 3) {
|
||||||
|
world.setData(i, j, k, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
if (!c) {
|
||||||
|
TileEntityFurnace tileentityfurnace = (TileEntityFurnace) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
if (tileentityfurnace == null) return; // CraftBukkit
|
||||||
|
for (int l = 0; l < tileentityfurnace.getSize(); ++l) {
|
||||||
|
ItemStack itemstack = tileentityfurnace.getItem(l);
|
||||||
|
|
||||||
|
if (itemstack != null) {
|
||||||
|
float f = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f1 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
float f2 = this.a.nextFloat() * 0.8F + 0.1F;
|
||||||
|
|
||||||
|
while (itemstack.count > 0) {
|
||||||
|
int i1 = this.a.nextInt(21) + 10;
|
||||||
|
|
||||||
|
if (i1 > itemstack.count) {
|
||||||
|
i1 = itemstack.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemstack.count -= i1;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) ((float) i + f), (double) ((float) j + f1), (double) ((float) k + f2), new ItemStack(itemstack.id, i1, itemstack.getData()));
|
||||||
|
float f3 = 0.05F;
|
||||||
|
|
||||||
|
entityitem.motX = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F);
|
||||||
|
entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3);
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
tileentityfurnace.setItem(l, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockGlass extends BlockBreakable {
|
||||||
|
|
||||||
|
public BlockGlass(int i, int j, Material material, boolean flag) {
|
||||||
|
super(i, j, material, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
import org.bukkit.event.block.BlockSpreadEvent;
|
||||||
|
import org.bukkit.event.block.BlockFadeEvent;
|
||||||
|
//CraftBukkit end
|
||||||
|
|
||||||
|
public class BlockGrass extends Block {
|
||||||
|
|
||||||
|
protected BlockGrass(int i) {
|
||||||
|
super(i, Material.GRASS);
|
||||||
|
this.textureId = 3;
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
if (world.getLightLevel(i, j + 1, k) < 4 && Block.q[world.getTypeId(i, j + 1, k)] > 2) {
|
||||||
|
if (random.nextInt(4) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.World bworld = world.getWorld();
|
||||||
|
org.bukkit.block.BlockState blockState = bworld.getBlockAt(i, j, k).getState();
|
||||||
|
blockState.setTypeId(Block.DIRT.id);
|
||||||
|
|
||||||
|
BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState);
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
blockState.update(true);
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
} else if (world.getLightLevel(i, j + 1, k) >= 9) {
|
||||||
|
int l = i + random.nextInt(3) - 1;
|
||||||
|
int i1 = j + random.nextInt(5) - 3;
|
||||||
|
int j1 = k + random.nextInt(3) - 1;
|
||||||
|
int k1 = world.getTypeId(l, i1 + 1, j1);
|
||||||
|
|
||||||
|
if (world.getTypeId(l, i1, j1) == Block.DIRT.id && world.getLightLevel(l, i1 + 1, j1) >= 4 && Block.q[k1] <= 2) {
|
||||||
|
// CraftBukkit start
|
||||||
|
org.bukkit.World bworld = world.getWorld();
|
||||||
|
org.bukkit.block.BlockState blockState = bworld.getBlockAt(l, i1, j1).getState();
|
||||||
|
blockState.setTypeId(this.id);
|
||||||
|
|
||||||
|
BlockSpreadEvent event = new BlockSpreadEvent(blockState.getBlock(), bworld.getBlockAt(i, j, k), blockState);
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
blockState.update(true);
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Block.DIRT.a(0, random);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockGravel extends BlockSand {
|
||||||
|
|
||||||
|
public BlockGravel(int i, int j) {
|
||||||
|
super(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return random.nextInt(10) == 0 ? Item.FLINT.id : this.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockIce extends BlockBreakable {
|
||||||
|
|
||||||
|
public BlockIce(int i, int j) {
|
||||||
|
super(i, j, Material.ICE, false);
|
||||||
|
this.frictionFactor = 0.98F;
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, EntityHuman entityhuman, int i, int j, int k, int l) {
|
||||||
|
super.a(world, entityhuman, i, j, k, l);
|
||||||
|
Material material = world.getMaterial(i, j - 1, k);
|
||||||
|
|
||||||
|
if (material.isSolid() || material.isLiquid()) {
|
||||||
|
world.setTypeId(i, j, k, Block.WATER.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (world.a(EnumSkyBlock.BLOCK, i, j, k) > 11 - Block.q[this.id]) {
|
||||||
|
// CraftBukkit start
|
||||||
|
if (CraftEventFactory.callBlockFadeEvent(world.getWorld().getBlockAt(i, j, k), Block.STATIONARY_WATER.id).isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, Block.STATIONARY_WATER.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int e() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BlockJukeBox extends BlockContainer {
|
||||||
|
|
||||||
|
protected BlockJukeBox(int i, int j) {
|
||||||
|
super(i, j, Material.WOOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return this.textureId + (i == 1 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (world.getData(i, j, k) == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.b_(world, i, j, k);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void f(World world, int i, int j, int k, int l) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
TileEntityRecordPlayer tileentityrecordplayer = (TileEntityRecordPlayer) world.getTileEntity(i, j, k);
|
||||||
|
|
||||||
|
tileentityrecordplayer.a = l;
|
||||||
|
tileentityrecordplayer.update();
|
||||||
|
world.setData(i, j, k, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b_(World world, int i, int j, int k) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
TileEntityRecordPlayer tileentityrecordplayer = (TileEntityRecordPlayer) world.getTileEntity(i, j, k);
|
||||||
|
if (tileentityrecordplayer == null) return; // CraftBukkit
|
||||||
|
int l = tileentityrecordplayer.a;
|
||||||
|
|
||||||
|
if (l != 0) {
|
||||||
|
world.e(1005, i, j, k, 0);
|
||||||
|
world.a((String) null, i, j, k);
|
||||||
|
tileentityrecordplayer.a = 0;
|
||||||
|
tileentityrecordplayer.update();
|
||||||
|
world.setData(i, j, k, 0);
|
||||||
|
float f = 0.7F;
|
||||||
|
double d0 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.5D;
|
||||||
|
double d1 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.2D + 0.6D;
|
||||||
|
double d2 = (double) (world.random.nextFloat() * f) + (double) (1.0F - f) * 0.5D;
|
||||||
|
EntityItem entityitem = new EntityItem(world, (double) i + d0, (double) j + d1, (double) k + d2, new ItemStack(l, 1, 0));
|
||||||
|
|
||||||
|
entityitem.pickupDelay = 10;
|
||||||
|
world.addEntity(entityitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
this.b_(world, i, j, k);
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropNaturally(World world, int i, int j, int k, int l, float f) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
super.dropNaturally(world, i, j, k, l, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TileEntity a_() {
|
||||||
|
return new TileEntityRecordPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLadder extends Block {
|
||||||
|
|
||||||
|
protected BlockLadder(int i, int j) {
|
||||||
|
super(i, j, Material.ORIENTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
float f = 0.125F;
|
||||||
|
|
||||||
|
if (l == 2) {
|
||||||
|
this.a(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 3) {
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 4) {
|
||||||
|
this.a(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 5) {
|
||||||
|
this.a(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.e(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return world.e(i - 1, j, k) ? true : (world.e(i + 1, j, k) ? true : (world.e(i, j, k - 1) ? true : world.e(i, j, k + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((i1 == 0 || l == 2) && world.e(i, j, k + 1)) {
|
||||||
|
i1 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i1 == 0 || l == 3) && world.e(i, j, k - 1)) {
|
||||||
|
i1 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i1 == 0 || l == 4) && world.e(i + 1, j, k)) {
|
||||||
|
i1 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i1 == 0 || l == 5) && world.e(i - 1, j, k)) {
|
||||||
|
i1 = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.setData(i, j, k, i1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (i1 == 2 && world.e(i, j, k + 1)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 3 && world.e(i, j, k - 1)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 4 && world.e(i + 1, j, k)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == 5 && world.e(i - 1, j, k)) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag) {
|
||||||
|
this.g(world, i, j, k, i1);
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.doPhysics(world, i, j, k, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.LeavesDecayEvent;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLeaves extends BlockLeavesBase {
|
||||||
|
|
||||||
|
private int c;
|
||||||
|
int[] a;
|
||||||
|
|
||||||
|
protected BlockLeaves(int i, int j) {
|
||||||
|
super(i, j, Material.LEAVES, false);
|
||||||
|
this.c = j;
|
||||||
|
this.a(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
byte b0 = 1;
|
||||||
|
int l = b0 + 1;
|
||||||
|
|
||||||
|
if (world.a(i - l, j - l, k - l, i + l, j + l, k + l)) {
|
||||||
|
for (int i1 = -b0; i1 <= b0; ++i1) {
|
||||||
|
for (int j1 = -b0; j1 <= b0; ++j1) {
|
||||||
|
for (int k1 = -b0; k1 <= b0; ++k1) {
|
||||||
|
int l1 = world.getTypeId(i + i1, j + j1, k + k1);
|
||||||
|
|
||||||
|
if (l1 == Block.LEAVES.id) {
|
||||||
|
int i2 = world.getData(i + i1, j + j1, k + k1);
|
||||||
|
|
||||||
|
world.setRawData(i + i1, j + j1, k + k1, i2 | 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
if (!world.isStatic) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) != 0) {
|
||||||
|
byte b0 = 4;
|
||||||
|
int i1 = b0 + 1;
|
||||||
|
byte b1 = 32;
|
||||||
|
int j1 = b1 * b1;
|
||||||
|
int k1 = b1 / 2;
|
||||||
|
|
||||||
|
if (this.a == null) {
|
||||||
|
this.a = new int[b1 * b1 * b1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int l1;
|
||||||
|
|
||||||
|
if (world.a(i - i1, j - i1, k - i1, i + i1, j + i1, k + i1)) {
|
||||||
|
int i2;
|
||||||
|
int j2;
|
||||||
|
int k2;
|
||||||
|
|
||||||
|
for (l1 = -b0; l1 <= b0; ++l1) {
|
||||||
|
for (i2 = -b0; i2 <= b0; ++i2) {
|
||||||
|
for (j2 = -b0; j2 <= b0; ++j2) {
|
||||||
|
k2 = world.getTypeId(i + l1, j + i2, k + j2);
|
||||||
|
if (k2 == Block.LOG.id) {
|
||||||
|
this.a[(l1 + k1) * j1 + (i2 + k1) * b1 + j2 + k1] = 0;
|
||||||
|
} else if (k2 == Block.LEAVES.id) {
|
||||||
|
this.a[(l1 + k1) * j1 + (i2 + k1) * b1 + j2 + k1] = -2;
|
||||||
|
} else {
|
||||||
|
this.a[(l1 + k1) * j1 + (i2 + k1) * b1 + j2 + k1] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l1 = 1; l1 <= 4; ++l1) {
|
||||||
|
for (i2 = -b0; i2 <= b0; ++i2) {
|
||||||
|
for (j2 = -b0; j2 <= b0; ++j2) {
|
||||||
|
for (k2 = -b0; k2 <= b0; ++k2) {
|
||||||
|
if (this.a[(i2 + k1) * j1 + (j2 + k1) * b1 + k2 + k1] == l1 - 1) {
|
||||||
|
if (this.a[(i2 + k1 - 1) * j1 + (j2 + k1) * b1 + k2 + k1] == -2) {
|
||||||
|
this.a[(i2 + k1 - 1) * j1 + (j2 + k1) * b1 + k2 + k1] = l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a[(i2 + k1 + 1) * j1 + (j2 + k1) * b1 + k2 + k1] == -2) {
|
||||||
|
this.a[(i2 + k1 + 1) * j1 + (j2 + k1) * b1 + k2 + k1] = l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a[(i2 + k1) * j1 + (j2 + k1 - 1) * b1 + k2 + k1] == -2) {
|
||||||
|
this.a[(i2 + k1) * j1 + (j2 + k1 - 1) * b1 + k2 + k1] = l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a[(i2 + k1) * j1 + (j2 + k1 + 1) * b1 + k2 + k1] == -2) {
|
||||||
|
this.a[(i2 + k1) * j1 + (j2 + k1 + 1) * b1 + k2 + k1] = l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a[(i2 + k1) * j1 + (j2 + k1) * b1 + (k2 + k1 - 1)] == -2) {
|
||||||
|
this.a[(i2 + k1) * j1 + (j2 + k1) * b1 + (k2 + k1 - 1)] = l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.a[(i2 + k1) * j1 + (j2 + k1) * b1 + k2 + k1 + 1] == -2) {
|
||||||
|
this.a[(i2 + k1) * j1 + (j2 + k1) * b1 + k2 + k1 + 1] = l1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l1 = this.a[k1 * j1 + k1 * b1 + k1];
|
||||||
|
if (l1 >= 0) {
|
||||||
|
world.setRawData(i, j, k, l & -9);
|
||||||
|
} else {
|
||||||
|
this.g(world, i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void g(World world, int i, int j, int k) {
|
||||||
|
// CraftBukkit start
|
||||||
|
LeavesDecayEvent event = new LeavesDecayEvent(world.getWorld().getBlockAt(i, j, k));
|
||||||
|
world.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (event.isCancelled()) return;
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return random.nextInt(20) == 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Block.SAPLING.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, EntityHuman entityhuman, int i, int j, int k, int l) {
|
||||||
|
if (!world.isStatic && entityhuman.G() != null && entityhuman.G().id == Item.SHEARS.id) {
|
||||||
|
entityhuman.a(StatisticList.C[this.id], 1);
|
||||||
|
this.a(world, i, j, k, new ItemStack(Block.LEAVES.id, 1, l & 3));
|
||||||
|
} else {
|
||||||
|
super.a(world, entityhuman, i, j, k, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int a_(int i) {
|
||||||
|
return i & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return !this.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return (j & 3) == 1 ? this.textureId + 80 : this.textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, Entity entity) {
|
||||||
|
super.b(world, i, j, k, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
public class BlockLeavesBase extends Block {
|
||||||
|
|
||||||
|
protected boolean b;
|
||||||
|
|
||||||
|
protected BlockLeavesBase(int i, int j, Material material, boolean flag) {
|
||||||
|
super(i, j, material);
|
||||||
|
this.b = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import org.bukkit.event.block.BlockRedstoneEvent;
|
||||||
|
|
||||||
|
public class BlockLever extends Block {
|
||||||
|
|
||||||
|
protected BlockLever(int i, int j) {
|
||||||
|
super(i, j, Material.ORIENTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB e(World world, int i, int j, int k) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean b() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k, int l) {
|
||||||
|
return l == 1 && world.e(i, j - 1, k) ? true : (l == 2 && world.e(i, j, k + 1) ? true : (l == 3 && world.e(i, j, k - 1) ? true : (l == 4 && world.e(i + 1, j, k) ? true : l == 5 && world.e(i - 1, j, k))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return world.e(i - 1, j, k) ? true : (world.e(i + 1, j, k) ? true : (world.e(i, j, k - 1) ? true : (world.e(i, j, k + 1) ? true : world.e(i, j - 1, k))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postPlace(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
int j1 = i1 & 8;
|
||||||
|
|
||||||
|
i1 &= 7;
|
||||||
|
i1 = -1;
|
||||||
|
if (l == 1 && world.e(i, j - 1, k)) {
|
||||||
|
i1 = 5 + world.random.nextInt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 2 && world.e(i, j, k + 1)) {
|
||||||
|
i1 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 3 && world.e(i, j, k - 1)) {
|
||||||
|
i1 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 4 && world.e(i + 1, j, k)) {
|
||||||
|
i1 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l == 5 && world.e(i - 1, j, k)) {
|
||||||
|
i1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i1 == -1) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
} else {
|
||||||
|
world.setData(i, j, k, i1 + j1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPhysics(World world, int i, int j, int k, int l) {
|
||||||
|
if (this.g(world, i, j, k)) {
|
||||||
|
int i1 = world.getData(i, j, k) & 7;
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if (!world.e(i - 1, j, k) && i1 == 1) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i + 1, j, k) && i1 == 2) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j, k - 1) && i1 == 3) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j, k + 1) && i1 == 4) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j - 1, k) && i1 == 5) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.e(i, j - 1, k) && i1 == 6) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean g(World world, int i, int j, int k) {
|
||||||
|
if (!this.canPlace(world, i, j, k)) {
|
||||||
|
this.g(world, i, j, k, world.getData(i, j, k));
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(IBlockAccess iblockaccess, int i, int j, int k) {
|
||||||
|
int l = iblockaccess.getData(i, j, k) & 7;
|
||||||
|
float f = 0.1875F;
|
||||||
|
|
||||||
|
if (l == 1) {
|
||||||
|
this.a(0.0F, 0.2F, 0.5F - f, f * 2.0F, 0.8F, 0.5F + f);
|
||||||
|
} else if (l == 2) {
|
||||||
|
this.a(1.0F - f * 2.0F, 0.2F, 0.5F - f, 1.0F, 0.8F, 0.5F + f);
|
||||||
|
} else if (l == 3) {
|
||||||
|
this.a(0.5F - f, 0.2F, 0.0F, 0.5F + f, 0.8F, f * 2.0F);
|
||||||
|
} else if (l == 4) {
|
||||||
|
this.a(0.5F - f, 0.2F, 1.0F - f * 2.0F, 0.5F + f, 0.8F, 1.0F);
|
||||||
|
} else {
|
||||||
|
f = 0.25F;
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.6F, 0.5F + f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void b(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
this.interact(world, i, j, k, entityhuman);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interact(World world, int i, int j, int k, EntityHuman entityhuman) {
|
||||||
|
if (world.isStatic) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
int i1 = l & 7;
|
||||||
|
int j1 = 8 - (l & 8);
|
||||||
|
|
||||||
|
// CraftBukkit start - Interact Lever
|
||||||
|
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
|
||||||
|
int old = (j1 != 8) ? 1 : 0;
|
||||||
|
int current = (j1 == 8) ? 1 : 0;
|
||||||
|
|
||||||
|
BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
|
||||||
|
world.getServer().getPluginManager().callEvent(eventRedstone);
|
||||||
|
|
||||||
|
if ((eventRedstone.getNewCurrent() > 0) != (j1 == 8)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
|
||||||
|
world.setData(i, j, k, i1 + j1);
|
||||||
|
world.b(i, j, k, i, j, k);
|
||||||
|
world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.click", 0.3F, j1 > 0 ? 0.6F : 0.5F);
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
if (i1 == 1) {
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
} else {
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
int l = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((l & 8) > 0) {
|
||||||
|
world.applyPhysics(i, j, k, this.id);
|
||||||
|
int i1 = l & 7;
|
||||||
|
|
||||||
|
if (i1 == 1) {
|
||||||
|
world.applyPhysics(i - 1, j, k, this.id);
|
||||||
|
} else if (i1 == 2) {
|
||||||
|
world.applyPhysics(i + 1, j, k, this.id);
|
||||||
|
} else if (i1 == 3) {
|
||||||
|
world.applyPhysics(i, j, k - 1, this.id);
|
||||||
|
} else if (i1 == 4) {
|
||||||
|
world.applyPhysics(i, j, k + 1, this.id);
|
||||||
|
} else {
|
||||||
|
world.applyPhysics(i, j - 1, k, this.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.remove(world, i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
|
||||||
|
return (iblockaccess.getData(i, j, k) & 8) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean d(World world, int i, int j, int k, int l) {
|
||||||
|
int i1 = world.getData(i, j, k);
|
||||||
|
|
||||||
|
if ((i1 & 8) == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int j1 = i1 & 7;
|
||||||
|
|
||||||
|
return j1 == 6 && l == 1 ? true : (j1 == 5 && l == 1 ? true : (j1 == 4 && l == 2 ? true : (j1 == 3 && l == 3 ? true : (j1 == 2 && l == 4 ? true : j1 == 1 && l == 5))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPowerSource() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLightStone extends Block {
|
||||||
|
|
||||||
|
public BlockLightStone(int i, int j, Material material) {
|
||||||
|
super(i, j, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 2 + random.nextInt(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Item.GLOWSTONE_DUST.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLockedChest extends Block {
|
||||||
|
|
||||||
|
protected BlockLockedChest(int i) {
|
||||||
|
super(i, Material.WOOD);
|
||||||
|
this.textureId = 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i) {
|
||||||
|
return i == 1 ? this.textureId - 1 : (i == 0 ? this.textureId - 1 : (i == 3 ? this.textureId + 1 : this.textureId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPlace(World world, int i, int j, int k) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, int i, int j, int k, Random random) {
|
||||||
|
world.setTypeId(i, j, k, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLog extends Block {
|
||||||
|
|
||||||
|
protected BlockLog(int i) {
|
||||||
|
super(i, Material.WOOD);
|
||||||
|
this.textureId = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(Random random) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return Block.LOG.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void a(World world, EntityHuman entityhuman, int i, int j, int k, int l) {
|
||||||
|
super.a(world, entityhuman, i, j, k, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(World world, int i, int j, int k) {
|
||||||
|
byte b0 = 4;
|
||||||
|
int l = b0 + 1;
|
||||||
|
|
||||||
|
if (world.a(i - l, j - l, k - l, i + l, j + l, k + l)) {
|
||||||
|
for (int i1 = -b0; i1 <= b0; ++i1) {
|
||||||
|
for (int j1 = -b0; j1 <= b0; ++j1) {
|
||||||
|
for (int k1 = -b0; k1 <= b0; ++k1) {
|
||||||
|
int l1 = world.getTypeId(i + i1, j + j1, k + k1);
|
||||||
|
|
||||||
|
if (l1 == Block.LEAVES.id) {
|
||||||
|
int i2 = world.getData(i + i1, j + j1, k + k1);
|
||||||
|
|
||||||
|
if ((i2 & 8) == 0) {
|
||||||
|
world.setRawData(i + i1, j + j1, k + k1, i2 | 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return i == 1 ? 21 : (i == 0 ? 21 : (j == 1 ? 116 : (j == 2 ? 117 : 20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int a_(int i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package net.minecraft.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class BlockLongGrass extends BlockFlower {
|
||||||
|
|
||||||
|
protected BlockLongGrass(int i, int j) {
|
||||||
|
super(i, j);
|
||||||
|
float f = 0.4F;
|
||||||
|
|
||||||
|
this.a(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, int j) {
|
||||||
|
return j == 1 ? this.textureId : (j == 2 ? this.textureId + 16 + 1 : (j == 0 ? this.textureId + 16 : this.textureId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int a(int i, Random random) {
|
||||||
|
return random.nextInt(8) == 0 ? Item.SEEDS.id : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user